@@ -72,39 +72,43 @@ Pyth also provides a javascript SDK to construct transaction blocks that update
72
72
The code snippet below provides a general template for what your contract code should look like:
73
73
74
74
``` 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 );
108
112
}
109
113
```
110
114
@@ -113,48 +117,74 @@ One can consume the price by calling `pyth::get_price` abovementioned or other u
113
117
The code snippet below provides an example of how to update the Pyth price feeds:
114
118
115
119
``` ts copy
116
- import { SuiPriceServiceConnection , SuiPythClient } from " @pythnetwork/pyth-sui-js" ;
117
- import { TransactionBlock } from " @mysten/sui.js" ;
120
+ import { SuiPythClient , SuiPriceServiceConnection } from " @pythnetwork/pyth-sui-js"
121
+ import { SuiClient } from " @mysten/sui/client"
122
+ import { Transaction } from " @mysten/sui/transactions"
123
+ import { Ed25519Keypair } from " @mysten/sui/keypairs/ed25519" ;
124
+
125
+ // / Step 1: Get the off-chain data.
126
+ const connection = new SuiPriceServiceConnection (
127
+ " https://hermes-beta.pyth.network" , // [!] Only for Sui Testnet
128
+ // "https://hermes.pyth.network/", // Use this for Mainnet
129
+ {
130
+ // Provide this option to retrieve signed price updates for on-chain contracts!
131
+ priceFeedRequestConfig: {
132
+ ' binary' : true
133
+ }
134
+ }
135
+ );
136
+ const priceIDs = [
137
+ // You can find the IDs of prices at:
138
+ // - https://pyth.network/developers/price-feed-ids for Mainnet
139
+ // - https://www.pyth.network/developers/price-feed-ids#beta for Testnet
140
+ " 0x50c67b3fd225db8912a424dd4baed60ffdde625ed2feaaf283724f9608fea266" , // SUI/USD price ID
141
+ ];
142
+ const priceUpdateData = await connection .getPriceFeedsUpdateData (priceIDs );
118
143
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 " );
144
+ // / Step 2: Submit the new price on-chain and verify it using the contract.
145
+ const suiClient = new SuiClient ({ url: ' https://fullnode.testnet.sui.io:443 ' } );
121
146
122
- const 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
126
- ];
127
-
128
- const priceUpdateData = await connection .getPriceFeedsUpdateData (priceIDs );
129
-
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 ` ,
147
+ // Fixed the StateIds using the CLI example extracting them from
148
+ // here: https://docs.pyth.network/price-feeds/contract-addresses/sui
149
+ const pythTestnetStateId = " 0x243759059f4c3111179da5878c12f68d612c21a8d54d85edc86164bb18be1c7c" ; // Testnet
150
+ const wormholeTestnetStateId = " 0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790" ; // Testnet
151
+
152
+ const pythClient = new SuiPythClient (suiClient , pythTestnetStateId , wormholeTestnetStateId );
153
+
154
+ const transaction = new Transaction ();
155
+
156
+ // / By calling the updatePriceFeeds function, the SuiPythClient adds the necessary
157
+ // / transactions to the transaction block to update the price feeds.
158
+ const priceInfoObjectIds = await pythClient .updatePriceFeeds (transaction , priceUpdateData , priceIDs );
159
+
160
+ let suiPriceObjectId = priceInfoObjectIds [0 ]
161
+ if (! suiPriceObjectId ) {
162
+ throw new Error (" suiPriceObjectId is undefined" );
163
+ }
164
+
165
+ // / This is the package id that we receive after publishing `oracle` contract from the previous step.
166
+ let testnetExampleContractPackageId = " 0x42d05111a160febe4144338647e0b7a80daea459c765c1e29a7a6198b235f67c" ;
167
+ const CLOCK = " 0x0000000000000000000000000000000000000000000000000000000000000006" ;
168
+ transaction .moveCall ({
169
+ target: ` ${testnetExampleContractPackageId }::oracle::get_sui_price ` ,
143
170
arguments: [
144
- ... , // other arguments needed for your contract
145
- tx .object (priceInfoObjectIds [ 0 ] ),
171
+ transaction . object ( CLOCK ),
172
+ transaction .object (suiPriceObjectId ),
146
173
],
147
174
});
148
-
149
- const txBlock = {
150
- transactionBlock: tx ,
151
- options: {
175
+ transaction .setGasBudget (1000000000 );
176
+
177
+ const keypair = Ed25519Keypair .fromSecretKey (
178
+ process .env .ADMIN_SECRET_KEY ! .toLowerCase ()
179
+ );
180
+ const result = await suiClient .signAndExecuteTransaction ({
181
+ transaction ,
182
+ signer: keypair ,
183
+ options: {
152
184
showEffects: true ,
153
185
showEvents: true ,
154
186
},
155
- };
156
-
157
- const result = await wallet .signAndExecuteTransactionBlock (txBlock );
187
+ });
158
188
```
159
189
160
190
By calling the ` updatePriceFeeds ` function, the ` SuiPythClient ` adds the necessary transactions to the transaction block to update the price feeds.
@@ -190,7 +220,7 @@ export SUI_KEY=YOUR_PRIV_KEY;
190
220
npm run example-relay -- --feed-id " 5a035d5440f5c163069af66062bac6c79377bf88396fa27e6067bfca8096d280" \
191
221
--hermes " https://hermes-beta.pyth.network" \
192
222
--full-node " https://fullnode.testnet.sui.io:443" \
193
- --pyth-state-id " 0xd3e79c2c083b934e78b3bd58a490ec6b092561954da6e7322e1e2b3c8abfddc0 " \
223
+ --pyth-state-id " 0x243759059f4c3111179da5878c12f68d612c21a8d54d85edc86164bb18be1c7c " \
194
224
--wormhole-state-id " 0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790"
195
225
```
196
226
0 commit comments