Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ bigtable-writer.json
.aptos
tsconfig.tsbuildinfo
*~
*mnemonic*
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 18 additions & 6 deletions price_pusher/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,18 @@ npm run start -- evm --endpoint wss://example-rpc.com \
--price-service-endpoint https://example-pyth-price.com \
--price-config-file "path/to/price-config-file.yaml.testnet.sample.yaml" \
--mnemonic-file "path/to/mnemonic.txt" \
[--cooldown-duration 10] \
[--polling-frequency 5]
[--pushing-frequency 10] \
[--polling-frequency 5] \
[--override-gas-price-multiplier 1.1]

# For Injective
npm run start -- injective --grpc-endpoint https://grpc-endpoint.com \
--pyth-contract-address inj1z60tg0... --price-service-endpoint "https://example-pyth-price.com" \
--price-config-file "path/to/price-config-file.yaml.testnet.sample.yaml" \
--mnemonic-file "path/to/mnemonic.txt" \
[--cooldown-duration 10] \
[--polling-frequency 5]
[--pushing-frequency 10] \
[--polling-frequency 5] \


# Or, run the price pusher docker image instead of building from the source
docker run public.ecr.aws/pyth-network/xc-price-pusher:v<version> -- <above-arguments>
Expand All @@ -82,11 +84,11 @@ npm run start -- {network} --help

### Example

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

```sh
npm run dev -- evm --endpoint https://endpoints.omniatech.io/v1/fantom/testnet/public \
--pyth-contract-address 0xd7308b14BF4008e7C7196eC35610B1427C5702EA --price-service-endpoint https://xc-testnet.pyth.network \
--pyth-contract-address 0xff1a0f4744e8582DF1aE09D5611b887B6a12925C --price-service-endpoint https://xc-testnet.pyth.network \
--mnemonic-file "./mnemonic" --price-config-file "./price-config.testnet.sample.yaml"
```

Expand Down Expand Up @@ -125,3 +127,13 @@ docker-compose -f docker-compose.testnet.sample.yaml up
It will take a few minutes until all the services are up and running.

[pyth price service]: https://github.com/pyth-network/pyth-crosschain/tree/main/price_service/server

## Reliability

You can run multiple instances of the price pusher to increase the reliability. It is better to use
difference RPCs to get better reliability in case an RPC goes down. **If you use the same payer account
in different pushers, then due to blockchains nonce or sequence for accounts, a transaction won't be
pushed twiced and you won't pay additional costs most of the time.** However, there might be some race
condiitons in the RPCs because they are often behind a load balancer than can sometimes cause rejected
transactions land on-chain. You can reduce the chances of additional cost overhead by reducing the
pushing frequency.
7 changes: 7 additions & 0 deletions price_pusher/config.evm.testnet.sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"endpoint": "https://endpoints.omniatech.io/v1/fantom/testnet/public",
"pyth-contract-address": "0xff1a0f4744e8582DF1aE09D5611b887B6a12925CZ",
"price-service-endpoint": "https://xc-testnet.pyth.network",
"mnemonic-file": "./mnemonic",
"price-config-file": "./price-config.testnet.sample.yaml"
}
10 changes: 9 additions & 1 deletion price_pusher/docker-compose.testnet.sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,17 @@ services:
- "/command_config"
configs:
- command_config
- mnemonic
- price_config
depends_on:
price-service:
condition: service_healthy
configs:
command_config:
file: ./config.injective.testnet.sample.json # Replace this with the path to the configuration file
# Replace this with the path to the configuration file. You need to update the paths defined in
# the config file
file: ./config.injective.testnet.sample.json
mnemonic:
file: ./mnemonic # Replace this with the path to the mnemonic file
price_config:
file: ./price-config.testnet.sample.yaml # Replace this with the path to the price configuration file
2 changes: 1 addition & 1 deletion price_pusher/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pythnetwork/pyth-price-pusher",
"version": "3.0.0",
"version": "4.0.0",
"description": "Pyth Price Pusher",
"homepage": "https://pyth.network",
"main": "lib/index.js",
Expand Down
10 changes: 5 additions & 5 deletions price_pusher/src/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ import { IPricePusher, IPriceListener } from "./interface";
import { PriceConfig, shouldUpdate } from "./price-config";

