Skip to content

Commit f5620ec

Browse files
author
Dev Kalra
authored
[price-pusher] refactor (#648)
* add a dev command for ease * implement a new command structure * remove comments * move files * add config * update readme * testnet compose files update * update mainnet compose file
1 parent deb8046 commit f5620ec

12 files changed

+326
-255
lines changed

price_pusher/README.md

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -48,71 +48,73 @@ To run the price pusher, please run the following commands, replacing the comman
4848
```sh
4949
npm install # Only run it the first time
5050

51-
npm run start -- --evm-endpoint wss://example-rpc.com --mnemonic-file "path/to/mnemonic.txt" \
52-
--pyth-contract example_network --price-endpoint https://example-pyth-price.com \
53-
--price-config-file "path/to/price-config-file.yaml" \
51+
# For EVM
52+
npm run start -- evm --endpoint wss://example-rpc.com \
53+
--pyth-contract-address 0xff1a0f4744e8582DF...... \
54+
--price-service-endpoint https://example-pyth-price.com \
55+
--price-config-file "path/to/price-config-file.yaml.testnet.sample.yaml" \
56+
--mnemonic-file "path/to/mnemonic.txt" \
5457
[--cooldown-duration 10] \
55-
[--evm-polling-frequency 5]
58+
[--polling-frequency 5]
59+
60+
# For Injective
61+
npm run start -- injective --grpc-endpoint https://grpc-endpoint.com \
62+
--pyth-contract-address inj1z60tg0... --price-service-endpoint "https://example-pyth-price.com" \
63+
--price-config-file "path/to/price-config-file.yaml.testnet.sample.yaml" \
64+
--mnemonic-file "path/to/mnemonic.txt" \
65+
[--cooldown-duration 10] \
66+
[--polling-frequency 5]
5667

5768
# Or, run the price pusher docker image instead of building from the source
5869
docker run public.ecr.aws/pyth-network/xc-evm-price-pusher:v<version> -- <above-arguments>
5970
```
6071

6172
### Command Line Arguments
6273

63-
The program accepts the following command line arguments:
64-
65-
- `evm-endpoint`: RPC endpoint URL for the EVM network. If you provide a normal HTTP endpoint,
66-
the pusher will periodically poll for updates. The polling interval is configurable via the
67-
`evm-polling-frequency` command-line argument (described below). If you provide a websocket RPC endpoint
68-
(`ws[s]://...`), the price pusher will use event subscriptions to read the current EVM
69-
price in addition to polling.
70-
- `mnemonic-file`: Path to payer mnemonic (private key) file.
71-
- `pyth-contract`: The Pyth contract address. Provide the network name on which Pyth is deployed
72-
or the Pyth contract address if you use a local network.
73-
You can find the networks on which pyth is live and their corresponding names
74-
[here](../pyth-evm-js/src/index.ts#L13). An example is `bnb_testnet`.
75-
- `price-endpoint`: Endpoint URL for the price service. You can use
76-
`https://xc-testnet.pyth.network` for testnet and
77-
`https://xc-mainnet.pyth.network` for mainnet. It is recommended
78-
to run a standalone price service for more resiliency.
79-
- `price-config-file`: Path to price configuration YAML file.
80-
- `cooldown-duration` (Optional): The amount of time (in seconds) to wait between pushing
81-
price updates. It should be greater than the block time of the network, so this
82-
program confirms the price is updated and does not push it twice. Default: 10 seconds.
83-
- `evm-polling-frequency` (Optional): The frequency to poll price info data from the EVM network
84-
if the RPC is not a Websocket. It has no effect if the RPC is a Websocket.
85-
Default: 5 seconds.
74+
To know more about the arguments the price-pusher accepts. You can run:
75+
76+
```sh
77+
npm run start -- --help
78+
79+
# for specific network run
80+
npm run start -- {network} --help
81+
```
8682

8783
### Example
8884

8985
For example, to push `BTC/USD` and `BNB/USD` prices on BNB testnet, run the following command:
9086

9187
```sh
92-
npm run start -- --evm-endpoint "https://data-seed-prebsc-1-s1.binance.org:8545" --mnemonic-file "path/to/mnemonic.txt" \
93-
--pyth-contract bnb_testnet --price-endpoint https://xc-testnet.pyth.network \
94-
--price-config-file "price-config.testnet.sample.yaml"
88+
npm run dev -- evm --endpoint https://endpoints.omniatech.io/v1/fantom/testnet/public \
89+
--pyth-contract-address 0xd7308b14BF4008e7C7196eC35610B1427C5702EA --price-service-endpoint https://xc-testnet.pyth.network \
90+
--mnemonic-file "./mnemonic" --price-config-file "./price-config.testnet.sample.yaml"
9591
```
9692

9793
[`price-config.testnet.sample.yaml`](./price-config.testnet.sample.yaml) contains configuration for `BTC/USD`
9894
and `BNB/USD` price feeds on Pyth testnet. [`price-config.mainnet.sample.yaml`](./price-config.mainnet.sample.yaml)
9995
contains the same configuration for `BTC/USD` and `BNB/USD` on Pyth mainnet.
10096

97+
You can also provide a config file instead of providing command line options, run the following command:
98+
99+
```sh
100+
npm run start -- injective --config "./config.injective.sample.json"
101+
```
102+
103+
[`config.injective.sample.json`](./config.injective.sample.json) contains configuration to publish on Injective testnet.
104+
101105
## Running using a standalone price service (via docker-compose)
102106

103-
EVM price pusher communicates with [Pyth price service][] to get the most recent price updates. Pyth price service listens to the
107+
Price pusher communicates with [Pyth price service][] to get the most recent price updates. Pyth price service listens to the
104108
Wormhole network to get latest price updates, and serves REST and websocket APIs for consumers to fetch the updates.
105109
Pyth hosts public endpoints for the price service; however, it is recommended to run it standalone to achieve more resiliency and
106110
scalability.
107111

108112
This directory contains sample docker compose files ([testnet](./docker-compose.testnet.sample.yaml),
109-
[mainnet](./docker-compose.mainnet.sample.yaml)) an EVM price pusher and its dependencies, including a
113+
[mainnet](./docker-compose.mainnet.sample.yaml)) a price pusher and its dependencies, including a
110114
price service and a Wormhole spy. A price service depends on a Wormhole spy. A spy listens to the Wormhole
111115
network and reports all Pyth-related Wormhole messages to the price service.
112116

113-
To run the services via docker-compose, please modify the your target network (testnet, mainnet) sample docker-compose file to adjust
114-
the path to your mnemonic file, the path to your price configuration file, the EVM endpoint, and the Pyth contract address
115-
as necessary.
117+
To run the services via docker-compose, please modify the your target network (testnet, mainnet) sample docker-compose file to adjust the configurations.
116118

117119
Then, start the docker-compose like this:
118120

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"grpc-endpoint": "https://k8s.testnet.chain.grpc-web.injective.network",
3+
"pyth-contract-address": "inj1z60tg0tekdzcasenhuuwq3htjcd5slmgf7gpez",
4+
"price-service-endpoint": "https://xc-testnet.pyth.network",
5+
"mnemonic-file": "./mnemonic",
6+
"price-config-file": "./price-config.testnet.sample.yaml"
7+
}

