Skip to content
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

feat(target_chains/fuel): update fuel toolchains to the latest version #1911

Merged
merged 2 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
789 changes: 578 additions & 211 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

471 changes: 289 additions & 182 deletions target_chains/fuel/contracts/Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion target_chains/fuel/contracts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ license = "Apache-2.0"
[dependencies]
rand = "0.8.5"
base64 = "0.22"
fuels = { version = "0.66.2", features = ["fuel-core-lib"] }
fuels = { version = "0.66.4", features = ["fuel-core-lib"] }
tokio = { version = "1.12", features = ["rt", "macros"] }
hex = "0.4.3"
reqwest = "0.11.27"
Expand Down
4 changes: 2 additions & 2 deletions target_chains/fuel/contracts/Forc.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[[package]]
name = "core"
source = "path+from-root-D19F39D92CA9923C"
source = "path+from-root-4BB20845430AF9CF"

[[package]]
name = "pyth-contract"
Expand Down Expand Up @@ -32,7 +32,7 @@ dependencies = ["std"]

[[package]]
name = "std"
source = "git+https://github.com/fuellabs/sway?tag=v0.63.1#169f91ae0a6a698bd1cb459c4c203bab646a38ec"
source = "git+https://github.com/fuellabs/sway?tag=v0.63.5#31a1d6f98395f571cd3674b492d9bf4773c55f65"
dependencies = ["core"]

[[package]]
Expand Down
4 changes: 2 additions & 2 deletions target_chains/fuel/contracts/fuel-toolchain.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
channel = "latest-aarch64-apple-darwin"

[components]
forc = "0.63.1"
fuel-core = "0.33.0"
forc = "0.63.5"
fuel-core = "0.35.0"
Original file line number Diff line number Diff line change
Expand Up @@ -1535,7 +1535,7 @@
{
"name": "DEPLOYER",
"concreteTypeId": "ab7cd04e05be58e3fc15d424c2c4a57f824a2a2d97d67252440a3925ebdc1335",
"offset": 131600
"offset": 132984
}
]
}
Binary file not shown.
102 changes: 53 additions & 49 deletions target_chains/fuel/contracts/pyth-contract/src/main.sw
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ use sway_libs::ownership::*;
use standards::src5::{SRC5, State};

const GUARDIAN_SET_EXPIRATION_TIME_SECONDS: u64 = 86400; // 24 hours in seconds

configurable {
DEPLOYER: Identity = Identity::Address(Address::from(ZERO_B256)),
}
Expand Down Expand Up @@ -848,57 +847,62 @@ impl PythGovernance for Contract {

#[storage(read, write)]
fn execute_governance_instruction(encoded_vm: Bytes) {
let vm = verify_governance_vm(encoded_vm);
// Log so that the WormholeVM struct will show up in the ABI and can be used in the tests
log(vm);
execute_governance_instruction(encoded_vm)
}
}

