import { Coin } from "@cosmjs/stargate"; import { ChainExecutor, ExecuteContractResponse, } from "./chains-manager/chain-executor"; import { ChainQuerier } from "./chains-manager/chain-querier"; export type Price = { price: number; conf: number; expo: number; publish_time: number; }; export type PriceFeedResponse = { id: string; price: Price; ema_price: Price; }; /** * `PythWrapperQuerier` wraps the ChainQuerier which can be a querier for any cosmwasm chain. * The ChainQuerier is contract independent, and it doesn't work with pyth specific objects which we know of. * * `PythWrapperQuerier` uses the ChainQuerier to query Pyth contracts but it works with Pyth specific objects */ export class PythWrapperQuerier { constructor(private chainQuerier: ChainQuerier) {} /** * Get the fee required to update the Pyth on-chain contract with the given VAAs. * This function will invoke the corresponding function on the contract itself and * return the result. The result is represented as both a quantity of tokens and a * denomination which may vary depending on the chain being queried. * * @throws an error if it fails */ async getUpdateFee(contractAddr: string, vaas: string[]): Promise { try { const updateFeeResponse = await this.chainQuerier.getSmartContractState({ contractAddr, query: { get_update_fee: { vaas, }, }, }); return updateFeeResponse as Coin; } catch (e) { throw new Error("Error fetching update fee"); } } /** * Get the price feed stored in the Pyth on-chain contract with the given id. * This function will invoke the corresponding function on the contract itself and * return the result. * * It returns the PriceFeedResponse. See {@link PriceFeedResponse} * * @throws an error if it fails */ async getPriceFeed( contractAddr: string, id: string ): Promise { try { const priceFeedResponse = await this.chainQuerier.getSmartContractState({ contractAddr, query: { price_feed: { id, }, }, }); return (priceFeedResponse as any).price_feed as PriceFeedResponse; } catch (e) { throw new Error("Error fetching update fee"); } } } export type ExecuteUpdatePriceFeedsRequest = { contractAddr: string; vaas: string[]; fund: Coin; }; export type ExecuteGovernanceInstructionRequest = { contractAddr: string; vaa: string; }; /** * `PythWrapperExecutor` wraps the ChainExecutor which can be a executor for any cosmwasm chain. * The ChainExecutor is contract independent, and it doesn't work with pyth specific objects which we know of. * * `PythWrapperExecutor` uses the ChainExecutor to execute Pyth contracts but it works with Pyth specific objects */ export class PythWrapperExecutor { constructor(private chainExecutor: ChainExecutor) {} /** * Update the price feed stored in Pyth Contracts on chain. This function will send an execute request * to the Pyth contracts with the funds required to update a price feed. * * @param {ExecuteUpdatePriceFeedsRequest} req * @param {string} req.contractAddr * @param {string[]} req.vaas - The vaas for the price feed update * @param {Coin} req.fund - Update fee * @returns {ExecuteContractResponse} - The broadcasted transaction hash. * * @throws an error if it fails */ async executeUpdatePriceFeeds( req: ExecuteUpdatePriceFeedsRequest ): Promise { const { contractAddr, vaas, fund } = req; return await this.chainExecutor.executeContract({ contractAddr: contractAddr, msg: { update_price_feeds: { data: vaas, }, }, funds: [fund], }); } /** * Execute the governance instruction on Pyth contracts on chain for the given VAA. * * @param {ExecuteGovernanceInstructionRequest} req * @param {string} req.contractAddr * @param {string} req.vaa - The govenance instruction vaa. * @returns {ExecuteContractResponse} - The broadcasted transaction hash. * * @throws an error if it fails */ async executeGovernanceInstruction( req: ExecuteGovernanceInstructionRequest ): Promise { const { contractAddr, vaa } = req; return await this.chainExecutor.executeContract({ contractAddr: contractAddr, msg: { execute_governance_instruction: { data: vaa, }, }, }); } }