price_pusher/docker-compose.mainnet.sample.yaml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,14 @@ services:
5858
restart: always
5959
command:
6060
- "--"
61-
- "--evm-endpoint"
61+
- "--endpoint"
6262
# Replace this with RPC endpoint URL for the EVM network.
6363
- "https://bsc-dataseed2.binance.org"
6464
- "--mnemonic-file"
6565
- "/mnemonic"
66-
- "--pyth-contract"
67-
# Replace this with the Pyth contract address. Provide the network name on which Pyth is deployed
68-
# or the Pyth contract address if you use a local network
69-
- "bnb"
70-
- "--price-endpoint"
66+
- "--pyth-contract-address"
67+
- "0xd7308b14BF4008e7C7196eC35610B1427C5702EA"
68+
- "--price-service-endpoint"
7169
- "http://price-service:4200"
7270
- "--price-config-file"
7371
- "/price_config"

price_pusher/docker-compose.testnet.sample.yaml

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -58,27 +58,16 @@ services:
5858
restart: always
5959
command:
6060
- "--"
61-
- "--evm-endpoint"
62-
# Replace this with RPC endpoint URL for the EVM network.
63-
- "https://data-seed-prebsc-1-s1.binance.org:8545"
64-
- "--mnemonic-file"
65-
- "/mnemonic"
66-
- "--pyth-contract"
67-
# Replace this with the Pyth contract address. Provide the network name on which Pyth is deployed
68-
# or the Pyth contract address if you use a local network
69-
- "bnb_testnet"
70-
- "--price-endpoint"
71-
- "http://price-service:4200"
72-
- "--price-config-file"
73-
- "/price_config"
61+
- "injective"
62+
# you can choose to provide all the options here or a path to the config file
63+
# we are providing a path to the config file
64+
- "--config"
65+
- "/command_config"
7466
configs:
75-
- mnemonic
76-
- price_config
67+
- command_config
7768
depends_on:
7869
price-service:
7970
condition: service_healthy
8071
configs:
81-
mnemonic:
82-
file: ./path/to/mnemonic.txt # Replace this with the path to the mnemonic file
83-
price_config:
84-
file: ./price-config.testnet.sample.yaml # Replace this with the path to the price configuration file
72+
command_config:
73+
file: ./config.injective.sample.json # Replace this with the path to the configuration file

price_pusher/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"format": "prettier --write \"src/**/*.ts\"",
2323
"lint": "eslint src/",
2424
"start": "node lib/index.js",
25+
"dev": "ts-node src/index.ts",
2526
"prepublishOnly": "npm run build && npm test && npm run lint",
2627
"preversion": "npm run lint",
2728
"version": "npm run format && git add -A src"

