Skip to content

Commit fe5d5be

Browse files
Feat: add IOTA testnet (#630)
* feat: add IOTA testnet * feat: add IOTA testnet * fix: run pre-commit * match the config * fix missed items --------- Co-authored-by: Ali Behjati <bahjatia@gmail.com>
1 parent d20d11c commit fe5d5be

File tree

8 files changed

+204
-41
lines changed

8 files changed

+204
-41
lines changed

pages/price-feeds/contract-addresses.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ The contracts are split by ecosystem into several different documents:
77
- [Solana/SVM](contract-addresses/solana)
88
- [Aptos](contract-addresses/aptos)
99
- [Sui](contract-addresses/sui)
10+
- [IOTA](contract-addresses/iota)
1011
- [Movement](contract-addresses/movement)
1112
- [TON](contract-addresses/ton)
1213
- [Fuel](contract-addresses/fuel)

pages/price-feeds/contract-addresses/_meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"solana": "Solana / SVM",
44
"aptos": "Aptos",
55
"sui": "Sui",
6+
"iota": "IOTA",
67
"movement": "Movement",
78
"ton": "TON",
89
"fuel": "Fuel",
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Price Feed Contract Addresses on IOTA
2+
3+
#### IOTA testnet
4+
5+
| Name | Address |
6+
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
7+
| Pyth State ID | [`0x68dda579251917b3db28e35c4df495c6e664ccc085ede867a9b773c8ebedc2c1`](https://explorer.rebased.iota.org/object/0x68dda579251917b3db28e35c4df495c6e664ccc085ede867a9b773c8ebedc2c1?network=testnet) |
8+
| Pyth Package ID | [`0x23994dd119480ea614f7623520337058dca913cb1bb6e5d8d51c7b067d3ca3bb`](https://explorer.rebased.iota.org/object/0x23994dd119480ea614f7623520337058dca913cb1bb6e5d8d51c7b067d3ca3bb?network=testnet) |
9+
| Wormhole State ID | [`0x8bc490f69520a97ca1b3de864c96aa2265a0cf5d90f5f3f016b2eddf0cf2af2b`](https://explorer.rebased.iota.org/object/0x8bc490f69520a97ca1b3de864c96aa2265a0cf5d90f5f3f016b2eddf0cf2af2b?network=testnet) |
10+
| Wormhole Package ID | [`0xfca58c557f09cddb7930588c4e2a4edbe3cdded1ac1ed2270aa2dfa8d2b9ae0d`](https://explorer.rebased.iota.org/object/0xfca58c557f09cddb7930588c4e2a4edbe3cdded1ac1ed2270aa2dfa8d2b9ae0d?network=testnet) |
11+
12+
#### IOTA mainnet
13+
14+
Coming soon.

pages/price-feeds/contract-addresses/sui.mdx

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,6 @@ Pyth is currently available on the following sui-based chains:
1313
| Wormhole State ID | [`0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c`](https://explorer.sui.io/object/0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c) |
1414
| Wormhole Package ID | [`0x5306f64e312b581766351c07af79c72fcb1cd25147157fdc2f8ad76de9a3fb6a`](https://explorer.sui.io/object/0x5306f64e312b581766351c07af79c72fcb1cd25147157fdc2f8ad76de9a3fb6a) |
1515

16-
#### IOTA testnet
17-
18-
| Name | Address |
19-
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
20-
| Pyth State ID | [`0x68dda579251917b3db28e35c4df495c6e664ccc085ede867a9b773c8ebedc2c1`](https://explorer.rebased.iota.org/object/0x68dda579251917b3db28e35c4df495c6e664ccc085ede867a9b773c8ebedc2c1?network=testnet) |
21-
| Pyth Package ID | [`0x23994dd119480ea614f7623520337058dca913cb1bb6e5d8d51c7b067d3ca3bb`](https://explorer.rebased.iota.org/object/0x23994dd119480ea614f7623520337058dca913cb1bb6e5d8d51c7b067d3ca3bb?network=testnet) |
22-
| Wormhole State ID | [`0x8bc490f69520a97ca1b3de864c96aa2265a0cf5d90f5f3f016b2eddf0cf2af2b`](https://explorer.rebased.iota.org/object/0x8bc490f69520a97ca1b3de864c96aa2265a0cf5d90f5f3f016b2eddf0cf2af2b?network=testnet) |
23-
| Wormhole Package ID | [`0xfca58c557f09cddb7930588c4e2a4edbe3cdded1ac1ed2270aa2dfa8d2b9ae0d`](https://explorer.rebased.iota.org/object/0xfca58c557f09cddb7930588c4e2a4edbe3cdded1ac1ed2270aa2dfa8d2b9ae0d?network=testnet) |
24-
2516
### Beta channel
2617

2718
#### Sui Testnet

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Then, consult the relevant ecosystem guide to get started using Pyth real-time p
1515
- [Aptos](use-real-time-data/aptos.md)
1616
- [CosmWasm](use-real-time-data/cosmwasm.md)
1717
- [Sui](use-real-time-data/sui.md)
18+
- [IOTA](use-real-time-data/iota.md)
1819
- [Near](use-real-time-data/sui.md)
1920

2021
Pyth price feeds can also be used in off-chain applications.

pages/price-feeds/use-real-time-data/_meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"fuel": "in Fuel Contracts",
66
"aptos": "in Aptos Contracts",
77
"sui": "in Sui Contracts",
8+
"iota": "in IOTA Contracts",
89
"ton": "in TON Contracts",
910
"cosmwasm": "in CosmWasm Contracts",
1011
"near": "in Near Contracts",
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
import { Callout, Tabs } from "nextra/components";
2+
3+
# How to Use Real-Time Data in IOTA Contracts
4+
5+
This guide explains how to use real-time Pyth data in IOTA applications.
6+
7+
## Install Pyth SDK
8+
9+
Use the following dependency in your `Move.toml` file to use the latest Pyth IOTA package and its dependencies:
10+
11+
<Tabs items={['IOTA Testnet']}>
12+
<Tabs.Tab>
13+
14+
```sh copy
15+
[dependencies.Pyth]
16+
git = "https://github.com/pyth-network/pyth-crosschain.git"
17+
subdir = "target_chains/iota/contracts"
18+
rev = "iota-contract-testnet"
19+
20+
[dependencies.Wormhole]
21+
git = "https://github.com/pyth-network/pyth-crosschain.git"
22+
subdir = "target_chains/iota/contracts/vendor/wormhole_iota_testnet/wormhole"
23+
rev = "iota-contract-testnet"
24+
25+
[dependencies.Iota]
26+
git = "https://github.com/iotaledger/iota.git"
27+
subdir = "crates/iota-framework/packages/iota-framework"
28+
rev = "751c23caf24efd071463b9ffd07eabcb15f44f31"
29+
```
30+
31+
</Tabs.Tab>
32+
</Tabs>
33+
34+
Pyth also provides a javascript SDK to construct transaction blocks that update price feeds:
35+
36+
<Tabs items={["IOTA"]}>
37+
<Tabs.Tab>
38+
```sh
39+
# NPM
40+
npm install --save @pythnetwork/pyth-iota-js
41+
42+
# Yarn
43+
yarn add @pythnetwork/pyth-iota-js
44+
```
45+
46+
</Tabs.Tab>
47+
</Tabs>
48+
49+
## Write Contract Code
50+
51+
The code snippet below provides a general template for what your contract code should look like:
52+
53+
```rust {18} copy
54+
module pyth_example::main {
55+
use iota::clock::Clock;
56+
use pyth::price_info;
57+
use pyth::price_identifier;
58+
use pyth::price;
59+
use pyth::pyth;
60+
use pyth::price_info::PriceInfoObject;
61+
62+
const E_INVALID_ID: u64 = 1;
63+
64+
public fun use_pyth_price(
65+
// Other arguments
66+
clock: &Clock,
67+
price_info_object: &PriceInfoObject,
68+
){
69+
let max_age = 60;
70+
// Make sure the price is not older than max_age seconds
71+
let price_struct = pyth::get_price_no_older_than(price_info_object,clock, max_age);
72+
73+
// Check the price feed ID
74+
let price_info = price_info::get_price_info_from_price_info_object(price_info_object);
75+
let price_id = price_identifier::get_bytes(&price_info::get_price_identifier(&price_info));
76+
77+
// ETH/USD price feed ID
78+
// The complete list of feed IDs is available at https://pyth.network/developers/price-feed-ids
79+
// Note: IOTA uses the Pyth price feed ID without the `0x` prefix.
80+
assert!(price_id!=x"ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace", E_INVALID_ID);
81+
82+
// Extract the price, decimal, and timestamp from the price struct and use them
83+
let decimal_i64 = price::get_expo(&price_struct);
84+
let price_i64 = price::get_price(&price_struct);
85+
let timestamp_sec = price::get_timestamp(&price_struct);
86+
}
87+
}
88+
```
89+
90+
One can consume the price by calling `pyth::get_price` abovementioned or other utility functions on the `PriceInfoObject` in the Move module
91+
92+
The code snippet below provides an example of how to update the Pyth price feeds:
93+
94+
```ts copy
95+
import { IotaPriceServiceConnection, IotaPythClient } from "@pythnetwork/pyth-iota-js";
96+
import { Transaction } from "@iota/iota-sdk/transactions";
97+
98+
// Get the Stable Hermes service URL from https://docs.pyth.network/price-feeds/api-instances-and-providers/hermes
99+
const connection = new IotaPriceServiceConnection("https://hermes-beta.pyth.network");
100+
101+
const priceIDs = [
102+
// You can find the IDs of prices at https://pyth.network/developers/price-feed-ids
103+
"0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43", // BTC/USD price ID
104+
"0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace", // ETH/USD price ID
105+
];
106+
107+
const priceUpdateData = await connection.getPriceFeedsUpdateData(priceIDs);
108+
109+
// It is either injected from the browser (https://www.npmjs.com/package/@iota/dapp-kit)
110+
// or instantiated in the backend via some private key (https://www.npmjs.com/package/@iota/iota-sdk)
111+
const wallet: SignerWithProvider = getWallet();
112+
// Get the state IDs of the Pyth and Wormhole contracts from
113+
// https://docs.pyth.network/price-feeds/contract-addresses/iota
114+
const wormholeStateId = "0x8bc490f69520a97ca1b3de864c96aa2265a0cf5d90f5f3f016b2eddf0cf2af2b";
115+
const pythStateId = "0x68dda579251917b3db28e35c4df495c6e664ccc085ede867a9b773c8ebedc2c1";
116+
117+
const client = new IotaPythClient(wallet.provider, pythStateId, wormholeStateId);
118+
const tx = new Transaction();
119+
const priceInfoObjectIds = await client.updatePriceFeeds(tx, priceFeedUpdateData, priceIDs);
120+
121+
tx.moveCall({
122+
target: `pyth_example::main::use_pyth_price`,
123+
arguments: [
124+
..., // other arguments needed for your contract
125+
tx.object(priceInfoObjectIds[0]),
126+
],
127+
});
128+
129+
const txBlock = {
130+
transaction: tx,
131+
wallet,
132+
options: {
133+
showEffects: true,
134+
showEvents: true,
135+
},
136+
};
137+
138+
const result = await wallet.signAndExecuteTransaction(txBlock);
139+
```
140+
141+
By calling the `updatePriceFeeds` function, the `IotaPythClient` adds the necessary transactions to the transaction block to update the price feeds.
142+
143+
<Callout type="warning" emoji="⚠️">
144+
145+
Your IOTA Move module **should NOT** have a hard-coded call to `pyth::update_single_price_feed.` In other words, a contract should **never call** the IOTA Pyth `pyth::update_single_price_feed` entry point. Instead, it should be called directly from client code (e.g., Typescript or Rust).
146+
147+
When IOTA contracts are [upgraded](https://docs.iota.org/developer/iota-101/move-overview/package-upgrades/introduction), the address changes, which makes the old address no longer valid. 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. (Pyth only allow users to interact with the most recent package version for security reasons).
148+
149+
Therefore, you should build a [IOTA programmable transaction](https://docs.iota.org/developer/iota-101/transactions/ptb/programmable-transaction-blocks-overview) 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.
150+
You can use `IOTAPythClient` to build such transactions and handle all the complexity of updating the price feeds.
151+
152+
Consult [Fetch Price Updates](../fetch-price-updates) for more information on how to fetch the `pyth_price_update`.
153+
154+
</Callout>
155+
156+
## Additional Resources
157+
158+
You may find these additional resources helpful for developing your IOTA application.
159+
160+
### CLI Example
161+
162+
[This example](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/iota/cli) shows how to update prices on a IOTA network. It does the following:
163+
164+
1. Fetches update data from Hermes for the given price feeds.
165+
1. Call the Pyth IOTA contract with a price update.
166+
167+
You can run this example with `npm run example-relay`. A full command that updates prices on the IOTA testnet looks like this:
168+
169+
```bash
170+
export IOTA_KEY=YOUR_PRIV_KEY;
171+
npm run example-relay -- --feed-id "ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace" \
172+
--hermes "https://hermes.pyth.network" \
173+
--full-node "https://api.testnet.iota.cafe" \
174+
--pyth-state-id "0x68dda579251917b3db28e35c4df495c6e664ccc085ede867a9b773c8ebedc2c1" \
175+
--wormhole-state-id "0x8bc490f69520a97ca1b3de864c96aa2265a0cf5d90f5f3f016b2eddf0cf2af2b"
176+
```
177+
178+
### Contract Addresses
179+
180+
Consult [IOTA Contract Addresses](../contract-addresses/iota) to find the package IDs.
181+
182+
### Pyth Price Feed IDs
183+
184+
Consult [Pyth Price Feed IDs](https://pyth.network/developers/price-feed-ids) to find Pyth price feed IDs for various assets.

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

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ This guide explains how to use real-time Pyth data in Sui applications.
88

99
Use the following dependency in your `Move.toml` file to use the latest Pyth Sui package and its dependencies:
1010

11-
<Tabs items={['Sui Mainnet', 'Sui Testnet', 'IOTA Testnet']}>
11+
<Tabs items={['Sui Mainnet', 'Sui Testnet']}>
1212
<Tabs.Tab>
1313
```sh copy
1414
[dependencies.Pyth]
@@ -49,32 +49,12 @@ subdir = "crates/sui-framework/packages/sui-framework"
4949
rev = "041c5f2bae2fe52079e44b70514333532d69f4e6"
5050
````
5151
52-
</Tabs.Tab>
53-
<Tabs.Tab>
54-
55-
```sh copy
56-
[dependencies.Pyth]
57-
git = "https://github.com/pyth-network/pyth-crosschain.git"
58-
subdir = "target_chains/sui/contracts"
59-
rev = "sui-contract-iota-testnet"
60-
61-
[dependencies.Wormhole]
62-
git = "https://github.com/pyth-network/pyth-crosschain.git"
63-
subdir = "target_chains/sui/contracts/vendor/wormhole_iota_testnet/wormhole"
64-
rev = "sui-contract-iota-testnet"
65-
66-
[dependencies.Iota]
67-
git = "https://github.com/iotaledger/iota.git"
68-
subdir = "crates/iota-framework/packages/iota-framework"
69-
rev = "751c23caf24efd071463b9ffd07eabcb15f44f31"
70-
```
71-
7252
</Tabs.Tab>
7353
</Tabs>
7454
7555
Pyth also provides a javascript SDK to construct transaction blocks that update price feeds:
7656
77-
<Tabs items={["Sui", "IOTA"]}>
57+
<Tabs items={["Sui"]}>
7858
<Tabs.Tab>
7959
```sh
8060
# NPM
@@ -85,16 +65,6 @@ Pyth also provides a javascript SDK to construct transaction blocks that update
8565
```
8666

8767
</Tabs.Tab>
88-
<Tabs.Tab>
89-
```sh
90-
# NPM
91-
npm install --save @pythnetwork/pyth-iota-js
92-
93-
# Yarn
94-
yarn add @pythnetwork/pyth-iota-js
95-
```
96-
97-
</Tabs.Tab>
9868
</Tabs>
9969

10070
## Write Contract Code

0 commit comments

Comments
 (0)