Skip to content

Commit 7bfa02a

Browse files
authored
(chore) pricefeed/guides: Add Starknet Guide (#335)
* Initial commit * tiny change * tiny change * requested changes * requested changes * requested chages * pre-commit issue * pre-commit issue * uh
1 parent 7e593f5 commit 7bfa02a

File tree

3 files changed

+186
-0
lines changed

3 files changed

+186
-0
lines changed

.prettierignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Starknet Guide
2+
3+
pages/price-feeds/use-real-time-data/starknet.mdx

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"evm": "in EVM Contracts",
33
"solana": "in Solana and SVM Programs",
4+
"starknet": "in Starknet Contracts",
45
"aptos": "in Aptos Contracts",
56
"sui": "in Sui Contracts",
67
"cosmwasm": "in CosmWasm Contracts",
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
---
2+
description: Consume Pyth Network prices in Starknet applications
3+
---
4+
5+
import { Callout, Tabs } from "nextra/components";
6+
7+
# How to Use Real-Time Data in Starknet Contracts
8+
9+
This guide explains how to use real-time Pyth data in Starknet contracts.
10+
11+
## Install the Pyth SDK
12+
13+
Use the following dependency in your `Scarb.toml` file to use the latest Pyth Starkenet package:
14+
15+
```toml copy
16+
[dependencies]
17+
pyth = { git = "https://github.com/pyth-network/pyth-crosschain.git", tag = "pyth-starknet-contract-v0.1.0"}
18+
```
19+
20+
Pyth also provides a javascript SDK to interact with the Pyth contract on Starknet. You can install it using the following command:
21+
22+
<Tabs items={["npm", "yarn"]}>
23+
<Tabs.Tab>
24+
```sh copy
25+
npm install --save @pythnetwork/pyth-starknet-js
26+
```
27+
</Tabs.Tab>
28+
<Tabs.Tab>
29+
```sh copy
30+
yarn add @pythnetwork/pyth-starknet-js
31+
```
32+
</Tabs.Tab>
33+
</Tabs>
34+
35+
## Write Contract Code
36+
37+
The code snippet below provides an example module fetching the STRK/USD price from Pyth price feeds:
38+
39+
```rust {2,17,47,55,64,71-73} copy
40+
use starknet::ContractAddress;
41+
use pyth::ByteBuffer;
42+
43+
#[starknet::interface]
44+
pub trait IExampleContract<T> {
45+
// pyth_price_update is the price update data from Pyth to update the price feeds.
46+
// It should be passed as a ByteBuffer.
47+
fn example_method(
48+
ref self: T, pyth_price_update: ByteBuffer
49+
);
50+
}
51+
52+
#[starknet::contract]
53+
mod example_contract {
54+
use core::panic_with_felt252;
55+
use starknet::{ContractAddress, get_caller_address, get_contract_address};
56+
use pyth::{ByteBuffer, IPythDispatcher, IPythDispatcherTrait, UnwrapWithFelt252};
57+
use openzeppelin::token::erc20::interface::{IERC20CamelDispatcherTrait, IERC20CamelDispatcher};
58+
59+
const MAX_PRICE_AGE: u64 = 3600; // 1 hour
60+
// Storage to store the Pyth contract address, the ERC20 contract address representing ETH, and the ETH/USD price feed ID.
61+
#[storage]
62+
struct Storage {
63+
pyth_address: ContractAddress,
64+
strk_erc20_address: ContractAddress,
65+
}
66+
67+
// Constructor to initialize the contract storage.
68+
// * @param pyth_address: The address of the Pyth contract on Starknet.
69+
// * @param strk_erc20_address: The address of the ERC20 contract representing STRK on Starknet.
70+
#[constructor]
71+
fn constructor(
72+
ref self: ContractState,
73+
pyth_address: ContractAddress,
74+
strk_erc20_address: ContractAddress,
75+
) {
76+
self.pyth_address.write(pyth_address);
77+
self.strk_erc20_address.write(strk_erc20_address);
78+
}
79+
80+
#[abi(embed_v0)]
81+
impl ExampleContract of super::IExampleContract<ContractState> {
82+
fn example_method(
83+
ref self: ContractState,
84+
pyth_price_update: ByteBuffer
85+
) {
86+
let pyth = IPythDispatcher { contract_address: self.pyth_address.read() };
87+
let strk_erc20 = IERC20CamelDispatcher {
88+
contract_address: self.strk_erc20_address.read()
89+
};
90+
let caller = get_caller_address();
91+
let contract = get_contract_address();
92+
93+
// Get the fee required to update the Pyth price feeds.
94+
let pyth_fee = pyth.get_update_fee(pyth_price_update.clone(), strk_erc20.contract_address);
95+
if !strk_erc20.transferFrom(caller, contract, pyth_fee) {
96+
panic_with_felt252('insufficient allowance for fee');
97+
}
98+
if !strk_erc20.approve(pyth.contract_address, pyth_fee) {
99+
panic_with_felt252('approve failed');
100+
}
101+
102+
// Submit a pyth_price_update to the Pyth contract to update the on-chain price.
103+
pyth.update_price_feeds(pyth_price_update);
104+
105+
// Read the current price from a price feed.
106+
// STRK/USD price feed ID
107+
// The complete list of feed IDs is available at https://pyth.network/developers/price-feed-ids
108+
let strk_usd_price_id =
109+
0x6a182399ff70ccf3e06024898942028204125a819e519a335ffa4579e66cd870;
110+
let price = pyth
111+
.get_price_no_older_than(strk_usd_price_id, MAX_PRICE_AGE)
112+
.unwrap_with_felt252();
113+
let _: u64 = price.price.try_into().unwrap(); // Price in u64
114+
}
115+
}
116+
}
117+
```
118+
119+
The pyth_price_update argument contains verified prices from Pyth.
120+
Calling pyth.update_price_feeds with this value updates the on-chain Pyth price and ensures your application has recent price data.
121+
The pyth_price_update 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 pyth_price_update.
122+
123+
<Callout type="info" emoji="ℹ️">
124+
Unlike Ethereum, there is no native token on Starknet. You cannot pass tokens
125+
implicitly when calling functions. Moreover, there is no concept of a
126+
designated payer account, unlike Solana. In Starknet, all token transfers must
127+
be performed explicitly by calling functions on the token's ERC20 contract.
128+
Regarding the Pyth contract on Starknet, the caller must approve the fee
129+
transfer before calling `update_price_feeds` or using similar methods. You can
130+
use **STRK** or **ETH** to pay the fee, but STRK is preferred. The fee is
131+
currently set to the minimum possible value (1e-18 STRK, 1 WEI).
132+
</Callout>
133+
134+
The code snippet above does the following things:
135+
136+
1. Call `pyth.get_update_fee` to get the fee required to update the Pyth price feeds.
137+
1. Call `pyth.update_price_feeds` and pass `pyth_price_update` to update the Pyth price feeds.
138+
1. Call `pyth.get_price_no_older_than` to read the price, providing the [price feed ID](https://pyth.network/developers/price-feed-ids) you wish to read.
139+
140+
### Write Client Code
141+
142+
The code snippet below provides an example of how to fetch price updates and convert to `ByteBuffer` for Starknet using the `pyth-starknet-js` in JavaScript:
143+
144+
```ts {16} copy
145+
import { PriceServiceConnection } from "@pythnetwork/price-service-client";
146+
import { ByteBuffer } from "@pythnetwork/pyth-starknet-js";
147+
// The URL below is a public Hermes instance operated by the Pyth Data Association.
148+
// Hermes is also available from several third-party providers listed here:
149+
// https://docs.pyth.network/price-feeds/api-instances-and-providers/hermes
150+
const connection = new PriceServiceConnection("https://hermes.pyth.network", {
151+
priceFeedRequestConfig: {
152+
binary: true,
153+
},
154+
});
155+
156+
const priceId =
157+
"0x6a182399ff70ccf3e06024898942028204125a819e519a335ffa4579e66cd870"; // STRK/USD
158+
159+
// Get the latest values of the price feeds as json objects.
160+
const currentPrices = await connection.getLatestPriceFeeds([priceId]);
161+
162+
// Convert the price update to Starknet format.
163+
const pythUpdate = ByteBuffer.fromHex(currentPrices[0].vaa);
164+
```
165+
166+
<Callout type="info" emoji="ℹ️">
167+
Price updates must be converted to `ByteBuffer` before being passed on to the
168+
Pyth contract on Starknet. Use the `ByteBuffer` type from
169+
`@pythnetwork/pyth-starknet-js` package as shown above.
170+
</Callout>
171+
172+
## Additional Resources
173+
174+
You may find these additional resources helpful for developing your Starknet application.
175+
176+
### Interface
177+
178+
The [Starknet Interface](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/starknet/contracts/src/pyth/interface.cairo#L9) provides a list of functions that can be called on the Pyth contract deployed on Starknet.
179+
180+
### Example Applications
181+
182+
- [Send-USD](https://github.com/pyth-network/pyth-examples/tree/main/price_feeds/starknet), which updates and consumes STRK/USD price feeds on Starknet to send USD to a recipient.

0 commit comments

Comments
 (0)