Skip to content

Commit aa5c05e

Browse files
feat: enhance near pyth docs (#508)
* feat: enhance near pyth docs * fix: run precommit --------- Co-authored-by: Ali Behjati <bahjatia@gmail.com>
1 parent b31cf15 commit aa5c05e

File tree

1 file changed

+306
-79
lines changed
  • pages/price-feeds/use-real-time-data

1 file changed

+306
-79
lines changed

pages/price-feeds/use-real-time-data/near.mdx

Lines changed: 306 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -9,83 +9,315 @@ price feeds, handling the retrieval and updating of price data.
99
The two Key functions in the Pyth receiver contract to get started
1010
are 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

1524
These functions are core for interacting with Pyth price feeds in
1625
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+
---
89321

90322
## On-Chain Prices
91323

@@ -100,8 +332,3 @@ see the [update.sh][] example script in the repository to see how to
100332
pull 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

Comments
 (0)