@@ -9,83 +9,315 @@ price feeds, handling the retrieval and updating of price data.
99The two Key functions in the Pyth receiver contract to get started
1010are as follows:
1111
12- - ` update_price_feeds ` : Updates multiple price feeds if they are fresh.
13- - ` get_price ` : Retrieves the current price from a specific price feed.
12+ 1 . [ ` update_price_feeds ` ] ( #update_price_feeds )
13+ _ (updates Pyth smart contract with the price feed you provide)_
14+
15+ - args: ` data `
16+ - type: ` object `
17+ - example: ` { "data": "504e41...' } `
18+
19+ 2 . [ ` get_price ` ] ( #get_price ) (fetches the most recent price stored in the contract)\_
20+ - args: ` price_identifier `
21+ - type: ` object `
22+ - example: ` { price_identifier: 'f9c0172ba10dfa8...' } `
1423
1524These functions are core for interacting with Pyth price feeds in
1625NEAR-based applications, providing a reliable and up-to-date source of
17- price information. For a full overview of methods provided by the NEAR
18- contract, see [ the interface] [ ] exposed by the receiver contract.
19-
20- [ the interface ] : https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/near/receiver/src/ext.rs
21-
22- ## How to Update and Consume Price Feeds
23-
24- 1 . Install NEAR JavaScript SDK: First, add the NEAR JavaScript SDK to
25- your project. You can do this using npm or yarn:
26- ```
27- npm install near-api-js
28- ```
29- or
30- ```
31- yarn add near-api-js
32- ```
33- 2 . Interact with the NEAR contract. This can be done with the Contract
34- interface. Updating a price feed can be achieved using the NEAR JS
35- API. See the [ official docs] ( https://docs.near.org/tools/near-api-js/quick-reference )
36- for a guide on setting up a keystore correctly as this will depend
37- heavily on your app. The skeleton you can use to get started for
38- calling the Pyth contract looks like so:
39-
40- ``` js
41- // @data: A payload containing price feed update information fetched from Hermes.
42- async function updatePriceFeeds (data ) {
43- const near = await connect (config);
44- const result = await account .functionCall ({
45- " pyth.testnet" ,
46- methodName: " update_price_feeds" ,
47- args: { data },
48- gas: new utils.BN (" 30000000000000" ),
49- attachedDeposit: utils .format .parseNearAmount (" 1" ),
50- });
51- console .log (" Update Price Feeds Result: " , result);
52- }
53- ```
54-
55- You can find an update to submit with this call from the Hermes API
56- which for example [ can be found for testnet here.] ( https://hermes-beta.pyth.network/ )
57- To try this out, use the ` get_vaa ` endpoint to request a price feed
58- update for a price feed. You must convert the returned base64 blob to
59- hex before using it in the ` update_price_feeds ` call due to NEAR passing
60- bytes around with hex encoding.
61-
62- It's also possible to integrate this process into your contract itself
63- to reduce the number of transactions required. See the example contract
64- linked below.
65-
66- Note: gas and attachedDeposit are NEAR-specific parameters that you
67- may need to set depending on the contract's requirements. Unused
68- deposit will be refunded, but you can calculate an esimtate by calling
69- the ` get_update_fee_estimate ` method against the Pyth contract.
70-
71- Fetching a price feed is similar:
72-
73- ``` js
74- async function fetchPriceFeed () {
75- const near = await connect (config);
76- const account = await near .account ();
77- const contractId = " pyth-oracle.testnet" ;
78- const identifier = " PriceIdentifier" ;
79-
80- const priceFeed = await account .viewFunction (
81- contractId,
82- " get_price" ,
83- args: { identifier }
84- );
85-
86- console .log (" Price Feed Data: " , priceFeed);
87- }
88- ```
26+ price information.
27+
28+ For a full overview of methods provided by the NEAR
29+ contract, see [ the interface] ( https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/near/receiver/src/ext.rs )] exposed by the receiver contract.
30+
31+ ## Getting Started
32+
33+ To get started with Pyth oracle you will need to gather the following information which differ between networks:
34+
35+ - Price ID(s)
36+ - HermesAPI Endpoint
37+ - Smart contract address
38+
39+ | Network | Price Feed IDs | Hermes API Address | Contract Address |
40+ | --------- | ------------------------------------------------------------------------------------------------ | -------------------------- | -------------------------------------------------------------------------------- |
41+ | ` testnet ` | [ NEAR ` testnet ` Price Feed IDs] ( https://www.pyth.network/developers/price-feed-ids#near-testnet ) | ` hermes-beta.pyth.network ` | [ pyth-oracle.testnet] ( https://testnet.nearblocks.io/address/pyth-oracle.testnet ) |
42+ | ` mainnet ` | [ NEAR ` mainnet ` Price Feed IDs] ( https://www.pyth.network/developers/price-feed-ids#near-mainnet ) | ` hermes.pyth.network ` | [ pyth-oracle.near] ( https://nearblocks.io/address/pyth-oracle.near ) |
43+
44+ Note: When using Price Feed IDs, you will need to remove the ` 0x ` prefix.
45+
46+ ---
47+
48+ ### ` update_price_feeds `
49+
50+ > Updates the Pyth Oracle contract data with the price feed you provide.
51+
52+ - args: ` data ` _ (off-chain hex-encoded price feed)_
53+ - type: ` object `
54+ - example: ` { "data": "504e41...' } `
55+
56+ Update the Pyth Oracle contract with new price feed data in two main steps:
57+
58+ 1 . [ Fetch off-chain price feed] ( #1-fetch-off-chain-price-feed )
59+ 2 . [ Update Pyth Oracle contract with off-chain price feed] ( #2-update-pyth-oracle-contract-price-feed )
60+
61+ #### 1) Fetch off-chain price feed
62+
63+ You can obtain an off-chain price feed using Pyth's [ Hermes API] ( https://hermes-beta.pyth.network/docs/ ) .
64+
65+ To use these endpoints, you will need to provide a Price Feed ID and ensure you are targeting the correct network. See [ Getting Started] ( #getting-started ) for more information.
66+
67+ Here is a node.js example of fetching the latest price feed using ` /v2/updates/price/latest ` endpoint:
68+
69+ ` Example: `
70+
71+ ``` js
72+ const axios = require (" axios" );
73+
74+ // There are separate endpoints for testnet and mainnet
75+ const HERMES_TESTNET_URL = " https://hermes-beta.pyth.network" ;
76+ const HERMES_MAINNET_URL = " https://hermes.pyth.network" ;
77+
78+ async function getHermesPriceData (priceId , network ) {
79+ try {
80+ let url;
81+ network === " testnet"
82+ ? (url = HERMES_TESTNET_URL )
83+ : (url = HERMES_MAINNET_URL );
84+
85+ // Fetch the price data from the Hermes API
86+ const response = await axios .get (
87+ ` ${ url} /v2/updates/price/latest?ids[]=${ priceId} `
88+ );
89+
90+ return response .data .binary .data [0 ];
91+ } catch (error) {
92+ console .error (
93+ " Error:" ,
94+ error .response ? error .response .data : error .message
95+ );
96+ }
97+ }
98+
99+ module .exports = { getHermesPriceData };
100+ ```
101+
102+ <center >
103+ z [ See full example on
104+ GitHub] ( https://github.com/near-examples/near-js/blob/main/node-js/utils/fetch-hermes-price-data.js )
105+ </center >
106+
107+ ---
108+
109+ ### 2) Update Pyth Oracle Contract Price Feed
110+
111+ After [ fetching an off-chain price feed] ( #1-fetch-off-chain-price-feed ) , you can now perform a contract call to the Pyth Oracle contract to update.
112+ Call ` update_price_feeds ` on the Pyth Oracle contract deployed on NEAR with ` data ` as your arguments.
113+
114+ ` example args: `
115+
116+ ``` json
117+ {
118+ "data": "504e41550100000000a00100000000010070b0ee3a00d1a3c07ee440887eb34a5a35860e6f4b9230fd62f0593fe35c8a3561735a6a37d269c5f166b84ead8918f710dc1be2ee6b51db5b22340ea2c173fc01673d544b00000000001ae101faedac5851e32b9b23b5f9411a8c2bac4aae3ed4dd7b811dd1a72ea4aa7100000000061bc18c014155575600000000000ab0f04600002710f41bc8c224ed983c68dbf5dab7dd34c9129fecfa03005500ca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a600000047e2eb4ef0000000000692480ffffffff800000000673d544b00000000673d544b00000048200e66a00000000005e495a60bb9370c458dd50558b34699b5b179f45e56be22f0a1a0feb1db8469adc8c5efeb53988495bac07bf9efed07f5eee43818150c55055882f6872a228e8e9bc78459ed3ea7fe0b86f3048f6bf0aad34befc46063ab7d200beb8bc9fe5839844d2233546f0742bb665f1e610370fcf8ce5be83d0f47e584b685af87cf3ebcb79e714827dcb99dba579e1a03785052ab3c7c7147d3f7bba822b04dbda159670e9a8d29e7ccf68474b2ca85e00224d29bf65b06b09f95e91703313e053b697b48ac1e4d1c57605a71ab77e7ef276bfe8a369c268333b9a37461bf2b7cb7fd4c005500ecf553770d9b10965f8fb64771e93f5690a182edc32be4a3236e0caaa6e0581a0000000e2ba8cd280000000001b40517fffffff800000000673d544b00000000673d544b0000000e3ea44c6800000000016aee120b47b853f55949284cb8ba0b63824ff9b48cd1da8417f45421b79ee3195fc8d107540a0bbb95c2445b66065754f135cb842db09a7e7ab33f79c546a48db872bd7197b04e3d7b52fbb55b3b9f51707c5a55fac3707cb563dbcde4aadeecc3649c237454cecf519dc567c0da03d81808523aa4fa71815eab25ce7da61b48647bac645d403208135002aab5fde2d7ab3c7c7147d3f7bba822b04dbda159670e9a8d29e7ccf68474b2ca85e00224d29bf65b06b09f95e91703313e053b697b48ac1e4d1c57605a71ab77e7ef276bfe8a369c268333b9a37461bf2b7cb7fd4c"
119+ }
120+ ```
121+
122+ To perform this contract call you must first create a NEAR account which can be done using ` near-cli ` .
123+
124+ Fist, install ` near-cli ` :
125+
126+ ``` bash
127+
128+ npm install -g near-cli-rs@latest
129+
130+ ```
131+
132+ This CLI allows you to simply run ` near ` and let the prompts guide you through the process.
133+
134+ To quickly create a NEAR account, run the following command (replacing ` your-new-account.testnet ` with your desired account name):
135+
136+ ``` bash
137+ near account \
138+ create-account sponsor-by-faucet-service \
139+ your-new-account.testnet \
140+ autogenerate-new-keypair save-to-legacy-keychain \
141+ network-config testnet \
142+ create
143+ ```
144+
145+ To perform a contract call to the Pyth Oracle contract, run the following command:
146+
147+ Replace:
148+
149+ - ` your-account.testnet ` with your account name
150+ - ` '{"data": "504e41550100..."}' ` with your off-chain price feed
151+
152+ ```
153+ near contract \
154+ call-function \
155+ as-transaction pyth-oracle.testnet update_price_feeds \
156+ json-args '{"data": "504e41550100..."}' \
157+ prepaid-gas '300.0 Tgas' \
158+ attached-deposit '0.01 NEAR' \
159+ sign-as your-account.testnet \
160+ network-config testnet \
161+ sign-with-legacy-keychain \
162+ send
163+ ```
164+
165+ Alternatively, you can use ` near-js ` libraries to perform the contract call. For this example we will create a simple node.js project.
166+
167+ First, install the ` near-js ` libraries we will use:
168+
169+ ``` bash
170+ npm install @near-js/client @near-js/keystores-node
171+ ```
172+
173+ To setup a NEAR connection, we'll create a ` connect.js ` file that will initialize an RPC provider and signer. This will look for your NEAR credentials in your ` .near-credentials ` directory.
174+
175+ ``` js
176+ // node.js imports
177+ const { join } = require (" node:path" );
178+ const { homedir } = require (" node:os" );
179+
180+ // near-js imports
181+ const {
182+ getTestnetRpcProvider ,
183+ getSignerFromKeystore ,
184+ } = require (" @near-js/client" );
185+ const { UnencryptedFileSystemKeyStore } = require (" @near-js/keystores-node" );
186+
187+ // initialize RPC provider and signer
188+ const nearConnect = (sender , network ) => ({
189+ rpcProvider: getTestnetRpcProvider (),
190+ signer: getSignerFromKeystore (
191+ sender,
192+ network,
193+ new UnencryptedFileSystemKeyStore (join (homedir (), " .near-credentials" ))
194+ ),
195+ });
196+
197+ module .exports = { nearConnect };
198+ ```
199+
200+ Next we can create a ` update-oracle.js ` file that will perform the contract call to update the Pyth Oracle contract's price feed.
201+
202+ ``` js
203+ // near-js imports
204+ // https://www.npmjs.com/package/@near-js/client
205+ const { nearConnect } = require (" ../utils/connect" );
206+ const { functionCall } = require (" @near-js/client" );
207+
208+ const sender = " your-account.testnet" ;
209+ const receiver = " pyth-oracle.testnet" ;
210+ const network = " testnet" ;
211+
212+ const PRICE_IDS = [
213+ // Price ids can be found at https://www.pyth.network/developers/price-feed-ids#near-testnet
214+ // NOTE: Ensure you are using NEAR specific price ids & remove the '0x' prefix before using them
215+ " f9c0172ba10dfa4d19088d94f5bf61d3b54d5bd7483a322a982e1373ee8ea31b" , // BTC/USD price id
216+ " ca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a6" , // ETH/USD price id
217+ ];
218+
219+ async function updatePythContractPriceFeeds (network ) {
220+ // Connect to the NEAR network
221+ const { rpcProvider , signer } = nearConnect (sender, network);
222+
223+ // Update the Pyth Oracle contract with the price data
224+ // Performs a NEAR function call to the Pyth Oracle contract
225+ // Deposit for transaction fee (balance will be refunded)
226+ const result = await functionCall ({
227+ sender,
228+ receiver,
229+ method: " update_price_feeds" ,
230+ args: { data: " 504e4155010..." },
231+ deposit: 10000000000000000000000 ,
232+ deps: { rpcProvider, signer },
233+ });
234+
235+ console .log (
236+ ` Transaction 👉 https://testnet.nearblocks.io/txns/${ result .outcome .transaction .hash } `
237+ );
238+ return result;
239+ }
240+
241+ updatePythOracle ();
242+ ```
243+
244+ <center >
245+ [ See full example on
246+ GitHub] ( https://github.com/near-examples/near-js/blob/main/node-js/oracle-example/pyth-oracle-update.js )
247+ </center >
248+
249+ Although unused deposit will be refunded, you can calculate an estimate by calling the ` get_update_fee_estimate ` method against the Pyth contract.
250+
251+ ---
252+
253+ ### ` get_price `
254+
255+ > Fetches the most recent price feed stored in the Pyth Oracle contract. Is a view method, so does not require a signature or payment.
256+
257+ - args: ` price_identifier ` _ (unique [ price feed identifier] ( #environment-variables ) )_
258+ - type: ` object `
259+ - example: ` { price_identifier: 'f9c0172ba10dfa8...' } `
260+
261+ After [ updating the price feed] ( #update_price_feeds ) , you can view the feed on-chain by calling ` get_price ` on the Pyth Oracle contract. Note that this is a view method and does not require a signature or deposit.
262+
263+ #### NEAR CLI example
264+
265+ ``` bash
266+ near contract \
267+ call-function \
268+ as-read-only pyth-oracle.testnet get_price \
269+ json-args ' {"price_identifier": "f9c0172ba10dfa4d19088d94f5bf61d3b54d5bd7483a322a982e1373ee8ea31b"}' \
270+ network-config testnet \
271+ now
272+
273+ ```
274+
275+ #### NEAR-JS Example
276+
277+ For this example we will create a simple node.js project. First, install the [ ` near-js\client ` ] ( https://www.npmjs.com/package/@near-js/client ) library:
278+
279+ ``` bash
280+ npm install @near-js/client
281+ ```
282+
283+ Create a ` get-price.js ` file that will perform the view call from the Pyth Oracle contract. Note that this does not require a signature or deposit.
284+
285+ ``` js
286+ // near-js import
287+ // https://www.npmjs.com/package/@near-js/client
288+ const { getTestnetRpcProvider , view } = require (" @near-js/client" );
289+
290+ const PRICE_IDS = [
291+ // Price ids can be found at https://www.pyth.network/developers/price-feed-ids#near-testnet
292+ // NOTE: Ensure you are using NEAR specific price ids & remove the '0x' prefix before using them
293+ " f9c0172ba10dfa4d19088d94f5bf61d3b54d5bd7483a322a982e1373ee8ea31b" , // BTC/USD price id
294+ " ca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a6" , // ETH/USD price id
295+ ];
296+
297+ async function getPrice (price_ID , symbol ) {
298+ try {
299+ const rpcProvider = getTestnetRpcProvider ();
300+ const result = await view ({
301+ account: " pyth-oracle.testnet" ,
302+ method: " get_price" ,
303+ args: { price_identifier: price_ID },
304+ deps: { rpcProvider },
305+ });
306+ console .log (symbol, result);
307+ } catch (error) {
308+ console .error (` Error fetching ${ symbol} price:` , error .message );
309+ }
310+ }
311+
312+ getPrice (PRICE_IDS [0 ], " BTC/USD:" );
313+ ```
314+
315+ <center >
316+ [ See full example on
317+ GitHub] ( https://github.com/near-examples/near-js/blob/main/node-js/oracle-example/pyth-oracle-view.js )
318+ </center >
319+
320+ ---
89321
90322## On-Chain Prices
91323
@@ -100,8 +332,3 @@ see the [update.sh][] example script in the repository to see how to
100332pull prices with the official NEAR cli.
101333
102334[ update.sh ] : https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/near/scripts/update.sh
103-
104- ## Contract Addresses
105-
106- Developers will need the address of the Pyth price feed contract on their blockchain in order to use Pyth.
107- Please consult [ Near Contract Addresses] ( ../contract-addresses/near ) to find the address for your blockchain.
0 commit comments