Skip to content

Commit 003ecc2

Browse files
authored
add fuel example (#386)
* add fuel example * update client code to use HermesClient
1 parent b9436d0 commit 003ecc2

File tree

2 files changed

+188
-0
lines changed

2 files changed

+188
-0
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"evm": "in EVM Contracts",
33
"solana": "in Solana and SVM Programs",
44
"starknet": "in Starknet Contracts",
5+
"fuel": "in Fuel Contracts",
56
"aptos": "in Aptos Contracts",
67
"sui": "in Sui Contracts",
78
"cosmwasm": "in CosmWasm Contracts",
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
---
2+
description: Consume Pyth Network prices in Fuel applications
3+
---
4+
5+
import { Callout, Tabs } from "nextra/components";
6+
7+
# How to Use Real-Time Data in Fuel Contracts
8+
9+
This guide explains how to use real-time Pyth data in Fuel contracts.
10+
11+
## Install the Pyth SDK
12+
13+
Use the following dependency in your `Forc.toml` file to use the latest Pyth Fuel package:
14+
15+
```toml copy
16+
[dependencies]
17+
pyth_interface = { git = "https://github.com/pyth-network/pyth-crosschain", tag = "pyth-fuel-contract-v0.5.0" }
18+
```
19+
20+
Pyth also provides a javascript SDK to interact with the Pyth contract on Fuel. You can install it using the following command:
21+
22+
<Tabs items={["npm", "yarn"]}>
23+
<Tabs.Tab>```npm install --save @pythnetwork/pyth-fuel-js ```</Tabs.Tab>
24+
<Tabs.Tab>```yarn add @pythnetwork/pyth-fuel-js ```</Tabs.Tab>
25+
</Tabs>
26+
27+
## Write Contract Code
28+
29+
The code snippet below provides an example module fetching the ETH/USD price from Pyth price feeds:
30+
31+
```sway copy
32+
contract;
33+
34+
use pyth_interface::{data_structures::price::{Price, PriceFeedId}, PythCore};
35+
36+
use std::bytes::Bytes;
37+
38+
abi UpdatePrice {
39+
fn valid_time_period() -> u64;
40+
fn get_price(price_feed_id: PriceFeedId) -> Price;
41+
fn get_price_unsafe(price_feed_id: PriceFeedId) -> Price;
42+
fn update_fee(update_data: Vec<Bytes>) -> u64;
43+
#[payable]
44+
fn update_price_feeds(update_fee: u64, update_data: Vec<Bytes>);
45+
}
46+
47+
const PYTH_CONTRACT_ID = 0x1ab91bc1402a187055d3e827017ace566a103ce2a4126517da5d656d6a436aea; // Testnet Contract
48+
const FUEL_ETH_BASE_ASSET_ID = 0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07;
49+
50+
impl UpdatePrice for Contract {
51+
fn valid_time_period() -> u64 {
52+
let pyth_contract = abi(PythCore, PYTH_CONTRACT_ID);
53+
let period = pyth_contract.valid_time_period();
54+
period
55+
}
56+
fn get_price(price_feed_id: PriceFeedId) -> Price {
57+
let pyth_contract = abi(PythCore, PYTH_CONTRACT_ID);
58+
let price = pyth_contract.price(price_feed_id);
59+
price
60+
}
61+
fn get_price_unsafe(price_feed_id: PriceFeedId) -> Price {
62+
let pyth_contract = abi(PythCore, PYTH_CONTRACT_ID);
63+
let price = pyth_contract.price_unsafe(price_feed_id);
64+
price
65+
}
66+
fn update_fee(update_data: Vec<Bytes>) -> u64 {
67+
let pyth_contract = abi(PythCore, PYTH_CONTRACT_ID);
68+
let fee = pyth_contract.update_fee(update_data);
69+
fee
70+
}
71+
#[payable]
72+
fn update_price_feeds(update_fee: u64, update_data: Vec<Bytes>) {
73+
let pyth_contract = abi(PythCore, PYTH_CONTRACT_ID);
74+
pyth_contract
75+
.update_price_feeds {
76+
asset_id: FUEL_ETH_BASE_ASSET_ID,
77+
coins: update_fee,
78+
}(update_data);
79+
}
80+
}
81+
```
82+
83+
The `update_data` argument contains verified prices from Pyth.
84+
Calling `pyth_contract.update_price_feeds` with this value updates the on-chain Pyth price and ensures your application has recent price data.
85+
The `update_data` can be fetched from Hermes; Consult [Fetch Price Updates](https://docs.pyth.network/price-feeds/fetch-price-updates) for more information on how to fetch the `update_data`.
86+
87+
<Callout type="info" emoji="ℹ️">
88+
Regarding the Pyth contract on Fuel, the caller must pay the fee in the base
89+
asset for functions like `update_price_feeds`. The fee is currently set to the
90+
minimum possible value (1 wei).
91+
</Callout>
92+
93+
The code snippet above does the following things:
94+
95+
1. Defines an `UpdatePrice` ABI with functions to interact with the Pyth contract.
96+
2. Implements the `UpdatePrice` ABI for the contract, providing the following functionality:
97+
98+
- `valid_time_period()`: Retrieves the valid time period from the Pyth contract.
99+
- `get_price(price_feed_id)`: Gets the price for a given price feed ID.
100+
- `get_price_unsafe(price_feed_id)`: Gets the price for a given price feed ID without staleness checks.
101+
- `update_fee(update_data)`: Calculates the fee required to update the price feeds.
102+
- `update_price_feeds(update_fee, update_data)`: Updates the price feeds with the provided data and fee.
103+
104+
3. Uses the `PYTH_CONTRACT_ID` constant to interact with the Pyth contract on testnet.
105+
4. Uses the `FUEL_ETH_BASE_ASSET_ID` constant as the asset ID for paying update fees.
106+
107+
To use this contract, you would typically:
108+
109+
1. Call `update_fee()` to get the required fee for updating price feeds.
110+
2. Call `update_price_feeds()` with the fee and update data to refresh the price feeds.
111+
3. Use `get_price()` or `get_price_unsafe()` to read the updated prices.
112+
113+
### Write Client Code
114+
115+
The code snippet below provides an example of how to fetch price updates using NextJS, a full example can be found [here](https://github.com/pyth-network/pyth-examples/tree/main/price_feeds/fuel/fetch-and-update-btc-price).
116+
117+
```ts copy
118+
import { TestContractAbi__factory } from "@/sway-api";
119+
import PYTH_CONTRACT_ABI from "../abi/pyth-contract-abi.json";
120+
import { arrayify, Contract, hexlify } from "fuels";
121+
import { HermesClient } from "@pythnetwork/hermes-client";
122+
123+
const HERMES_ENDPOINT = "https://hermes.pyth.network/";
124+
const FUEL_ETH_BASE_ASSET_ID =
125+
"0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07";
126+
const ETH_USD_PRICE_FEED_ID =
127+
"0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace"; // ETH/USD
128+
129+
const contractId =
130+
CURRENT_ENVIRONMENT === "local"
131+
? contractIds.testContract
132+
: (process.env.NEXT_PUBLIC_TESTNET_CONTRACT_ID as string); // Testnet Contract ID
133+
const pythContractId = process.env
134+
.NEXT_PUBLIC_PYTH_TESTNET_CONTRACT_ID as string; // Testnet Contract ID
135+
136+
async function updateAndGetPrice() {
137+
const fetchPriceUpdateData = async () => {
138+
const connection = new HermesClient(HERMES_ENDPOINT);
139+
140+
// Latest price updates
141+
const priceUpdates = await connection.getLatestPriceUpdates([
142+
ETH_USD_PRICE_FEED_ID,
143+
]);
144+
145+
const buffer = Buffer.from(priceUpdates.binary.data[0], "hex");
146+
return buffer;
147+
};
148+
149+
const updateData = await fetchPriceUpdateData();
150+
151+
const { waitForResult: waitForResultFee } = await contract.functions
152+
.update_fee([arrayify(updateData)])
153+
.addContracts([pythContract])
154+
.call();
155+
const { value: fee } = await waitForResultFee();
156+
157+
await contract.functions
158+
.update_price_feeds(fee, [arrayify(updateData)])
159+
.addContracts([pythContract])
160+
.callParams({
161+
forward: [fee, hexlify(FUEL_ETH_BASE_ASSET_ID)],
162+
})
163+
.call();
164+
165+
const { value: price } = await contract.functions
166+
.get_price(hexlify(PRICE_FEED_ID))
167+
.addContracts([pythContract])
168+
.get();
169+
170+
console.log("Latest ETH/USD price after update:", price);
171+
return price;
172+
}
173+
174+
updateAndGetPrice().catch(console.error);
175+
```
176+
177+
## Additional Resources
178+
179+
You may find these additional resources helpful for developing your Fuel application.
180+
181+
### Interface
182+
183+
The [Fuel Interface](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/fuel/contracts/pyth-interface/src) directory contains multiple files that define the functions and structures for interacting with the Pyth contract deployed on Fuel.
184+
185+
### Example Applications
186+
187+
- [fetch-and-update-btc-price](https://github.com/pyth-network/pyth-examples/tree/main/price_feeds/fuel/fetch-and-update-btc-price), which fetches the latest price update from Hermes and updates the Pyth price feeds on Fuel.

0 commit comments

Comments
 (0)