Error Implementation with Thirdweb

GM guys, first time integrating Pyth here so this may be a noobie question. I running a transaction with Pyth using third-party service provider Thirdweb. I get all the logs from Pyth so everything seems fine, but the transaction never pulls through. I wanted to ask if there was a problem with my implementation, or if it was with my thirdparty provider Thirdweb? Many thanks guys.

:link: Sonic Blaze Testnet

:receipt:Dummy Test Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Import the Pyth interface
import “pyth-sdk-solidity/IPyth.sol at main · pyth-network/pyth-sdk-solidity · GitHub”;
import “pyth-sdk-solidity/PythStructs.sol at main · pyth-network/pyth-sdk-solidity · GitHub”;

contract LegendOfSparta {
event LegendaryTransfer (address indexed from, address to, uint amountUSD, uint amountWei);

IPyth pyth;
bytes32 sonicPriceId;

int32 constant SONIC_IN_WEI_EXPO = 18;

constructor(address _pyth, bytes32 _sonicPriceId) {
    pyth = IPyth(_pyth);
    sonicPriceId = _sonicPriceId;
}

function sendToLegend(address payable to, uint amountUSD, bytes[] calldata updateData) external payable {
    uint updateFee = pyth.getUpdateFee(updateData);
    pyth.updatePriceFeeds{value: updateFee}(updateData);

    PythStructs.Price memory currentSonicPrice = pyth.getPrice(sonicPriceId);

    uint amountWei;

    require(currentSonicPrice.price >= 0, "Price should be positive.");

    if (currentSonicPrice.expo + SONIC_IN_WEI_EXPO >= 0) {
        amountWei = amountUSD * uint(uint64(currentSonicPrice.price)) * 10**uint32(SONIC_IN_WEI_EXPO+currentSonicPrice.expo);
    } else {
        amountWei = amountUSD * uint(uint64(currentSonicPrice.price)) * 10**uint32(SONIC_IN_WEI_EXPO-currentSonicPrice.expo);

    require (msg.value - updateFee >= amountWei, "Insufficient fee");

    to.transfer(amountWei);
    payable(msg.sender).transfer(msg.value - amountWei - updateFee);

    emit LegendaryTransfer(msg.sender, to, amountUSD, amountWei);
    }

}

}

Frontend:
export const legendAbi = Legend.abi;
export const PYTH_CONTRACT_ADDRESS = “0x2880ab155794e7179c9ee2e38200202908c17b43”;
export const LEGEND_CONTRACT_ADDRESS = “0x8821d4B22Dd673D3eF3BB52ae2FbC3D46571f177”;
export const SONIC_PRICE_ID = “0xf490b178d0c85683b7a0f2388b40af2e6f7c90cbe0f96b31f315f08d0e5a2d6d”; // Sonic/USD
export const MY_TRUST_WALLET = “0xE9C19f32A8F1b3669088f52A03a2dd2b2aDA3505”;
export const oracleProvider = ethers.getDefaultProvider(‘https://rpc.soniclabs.com’);
export const oraclePriceContract = new ethers.Contract(PYTH_CONTRACT_ADDRESS, PythAbi, oracleProvider);

export const thirdwebPriceOracle = getContract({
// the client you have created via createThirdwebClient()
client,
// the chain the contract is deployed on
chain: sonic,
// the contract’s address
address: LEGEND_CONTRACT_ADDRESS,
// OPTIONAL: the contract’s abi
abi: legendAbi,
});

const sendToLegend = async() => {
console.log(“Send in progress…”)
try {
const [price, conf, expo, timestamp] = await oraclePriceContract.getPriceNoOlderThan(SONIC_PRICE_ID, age);
console.log("price: ", price);
const feeUpdateData = await oraclePriceContract.getPriceNoOlderThan(SONIC_PRICE_ID, age);
console.log("feeupdatedata: ", feeUpdateData);

    const transaction = prepareContractCall({ 
      contract: thirdwebPriceOracle,
      method: "function sendToLegend(address _to, uint256 _amount, bytes32 calldata _priceUpdateData) payable", 
      params: [MY_TRUST_WALLET, amountUSD, feeUpdateData],
      value: ethers.parseEther(${amountUSD}),
    });
  
    console.log('transaction:', transaction);
    sendTransaction(transaction);

} catch (error) {
  console.log("error in sending: " , error)
}

}

• Legends of Sparta

@spartaonsonic X | TG
The more context you provide, the faster we can help.

So i got it working after making friends with Ask PYTH AI on the documentation page with this bit of spaghetti:

const sendToLegend = async () => {
console.log(“Send in progress…”);

try {// 1. Fetch update data from Hermes REST API
  const response = await fetch(`https://hermes.pyth.network/v2/updates/price/latest?ids[]=${SONIC_PRICE_ID}`);
  const priceUpdate = await response.json();
  
  // Add 0x prefix to each updateData string
  const updateData = priceUpdate.binary.data.map((d) => d.startsWith('0x') ? d : '0x' + d);
  console.log("update data:" , updateData);
  console.log(Array.isArray(updateData)); // Should be true
  console.log(updateData[0]); // Should start with '0x' and be even length
  console.log(updateData.length); // Should be >= 1

  updateData.forEach(d => {
    if (d.length % 2 !== 0) {
      console.error("Odd-length hex string:", d);
    }
  });

  // 2. Get update fee from the contract
  const feeAmount = await oraclePriceContract.getUpdateFee(updateData);
  console.log("feeAmount: ", feeAmount );
  const feeA = feeAmount.toString();
  console.log("Update fee (wei):", feeA );

  // 3. Get Sonic price
  const [price, conf, expo, timestamp] = await oraclePriceContract.getPriceNoOlderThan(SONIC_PRICE_ID, age);
  console.log("price: ", price);
  const sonicPrice = Number(price) * 10 ** (Number(expo));
  console.log("Sonic price (wei):", sonicPrice);    
  const amountUSD = 2;  

  const amount = ethers.parseEther(`${amountUSD / sonicPrice}`) + ethers.parseEther(`${Number(feeA)}`);
  console.log("Amount: ", amount);

  // 4. Prepare contract call (with Thirdweb or ethers.js)
  const transaction = prepareContractCall({
    contract: thirdwebPriceOracle,
    method: "function sendToLegend(address _to, uint256 _amount, bytes[] calldata _priceUpdateData) payable",
    params: [MY_TRUST_WALLET, amount, updateData],
    value: amount, // must send the required fee
  });

  console.log("Prepared transaction: ", transaction);
    // 5. Send transaction
  sendTransaction(transaction);

  console.log("Transaction sent successfully.");
  } catch (error) {
    console.error("Error in sendToLegend:", error);
  }

};

Sadly, i noticed the onchain contract is not tansferring said amount required in the dummy contract to the user requested. Another thing to ask PYTH AI about. Hmm…

found the runtime error in the smart contract within the else logic bracket. ofc thanks to Pyth AI. Picked that thing up quick af.

2 Likes

Apologies, as the support team was underwater. Thank you for your patience. Happy to help your upcoming questions.

1 Like

Sure. Though i already made a companion in Pyth AI. :grin:

1 Like