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
207 changes: 172 additions & 35 deletions apps/price_pusher/grafana-dashboard.sample.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/price_pusher/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pythnetwork/price-pusher",
"version": "9.1.2",
"version": "9.1.3",
"description": "Pyth Price Pusher",
"homepage": "https://pyth.network",
"main": "lib/index.js",
Expand Down
111 changes: 111 additions & 0 deletions apps/price_pusher/src/aptos/balance-tracker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { AptosClient } from "aptos";
import {
BaseBalanceTracker,
BaseBalanceTrackerConfig,
IBalanceTracker,
} from "../interface";
import { DurationInSeconds } from "../utils";
import { PricePusherMetrics } from "../metrics";
import { Logger } from "pino";

/**
* Aptos-specific configuration for balance tracker
*/
export interface AptosBalanceTrackerConfig extends BaseBalanceTrackerConfig {
/** Aptos node endpoint URL */
endpoint: string;
/** Aptos account address */
address: string;
/** Optional decimal places for APT token (default: 8) */
decimals?: number;
}

/**
* Aptos-specific implementation of the balance tracker
*/
export class AptosBalanceTracker extends BaseBalanceTracker {
private client: AptosClient;
private aptosAddress: string;
private decimals: number;

constructor(config: AptosBalanceTrackerConfig) {
super({
...config,
logger: config.logger.child({ module: "AptosBalanceTracker" }),
});

this.client = new AptosClient(config.endpoint);
this.aptosAddress = config.address;
// APT has 8 decimal places by default
this.decimals = config.decimals ?? 8;
}

/**
* Aptos-specific implementation of balance update
* Fetches the native APT balance for the configured address
*/
protected async updateBalance(): Promise<void> {
try {
// Get account resource to check the balance
const accountResource = await this.client.getAccountResource(
this.aptosAddress,
"0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>",
);

// Extract the balance value from the account resource
const rawBalance = (accountResource.data as any).coin.value;

// Convert the balance to a bigint
const balance = BigInt(rawBalance);

// Calculate the normalized balance for display
const normalizedBalance = Number(balance) / Math.pow(10, this.decimals);

// Update metrics with the new balance
this.metrics.updateWalletBalance(
this.address,
this.network,
normalizedBalance,
);

this.logger.debug(
`Updated Aptos wallet balance: ${this.address} = ${normalizedBalance.toString()} APT (raw: ${balance.toString()})`,
);
} catch (error) {
this.logger.error(
{ error },
"Error fetching Aptos wallet balance for metrics",
);
}
}
}

/**
* Parameters for creating an Aptos balance tracker
*/
export interface CreateAptosBalanceTrackerParams {
endpoint: string;
address: string;
network: string;
updateInterval: DurationInSeconds;
metrics: PricePusherMetrics;
logger: Logger;
decimals?: number;
}

