Skip to content

Commit

Permalink
feat: add dynamic jito tips (#2113)
Browse files Browse the repository at this point in the history
* add dynamic jito tips

* uncomment

* go

* using jito tip

* go

* bump

* cap it

* go

* go

* test

* disable health check

* go
  • Loading branch information
guibescos authored Nov 13, 2024
1 parent 0051203 commit c6ec886
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 18 deletions.
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

0 comments on commit c6ec886

Please sign in to comment.