Skip to content

Commit 4a75897

Browse files
committed
initial commit
1 parent 7b4ef61 commit 4a75897

File tree

1 file changed

+83
-139
lines changed
  • pages/price-feeds/use-real-time-data

1 file changed

+83
-139
lines changed

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

Lines changed: 83 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,98 @@
1-
# Pyth on Sui
1+
import { Callout, Tabs } from "nextra/components";
22

3-
Pyth price feeds on Sui are uniquely represented in the global store as `PriceInfoObjects`. These objects have the `key` ability and serve as wrappers around the `PriceInfo` object, which in turn contains the price info: namely the `PriceFeed`, the arrival time of the latest price update, and the attestation time of the latest update.
3+
# How to Use Real-Time Data in Sui Contracts
44

5-
`PriceInfoObject`s are central to Pyth on Sui, since they are in unique correspondence with each Pyth price feed and must be passed in to functions that update price feeds or which query info about price feeds, e.g.
5+
This guide explains how to use real-time Pyth data in Sui applications.
66

7-
- `update_single_price_feed`
8-
- `update_single_price_feeds_if_fresh`
9-
- `get_price`
7+
## Install Pyth SDK
108

11-
## How to Update and Consume Price Feeds
12-
13-
We provide a javascript sdk to use for constructing transaction blocks which updates price feeds.
14-
15-
### Installation
16-
17-
If you are using npm run:
9+
Use the following dependency in your `Move.toml` file to use the latest Pyth Sui package and its dependencies.
1810

11+
<Tabs items={['Mainnet', 'Testnet']}>
12+
<Tabs.Tab>
1913
```sh copy
20-
npm install --save @pythnetwork/pyth-sui-js
21-
```
14+
[dependencies.Pyth]
15+
git = "https://github.com/pyth-network/pyth-crosschain.git"
16+
subdir = "target_chains/sui/contracts"
17+
rev = "sui-contract-v0.0.2-mainnet-sui-1.19.1"
18+
19+
[dependencies.Wormhole]
20+
git = "https://github.com/wormhole-foundation/wormhole.git"
21+
subdir = "sui/wormhole"
22+
rev = "sui-upgrade-mainnet"
2223

23-
If you are using yarn run:
24+
[dependencies.Sui]
25+
git = "https://github.com/MystenLabs/sui.git"
26+
subdir = "crates/sui-framework/packages/sui-framework"
27+
rev = "041c5f2bae2fe52079e44b70514333532d69f4e6"
2428

