Skip to content

Commit 8bd9e57

Browse files
authored
Update Sui how-to guide with corrected code and IDs (#698)
* Update Sui how-to guide with corrected code and IDs 1. The assertion in the Move contract was incorrect. 2. Update the testnet pyth state id in the CLI example. 3. The TS code was deprecated. Used the latest @mysten/sui instead. 4. Added explanatory comments. * Fix lint errors * Resolve PR comment: return price_i64 * Run pre-commit
1 parent 2d2c731 commit 8bd9e57

File tree

1 file changed

+115
-71
lines changed
  • pages/price-feeds/use-real-time-data

1 file changed

+115
-71
lines changed

pages/price-feeds/use-real-time-data/sui.mdx

Lines changed: 115 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -72,39 +72,45 @@ Pyth also provides a javascript SDK to construct transaction blocks that update
7272
The 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
113119
The 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+
);
122141
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
126146
];
127-
128147
const 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

160204
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;
190234
npm 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

Comments
 (0)