let gi = GovernanceInstruction::parse_governance_instruction(vm.payload);
// Log so that the GovernanceInstruction struct will show up in the ABI and can be used in the tests
log(gi);
#[storage(read, write)]
fn execute_governance_instruction(encoded_vm: Bytes) {
let vm = verify_governance_vm(encoded_vm);
// Log so that the WormholeVM struct will show up in the ABI and can be used in the tests
log(vm);

require(
gi.target_chain_id == chain_id() || gi.target_chain_id == 0,
PythError::InvalidGovernanceTarget,
);
let gi = GovernanceInstruction::parse_governance_instruction(vm.payload);
// Log so that the GovernanceInstruction struct will show up in the ABI and can be used in the tests
log(gi);

match gi.action {
GovernanceAction::UpgradeContract => {
require(gi.target_chain_id != 0, PythError::InvalidGovernanceTarget);
// TODO: implement upgrade_upgradeable_contract(uc) when Fuel releases the upgrade standard library;
log("Upgrade functionality not implemented");
revert(0u64);
},
GovernanceAction::AuthorizeGovernanceDataSourceTransfer => {
let agdst = GovernanceInstruction::parse_authorize_governance_data_source_transfer_payload(gi.payload);
log(agdst);
authorize_governance_data_source_transfer(agdst);
},
GovernanceAction::SetDataSources => {
let sdsp = GovernanceInstruction::parse_set_data_sources_payload(gi.payload);
log(sdsp);
set_data_sources(sdsp);
},
GovernanceAction::SetFee => {
let sf = GovernanceInstruction::parse_set_fee_payload(gi.payload);
log(sf);
set_fee(sf);
},
GovernanceAction::SetValidPeriod => {
let svp = GovernanceInstruction::parse_set_valid_period_payload(gi.payload);
log(svp);
set_valid_period(svp);
},
GovernanceAction::RequestGovernanceDataSourceTransfer => {
// RequestGovernanceDataSourceTransfer can be only part of AuthorizeGovernanceDataSourceTransfer message
// The `revert` function only accepts u64, so as
// a workaround we use require.
require(false, PythError::InvalidGovernanceMessage);
},
_ => {
// The `revert` function only accepts u64, so as
// a workaround we use require.
require(false, PythError::InvalidGovernanceMessage);
}
require(
gi.target_chain_id == chain_id() || gi.target_chain_id == 0,
PythError::InvalidGovernanceTarget,
);

match gi.action {
GovernanceAction::UpgradeContract => {
require(gi.target_chain_id != 0, PythError::InvalidGovernanceTarget);
// TODO: implement upgrade_upgradeable_contract(uc) when Fuel releases the upgrade standard library;
log("Upgrade functionality not implemented");
revert(0u64);
},
GovernanceAction::AuthorizeGovernanceDataSourceTransfer => {
let agdst = GovernanceInstruction::parse_authorize_governance_data_source_transfer_payload(gi.payload);
log(agdst);
authorize_governance_data_source_transfer(agdst);
},
GovernanceAction::SetDataSources => {
let sdsp = GovernanceInstruction::parse_set_data_sources_payload(gi.payload);
log(sdsp);
set_data_sources(sdsp);
},
GovernanceAction::SetFee => {
let sf = GovernanceInstruction::parse_set_fee_payload(gi.payload);
log(sf);
set_fee(sf);
},
GovernanceAction::SetValidPeriod => {
let svp = GovernanceInstruction::parse_set_valid_period_payload(gi.payload);
log(svp);
set_valid_period(svp);
},
GovernanceAction::RequestGovernanceDataSourceTransfer => {
// RequestGovernanceDataSourceTransfer can be only part of AuthorizeGovernanceDataSourceTransfer message
// The `revert` function only accepts u64, so as
// a workaround we use require.
require(false, PythError::InvalidGovernanceMessage);
},
_ => {
// The `revert` function only accepts u64, so as
// a workaround we use require.
require(false, PythError::InvalidGovernanceMessage);
Comment on lines +850 to +905
Copy link
Contributor Author

@cctdaniel cctdaniel Sep 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a compiler issue with fuel where it fails to compile with Too many arguments, cannot handle.: Immediate12TooLarge error and the solution was to make the contract functions call internal functions, more context here: FuelLabs/sway#6542

}
}
}
Expand Down
87 changes: 2 additions & 85 deletions target_chains/fuel/sdk/js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,91 +36,8 @@ To use Pyth prices on chain,
they must be fetched from a Hermes instance. The `HermesClient` class from Pyth's `hermes-client` library can be used to interact with Hermes,
providing a way to fetch these prices directly in your code.
In order to use Pyth prices in your protocol you need to submit the price update data to Pyth contract in your target
chain. The following example shows how to obtain
Pyth prices and submit them to a Fuel network:
chain.

```typescript
import { HermesClient, PriceUpdate } from "@pythnetwork/hermes-client";
import {
PYTH_CONTRACT_ADDRESS_SEPOLIA,
PYTH_CONTRACT_ABI,
FUEL_ETH_ASSET_ID,
} from "../index";
import { Provider, Wallet, Contract, hexlify, arrayify } from "fuels";

async function main() {
// Create a provider for interacting with Fuel RPC
const provider = await Provider.create(
"https://testnet.fuel.network/v1/graphql"
);
const privateKey = process.env.ACCOUNT_PRIVATE_KEY;
if (privateKey === undefined) {
throw new Error("Missing ACCOUNT_PRIVATE_KEY env var");
}
const wallet = Wallet.fromPrivateKey(privateKey, provider);

// Create a `Contract` instance to interact with the Pyth contract on Fuel
const contract = new Contract(
PYTH_CONTRACT_ADDRESS_SEPOLIA,
PYTH_CONTRACT_ABI,
wallet
);

const priceFeedSymbol = "Crypto.ETH/USD";
const priceFeedId =
"0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace"; // Pyth ETH/USD price feed id
const previousPrice = (
await contract.functions.price_unsafe(priceFeedId).get()
).value;
console.log(
`Previous price: ${
previousPrice.price.toNumber() * 10 ** -previousPrice.exponent
}`
);

// Create a client for pulling price updates from Hermes.
const hermesClient = new HermesClient("https://hermes.pyth.network");

console.log(`Querying latest Pyth price update for ${priceFeedSymbol}`);
// Get the latest values of the price feeds as json objects.
const priceUpdates: PriceUpdate = await hermesClient.getLatestPriceUpdates([
priceFeedId,
]);
console.log(
`Current price from Hermes: ${
Number(priceUpdates.parsed?.[0].price.price) *
10 ** Number(priceUpdates.parsed?.[0].price.expo)
}`
);

const priceFeedUpdateData = arrayify(
Buffer.from(priceUpdates.binary.data[0], "hex")
);

// Query the amount of update fee required
console.log(`Querying update fee...`);
const updateFee: number = (
await contract.functions.update_fee([priceFeedUpdateData]).get()
).value;
console.log(`Update fee: ${updateFee}`);

const tx = await contract.functions
.update_price_feeds([priceFeedUpdateData])
.callParams({
forward: [updateFee, hexlify(FUEL_ETH_ASSET_ID)],
})
.call();
console.log(`Transaction confirmed: ${tx.transactionId}`);

const newPrice = (
await contract.functions.price_no_older_than(60, priceFeedId).get()
).value;
console.log(
`New price: ${newPrice.price.toNumber() * 10 ** -newPrice.exponent}`
);
}

main();
```
Comment on lines -42 to -124
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactored this into src/examples/usage.ts because i saw that in package.lock there is "usage-example": "ts-node src/examples/usage.ts" but the file doesn't exists

For a complete example of how to obtain Pyth prices and submit them to a Fuel network, check out the [usage example](src/examples/usage.ts) in the `src/examples` directory.

We strongly recommend reading our guide which explains [how to work with Pyth price feeds](https://docs.pyth.network/documentation/pythnet-price-feeds/best-practices).
5 changes: 3 additions & 2 deletions target_chains/fuel/sdk/js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pythnetwork/pyth-fuel-js",
"version": "1.0.5",
"version": "1.0.6",
"description": "Pyth Network Fuel Utils in JS",
"homepage": "https://pyth.network",
"author": {
Expand Down Expand Up @@ -37,13 +37,14 @@
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^7.7.0",
"@typescript-eslint/parser": "^7.7.0",
"@pythnetwork/hermes-client": "workspace:*",
"copyfiles": "^2.4.1",
"eslint": "^8.14.0",
"prettier": "^2.6.2",
"ts-node": "^10.9.2",
"typescript": "^5.4.5"
},
"dependencies": {
"fuels": "^0.94.2"
"fuels": "^0.94.5"
}
}
2 changes: 1 addition & 1 deletion target_chains/fuel/sdk/js/src/abi/pyth-contract-abi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1535,7 +1535,7 @@
{
"name": "DEPLOYER",
"concreteTypeId": "ab7cd04e05be58e3fc15d424c2c4a57f824a2a2d97d67252440a3925ebdc1335",
"offset": 131600
"offset": 132984
}
]
}
81 changes: 81 additions & 0 deletions target_chains/fuel/sdk/js/src/examples/usage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { HermesClient, PriceUpdate } from "@pythnetwork/hermes-client";
import {
PYTH_CONTRACT_ADDRESS_SEPOLIA,
PYTH_CONTRACT_ABI,
FUEL_ETH_ASSET_ID,
} from "../index";
import { Provider, Wallet, Contract, hexlify, arrayify } from "fuels";

