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
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": "8.1.0",
"version": "8.2.0",
"description": "Pyth Price Pusher",
"homepage": "https://pyth.network",
"main": "lib/index.js",
Expand Down
16 changes: 15 additions & 1 deletion apps/price_pusher/src/solana/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import { Controller } from "../controller";
import { PythSolanaReceiver } from "@pythnetwork/pyth-solana-receiver";
import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet";
import { Keypair, Connection } from "@solana/web3.js";
import { Keypair, Connection, LAMPORTS_PER_SOL } from "@solana/web3.js";
import fs from "fs";
import { PublicKey } from "@solana/web3.js";
import {
Expand Down Expand Up @@ -61,6 +61,16 @@ export default {
type: "number",
optional: true,
} as Options,
"dynamic-jito-tips": {
description: "Use dynamic jito tips",
type: "boolean",
default: false,
} as Options,
"max-jito-tip-lamports": {
description: "Maximum jito tip lamports",
type: "number",
default: LAMPORTS_PER_SOL / 100,
} as Options,
"jito-bundle-size": {
description: "Number of transactions in each bundle",
type: "number",
Expand Down Expand Up @@ -94,6 +104,8 @@ export default {
jitoEndpoint,
jitoKeypairFile,
jitoTipLamports,
dynamicJitoTips,
maxJitoTipLamports,
jitoBundleSize,
updatesPerJitoBundle,
logLevel,
Expand Down Expand Up @@ -148,6 +160,8 @@ export default {
logger.child({ module: "SolanaPricePusherJito" }),
shardId,
jitoTipLamports,
dynamicJitoTips,
maxJitoTipLamports,
jitoClient,
jitoBundleSize,
updatesPerJitoBundle
Expand Down
67 changes: 51 additions & 16 deletions apps/price_pusher/src/solana/solana.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import { SearcherClient } from "jito-ts/dist/sdk/block-engine/searcher";
import { sliceAccumulatorUpdateData } from "@pythnetwork/price-service-sdk";
import { Logger } from "pino";
import { LAMPORTS_PER_SOL } from "@solana/web3.js";

const HEALTH_CHECK_TIMEOUT_SECONDS = 60;

Expand All @@ -34,21 +35,24 @@ export class SolanaPriceListener extends ChainPriceListener {
// and ensuring it is not older than 30 seconds.
private async checkHealth() {
const slot = await this.pythSolanaReceiver.connection.getSlot("finalized");
const blockTime = await this.pythSolanaReceiver.connection.getBlockTime(
slot
);
if (
blockTime === null ||
blockTime < Date.now() / 1000 - HEALTH_CHECK_TIMEOUT_SECONDS
) {
if (blockTime !== null) {
this.logger.info(
`Solana connection is behind by ${
Date.now() / 1000 - blockTime
} seconds`
);
try {
const blockTime = await this.pythSolanaReceiver.connection.getBlockTime(
slot
);
if (
blockTime === null ||
blockTime < Date.now() / 1000 - HEALTH_CHECK_TIMEOUT_SECONDS
) {
if (blockTime !== null) {
this.logger.info(
`Solana connection is behind by ${
Date.now() / 1000 - blockTime
} seconds`
);
}
}
throw new Error("Solana connection is unhealthy");
} catch (err) {
this.logger.error({ err }, "checkHealth failed");
}
}

Expand Down Expand Up @@ -155,17 +159,48 @@ export class SolanaPricePusherJito implements IPricePusher {
private priceServiceConnection: PriceServiceConnection,
private logger: Logger,
private shardId: number,
private jitoTipLamports: number,
private defaultJitoTipLamports: number,
private dynamicJitoTips: boolean,
private maxJitoTipLamports: number,
private searcherClient: SearcherClient,
private jitoBundleSize: number,
private updatesPerJitoBundle: number
) {}

async getRecentJitoTipLamports(): Promise<number | undefined> {
try {
const response = await fetch(
"http://bundles-api-rest.jito.wtf/api/v1/bundles/tip_floor"
);
if (!response.ok) {
this.logger.error(
{ status: response.status, statusText: response.statusText },
"getRecentJitoTips http request failed"
);
return undefined;
}
const data = await response.json();
return Math.floor(
Number(data[0].landed_tips_25th_percentile) * LAMPORTS_PER_SOL
);
} catch (err: any) {
this.logger.error({ err }, "getRecentJitoTips failed");
return undefined;
}
}

async updatePriceFeed(
priceIds: string[],
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_pubTimesToPush: number[]
): Promise<void> {
const jitoTip = this.dynamicJitoTips
? (await this.getRecentJitoTipLamports()) ?? this.defaultJitoTipLamports
: this.defaultJitoTipLamports;

const cappedJitoTip = Math.min(jitoTip, this.maxJitoTipLamports);
this.logger.info({ cappedJitoTip }, "using jito tip of");

let priceFeedUpdateData: string[];
try {
priceFeedUpdateData = await this.priceServiceConnection.getLatestVaas(
Expand All @@ -192,7 +227,7 @@ export class SolanaPricePusherJito implements IPricePusher {
);

const transactions = await transactionBuilder.buildVersionedTransactions({
jitoTipLamports: this.jitoTipLamports,
jitoTipLamports: cappedJitoTip,
tightComputeBudget: true,
jitoBundleSize: this.jitoBundleSize,
});
Expand Down
Loading