import Web3 from "web3"; import yargs from "yargs"; import { hideBin } from "yargs/helpers"; import { EvmPriceServiceConnection } from "../index"; import HDWalletProvider from "@truffle/hdwallet-provider"; import PythInterfaceAbi from "@pythnetwork/pyth-sdk-solidity/abis/IPyth.json"; const argv = yargs(hideBin(process.argv)) .option("network", { description: "RPC of the network to relay on.", type: "string", required: true, }) .option("endpoint", { description: "Endpoint URL for the price service. e.g: https://endpoint/example", type: "string", required: true, }) .option("pyth-contract", { description: "Pyth contract address.", type: "string", required: true, }) .option("price-id", { description: "Price feed id (in hex) to fetch" + " e.g: 0xf9c0172ba10dfa4d19088d...", type: "string", required: true, }) .option("timestamp", { description: "Timestamp of the prices to fetch" + " e.g., 2022-", // TODO type: "string", required: true, }) .option("mnemonic", { description: "Mnemonic (private key) for sender", type: "string", required: true, }) .help() .alias("help", "h") .parserConfiguration({ "parse-numbers": false, }) .parseSync(); const network = argv.network; const pythContractAddr = argv.pythContract; const connection = new EvmPriceServiceConnection(argv.endpoint); async function run() { const provider = new HDWalletProvider({ mnemonic: { phrase: argv.mnemonic, }, providerOrUrl: network, }); // @ts-ignore const web3 = new Web3(provider); const priceId = argv.priceId as string; // The unix timestamp in seconds const unixTimestamp = Date.parse(argv.timestamp) / 1000; console.log(`Querying unix timestamp: ${unixTimestamp}`); const [priceFeedUpdateVaa, updateTimestamp] = await connection.getVaa( priceId, unixTimestamp ); console.log(`Next pyth update was at: ${updateTimestamp}`); console.log(priceFeedUpdateVaa); const priceFeedUpdate = "0x" + Buffer.from(priceFeedUpdateVaa, "base64").toString("hex"); const pythContract = new web3.eth.Contract( PythInterfaceAbi as any, pythContractAddr, { from: provider.getAddress(0), } ); const updateFee = await pythContract.methods .getUpdateFee([priceFeedUpdate]) .call(); console.log(`Update fee: ${updateFee}`); // In real use cases, you would pass the update to your contract, then call parsePriceFeedUpdates within your contract. // When invoked on-chain, this function will return a PriceFeed struct containing the data in the price update // (such as the current price). await pythContract.methods .parsePriceFeedUpdates( [priceFeedUpdate], [priceId], // parsePriceFeedUpdates will reject any price update outside of the time window provided in the following // two arguments. Integrators can use this to specify the timestamp of the update they are expecting. unixTimestamp, unixTimestamp + 5 ) .send({ value: updateFee }) .on("transactionHash", (hash: string) => { console.log(`Tx hash: ${hash}`); }) .on("error", (err: any, receipt: any) => { console.error(receipt); throw err; }); provider.engine.stop(); } run();