/**
* Factory function to create a balance tracker for Aptos chain
*/
export function createAptosBalanceTracker(
params: CreateAptosBalanceTrackerParams,
): IBalanceTracker {
return new AptosBalanceTracker({
endpoint: params.endpoint,
address: params.address,
network: params.network,
updateInterval: params.updateInterval,
metrics: params.metrics,
logger: params.logger,
decimals: params.decimals,
});
}
35 changes: 34 additions & 1 deletion apps/price_pusher/src/aptos/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import {
import { AptosAccount } from "aptos";
import pino from "pino";
import { filterInvalidPriceItems } from "../utils";
import { PricePusherMetrics } from "../metrics";
import { createAptosBalanceTracker } from "./balance-tracker";

export default {
command: "aptos",
describe: "run price pusher for aptos",
Expand Down Expand Up @@ -40,6 +43,8 @@ export default {
...options.pushingFrequency,
...options.logLevel,
...options.controllerLogLevel,
...options.enableMetrics,
...options.metricsPort,
},
handler: async function (argv: any) {
// FIXME: type checks for this
Expand All @@ -54,13 +59,23 @@ export default {
overrideGasPriceMultiplier,
logLevel,
controllerLogLevel,
enableMetrics,
metricsPort,
} = argv;

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

const priceConfigs = readPriceConfigFile(priceConfigFile);
const hermesClient = new HermesClient(priceServiceEndpoint);

// Initialize metrics if enabled
let metrics: PricePusherMetrics | undefined;
if (enableMetrics) {
metrics = new PricePusherMetrics(logger.child({ module: "Metrics" }));
metrics.start(metricsPort);
logger.info(`Metrics server started on port ${metricsPort}`);
}

const mnemonic = fs.readFileSync(mnemonicFile, "utf-8").trim();
const account = AptosAccount.fromDerivePath(
APTOS_ACCOUNT_HD_PATH,
Expand Down Expand Up @@ -113,9 +128,27 @@ export default {
aptosListener,
aptosPusher,
logger.child({ module: "Controller" }, { level: controllerLogLevel }),
{ pushingFrequency },
{
pushingFrequency,
metrics,
},
);

// Create and start the balance tracker if metrics are enabled
if (metrics) {
const balanceTracker = createAptosBalanceTracker({
address: account.address().toString(),
endpoint,
network: "aptos",
updateInterval: pushingFrequency,
metrics,
logger: logger.child({ module: "AptosBalanceTracker" }),
});

// Start the balance tracker
await balanceTracker.start();
}

controller.start();
},
};
38 changes: 0 additions & 38 deletions apps/price_pusher/src/balance-tracker.ts

This file was deleted.

37 changes: 36 additions & 1 deletion apps/price_pusher/src/evm/balance-tracker.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { SuperWalletClient } from "./super-wallet";
import { BaseBalanceTracker, BaseBalanceTrackerConfig } from "../interface";
import {
BaseBalanceTracker,
BaseBalanceTrackerConfig,
IBalanceTracker,
} from "../interface";
import { DurationInSeconds } from "../utils";
import { PricePusherMetrics } from "../metrics";
import { Logger } from "pino";

/**
* EVM-specific configuration for balance tracker
Expand Down Expand Up @@ -49,3 +56,31 @@ export class EvmBalanceTracker extends BaseBalanceTracker {
}
}
}

/**
* Parameters for creating an EVM balance tracker
*/
export interface CreateEvmBalanceTrackerParams {
client: SuperWalletClient;
address: `0x${string}`;
network: string;
updateInterval: DurationInSeconds;
metrics: PricePusherMetrics;
logger: Logger;
}

/**
* Factory function to create a balance tracker for EVM chains
*/
export function createEvmBalanceTracker(
params: CreateEvmBalanceTrackerParams,
): IBalanceTracker {
return new EvmBalanceTracker({
client: params.client,
address: params.address,
network: params.network,
updateInterval: params.updateInterval,
metrics: params.metrics,
logger: params.logger,
});
}
2 changes: 1 addition & 1 deletion apps/price_pusher/src/evm/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { createClient } from "./super-wallet";
import { createPythContract } from "./pyth-contract";
import { isWsEndpoint, filterInvalidPriceItems } from "../utils";
import { PricePusherMetrics } from "../metrics";
import { createEvmBalanceTracker } from "../balance-tracker";
import { createEvmBalanceTracker } from "./balance-tracker";

export default {
command: "evm",
Expand Down
96 changes: 96 additions & 0 deletions apps/price_pusher/src/sui/balance-tracker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { SuiClient } from "@mysten/sui/client";
import {
BaseBalanceTracker,
BaseBalanceTrackerConfig,
IBalanceTracker,
} from "../interface";
import { DurationInSeconds } from "../utils";
import { PricePusherMetrics } from "../metrics";
import { Logger } from "pino";

/**
* Sui-specific configuration for balance tracker
*/
export interface SuiBalanceTrackerConfig extends BaseBalanceTrackerConfig {
/** Sui client instance */
client: SuiClient;
}

/**
* Sui-specific implementation of the balance tracker
*/
export class SuiBalanceTracker extends BaseBalanceTracker {
private client: SuiClient;

constructor(config: SuiBalanceTrackerConfig) {
super({
...config,
logger: config.logger.child({ module: "SuiBalanceTracker" }),
});

this.client = config.client;
}

/**
* Sui-specific implementation of balance update
*/
protected async updateBalance(): Promise<void> {
try {
// Get all coins owned by the address
const { data: coins } = await this.client.getCoins({
owner: this.address,
});

// Sum up all coin balances
const totalBalance = coins.reduce((acc, coin) => {
return acc + BigInt(coin.balance);
}, BigInt(0));

// Convert to a normalized number for reporting (SUI has 9 decimals)
const normalizedBalance = Number(totalBalance) / 1e9;

this.metrics.updateWalletBalance(
this.address,
this.network,
normalizedBalance,
);

this.logger.debug(
`Updated Sui wallet balance: ${this.address} = ${normalizedBalance} SUI`,
);
} catch (error) {
this.logger.error(
{ error },
"Error fetching Sui wallet balance for metrics",
);
}
}
}

/**
* Parameters for creating a Sui balance tracker
*/
export interface CreateSuiBalanceTrackerParams {
client: SuiClient;
address: string;
network: string;
updateInterval: DurationInSeconds;
metrics: PricePusherMetrics;
logger: Logger;
}

/**
* Factory function to create a balance tracker for Sui chain
*/
export function createSuiBalanceTracker(
params: CreateSuiBalanceTrackerParams,
): IBalanceTracker {
return new SuiBalanceTracker({
client: params.client,
address: params.address,
network: params.network,
updateInterval: params.updateInterval,
metrics: params.metrics,
logger: params.logger,
});
}
Loading
Loading