@@ -72,39 +72,45 @@ Pyth also provides a javascript SDK to construct transaction blocks that update
7272The code snippet below provides a general template for what your contract code should look like:
7373
7474``` rust {18} copy
75- module pyth_example :: main {
76- use sui :: clock :: Clock ;
77- use pyth :: price_info;
78- use pyth :: price_identifier;
79- use pyth :: price;
80- use pyth :: pyth;
81- use pyth :: price_info :: PriceInfoObject ;
82-
83- const E_INVALID_ID : u64 = 1 ;
84-
85- public fun use_pyth_price (
86- // Other arguments
87- clock : & Clock ,
88- price_info_object : & PriceInfoObject ,
89- ){
90- let max_age = 60 ;
91- // Make sure the price is not older than max_age seconds
92- let price_struct = pyth :: get_price_no_older_than (price_info_object ,clock , max_age );
93-
94- // Check the price feed ID
95- let price_info = price_info :: get_price_info_from_price_info_object (price_info_object );
96- let price_id = price_identifier :: get_bytes (& price_info :: get_price_identifier (& price_info ));
97-
98- // ETH/USD price feed ID
99- // The complete list of feed IDs is available at https://pyth.network/developers/price-feed-ids
100- // Note: Sui uses the Pyth price feed ID without the `0x` prefix.
101- assert! (price_id! = x " ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace" , E_INVALID_ID );
102-
103- // Extract the price, decimal, and timestamp from the price struct and use them
104- let decimal_i64 = price :: get_expo (& price_struct );
105- let price_i64 = price :: get_price (& price_struct );
106- let timestamp_sec = price :: get_timestamp (& price_struct );
107- }
75+ /// Module: oracle
76+ module oracle :: oracle ;
77+
78+ use sui :: clock :: Clock ;
79+ use pyth :: price_info;
80+ use pyth :: price_identifier;
81+ use pyth :: price;
82+ use pyth :: i64 :: I64 ;
83+ use pyth :: pyth;
84+ use pyth :: price_info :: PriceInfoObject ;
85+
86+ const E_INVALID_ID : u64 = 1 ;
87+
88+ public fun get_sui_price (
89+ // Other arguments
90+ clock : & Clock ,
91+ price_info_object : & PriceInfoObject ,
92+ ): I64 {
93+ let max_age = 60 ;
94+
95+ // Make sure the price is not older than max_age seconds
96+ let price_struct = pyth :: get_price_no_older_than (price_info_object , clock , max_age );
97+
98+ // Check the price feed ID
99+ let price_info = price_info :: get_price_info_from_price_info_object (price_info_object );
100+ let price_id = price_identifier :: get_bytes (& price_info :: get_price_identifier (& price_info ));
101+
102+ // SUI/USD price feed ID
103+ // The complete list of feed IDs is available at https://pyth.network/developers/price-feed-ids
104+ // Note: Sui uses the Pyth price feed ID without the `0x` prefix.
105+ let testnet_sui_price_id = x " 50c67b3fd225db8912a424dd4baed60ffdde625ed2feaaf283724f9608fea266" ;
106+ assert! (price_id == testnet_sui_price_id , E_INVALID_ID );
107+
108+ // Extract the price, decimal, and timestamp from the price struct and use them.
109+ let _decimal_i64 = price :: get_expo (& price_struct );
110+ let price_i64 = price :: get_price (& price_struct );
111+ let _timestamp_sec = price :: get_timestamp (& price_struct );
112+
113+ price_i64
108114}
109115```
110116
@@ -113,48 +119,86 @@ One can consume the price by calling `pyth::get_price` abovementioned or other u
113119The code snippet below provides an example of how to update the Pyth price feeds:
114120
115121``` ts copy
116- import { SuiPriceServiceConnection , SuiPythClient } from " @pythnetwork/pyth-sui-js" ;
117- import { TransactionBlock } from " @mysten/sui.js" ;
118-
119- // Get the Stable Hermes service URL from https://docs.pyth.network/price-feeds/api-instances-and-providers/hermes
120- const connection = new SuiPriceServiceConnection (" https://hermes-beta.pyth.network" );
121-
122+ import {
123+ SuiPythClient ,
124+ SuiPriceServiceConnection ,
125+ } from " @pythnetwork/pyth-sui-js" ;
126+ import { SuiClient } from " @mysten/sui/client" ;
127+ import { Transaction } from " @mysten/sui/transactions" ;
128+ import { Ed25519Keypair } from " @mysten/sui/keypairs/ed25519" ;
129+
130+ // / Step 1: Get the off-chain data.
131+ const connection = new SuiPriceServiceConnection (
132+ " https://hermes-beta.pyth.network" , // [!] Only for Sui Testnet
133+ // "https://hermes.pyth.network/", // Use this for Mainnet
134+ {
135+ // Provide this option to retrieve signed price updates for on-chain contracts!
136+ priceFeedRequestConfig: {
137+ binary: true ,
138+ },
139+ }
140+ );
122141const priceIDs = [
123- // You can find the IDs of prices at https://pyth.network/developers/price-feed-ids
124- " 0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43" , // BTC/USD price ID
125- " 0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace" , // ETH/USD price ID
142+ // You can find the IDs of prices at:
143+ // - https://pyth.network/developers/price-feed-ids for Mainnet
144+ // - https://www.pyth.network/developers/price-feed-ids#beta for Testnet
145+ " 0x50c67b3fd225db8912a424dd4baed60ffdde625ed2feaaf283724f9608fea266" , // SUI/USD price ID
126146];
127-
128147const priceUpdateData = await connection .getPriceFeedsUpdateData (priceIDs );
129148
130- // It is either injected from the browser or instantiated in the backend via some private key
131- const wallet: SignerWithProvider = getWallet ();
132- // Get the state IDs of the Pyth and Wormhole contracts from
133- // https://docs.pyth.network/price-feeds/contract-addresses/sui
134- const wormholeStateId = " 0x5306f64e312b581766351c07af79c72fcb1cd25147157fdc2f8ad76de9a3fb6a" ;
135- const pythStateId = " 0x1f9310238ee9298fb703c3419030b35b22bb1cc37113e3bb5007c99aec79e5b8" ;
136-
137- const client = new SuiPythClient (wallet .provider , pythStateId , wormholeStateId );
138- const tx = new TransactionBlock ();
139- const priceInfoObjectIds = await client .updatePriceFeeds (tx , priceFeedUpdateData , priceIDs );
140-
141- tx .moveCall ({
142- target: ` pyth_example::main::use_pyth_price ` ,
143- arguments: [
144- ... , // other arguments needed for your contract
145- tx .object (priceInfoObjectIds [0 ]),
146- ],
147- });
148-
149- const txBlock = {
150- transactionBlock: tx ,
151- options: {
152- showEffects: true ,
153- showEvents: true ,
154- },
155- };
149+ // / Step 2: Submit the new price on-chain and verify it using the contract.
150+ const suiClient = new SuiClient ({ url: " https://fullnode.testnet.sui.io:443" });
151+
152+ // Fixed the StateIds using the CLI example extracting them from
153+ // here: https://docs.pyth.network/price-feeds/contract-addresses/sui
154+ const pythTestnetStateId =
155+ " 0x243759059f4c3111179da5878c12f68d612c21a8d54d85edc86164bb18be1c7c" ; // Testnet
156+ const wormholeTestnetStateId =
157+ " 0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790" ; // Testnet
158+
159+ const pythClient = new SuiPythClient (
160+ suiClient ,
161+ pythTestnetStateId ,
162+ wormholeTestnetStateId
163+ );
164+
165+ const transaction = new Transaction ();
166+
167+ // / By calling the updatePriceFeeds function, the SuiPythClient adds the necessary
168+ // / transactions to the transaction block to update the price feeds.
169+ const priceInfoObjectIds = await pythClient .updatePriceFeeds (
170+ transaction ,
171+ priceUpdateData ,
172+ priceIDs
173+ );
174+
175+ let suiPriceObjectId = priceInfoObjectIds [0 ];
176+ if (! suiPriceObjectId ) {
177+ throw new Error (" suiPriceObjectId is undefined" );
178+ }
156179
157- const result = await wallet .signAndExecuteTransactionBlock (txBlock );
180+ // / This is the package id that we receive after publishing `oracle` contract from the previous step.
181+ let testnetExampleContractPackageId =
182+ " 0x42d05111a160febe4144338647e0b7a80daea459c765c1e29a7a6198b235f67c" ;
183+ const CLOCK =
184+ " 0x0000000000000000000000000000000000000000000000000000000000000006" ;
185+ transaction .moveCall ({
186+ target: ` ${testnetExampleContractPackageId }::oracle::get_sui_price ` ,
187+ arguments: [transaction .object (CLOCK ), transaction .object (suiPriceObjectId )],
188+ });
189+ transaction .setGasBudget (1000000000 );
190+
191+ const keypair = Ed25519Keypair .fromSecretKey (
192+ process .env .ADMIN_SECRET_KEY ! .toLowerCase ()
193+ );
194+ const result = await suiClient .signAndExecuteTransaction ({
195+ transaction ,
196+ signer: keypair ,
197+ options: {
198+ showEffects: true ,
199+ showEvents: true ,
200+ },
201+ });
158202```
159203
160204By calling the ` updatePriceFeeds ` function, the ` SuiPythClient ` adds the necessary transactions to the transaction block to update the price feeds.
@@ -190,7 +234,7 @@ export SUI_KEY=YOUR_PRIV_KEY;
190234npm run example-relay -- --feed-id " 5a035d5440f5c163069af66062bac6c79377bf88396fa27e6067bfca8096d280" \
191235--hermes " https://hermes-beta.pyth.network" \
192236--full-node " https://fullnode.testnet.sui.io:443" \
193- --pyth-state-id " 0xd3e79c2c083b934e78b3bd58a490ec6b092561954da6e7322e1e2b3c8abfddc0 " \
237+ --pyth-state-id " 0x243759059f4c3111179da5878c12f68d612c21a8d54d85edc86164bb18be1c7c " \
194238--wormhole-state-id " 0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790"
195239```
196240
0 commit comments