@@ -9,83 +9,315 @@ price feeds, handling the retrieval and updating of price data.
9
9
The two Key functions in the Pyth receiver contract to get started
10
10
are as follows:
11
11
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...' } `
14
23
15
24
These functions are core for interacting with Pyth price feeds in
16
25
NEAR-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
+ ---
89
321
90
322
## On-Chain Prices
91
323
@@ -100,8 +332,3 @@ see the [update.sh][] example script in the repository to see how to
100
332
pull prices with the official NEAR cli.
101
333
102
334
[ 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