@@ -72,39 +72,45 @@ 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 );
112
+
113
+ price_i64
108
114
}
109
115
```
110
116
@@ -113,48 +119,86 @@ One can consume the price by calling `pyth::get_price` abovementioned or other u
113
119
The code snippet below provides an example of how to update the Pyth price feeds:
114
120
115
121
``` 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
+ );
122
141
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
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
126
146
];
127
-
128
147
const priceUpdateData = await connection .getPriceFeedsUpdateData (priceIDs );
129
148
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
+ }
156
179
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
+ });
158
202
```
159
203
160
204
By 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;
190
234
npm run example-relay -- --feed-id " 5a035d5440f5c163069af66062bac6c79377bf88396fa27e6067bfca8096d280" \
191
235
--hermes " https://hermes-beta.pyth.network" \
192
236
--full-node " https://fullnode.testnet.sui.io:443" \
193
- --pyth-state-id " 0xd3e79c2c083b934e78b3bd58a490ec6b092561954da6e7322e1e2b3c8abfddc0 " \
237
+ --pyth-state-id " 0x243759059f4c3111179da5878c12f68d612c21a8d54d85edc86164bb18be1c7c " \
194
238
--wormhole-state-id " 0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790"
195
239
```
196
240
0 commit comments