diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 66e2d13862..ca4af0d568 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3185,9 +3185,9 @@ importers: '@mysten/sui': specifier: ^1.3.0 version: 1.26.1(typescript@5.8.2) - '@pythnetwork/price-service-client': + '@pythnetwork/hermes-client': specifier: workspace:* - version: link:../../../../price_service/client/js + version: link:../../../../apps/hermes/client/js buffer: specifier: ^6.0.3 version: 6.0.3 diff --git a/target_chains/sui/sdk/js/README.md b/target_chains/sui/sdk/js/README.md index e2532e6064..04dc80e995 100644 --- a/target_chains/sui/sdk/js/README.md +++ b/target_chains/sui/sdk/js/README.md @@ -61,7 +61,7 @@ const priceUpdateData = await connection.getPriceFeedsUpdateData(priceIds); // s // It is either injected from browser or instantiated in backend via some private key const wallet: SignerWithProvider = getWallet(); // Get the state ids of the Pyth and Wormhole contracts from -// https://docs.pyth.network/documentation/pythnet-price-feeds/sui +// https://docs.pyth.network/price-feeds/contract-addresses/sui const wormholeStateId = " 0xFILL_ME"; const pythStateId = "0xFILL_ME"; @@ -115,36 +115,36 @@ pnpm turbo run example-relay --filter @pythnetwork/pyth-sui-js -- \ ## Off-chain prices Many applications additionally need to display Pyth prices off-chain, for example, in their frontend application. -The `SuiPriceServiceConnection` provides two different ways to fetch the current Pyth price. +The `SuiPriceServiceConnection` is an extension of the [Hermes client](https://github.com/pyth-network/pyth-crosschain/tree/main/apps/hermes/client/js) +and provides two different ways to fetch the current Pyth price. The code blocks below assume that the `connection` and `priceIds` objects have been initialized as shown above. The first method is a single-shot query: ```typescript -// `getLatestPriceFeeds` returns a `PriceFeed` for each price id. It contains all information about a price and has -// utility functions to get the current and exponentially-weighted moving average price, and other functionality. -const priceFeeds = await connection.getLatestPriceFeeds(priceIds); -// Get the price if it is not older than 60 seconds from the current time. -console.log(priceFeeds[0].getPriceNoOlderThan(60)); // Price { conf: '1234', expo: -8, price: '12345678' } -// Get the exponentially-weighted moving average price if it is not older than 60 seconds from the current time. -console.log(priceFeeds[1].getEmaPriceNoOlderThan(60)); +// `getLatestPriceFeeds` returns a `PriceUpdate`; see the [hermes-client](https://github.com/pyth-network/pyth-crosschain/tree/main/apps/hermes/client/js) documentation for details. +const priceUpdate: PriceUpdate = await connection.getLatestPriceUpdates(priceIds, { parsed: true }); +if (priceUpdate.parsed) { + console.log("ParsedPriceUpdate:", priceUpdate.parsed); +} ``` -The object also supports a streaming websocket connection that allows you to subscribe to every new price update for a given feed. +The object also supports a streaming Server-Sent Events (SSE) connection that allows you to subscribe to every new price update for a given feed. This method is useful if you want to show continuously updating real-time prices in your frontend: ```typescript -// Subscribe to the price feeds given by `priceId`. The callback will be invoked every time the requested feed -// gets a price update. -connection.subscribePriceFeedUpdates(priceIds, (priceFeed) => { - console.log( - `Received update for ${priceFeed.id}: ${priceFeed.getPriceNoOlderThan(60)}`, - ); -}); - -// When using the subscription, make sure to close the websocket upon termination to finish the process gracefully. -setTimeout(() => { - connection.closeWebSocket(); -}, 60000); +// Streaming price updates +const eventSource = await connection.getPriceUpdatesStream(priceIds, { parsed: true }); +eventSource.onmessage = (event) => { + console.log("Received price update:", event.data); +}; +eventSource.onerror = (error) => { + console.error("Error receiving updates:", error); + eventSource.close(); +}; +await sleep(5000); +// To stop listening to the updates, you can call eventSource.close(); +console.log("Closing event source."); +eventSource.close(); ``` ## Hermes endpoints diff --git a/target_chains/sui/sdk/js/package.json b/target_chains/sui/sdk/js/package.json index 8a401ed5f1..81bdaa927b 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.2.0", + "version": "2.3.0", "description": "Pyth Network Sui Utilities", "homepage": "https://pyth.network", "author": { @@ -55,7 +55,7 @@ }, "dependencies": { "@mysten/sui": "^1.3.0", - "@pythnetwork/price-service-client": "workspace:*", + "@pythnetwork/hermes-client": "workspace:*", "buffer": "^6.0.3" } } diff --git a/target_chains/sui/sdk/js/src/SuiPriceServiceConnection.ts b/target_chains/sui/sdk/js/src/SuiPriceServiceConnection.ts index 6d520cf3e3..37293e30fe 100644 --- a/target_chains/sui/sdk/js/src/SuiPriceServiceConnection.ts +++ b/target_chains/sui/sdk/js/src/SuiPriceServiceConnection.ts @@ -1,10 +1,11 @@ import { - PriceServiceConnection, + HermesClient, HexString, -} from "@pythnetwork/price-service-client"; + PriceUpdate, +} from "@pythnetwork/hermes-client"; import { Buffer } from "buffer"; -export class SuiPriceServiceConnection extends PriceServiceConnection { +export class SuiPriceServiceConnection extends HermesClient { /** * Gets price update data (either batch price attestation VAAs or accumulator messages, depending on the chosen endpoint), which then * can be submitted to the Pyth contract to update the prices. This will throw an axios error if there is a network problem or @@ -15,7 +16,12 @@ export class SuiPriceServiceConnection extends PriceServiceConnection { */ async getPriceFeedsUpdateData(priceIds: HexString[]): Promise { // Fetch the latest price feed update VAAs from the price service - const latestVaas = await this.getLatestVaas(priceIds); - return latestVaas.map((vaa) => Buffer.from(vaa, "base64")); + const updateData: PriceUpdate = await this.getLatestPriceUpdates(priceIds, { + encoding: "base64", + parsed: false, + }); + return updateData.binary.data.map((update) => + Buffer.from(update, "base64"), + ); } } diff --git a/target_chains/sui/sdk/js/src/client.ts b/target_chains/sui/sdk/js/src/client.ts index a047c0e983..0c775cb214 100644 --- a/target_chains/sui/sdk/js/src/client.ts +++ b/target_chains/sui/sdk/js/src/client.ts @@ -2,7 +2,7 @@ import { SuiClient } from "@mysten/sui/client"; import { SUI_CLOCK_OBJECT_ID } from "@mysten/sui/utils"; import { Transaction } from "@mysten/sui/transactions"; import { bcs } from "@mysten/sui/bcs"; -import { HexString } from "@pythnetwork/price-service-client"; +import { HexString } from "@pythnetwork/hermes-client"; import { Buffer } from "buffer"; const MAX_ARGUMENT_SIZE = 16 * 1024; diff --git a/target_chains/sui/sdk/js/src/examples/SuiRelay.ts b/target_chains/sui/sdk/js/src/examples/SuiRelay.ts index 164d09c832..b98bd6e396 100644 --- a/target_chains/sui/sdk/js/src/examples/SuiRelay.ts +++ b/target_chains/sui/sdk/js/src/examples/SuiRelay.ts @@ -89,7 +89,7 @@ async function run() { const wallet = Ed25519Keypair.fromSecretKey( Buffer.from(process.env.SUI_KEY, "hex"), ); - + tx.setGasBudget(1000000); const result = await provider.signAndExecuteTransaction({ signer: wallet, transaction: tx, diff --git a/target_chains/sui/sdk/js/src/index.ts b/target_chains/sui/sdk/js/src/index.ts index f4cfecf948..a2056030ac 100644 --- a/target_chains/sui/sdk/js/src/index.ts +++ b/target_chains/sui/sdk/js/src/index.ts @@ -2,10 +2,17 @@ export { SuiPriceServiceConnection } from "./SuiPriceServiceConnection"; export { SuiPythClient } from "./client"; export { + AssetType, + BinaryPriceUpdate, DurationInMs, + DurationInSeconds, + EncodingType, + HermesClientConfig, HexString, - Price, - PriceFeed, - PriceServiceConnectionConfig, + PriceFeedMetadata, + PriceIdInput, + PriceUpdate, + PublisherCaps, + TwapsResponse, UnixTimestamp, -} from "@pythnetwork/price-service-client"; +} from "@pythnetwork/hermes-client";