-
Notifications
You must be signed in to change notification settings - Fork 35
add fuel example #386
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
add fuel example #386
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
--- | ||
description: Consume Pyth Network prices in Fuel applications | ||
--- | ||
|
||
import { Callout, Tabs } from "nextra/components"; | ||
|
||
# How to Use Real-Time Data in Fuel Contracts | ||
|
||
This guide explains how to use real-time Pyth data in Fuel contracts. | ||
|
||
## Install the Pyth SDK | ||
|
||
Use the following dependency in your `Forc.toml` file to use the latest Pyth Fuel package: | ||
|
||
```toml copy | ||
[dependencies] | ||
pyth_interface = { git = "https://github.com/pyth-network/pyth-crosschain", tag = "pyth-fuel-contract-v0.5.0" } | ||
``` | ||
|
||
Pyth also provides a javascript SDK to interact with the Pyth contract on Fuel. You can install it using the following command: | ||
|
||
<Tabs items={["npm", "yarn"]}> | ||
<Tabs.Tab>```npm install --save @pythnetwork/pyth-fuel-js ```</Tabs.Tab> | ||
<Tabs.Tab>```yarn add @pythnetwork/pyth-fuel-js ```</Tabs.Tab> | ||
</Tabs> | ||
|
||
## Write Contract Code | ||
|
||
The code snippet below provides an example module fetching the ETH/USD price from Pyth price feeds: | ||
|
||
```sway copy | ||
contract; | ||
|
||
use pyth_interface::{data_structures::price::{Price, PriceFeedId}, PythCore}; | ||
|
||
use std::bytes::Bytes; | ||
|
||
abi UpdatePrice { | ||
fn valid_time_period() -> u64; | ||
fn get_price(price_feed_id: PriceFeedId) -> Price; | ||
fn get_price_unsafe(price_feed_id: PriceFeedId) -> Price; | ||
fn update_fee(update_data: Vec<Bytes>) -> u64; | ||
#[payable] | ||
fn update_price_feeds(update_fee: u64, update_data: Vec<Bytes>); | ||
} | ||
|
||
const PYTH_CONTRACT_ID = 0x1ab91bc1402a187055d3e827017ace566a103ce2a4126517da5d656d6a436aea; // Testnet Contract | ||
const FUEL_ETH_BASE_ASSET_ID = 0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07; | ||
|
||
impl UpdatePrice for Contract { | ||
fn valid_time_period() -> u64 { | ||
let pyth_contract = abi(PythCore, PYTH_CONTRACT_ID); | ||
let period = pyth_contract.valid_time_period(); | ||
period | ||
} | ||
fn get_price(price_feed_id: PriceFeedId) -> Price { | ||
let pyth_contract = abi(PythCore, PYTH_CONTRACT_ID); | ||
let price = pyth_contract.price(price_feed_id); | ||
price | ||
} | ||
fn get_price_unsafe(price_feed_id: PriceFeedId) -> Price { | ||
let pyth_contract = abi(PythCore, PYTH_CONTRACT_ID); | ||
let price = pyth_contract.price_unsafe(price_feed_id); | ||
price | ||
} | ||
fn update_fee(update_data: Vec<Bytes>) -> u64 { | ||
let pyth_contract = abi(PythCore, PYTH_CONTRACT_ID); | ||
let fee = pyth_contract.update_fee(update_data); | ||
fee | ||
} | ||
#[payable] | ||
fn update_price_feeds(update_fee: u64, update_data: Vec<Bytes>) { | ||
let pyth_contract = abi(PythCore, PYTH_CONTRACT_ID); | ||
pyth_contract | ||
.update_price_feeds { | ||
asset_id: FUEL_ETH_BASE_ASSET_ID, | ||
coins: update_fee, | ||
}(update_data); | ||
} | ||
} | ||
``` | ||
|
||
The `update_data` argument contains verified prices from Pyth. | ||
Calling `pyth_contract.update_price_feeds` with this value updates the on-chain Pyth price and ensures your application has recent price data. | ||
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`. | ||
|
||
<Callout type="info" emoji="ℹ️"> | ||
Regarding the Pyth contract on Fuel, the caller must pay the fee in the base | ||
asset for functions like `update_price_feeds`. The fee is currently set to the | ||
minimum possible value (1 wei). | ||
</Callout> | ||
|
||
The code snippet above does the following things: | ||
|
||
1. Defines an `UpdatePrice` ABI with functions to interact with the Pyth contract. | ||
2. Implements the `UpdatePrice` ABI for the contract, providing the following functionality: | ||
|
||
- `valid_time_period()`: Retrieves the valid time period from the Pyth contract. | ||
- `get_price(price_feed_id)`: Gets the price for a given price feed ID. | ||
- `get_price_unsafe(price_feed_id)`: Gets the price for a given price feed ID without staleness checks. | ||
- `update_fee(update_data)`: Calculates the fee required to update the price feeds. | ||
- `update_price_feeds(update_fee, update_data)`: Updates the price feeds with the provided data and fee. | ||
|
||
3. Uses the `PYTH_CONTRACT_ID` constant to interact with the Pyth contract on testnet. | ||
4. Uses the `FUEL_ETH_BASE_ASSET_ID` constant as the asset ID for paying update fees. | ||
|
||
To use this contract, you would typically: | ||
|
||
1. Call `update_fee()` to get the required fee for updating price feeds. | ||
2. Call `update_price_feeds()` with the fee and update data to refresh the price feeds. | ||
3. Use `get_price()` or `get_price_unsafe()` to read the updated prices. | ||
|
||
### Write Client Code | ||
|
||
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). | ||
|
||
```ts copy | ||
import { TestContractAbi__factory } from "@/sway-api"; | ||
import PYTH_CONTRACT_ABI from "../abi/pyth-contract-abi.json"; | ||
import { arrayify, Contract, hexlify } from "fuels"; | ||
|
||
const HERMES_V2_LATEST_PRICE_UPDATES_ENDPOINT = | ||
"https://hermes.pyth.network/v2/updates/price/latest?ids[]="; | ||
const FUEL_ETH_BASE_ASSET_ID = | ||
"0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07"; | ||
const PRICE_FEED_ID = | ||
"0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace"; // ETH/USD | ||
|
||
const contractId = | ||
CURRENT_ENVIRONMENT === "local" | ||
? contractIds.testContract | ||
: (process.env.NEXT_PUBLIC_TESTNET_CONTRACT_ID as string); // Testnet Contract ID | ||
const pythContractId = process.env | ||
.NEXT_PUBLIC_PYTH_TESTNET_CONTRACT_ID as string; // Testnet Contract ID | ||
|
||
async function updateAndGetPrice() { | ||
const fetchPriceUpdateData = async () => { | ||
const response = await fetch( | ||
HERMES_V2_LATEST_PRICE_UPDATES_ENDPOINT + PRICE_FEED_ID | ||
); | ||
if (!response.ok) { | ||
throw new Error("Failed to fetch price"); | ||
} | ||
const data = await response.json(); | ||
const binaryData = data.binary.data[0]; | ||
const buffer = Buffer.from(binaryData, "hex"); | ||
return buffer; | ||
}; | ||
|
||
const updateData = await fetchPriceUpdateData(); | ||
|
||
const { waitForResult: waitForResultFee } = await contract.functions | ||
.update_fee([arrayify(updateData)]) | ||
.addContracts([pythContract]) | ||
.call(); | ||
const { value: fee } = await waitForResultFee(); | ||
|
||
await contract.functions | ||
.update_price_feeds(fee, [arrayify(updateData)]) | ||
.addContracts([pythContract]) | ||
.callParams({ | ||
forward: [fee, hexlify(FUEL_ETH_BASE_ASSET_ID)], | ||
}) | ||
.call(); | ||
|
||
const { value: price } = await contract.functions | ||
.get_price(hexlify(PRICE_FEED_ID)) | ||
.addContracts([pythContract]) | ||
.get(); | ||
|
||
console.log("Latest ETH/USD price after update:", price); | ||
return price; | ||
} | ||
|
||
updateAndGetPrice().catch(console.error); | ||
``` | ||
|
||
## Additional Resources | ||
|
||
You may find these additional resources helpful for developing your Fuel application. | ||
|
||
### Interface | ||
|
||
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. | ||
|
||
### Example Applications | ||
|
||
- [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. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you not using the hermes client here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could but this was just more straightforward
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated to use
HermesClient