Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(price-puhser) Use Hermes Client #2312

Merged
merged 12 commits into from
Feb 6, 2025
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
3 changes: 1 addition & 2 deletions apps/price_pusher/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,7 @@ human-readable logs, you can pipe the output of the program to `pino-pretty`. Se

You can configure the log level of some of the modules of the price pusher as well. The available modules are PriceServiceConnection, which
is responsible for connecting to the Hermes price service, and Controller, which is responsible for checking the prices from the Hermes
and the on-chain Pyth contract and deciding whether to push a new price. You can configure the log level of these modules by passing the
`--price-service-connection-log-level` and `--controller-log-level` arguments, respectively.
and the on-chain Pyth contract and deciding whether to push a new price. You can configure the log level of these modules by passing the `--controller-log-level` arguments, respectively.

### Example

Expand Down
2 changes: 1 addition & 1 deletion apps/price_pusher/config.aptos.testnet.sample.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"endpoint": "https://fullnode.testnet.aptoslabs.com/v1",
"endpoint": "https://api.testnet.aptoslabs.com/v1",
"pyth-contract-address": "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387",
"price-service-endpoint": "https://hermes-beta.pyth.network",
"mnemonic-file": "./mnemonic",
Expand Down
2 changes: 1 addition & 1 deletion apps/price_pusher/config.injective.testnet.sample.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"grpc-endpoint": "https://k8s.testnet.chain.grpc-web.injective.network",
"pyth-contract-address": "inj1z60tg0tekdzcasenhuuwq3htjcd5slmgf7gpez",
"pyth-contract-address": "inj18rlflp3735h25jmjx97d22c72sxk260amdjxlu",
"price-service-endpoint": "https://hermes-beta.pyth.network",
"mnemonic-file": "./mnemonic",
"price-config-file": "./price-config.beta.sample.yaml",
Expand Down
6 changes: 3 additions & 3 deletions apps/price_pusher/config.sui.mainnet.sample.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"endpoint": "https://sui-testnet-rpc.allthatnode.com",
"pyth-package-id": "0x00b53b0f4174108627fbee72e2498b58d6a2714cded53fac537034c220d26302",
"pyth-state-id": "0xf9ff3ef935ef6cdfb659a203bf2754cebeb63346e29114a535ea6f41315e5a3f",
"endpoint": "https://sui-mainnet-endpoint.blockvision.org",
"pyth-package-id": "0x04e20ddf36af412a4096f9014f4a565af9e812db9a05cc40254846cf6ed0ad91",
"pyth-state-id": "0x1f9310238ee9298fb703c3419030b35b22bb1cc37113e3bb5007c99aec79e5b8",
"wormhole-package-id": "0x5306f64e312b581766351c07af79c72fcb1cd25147157fdc2f8ad76de9a3fb6a",
"wormhole-state-id": "0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c",
"price-feed-to-price-info-object-table-id": "0x14b4697477d24c30c8eecc31dd1bd49a3115a9fe0db6bd4fd570cf14640b79a0",
Expand Down
2 changes: 1 addition & 1 deletion apps/price_pusher/config.ton.mainnet.sample.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"endpoint": "https://toncenter.com/api/v2/jsonRPC",
"pyth-contract-address": "EQBU6k8HH6yX4Jf3d18swWbnYr31D3PJI7PgjXT",
"pyth-contract-address": "EQBU6k8HH6yX4Jf3d18swWbnYr31D3PJI7PgjXT-flsKHqql",
"price-service-endpoint": "https://hermes.pyth.network",
"private-key-file": "./mnemonic",
"price-config-file": "./price-config.stable.sample.yaml"
Expand Down
5 changes: 2 additions & 3 deletions apps/price_pusher/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pythnetwork/price-pusher",
"version": "8.3.3",
"version": "9.0.0",
"description": "Pyth Price Pusher",
"homepage": "https://pyth.network",
"main": "lib/index.js",
Expand All @@ -24,7 +24,6 @@
"format": "prettier --write \"src/**/*.ts\"",
"test:lint": "eslint src/",
"start": "node lib/index.js",
"test": "jest",
"dev": "ts-node src/index.ts",
"prepublishOnly": "pnpm run build && pnpm run test:lint",
"preversion": "pnpm run test:lint",
Expand Down Expand Up @@ -61,7 +60,7 @@
"@injectivelabs/networks": "^1.14.6",
"@injectivelabs/sdk-ts": "1.10.72",
"@mysten/sui": "^1.3.0",
"@pythnetwork/price-service-client": "workspace:*",
"@pythnetwork/hermes-client": "^1.3.1",
"@pythnetwork/price-service-sdk": "workspace:^",
"@pythnetwork/pyth-fuel-js": "workspace:*",
"@pythnetwork/pyth-sdk-solidity": "workspace:*",
Expand Down
5 changes: 5 additions & 0 deletions apps/price_pusher/price-config.stable.sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@
time_difference: 30
price_deviation: 0.5
confidence_ratio: 0.1
- alias: PYTH/USD
id: 2f95862b045670cd22bee3114c39763a4a08beeb663b145d283c31d7d1101c23
time_difference: 60
price_deviation: 0.5
confidence_ratio: 1
101 changes: 0 additions & 101 deletions apps/price_pusher/src/__tests__/pyth-price-listener.test.ts