export class Controller {
private cooldownDuration: DurationInSeconds;
private pushingFrequency: DurationInSeconds;
constructor(
private priceConfigs: PriceConfig[],
private sourcePriceListener: IPriceListener,
private targetPriceListener: IPriceListener,
private targetChainPricePusher: IPricePusher,
config: {
cooldownDuration: DurationInSeconds;
pushingFrequency: DurationInSeconds;
}
) {
this.cooldownDuration = config.cooldownDuration;
this.pushingFrequency = config.pushingFrequency;
}

async start() {
Expand All @@ -25,7 +25,7 @@ export class Controller {
// wait for the listeners to get updated. There could be a restart
// before this run and we need to respect the cooldown duration as
// their might be a message sent before.
await sleep(this.cooldownDuration * 1000);
await sleep(this.pushingFrequency * 1000);

for (;;) {
const pricesToPush: PriceConfig[] = [];
Expand Down Expand Up @@ -58,7 +58,7 @@ export class Controller {
);
}

await sleep(this.cooldownDuration * 1000);
await sleep(this.pushingFrequency * 1000);
}
}
}
26 changes: 21 additions & 5 deletions price_pusher/src/evm/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,19 @@ export default {
choices: ["slow", "standard", "fast"],
required: false,
} as Options,
"override-gas-price-multiplier": {
description:
"Multiply the gas price by this number if the transaction is not landing to override it. Default to 1.1",
type: "number",
required: false,
default: 1.1,
} as Options,
...options.priceConfigFile,
...options.priceServiceEndpoint,
...options.mnemonicFile,
...options.pythContractAddress,
...options.pollingFrequency,
...options.cooldownDuration,
...options.pushingFrequency,
},
handler: function (argv: any) {
// FIXME: type checks for this
Expand All @@ -49,17 +56,25 @@ export default {
priceServiceEndpoint,
mnemonicFile,
pythContractAddress,
cooldownDuration,
pushingFrequency,
pollingFrequency,
customGasStation,
txSpeed,
overrideGasPriceMultiplier,
} = argv;

const priceConfigs = readPriceConfigFile(priceConfigFile);
const priceServiceConnection = new PriceServiceConnection(
priceServiceEndpoint,
{
logger: console,
logger: {
// Log only warnings and errors from the price service client
info: () => undefined,
warn: console.warn,
error: console.error,
debug: () => undefined,
trace: () => undefined,
},
}
);
const mnemonic = fs.readFileSync(mnemonicFile, "utf-8").trim();
Expand All @@ -84,7 +99,8 @@ export default {
const gasStation = getCustomGasStation(customGasStation, txSpeed);
const evmPusher = new EvmPricePusher(
priceServiceConnection,
pythContractFactory.createPythContractWithPayer(),
pythContractFactory,
overrideGasPriceMultiplier,
gasStation
);

Expand All @@ -93,7 +109,7 @@ export default {
pythListener,
evmListener,
evmPusher,
{ cooldownDuration }
{ pushingFrequency }
);

controller.start();
Expand Down
20 changes: 14 additions & 6 deletions price_pusher/src/evm/custom-gas-station.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
customGasChainIds,
} from "../utils";

type chainMethods = Record<CustomGasChainId, () => Promise<string>>;
type chainMethods = Record<CustomGasChainId, () => Promise<string | undefined>>;

export class CustomGasStation {
private chain: CustomGasChainId;
Expand All @@ -25,11 +25,19 @@ export class CustomGasStation {
}

private async fetchMaticMainnetGasPrice() {
const res = await fetch("https://gasstation-mainnet.matic.network/v2");
const jsonRes = await res.json();
const gasPrice = jsonRes[this.speed].maxFee;
const gweiGasPrice = Web3.utils.toWei(gasPrice.toFixed(2), "Gwei");
return gweiGasPrice.toString();
try {
const res = await fetch("https://gasstation-mainnet.matic.network/v2");
const jsonRes = await res.json();
const gasPrice = jsonRes[this.speed].maxFee;
const gweiGasPrice = Web3.utils.toWei(gasPrice.toFixed(2), "Gwei");
return gweiGasPrice.toString();
} catch (e) {
console.error(
"Failed to fetch gas price from Matic mainnet. Returning undefined"
);
console.error(e);
return undefined;
}
}
}

Expand Down
Loading