Skip to content
This repository was archived by the owner on Apr 3, 2023. It is now read-only.

Commit 7e56030

Browse files
ali-behjatiJayant Krishnamurthy
andauthored
Add Price Pusher Readme (#30)
* Add Price Pusher Readme * Address review comments * doc updates Co-authored-by: Jayant Krishnamurthy <[email protected]>
1 parent 4a86c5a commit 7e56030

File tree

2 files changed

+107
-18
lines changed

2 files changed

+107
-18
lines changed

pyth-evm-price-pusher/README.md

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,85 @@
1-
# Pyth price pusher on EVM networks
1+
# Pyth EVM price pusher
2+
3+
Pyth EVM price pusher is a service that regularly pushes updates to the on-chain Pyth price based on configurable conditions.
4+
5+
## Background
6+
7+
Pyth is a cross-chain oracle that streams price updates over the peer-to-peer [Wormhole Network](https://wormholenetwork.com/).
8+
These price updates can be consumed on any chain that has a deployment of the Pyth contract.
9+
By default, Pyth does not automatically update the on-chain price every time the off-chain price changes;
10+
instead, anyone can permissionlessly update the on-chain price prior to using it.
11+
For more information please refer to [this document](../pyth-evm-js/README.md#how-pyth-works-on-evm-chains).
12+
13+
Protocols integrating with can update the on-chain Pyth prices in two different ways.
14+
The first approach is on-demand updates: package a Pyth price update together with each transaction that depends on it.
15+
On-demand updates minimize latency and are more gas efficient, as prices are only updated on-chain when they are needed.
16+
17+
The second approach is to run this service to regularly push updates to the on-chain price.
18+
This approach is useful for protocols that already depend on regular push updates.
19+
20+
## Running Price Pusher
21+
22+
The price pusher service monitors both the off-chain and on-chain Pyth price for a configured set of price feeds.
23+
It then pushes a price update to an on-chain Pyth contract if any of the following conditions are met:
24+
25+
- Time difference: The on-chain price is older than `time-difference` seconds
26+
from the latest Pyth price.
27+
- Price deviation: The latest Pyth price feed has changed more than `price-deviation` percent
28+
from the on-chain price feed price.
29+
- Confidence ratio: The latest Pyth price feed has confidence to price ratio of more than
30+
`confidence-ratio`.
31+
32+
To run the price pusher, please run the following commands, replacing the command line arguments as necessary:
33+
34+
```sh
35+
npm install # Only run it the first time
36+
37+
npm run start -- --evm-endpoint wss://example-rpc.com --mnemonic-file "path/to/mnemonic.txt" \
38+
--pyth-contract example_network --price-endpoint https://example-pyth-price.com \
39+
--time-difference 60 --price-deviation 0.5 --confidence-ratio 5 \
40+
--price-ids "abcd..." "efgh..." "..." \
41+
[--cooldown-duration 10] \
42+
[--evm-polling-frequency 5]
43+
```
44+
45+
### Command Line Arguments
46+
47+
The program accepts the following command line arguments:
48+
49+
- `evm-endpoint`: RPC endpoint URL for the EVM network. If you provide a websocket RPC endpoint (`ws[s]://...`),
50+
the price pusher will use event subscriptions to read the current EVM price. If you provide a normal
51+
HTTP endpoint, the pusher will periodically poll for updates. The polling interval is configurable via
52+
the `evm-polling-frequency` command-line argument (described below).
53+
- `mnemonic-file`: Payer mnemonic (private key) file.
54+
- `pyth-contract`: The Pyth contract address. Provide the network name on which Pyth is deployed
55+
or the Pyth contract address if you use a local network.
56+
You can find the networks on which pyth is live and their corresponding names
57+
[here](../pyth-evm-js/src/index.ts#L13). An example is `bnb_testnet`.
58+
- `price-endpoint`: Endpoint URL for the price service. You can use
59+
`https://prices.testnet.pyth.network` for testnet and
60+
`https://prices.mainnet.pyth.network` for mainnet. It is recommended
61+
to run a standalone price service for more resiliency.
62+
- `price-ids`: Space separated price feed ids (in hex) to push. List of available
63+
price feeds is available in the [price feed ids page][].
64+
- `time-difference`: Time difference threshold (in seconds) to push a newer price feed.
65+
- `price-deviation`: The price deviation (%) threshold to push a newer price feed.
66+
- `confidence-ratio`: The confidence/price (%) threshold to push a newer price feed.
67+
- `cooldown-duration` (Optional): The amount of time (in seconds) to wait between pushing
68+
price updates. It should be greater than the block time of the network, so this
69+
program confirms the price is updated and does not push it twice. Default: 10 seconds.
70+
- `evm-polling-frequency` (Optional): The frequency to poll price info data from the EVM network
71+
if the RPC is not a Websocket. It has no effect if the RPC is a Websocket.
72+
Default: 5 seconds.
73+
74+
[price feed ids page]: https://pyth.network/developers/price-feed-ids/#pyth-cross-chain-testnet
75+
76+
### Example
77+
78+
For example, to push `BTC/USD` and `BNB/USD` prices on BNB testnet, run the following command:
79+
80+
```sh
81+
npm run start -- --evm-endpoint "https://data-seed-prebsc-1-s1.binance.org:8545" --mnemonic-file "path/to/mnemonic.txt" \
82+
--pyth-contract bnb_testnet --price-endpoint https://prices.testnet.pyth.network \
83+
--price-ids "f9c0172ba10dfa4d19088d94f5bf61d3b54d5bd7483a322a982e1373ee8ea31b" "ecf553770d9b10965f8fb64771e93f5690a182edc32be4a3236e0caaa6e0581a" \
84+
--time-difference 60 --price-deviation 0.5 --confidence-ratio 1
85+
```

pyth-evm-price-pusher/src/index.ts

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,68 +13,73 @@ import { PythPriceListener } from "./pyth-price-listener";
1313
import * as fs from "fs";
1414

1515
const argv = yargs(hideBin(process.argv))
16-
.option("network", {
16+
.option("evm-endpoint", {
1717
description:
18-
"RPC of the target EVM network. Use ws[s]:// if you intent to use subscription " +
19-
"instead of polling.",
18+
"RPC endpoint URL for the EVM network. If you provide a websocket RPC endpoint (`ws[s]://...`), " +
19+
"the price pusher will use event subscriptions to read the current EVM price. If you provide " +
20+
"a normal HTTP endpoint, the pusher will periodically poll for updates. The polling interval " +
21+
"is configurable via the `evm-polling-frequency` command-line argument",
2022
type: "string",
2123
required: true,
2224
})
23-
.option("endpoint", {
25+
.option("price-endpoint", {
2426
description:
2527
"Endpoint URL for the price service. e.g: https://endpoint/example",
2628
type: "string",
2729
required: true,
2830
})
2931
.option("pyth-contract", {
3032
description:
31-
"Pyth contract address. Provide the network name which Pyth is deployed on, " +
32-
"or the Pyth contract address if you are using a local network",
33+
"Pyth contract address. Provide the network name on which Pyth is deployed " +
34+
"or the Pyth contract address if you use a local network.",
3335
type: "string",
3436
required: true,
3537
})
3638
.option("price-ids", {
3739
description:
38-
"Space separated price feed ids (in hex) to fetch" +
40+
"Space separated price feed ids (in hex) to push." +
3941
" e.g: 0xf9c0172ba10dfa4d19088d...",
4042
type: "array",
4143
required: true,
4244
})
4345
.option("mnemonic-file", {
44-
description: "Payer mnemonic (private key) file",
46+
description: "Payer mnemonic (private key) file.",
4547
type: "string",
4648
required: true,
4749
})
4850
.option("time-difference", {
49-
description: "Time difference (in seconds) to push a price feed",
51+
description:
52+
"Time difference threshold (in seconds) to push a newer price feed.",
5053
type: "number",
5154
required: true,
5255
})
5356
.option("price-deviation", {
54-
description: "Price deviation percent to push a price feed",
57+
description:
58+
"The price deviation (%) threshold to push a newer price feed.",
5559
type: "number",
5660
required: true,
5761
})
5862
.option("confidence-ratio", {
59-
description: "The confidence/price percent to push a price feed",
63+
description:
64+
"The confidence/price (%) threshold to push a newer price feed.",
6065
type: "number",
6166
required: true,
6267
})
6368
.option("cooldown-duration", {
6469
description:
6570
"The amount of time (in seconds) to wait between pushing price updates. " +
66-
"Should be greater than the block time of the network so one update is not " +
67-
"pushed twice.",
71+
"This value should be greater than the block time of the network, so this program confirms " +
72+
"it is updated and does not push it twice.",
6873
type: "number",
6974
required: false,
7075
default: 10,
7176
})
7277
.option("evm-polling-frequency", {
7378
description:
74-
"The frequency to poll price info data from the evm network if the RPC is not a websocket.",
79+
"The frequency to poll price info data from the EVM network if the RPC is not a websocket.",
7580
type: "number",
7681
required: false,
77-
default: 10,
82+
default: 5,
7883
})
7984
.help()
8085
.alias("help", "h")
@@ -83,7 +88,7 @@ const argv = yargs(hideBin(process.argv))
8388
})
8489
.parseSync();
8590

86-
const network = argv.network;
91+
const network = argv.evmEndpoint;
8792
let pythContractAddr: string;
8893

8994
if (CONTRACT_ADDR[argv.pythContract] !== undefined) {
@@ -93,7 +98,7 @@ if (CONTRACT_ADDR[argv.pythContract] !== undefined) {
9398
}
9499

95100
async function run() {
96-
const connection = new EvmPriceServiceConnection(argv.endpoint);
101+
const connection = new EvmPriceServiceConnection(argv.priceEndpoint);
97102

98103
const priceIds = (argv.priceIds as string[]).map(removeLeading0x);
99104

0 commit comments

Comments
 (0)