This file was deleted.

15 changes: 8 additions & 7 deletions apps/price_pusher/src/aptos/aptos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from "../interface";
import { AptosAccount, AptosClient } from "aptos";
import { DurationInSeconds } from "../utils";
import { PriceServiceConnection } from "@pythnetwork/price-service-client";
import { HermesClient } from "@pythnetwork/hermes-client";
import { Logger } from "pino";

export class AptosPriceListener extends ChainPriceListener {
Expand Down Expand Up @@ -89,7 +89,7 @@ export class AptosPricePusher implements IPricePusher {
private sequenceNumberLocked: boolean;

constructor(
private priceServiceConnection: PriceServiceConnection,
private hermesClient: HermesClient,
private logger: Logger,
private pythContractAddress: string,
private endpoint: string,
Expand All @@ -107,11 +107,12 @@ export class AptosPricePusher implements IPricePusher {
* @returns Array of price update data.
*/
async getPriceFeedsUpdateData(priceIds: string[]): Promise<number[][]> {
// Fetch the latest price feed update VAAs from the price service
const latestVaas = await this.priceServiceConnection.getLatestVaas(
priceIds
const response = await this.hermesClient.getLatestPriceUpdates(priceIds, {
encoding: "base64",
});
return response.binary.data.map((data) =>
Array.from(Buffer.from(data, "base64"))
);
return latestVaas.map((vaa) => Array.from(Buffer.from(vaa, "base64")));
}

async updatePriceFeed(
Expand Down Expand Up @@ -226,7 +227,7 @@ export class AptosPricePusher implements IPricePusher {
);
return this.lastSequenceNumber;
} catch (e: any) {
throw new Error("Failed to retrieve sequence number");
throw new Error("Failed to retrieve sequence number" + e);
} finally {
this.sequenceNumberLocked = false;
}
Expand Down
38 changes: 21 additions & 17 deletions apps/price_pusher/src/aptos/command.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PriceServiceConnection } from "@pythnetwork/price-service-client";
import { HermesClient } from "@pythnetwork/hermes-client";
import * as options from "../options";
import { readPriceConfigFile } from "../price-config";
import fs from "fs";
Expand All @@ -12,7 +12,7 @@ import {
} from "./aptos";
import { AptosAccount } from "aptos";
import pino from "pino";

import { filterInvalidPriceItems } from "../utils";
export default {
command: "aptos",
describe: "run price pusher for aptos",
Expand All @@ -39,10 +39,9 @@ export default {
...options.pollingFrequency,
...options.pushingFrequency,
...options.logLevel,
...options.priceServiceConnectionLogLevel,
...options.controllerLogLevel,
},
handler: function (argv: any) {
handler: async function (argv: any) {
// FIXME: type checks for this
const {
endpoint,
Expand All @@ -54,22 +53,13 @@ export default {
pollingFrequency,
overrideGasPriceMultiplier,
logLevel,
priceServiceConnectionLogLevel,
controllerLogLevel,
} = argv;

const logger = pino({ level: logLevel });

const priceConfigs = readPriceConfigFile(priceConfigFile);
const priceServiceConnection = new PriceServiceConnection(
priceServiceEndpoint,
{
logger: logger.child(
{ module: "PriceServiceConnection" },
{ level: priceServiceConnectionLogLevel }
),
}
);
const hermesClient = new HermesClient(priceServiceEndpoint);

const mnemonic = fs.readFileSync(mnemonicFile, "utf-8").trim();
const account = AptosAccount.fromDerivePath(
Expand All @@ -78,10 +68,24 @@ export default {
);
logger.info(`Pushing from account address: ${account.address()}`);

const priceItems = priceConfigs.map(({ id, alias }) => ({ id, alias }));
let priceItems = priceConfigs.map(({ id, alias }) => ({ id, alias }));

// Better to filter out invalid price items before creating the pyth listener
const { existingPriceItems, invalidPriceItems } =
await filterInvalidPriceItems(hermesClient, priceItems);

if (invalidPriceItems.length > 0) {
logger.error(
`Invalid price id submitted for: ${invalidPriceItems
.map(({ alias }) => alias)
.join(", ")}`
);
}

priceItems = existingPriceItems;

const pythListener = new PythPriceListener(
priceServiceConnection,
hermesClient,
priceItems,
logger.child({ module: "PythPriceListener" })
);
Expand All @@ -95,7 +99,7 @@ export default {
);

const aptosPusher = new AptosPricePusher(
priceServiceConnection,
hermesClient,
logger.child({ module: "AptosPricePusher" }),
pythContractAddress,
endpoint,
Expand Down
2 changes: 1 addition & 1 deletion apps/price_pusher/src/controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { UnixTimestamp } from "@pythnetwork/price-service-client";
import { UnixTimestamp } from "@pythnetwork/hermes-client";
import { DurationInSeconds, sleep } from "./utils";
import { IPriceListener, IPricePusher } from "./interface";
import { PriceConfig, shouldUpdate, UpdateCondition } from "./price-config";
Expand Down
41 changes: 24 additions & 17 deletions apps/price_pusher/src/evm/command.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PriceServiceConnection } from "@pythnetwork/price-service-client";
import { HermesClient } from "@pythnetwork/hermes-client";
import fs from "fs";
import { Options } from "yargs";
import * as options from "../options";
Expand All @@ -10,7 +10,7 @@ import { getCustomGasStation } from "./custom-gas-station";
import pino from "pino";
import { createClient } from "./super-wallet";
import { createPythContract } from "./pyth-contract";
import { isWsEndpoint } from "../utils";
import { isWsEndpoint, filterInvalidPriceItems } from "../utils";

export default {
command: "evm",
Expand Down Expand Up @@ -77,7 +77,6 @@ export default {
...options.pollingFrequency,
...options.pushingFrequency,
...options.logLevel,
...options.priceServiceConnectionLogLevel,
...options.controllerLogLevel,
},
handler: async function (argv: any) {
Expand All @@ -97,29 +96,37 @@ export default {
gasLimit,
updateFeeMultiplier,
logLevel,
priceServiceConnectionLogLevel,
controllerLogLevel,
} = argv;
console.log("***** priceServiceEndpoint *****", priceServiceEndpoint);

const logger = pino({ level: logLevel });
const logger = pino({
level: logLevel,
});

const priceConfigs = readPriceConfigFile(priceConfigFile);
const priceServiceConnection = new PriceServiceConnection(
priceServiceEndpoint,
{
logger: logger.child(
{ module: "PriceServiceConnection" },
{ level: priceServiceConnectionLogLevel }
),
}
);
const hermesClient = new HermesClient(priceServiceEndpoint);

const mnemonic = fs.readFileSync(mnemonicFile, "utf-8").trim();

const priceItems = priceConfigs.map(({ id, alias }) => ({ id, alias }));
let priceItems = priceConfigs.map(({ id, alias }) => ({ id, alias }));

// Better to filter out invalid price items before creating the pyth listener
const { existingPriceItems, invalidPriceItems } =
await filterInvalidPriceItems(hermesClient, priceItems);

if (invalidPriceItems.length > 0) {
logger.error(
`Invalid price id submitted for: ${invalidPriceItems
.map(({ alias }) => alias)
.join(", ")}`
);
}

priceItems = existingPriceItems;

const pythListener = new PythPriceListener(
priceServiceConnection,
hermesClient,
priceItems,
logger.child({ module: "PythPriceListener" })
);
Expand Down Expand Up @@ -152,7 +159,7 @@ export default {
txSpeed
);
const evmPusher = new EvmPricePusher(
priceServiceConnection,
hermesClient,
client,
pythContract,
logger.child({ module: "EvmPricePusher" }),
Expand Down
Loading
Loading