29+
````
30+
</Tabs.Tab>
31+
<Tabs.Tab>
2532
```sh copy
26-
yarn add @pythnetwork/pyth-sui-js
27-
```
33+
[dependencies.Pyth]
34+
git = "https://github.com/pyth-network/pyth-crosschain.git"
35+
subdir = "target_chains/sui/contracts"
36+
rev = "sui-contract-v0.0.2-testnet-sui-1.19.1"
2837
29-
## Quickstart
38+
[dependencies.Wormhole]
39+
git = "https://github.com/wormhole-foundation/wormhole.git"
40+
subdir = "sui/wormhole"
41+
rev = "sui-upgrade-testnet"
3042
31-
Pyth stores prices off-chain to minimize gas fees, which allows us to offer a wider selection of products and faster update times.
32-
See [Pull Updates](../pythnet-price-feeds/pull-updates) for more information about this approach.
33-
Typically, to use Pyth prices on chain,
34-
they must be fetched from the [Hermes API](https://hermes.pyth.network/docs). The `SuiPriceServiceConnection` class can be used to interact with these services,
35-
providing a way to fetch these prices directly in your code. The following example wraps an existing RPC provider and shows how to obtain
36-
Pyth prices and submit them to the network:
43+
[dependencies.Sui]
44+
git = "https://github.com/MystenLabs/sui.git"
45+
subdir = "crates/sui-framework/packages/sui-framework"
46+
rev = "041c5f2bae2fe52079e44b70514333532d69f4e6"
47+
````
3748
38-
```typescript copy
39-
import { SuiPriceServiceConnection } from "@pythnetwork/pyth-sui-js";
49+
</Tabs.Tab>
50+
</Tabs>
4051
41-
const connection = new SuiPriceServiceConnection(
42-
"https://hermes-beta.pyth.network"
43-
); // See Hermes endpoints section below for other endpoints
52+
Pyth provides a javascript SDK to construct transaction blocks that update price feeds.
4453
45-
const priceIds = [
46-
// You can find the ids of prices at https://pyth.network/developers/price-feed-ids
47-
"0xf9c0172ba10dfa4d19088d94f5bf61d3b54d5bd7483a322a982e1373ee8ea31b", // BTC/USD price id in testnet
48-
"0xca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a6", // ETH/USD price id in testnet
49-
];
54+
<Tabs items={["npm", "yarn"]}>
55+
<Tabs.Tab>
56+
```sh copy npm install --save @pythnetwork/pyth-sui-js ```
57+
</Tabs.Tab>
58+
<Tabs.Tab>```sh copy yarn add @pythnetwork/pyth-sui-js ```</Tabs.Tab>
59+
</Tabs>
5060
51-
// In order to use Pyth prices in your protocol you need to submit the price update data to Pyth contract in your target
52-
// chain. `getPriceUpdateData` creates the update data which can be submitted to your contract.
61+
## Write Contract Code
5362
54-
const priceUpdateData = await connection.getPriceFeedsUpdateData(priceIds);
55-
```
63+
<Callout type="warning" emoji="⚠️">
5664
57-
## On-chain prices
65+
Your Sui Move module **should NOT** have a hard-coded call to `pyth::update_single_price_feed.` In other words, a contract should **never call** the Sui Pyth `pyth::update_single_price_feed` entry point. Instead, it should be called directly from client code (e.g., Typescript or Rust).
5866
59-
### ⚠️ **_Important Note for Integrators_**
67+
This is because the new address differs from the original when a Sui contract is [upgraded](https://docs.sui.io/build/package-upgrades). If your module has a hard-coded call to `pyth::update_single_price_feed` living at a fixed call-site, it may eventually get bricked due to how Pyth upgrades are implemented. (We only allow users to interact with the most recent package version for security reasons).
6068
61-
Your Sui Move module **should NOT** have a hard-coded call to `pyth::update_single_price_feed`. In other words, the Sui Pyth `pyth::update_single_price_feed` entry point should never be called by a contract, instead it should be called directly from client code (e.g. Typescript or Rust).
69+
Therefore, you should build a [Sui programmable transaction](https://docs.sui.io/build/prog-trans-ts-sdk) that first updates the price by calling `pyth::update_single_price_feed` at the latest call-site from the client-side and then call a function in your contract that invokes `pyth::get_price` on the `PriceInfoObject` to get the recently updated price.
70+
You can use `SuiPythClient` to build such transactions and handle all the complexity of updating the price feeds.
6271
63-
This is because when a Sui contract is [upgraded](https://docs.sui.io/build/package-upgrades), the new address is different from the original. If your module has a hard-coded call to `pyth::update_single_price_feed` living at a fixed call-site, it may eventually get bricked due to the way Pyth upgrades are implemented. (We only allows users to interact with the most recent package version for security reasons).
72+
Consult [Fetch Price Updates](../fetch-price-updates) for more information on how to fetch the `pyth_price_update`.
6473
65-
Therefore, you should build a [Sui programmable transaction](https://docs.sui.io/build/prog-trans-ts-sdk) that first updates the price by calling `pyth::update_single_price_feed` at the latest call-site from the client-side and then call a function in your contract that invokes `pyth::get_price` on the `PriceInfoObject` to get the recently updated price.
66-
You can use `SuiPythClient` to build such transactions and handles all the complexity of updating the price feeds.
74+
</Callout>
6775
68-
### Update Example
76+
The code snippet below provides an example of how to update the Pyth price feeds:
6977
7078
```ts copy
71-
import { SuiPythClient } from "@pythnetwork/pyth-sui-js";
79+
import { SuiPriceServiceConnection, SuiPythClient } from "@pythnetwork/pyth-sui-js";
7280
import { TransactionBlock } from "@mysten/sui.js";
7381

74-
const priceUpdateData = await connection.getPriceFeedsUpdateData(priceIds); // see quickstart section
82+
// Get the Stable Hermes service URL from https://docs.pyth.network/price-feeds/api-instances-and-providers/hermes
83+
const connection = new SuiPriceServiceConnection("https://hermes-beta.pyth.network");
7584

85+
const priceIds = [
86+
// You can find the IDs of prices at https://pyth.network/developers/price-feed-ids
87+
"0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43", // BTC/USD price ID
88+
"0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace", // ETH/USD price ID
89+
];
7690

77-
// It is either injected from browser or instantiated in backend via some private key
91+
const priceUpdateData = await connection.getPriceFeedsUpdateData(priceIds);
92+
93+
// It is either injected from the browser or instantiated in the backend via some private key
7894
const wallet: SignerWithProvider = getWallet();
79-
// Get the state ids of the Pyth and Wormhole contracts from
95+
// Get the state IDs of the Pyth and Wormhole contracts from
8096
// https://docs.pyth.network/price-feeds/contract-addresses/sui
8197
const wormholeStateId = " 0xFILL_ME";
8298
const pythStateId = "0xFILL_ME";
@@ -106,9 +122,9 @@ const result = await wallet.signAndExecuteTransactionBlock(txBlock);
106122
```
107123
108124
By calling the `updatePriceFeeds` function, the `SuiPythClient` adds the necessary transactions to the transaction block to update the price feeds.
109-
Now in your contract you can consume the price by calling `pyth::get_price` or other utility functions on the `PriceInfoObject`:
125+
Now, one can consume the price by calling `pyth::get_price` or other utility functions on the `PriceInfoObject` in the Move module:
110126
111-
```rust copy
127+
```rust {20} copy
112128
module pyth_example::main {
113129
use sui::clock::Clock;
114130
use pyth::price_info;
@@ -121,79 +137,40 @@ module pyth_example::main {
121137
const E_INVALID_ID: u64 = 1;
122138

123139
public fun use_pyth_price(
124-
// other arguments
140+
// Other arguments
125141
clock: &Clock,
126142
pyth_state: &PythState,
127143
price_info_object: &PriceInfoObject,
128144
){
129145
let max_age = 60;
130-
// make sure the price is not older than max_age seconds
146+
// Make sure the price is not older than max_age seconds
131147
let price_struct = pyth::get_price(pyth_state,price_info_object, clock);
132148

133-
// check the price feed id
149+
// Check the price feed ID
134150
let price_info = price_info::get_price_info_from_price_info_object(price_info_object);
135151
let price_id = price_identifier::get_bytes(&price_info::get_price_identifier(&price_info));
136-
// ETH/USD price feed id
152+
153+
// ETH/USD price feed ID
154+
// The complete list of feed IDs is available at https://pyth.network/developers/price-feed-ids
155+
// Note: Sui uses the Pyth price feed ID without the `0x` prefix.
137156
assert!(price_id!=x"ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace", E_INVALID_ID);
138157

139-
// extract the price, decimal, and timestamp from the price struct and use them
158+
// Extract the price, decimal, and timestamp from the price struct and use them
140159
let decimal_i64 = price::get_expo(&price_struct);
141160
let price_i64 = price::get_price(&price_struct);
142161
let timestamp_sec = price::get_timestamp(&price_struct);
143162
}
144163
}
145164
```
146165
147-
### Pyth Dependency
148-
149-
Use the following dependency in your `Move.toml` file to use the latest Pyth Sui package and its dependencies.
150-
151-
Mainnet:
152-
153-
```sh copy
154-
[dependencies.Pyth]
155-
git = "https://github.com/pyth-network/pyth-crosschain.git"
156-
subdir = "target_chains/sui/contracts"
157-
rev = "sui-contract-v0.0.2-mainnet-sui-1.19.1"
158-
159-
[dependencies.Wormhole]
160-
git = "https://github.com/wormhole-foundation/wormhole.git"
161-
subdir = "sui/wormhole"
162-
rev = "sui-upgrade-mainnet"
163-
164-
[dependencies.Sui]
165-
git = "https://github.com/MystenLabs/sui.git"
166-
subdir = "crates/sui-framework/packages/sui-framework"
167-
rev = "041c5f2bae2fe52079e44b70514333532d69f4e6"
168-
```
169-
170-
Testnet:
171-
172-
```sh copy
173-
[dependencies.Pyth]
174-
git = "https://github.com/pyth-network/pyth-crosschain.git"
175-
subdir = "target_chains/sui/contracts"
176-
rev = "sui-contract-v0.0.2-testnet-sui-1.19.1"
177-
178-
[dependencies.Wormhole]
179-
git = "https://github.com/wormhole-foundation/wormhole.git"
180-
subdir = "sui/wormhole"
181-
rev = "sui-upgrade-testnet"
182-
183-
[dependencies.Sui]
184-
git = "https://github.com/MystenLabs/sui.git"
185-
subdir = "crates/sui-framework/packages/sui-framework"
186-
rev = "041c5f2bae2fe52079e44b70514333532d69f4e6"
187-
```
188-
189166
### CLI Example
190167
191-
[This example](./src/examples/SuiRelay.ts) shows how to update prices on an Sui network. It does the following:
168+
[This example](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/sui/cli) shows how to update prices on a Sui network. It does the following:
192169
193170
1. Fetches update data from Hermes for the given price feeds.
194-
2. Calls the Pyth Sui contract with the update data.
171+
1. Call the Pyth Sui contract with a price update.
195172
196-
You can run this example with `npm run example-relay`. A full command that updates prices on Sui testnet looks like:
173+
You can run this example with `npm run example-relay`. A full command that updates prices on the Sui testnet looks like this:
197174
198175
```bash
199176
export SUI_KEY=YOUR_PRIV_KEY;
@@ -204,46 +181,13 @@ npm run example-relay -- --feed-id "5a035d5440f5c163069af66062bac6c79377bf88396f
204181
--wormhole-state-id "0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790"
205182
```
206183
207-
## Off-chain prices
208-
209-
Many applications additionally need to display Pyth prices off-chain, for example, in their frontend application.
210-
The `SuiPriceServiceConnection` provides two different ways to fetch the current Pyth price.
211-
The code blocks below assume that the `connection` and `priceIds` objects have been initialized as shown above.
212-
The first method is a single-shot query:
213-
214-
```typescript
215-
// `getLatestPriceFeeds` returns a `PriceFeed` for each price id. It contains all information about a price and has
216-
// utility functions to get the current and exponentially-weighted moving average price, and other functionality.
217-
const priceFeeds = await connection.getLatestPriceFeeds(priceIds);
218-
// Get the price if it is not older than 60 seconds from the current time.
219-
console.log(priceFeeds[0].getPriceNoOlderThan(60)); // Price { conf: '1234', expo: -8, price: '12345678' }
220-
// Get the exponentially-weighted moving average price if it is not older than 60 seconds from the current time.
221-
console.log(priceFeeds[1].getEmaPriceNoOlderThan(60));
222-
```
223-
224-
The object also supports a streaming websocket connection that allows you to subscribe to every new price update for a given feed.
225-
This method is useful if you want to show continuously updating real-time prices in your frontend:
226-
227-
```typescript
228-
// Subscribe to the price feeds given by `priceId`. The callback will be invoked every time the requested feed
229-
// gets a price update.
230-
connection.subscribePriceFeedUpdates(priceIds, (priceFeed) => {
231-
console.log(
232-
`Received update for ${priceFeed.id}: ${priceFeed.getPriceNoOlderThan(60)}`
233-
);
234-
});
235-
236-
// When using the subscription, make sure to close the websocket upon termination to finish the process gracefully.
237-
setTimeout(() => {
238-
connection.closeWebSocket();
239-
}, 60000);
240-
```
184+
## Additional Resources
241185
242-
## [Hermes endpoints](hermes#public-endpoints)
186+
You may find these additional resources helpful for developing your Sui application.
243187
244-
## Contract Addresses
188+
### Contract Addresses
245189
246-
Developers will need the Pyth package IDs in order to use Pyth.
190+
Developers will need the Pyth package IDs to use Pyth.
247191
Please consult [Sui Contract Addresses](../contract-addresses/sui) to find the package IDs for your blockchain.
248192
249193
## Common Questions on How to Integrate with Pyth on Sui

0 commit comments

Comments
 (0)