async function main() {
// Create a provider for interacting with Fuel RPC
const provider = await Provider.create(
"https://testnet.fuel.network/v1/graphql"
);
const privateKey = process.env.ACCOUNT_PRIVATE_KEY;
if (privateKey === undefined) {
throw new Error("Missing ACCOUNT_PRIVATE_KEY env var");
}
const wallet = Wallet.fromPrivateKey(privateKey, provider);

// Create a `Contract` instance to interact with the Pyth contract on Fuel
const contract = new Contract(
PYTH_CONTRACT_ADDRESS_SEPOLIA,
PYTH_CONTRACT_ABI,
wallet
);

const priceFeedSymbol = "Crypto.ETH/USD";
const priceFeedId =
"0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace"; // Pyth ETH/USD price feed id
const previousPrice = (
await contract.functions.price_unsafe(priceFeedId).get()
).value;
console.log(
`Previous price: ${
previousPrice.price.toNumber() * 10 ** -previousPrice.exponent
}`
);

// Create a client for pulling price updates from Hermes.
const hermesClient = new HermesClient("https://hermes.pyth.network");

console.log(`Querying latest Pyth price update for ${priceFeedSymbol}`);
// Get the latest values of the price feeds as json objects.
const priceUpdates: PriceUpdate = await hermesClient.getLatestPriceUpdates([
priceFeedId,
]);
console.log(
`Current price from Hermes: ${
Number(priceUpdates.parsed?.[0].price.price) *
10 ** Number(priceUpdates.parsed?.[0].price.expo)
}`
);

const priceFeedUpdateData = arrayify(
Buffer.from(priceUpdates.binary.data[0], "hex")
);

// Query the amount of update fee required
console.log(`Querying update fee...`);
const updateFee: number = (
await contract.functions.update_fee([priceFeedUpdateData]).get()
).value;
console.log(`Update fee: ${updateFee}`);

const tx = await contract.functions
.update_price_feeds([priceFeedUpdateData])
.callParams({
forward: [updateFee, hexlify(FUEL_ETH_ASSET_ID)],
})
.call();
console.log(`Transaction confirmed: ${tx.transactionId}`);

const newPrice = (
await contract.functions.price_no_older_than(60, priceFeedId).get()
).value;
console.log(
`New price: ${newPrice.price.toNumber() * 10 ** -newPrice.exponent}`
);
}

main();
2 changes: 1 addition & 1 deletion target_chains/fuel/sdk/js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import PYTH_CONTRACT_ABI from "./abi/pyth-contract-abi.json";

/** Address of the Pyth contract on Fuel Sepolia (testnet). */
export const PYTH_CONTRACT_ADDRESS_SEPOLIA =
"0xc3c47cdeaec412778fc86842b44fb061b350db57f9d52def4f73036156f71506";
"0xe31e04946c67fb41923f93d50ee7fc1c6c99d6e07c02860c6bea5f4a13919277";

/** Asset ID of ETH on Fuel. */
export const FUEL_ETH_ASSET_ID =
Expand Down
Loading
Loading