price_pusher/src/evm/command.ts

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import { PriceServiceConnection } from "@pythnetwork/pyth-common-js";
2+
import * as options from "../options";
3+
import { readPriceConfigFile } from "../price-config";
4+
import fs from "fs";
5+
import { PythPriceListener } from "../pyth-price-listener";
6+
import { Controller } from "../controller";
7+
import { Options } from "yargs";
8+
import { EvmPriceListener, EvmPricePusher, PythContractFactory } from "./evm";
9+
import { getCustomGasStation } from "./custom-gas-station";
10+
11+
export default {
12+
command: "evm",
13+
describe: "run price pusher for evm",
14+
builder: {
15+
endpoint: {
16+
description:
17+
"RPC endpoint URL for evm network. If you provide a normal HTTP endpoint, the pusher " +
18+
"will periodically poll for updates. The polling interval is configurable via the " +
19+
"`polling-frequency` command-line argument. If you provide a websocket RPC " +
20+
"endpoint (`ws[s]://...`), the price pusher will use event subscriptions to read " +
21+
"the current EVM price in addition to polling. ",
22+
type: "string",
23+
required: true,
24+
} as Options,
25+
"custom-gas-station": {
26+
description:
27+
"If using a custom gas station, chainId of custom gas station to use",
28+
type: "number",
29+
required: false,
30+
} as Options,
31+
"tx-speed": {
32+
description:
33+
"txSpeed for custom gas station. choose between 'slow'|'standard'|'fast'",
34+
choices: ["slow", "standard", "fast"],
35+
required: false,
36+
} as Options,
37+
...options.priceConfigFile,
38+
...options.priceServiceEndpoint,
39+
...options.mnemonicFile,
40+
...options.pythContractAddress,
41+
...options.pollingFrequency,
42+
...options.cooldownDuration,
43+
},
44+
handler: function (argv: any) {
45+
// FIXME: type checks for this
46+
const {
47+
endpoint,
48+
priceConfigFile,
49+
priceServiceEndpoint,
50+
mnemonicFile,
51+
pythContractAddress,
52+
cooldownDuration,
53+
pollingFrequency,
54+
customGasStation,
55+
txSpeed,
56+
} = argv;
57+
58+
const priceConfigs = readPriceConfigFile(priceConfigFile);
59+
const priceServiceConnection = new PriceServiceConnection(
60+
priceServiceEndpoint,
61+
{
62+
logger: console,
63+
}
64+
);
65+
const mnemonic = fs.readFileSync(mnemonicFile, "utf-8").trim();
66+
67+
const priceItems = priceConfigs.map(({ id, alias }) => ({ id, alias }));
68+
69+
const pythListener = new PythPriceListener(
70+
priceServiceConnection,
71+
priceConfigs
72+
);
73+
74+
const pythContractFactory = new PythContractFactory(
75+
endpoint,
76+
mnemonic,
77+
pythContractAddress
78+
);
79+
80+
const evmListener = new EvmPriceListener(pythContractFactory, priceItems, {
81+
pollingFrequency,
82+
});
83+
84+
const gasStation = getCustomGasStation(customGasStation, txSpeed);
85+
const evmPusher = new EvmPricePusher(
86+
priceServiceConnection,
87+
pythContractFactory.createPythContractWithPayer(),
88+
gasStation
89+
);
90+
91+
const controller = new Controller(
92+
priceConfigs,
93+
pythListener,
94+
evmListener,
95+
evmPusher,
96+
{ cooldownDuration }
97+
);
98+
99+
controller.start();
100+
},
101+
};

price_pusher/src/custom-gas-station.ts renamed to price_pusher/src/evm/custom-gas-station.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
verifyValidOption,
66
txSpeeds,
77
customGasChainIds,
8-
} from "./utils";
8+
} from "../utils";
99

1010
type chainMethods = Record<CustomGasChainId, () => Promise<string>>;
1111

@@ -32,3 +32,12 @@ export class CustomGasStation {
3232
return gweiGasPrice.toString();
3333
}
3434
}
35+
36+
export function getCustomGasStation(
37+
customGasStation?: number,
38+
txSpeed?: string
39+
) {
40+
if (customGasStation && txSpeed) {
41+
return new CustomGasStation(customGasStation, txSpeed);
42+
}
43+
}

price_pusher/src/evm.ts renamed to price_pusher/src/evm/evm.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import {
44
PriceInfo,
55
ChainPriceListener,
66
PriceItem,
7-
} from "./interface";
7+
} from "../interface";
88
import { TransactionReceipt } from "ethereum-protocol";
9-
import { addLeading0x, DurationInSeconds, removeLeading0x } from "./utils";
9+
import { addLeading0x, DurationInSeconds, removeLeading0x } from "../utils";
1010
import AbstractPythAbi from "@pythnetwork/pyth-sdk-solidity/abis/AbstractPyth.json";
1111
import HDWalletProvider from "@truffle/hdwallet-provider";
1212
import { Provider } from "web3/providers";
1313
import Web3 from "web3";
14-
import { isWsEndpoint } from "./utils";
14+
import { isWsEndpoint } from "../utils";
1515
import {
1616
PriceServiceConnection,
1717
HexString,

0 commit comments

Comments
 (0)