diff --git a/target_chains/sui/sdk/js/README.md b/target_chains/sui/sdk/js/README.md index bbfbf8f68e..e2532e6064 100644 --- a/target_chains/sui/sdk/js/README.md +++ b/target_chains/sui/sdk/js/README.md @@ -22,7 +22,7 @@ Pyth prices and submit them to the network: ```typescript const connection = new SuiPriceServiceConnection( - "https://hermes-beta.pyth.network" + "https://hermes-beta.pyth.network", ); // See Hermes endpoints section below for other endpoints const priceIds = [ @@ -104,8 +104,9 @@ You can run this example with `pnpm turbo --filter @pythnetwork/pyth-sui-js run ```bash export SUI_KEY=YOUR_PRIV_KEY; -pnpm turbo --filter @pythnetwork/pyth-sui-js run example-relay -- --feed-id "5a035d5440f5c163069af66062bac6c79377bf88396fa27e6067bfca8096d280" \ ---price-service "https://hermes-beta.pyth.network" \ +pnpm turbo run example-relay --filter @pythnetwork/pyth-sui-js -- \ +--feed-id "5a035d5440f5c163069af66062bac6c79377bf88396fa27e6067bfca8096d280" \ +--hermes "https://hermes-beta.pyth.network" \ --full-node "https://fullnode.testnet.sui.io:443" \ --pyth-state-id "0xd3e79c2c083b934e78b3bd58a490ec6b092561954da6e7322e1e2b3c8abfddc0" \ --wormhole-state-id "0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790" @@ -136,7 +137,7 @@ This method is useful if you want to show continuously updating real-time prices // gets a price update. connection.subscribePriceFeedUpdates(priceIds, (priceFeed) => { console.log( - `Received update for ${priceFeed.id}: ${priceFeed.getPriceNoOlderThan(60)}` + `Received update for ${priceFeed.id}: ${priceFeed.getPriceNoOlderThan(60)}`, ); }); diff --git a/target_chains/sui/sdk/js/package.json b/target_chains/sui/sdk/js/package.json index 881cd69ebb..8a401ed5f1 100644 --- a/target_chains/sui/sdk/js/package.json +++ b/target_chains/sui/sdk/js/package.json @@ -1,6 +1,6 @@ { "name": "@pythnetwork/pyth-sui-js", - "version": "2.1.0", + "version": "2.2.0", "description": "Pyth Network Sui Utilities", "homepage": "https://pyth.network", "author": { diff --git a/target_chains/sui/sdk/js/src/client.ts b/target_chains/sui/sdk/js/src/client.ts index 1d49fa6ae9..a047c0e983 100644 --- a/target_chains/sui/sdk/js/src/client.ts +++ b/target_chains/sui/sdk/js/src/client.ts @@ -6,6 +6,10 @@ import { HexString } from "@pythnetwork/price-service-client"; import { Buffer } from "buffer"; const MAX_ARGUMENT_SIZE = 16 * 1024; +type NestedTransactionResult = { + $kind: "NestedResult"; + NestedResult: [number, number]; +}; export type ObjectId = string; export class SuiPythClient { @@ -104,20 +108,11 @@ export class SuiPythClient { return verifiedVaas; } - /** - * Adds the necessary commands for updating the pyth price feeds to the transaction block. - * @param tx transaction block to add commands to - * @param updates array of price feed updates received from the price service - * @param feedIds array of feed ids to update (in hex format) - */ - async updatePriceFeeds( + async verifyVaasAndGetHotPotato( tx: Transaction, updates: Buffer[], - feedIds: HexString[], - ): Promise { - const packageId = await this.getPythPackageId(); - - let priceUpdatesHotPotato; + packageId: string, + ): Promise { if (updates.length > 1) { throw new Error( "SDK does not support sending multiple accumulator messages in a single transaction", @@ -125,7 +120,7 @@ export class SuiPythClient { } const vaa = this.extractVaaBytesFromAccumulatorMessage(updates[0]); const verifiedVaas = await this.verifyVaas([vaa], tx); - [priceUpdatesHotPotato] = tx.moveCall({ + const [priceUpdatesHotPotato] = tx.moveCall({ target: `${packageId}::pyth::create_authenticated_price_infos_using_accumulator`, arguments: [ tx.object(this.pythStateId), @@ -141,13 +136,17 @@ export class SuiPythClient { tx.object(SUI_CLOCK_OBJECT_ID), ], }); + return priceUpdatesHotPotato; + } + async executePriceFeedUpdates( + tx: Transaction, + packageId: string, + feedIds: HexString[], + priceUpdatesHotPotato: any, + coins: NestedTransactionResult[], + ) { const priceInfoObjects: ObjectId[] = []; - const baseUpdateFee = await this.getBaseUpdateFee(); - const coins = tx.splitCoins( - tx.gas, - feedIds.map(() => tx.pure.u64(baseUpdateFee)), - ); let coinId = 0; for (const feedId of feedIds) { const priceInfoObjectId = await this.getPriceFeedObjectId(feedId); @@ -176,6 +175,69 @@ export class SuiPythClient { }); return priceInfoObjects; } + + /** + * Adds the necessary commands for updating the pyth price feeds to the transaction block. + * @param tx transaction block to add commands to + * @param updates array of price feed updates received from the price service + * @param feedIds array of feed ids to update (in hex format) + */ + async updatePriceFeeds( + tx: Transaction, + updates: Buffer[], + feedIds: HexString[], + ): Promise { + const packageId = await this.getPythPackageId(); + const priceUpdatesHotPotato = await this.verifyVaasAndGetHotPotato( + tx, + updates, + packageId, + ); + + const baseUpdateFee = await this.getBaseUpdateFee(); + const coins = tx.splitCoins( + tx.gas, + feedIds.map(() => tx.pure.u64(baseUpdateFee)), + ); + + return await this.executePriceFeedUpdates( + tx, + packageId, + feedIds, + priceUpdatesHotPotato, + coins, + ); + } + + /** + * Updates price feeds using the coin input for payment. Coins can be generated by calling splitCoin on tx.gas. + * @param tx transaction block to add commands to + * @param updates array of price feed updates received from the price service + * @param feedIds array of feed ids to update (in hex format) + * @param coins array of Coins for payment of update operations + */ + async updatePriceFeedsWithCoins( + tx: Transaction, + updates: Buffer[], + feedIds: HexString[], + coins: NestedTransactionResult[], + ): Promise { + const packageId = await this.getPythPackageId(); + const priceUpdatesHotPotato = await this.verifyVaasAndGetHotPotato( + tx, + updates, + packageId, + ); + + return await this.executePriceFeedUpdates( + tx, + packageId, + feedIds, + priceUpdatesHotPotato, + coins, + ); + } + async createPriceFeed(tx: Transaction, updates: Buffer[]) { const packageId = await this.getPythPackageId(); if (updates.length > 1) {