From dfedeef3ea56edc5515ae3ad1a831631775fc813 Mon Sep 17 00:00:00 2001 From: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 19:57:17 +0000 Subject: [PATCH 1/8] Bumping sdk and jit dependencies to 2.104.0-beta.31 and 0.12.18 --- package.json | 4 ++-- yarn.lock | 21 +++++++++++---------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 237eab4c..4e2fa72c 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "main": "lib/index.js", "license": "Apache-2.0", "dependencies": { - "@drift-labs/jit-proxy": "0.12.17", - "@drift-labs/sdk": "2.104.0-beta.30", + "@drift-labs/jit-proxy": "0.12.18", + "@drift-labs/sdk": "2.104.0-beta.31", "@opentelemetry/api": "1.7.0", "@opentelemetry/auto-instrumentations-node": "0.31.2", "@opentelemetry/exporter-prometheus": "0.31.0", diff --git a/yarn.lock b/yarn.lock index c9bd1f3f..d0a3761d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -168,19 +168,19 @@ enabled "2.0.x" kuler "^2.0.0" -"@drift-labs/jit-proxy@0.12.17": - version "0.12.17" - resolved "https://registry.yarnpkg.com/@drift-labs/jit-proxy/-/jit-proxy-0.12.17.tgz#b1adfbdf586bbef31c5ef7adf6719a214f424d97" - integrity sha512-N3PJp3npOWBgYsKX2tWpfL+wCyk7stFM9GRu87sGDwmUSkvTah7Mj9r5xG1UxmDp8Gyo5alMprdsoDW8bsX3Ug== +"@drift-labs/jit-proxy@0.12.18": + version "0.12.18" + resolved "https://registry.yarnpkg.com/@drift-labs/jit-proxy/-/jit-proxy-0.12.18.tgz#4bf92ca697eeabbfb2b4d1330694b01809bee617" + integrity sha512-RaIHYLwXn6TTM/1S7DhUYm0Py3JbE9+RVvlRpb7lU3pcYHwvLwzgee/fBBwss2VE+1LS2W2Z+AikkNJHi3AiRA== dependencies: "@coral-xyz/anchor" "0.26.0" - "@drift-labs/sdk" "2.104.0-beta.30" + "@drift-labs/sdk" "2.104.0-beta.31" "@solana/web3.js" "1.91.7" -"@drift-labs/sdk@2.104.0-beta.30": - version "2.104.0-beta.30" - resolved "https://registry.yarnpkg.com/@drift-labs/sdk/-/sdk-2.104.0-beta.30.tgz#7906065e0df019c27d14967f3a7019091abb802c" - integrity sha512-lwIeXozTHv1sZjS/yu+RZXlz2pTC+DA5YXqpOqfwgk6roUaXcr9t7T7rjs3YVe6Uv3C465UHMAcWRNRZOIBIIA== +"@drift-labs/sdk@2.104.0-beta.31": + version "2.104.0-beta.31" + resolved "https://registry.yarnpkg.com/@drift-labs/sdk/-/sdk-2.104.0-beta.31.tgz#495b7f94a2a008423823583ff159697736341f0a" + integrity sha512-XfL3HS+OGWQsoQADEOKiqUZSMPzfhYqbZiwQc+segJg8Uyhxlb7hihzp7wBmZdS9eZRdrjCm5GuI3imC3q+w0g== dependencies: "@coral-xyz/anchor" "0.29.0" "@coral-xyz/anchor-30" "npm:@coral-xyz/anchor@0.30.1" @@ -191,6 +191,7 @@ "@pythnetwork/client" "2.5.3" "@pythnetwork/price-service-sdk" "1.7.1" "@pythnetwork/pyth-solana-receiver" "0.7.0" + "@solana/buffer-layout" "4.0.1" "@solana/spl-token" "0.3.7" "@solana/web3.js" "1.92.3" "@switchboard-xyz/on-demand" "1.2.42" @@ -1185,7 +1186,7 @@ bigint-buffer "^1.1.5" bignumber.js "^9.0.1" -"@solana/buffer-layout@^4.0.0", "@solana/buffer-layout@^4.0.1": +"@solana/buffer-layout@4.0.1", "@solana/buffer-layout@^4.0.0", "@solana/buffer-layout@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz#b996235eaec15b1e0b5092a8ed6028df77fa6c15" integrity sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA== From 6c7abeb05c0d9914d0856de3f62c2a0b7367c22e Mon Sep 17 00:00:00 2001 From: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 21:52:16 +0000 Subject: [PATCH 2/8] Bumping sdk and jit dependencies to 2.104.0-beta.32 and 0.12.19 --- package.json | 4 ++-- yarn.lock | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 4e2fa72c..fa590639 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "main": "lib/index.js", "license": "Apache-2.0", "dependencies": { - "@drift-labs/jit-proxy": "0.12.18", - "@drift-labs/sdk": "2.104.0-beta.31", + "@drift-labs/jit-proxy": "0.12.19", + "@drift-labs/sdk": "2.104.0-beta.32", "@opentelemetry/api": "1.7.0", "@opentelemetry/auto-instrumentations-node": "0.31.2", "@opentelemetry/exporter-prometheus": "0.31.0", diff --git a/yarn.lock b/yarn.lock index d0a3761d..a242d25c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -168,19 +168,19 @@ enabled "2.0.x" kuler "^2.0.0" -"@drift-labs/jit-proxy@0.12.18": - version "0.12.18" - resolved "https://registry.yarnpkg.com/@drift-labs/jit-proxy/-/jit-proxy-0.12.18.tgz#4bf92ca697eeabbfb2b4d1330694b01809bee617" - integrity sha512-RaIHYLwXn6TTM/1S7DhUYm0Py3JbE9+RVvlRpb7lU3pcYHwvLwzgee/fBBwss2VE+1LS2W2Z+AikkNJHi3AiRA== +"@drift-labs/jit-proxy@0.12.19": + version "0.12.19" + resolved "https://registry.yarnpkg.com/@drift-labs/jit-proxy/-/jit-proxy-0.12.19.tgz#3cd6b3e9f3bae43fc8b250710f4073b8d5925b8b" + integrity sha512-w35uqL5TymBW3iZTw3mfYt2Gm8E8smqYf3s+yZyAEXDOQWkiusr/QLFZEYY07Pop4gzPszf9YvxFLf6/BIDFCg== dependencies: "@coral-xyz/anchor" "0.26.0" - "@drift-labs/sdk" "2.104.0-beta.31" + "@drift-labs/sdk" "2.104.0-beta.32" "@solana/web3.js" "1.91.7" -"@drift-labs/sdk@2.104.0-beta.31": - version "2.104.0-beta.31" - resolved "https://registry.yarnpkg.com/@drift-labs/sdk/-/sdk-2.104.0-beta.31.tgz#495b7f94a2a008423823583ff159697736341f0a" - integrity sha512-XfL3HS+OGWQsoQADEOKiqUZSMPzfhYqbZiwQc+segJg8Uyhxlb7hihzp7wBmZdS9eZRdrjCm5GuI3imC3q+w0g== +"@drift-labs/sdk@2.104.0-beta.32": + version "2.104.0-beta.32" + resolved "https://registry.yarnpkg.com/@drift-labs/sdk/-/sdk-2.104.0-beta.32.tgz#0065eb49089898fb9494ceb2728caef61c854510" + integrity sha512-G7XsghnJ9MugtXBo7kaOYdjToxFLPdN6+cfb8NXskfL/eMgwruoZSVuYK+Xv4Jscui+VDbWd1H/II6zBYcdjfw== dependencies: "@coral-xyz/anchor" "0.29.0" "@coral-xyz/anchor-30" "npm:@coral-xyz/anchor@0.30.1" From f6bdbf959a969a5e487bccd3edd0155f02506ebc Mon Sep 17 00:00:00 2001 From: moosecat Date: Wed, 18 Dec 2024 14:09:09 -0800 Subject: [PATCH 3/8] Nour/pyth lazer cranker (#321) * add pyth lazer cranker * rm unncessary libraries * remove unnecessary code * add entrypoint for the cranker * added improvements * increase the chunk size --- package.json | 1 + src/bots/pythLazerCranker.ts | 268 +++++++++++++++++++++++++++++++++++ src/config.ts | 12 ++ src/index.ts | 14 ++ yarn.lock | 17 ++- 5 files changed, 310 insertions(+), 2 deletions(-) create mode 100644 src/bots/pythLazerCranker.ts diff --git a/package.json b/package.json index fa590639..19c76068 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@project-serum/anchor": "0.19.1-beta.1", "@project-serum/serum": "0.13.65", "@pythnetwork/price-service-client": "1.9.0", + "@pythnetwork/pyth-lazer-sdk": "^0.1.1", "@solana/spl-token": "0.3.7", "@solana/web3.js": "1.92.3", "@types/bn.js": "5.1.5", diff --git a/src/bots/pythLazerCranker.ts b/src/bots/pythLazerCranker.ts new file mode 100644 index 00000000..f8382e42 --- /dev/null +++ b/src/bots/pythLazerCranker.ts @@ -0,0 +1,268 @@ +import { Bot } from '../types'; +import { logger } from '../logger'; +import { GlobalConfig, PythLazerCrankerBotConfig } from '../config'; +import { PriceUpdateAccount } from '@pythnetwork/pyth-solana-receiver/lib/PythSolanaReceiver'; +import { + BlockhashSubscriber, + DriftClient, + getOracleClient, + getPythLazerOraclePublicKey, + OracleClient, + OracleSource, + PriorityFeeSubscriber, + TxSigAndSlot, +} from '@drift-labs/sdk'; +import { BundleSender } from '../bundleSender'; +import { + AddressLookupTableAccount, + ComputeBudgetProgram, +} from '@solana/web3.js'; +import { chunks, simulateAndGetTxWithCUs, sleepMs } from '../utils'; +import { Agent, setGlobalDispatcher } from 'undici'; +import { PythLazerClient } from '@pythnetwork/pyth-lazer-sdk'; + +setGlobalDispatcher( + new Agent({ + connections: 200, + }) +); + +const SIM_CU_ESTIMATE_MULTIPLIER = 1.5; + +export class PythLazerCrankerBot implements Bot { + private wsClient: PythLazerClient; + private pythOracleClient: OracleClient; + readonly decodeFunc: (name: string, data: Buffer) => PriceUpdateAccount; + + public name: string; + public dryRun: boolean; + private intervalMs: number; + private feedIdChunkToPriceMessage: Map = new Map(); + public defaultIntervalMs = 30_000; + + private blockhashSubscriber: BlockhashSubscriber; + private health: boolean = true; + private slotStalenessThresholdRestart: number = 300; + private txSuccessRateThreshold: number = 0.5; + + constructor( + private globalConfig: GlobalConfig, + private crankConfigs: PythLazerCrankerBotConfig, + private driftClient: DriftClient, + private priorityFeeSubscriber?: PriorityFeeSubscriber, + private bundleSender?: BundleSender, + private lookupTableAccounts: AddressLookupTableAccount[] = [] + ) { + this.name = crankConfigs.botId; + this.dryRun = crankConfigs.dryRun; + this.intervalMs = crankConfigs.intervalMs; + if (!globalConfig.hermesEndpoint) { + throw new Error('Missing hermesEndpoint in global config'); + } + + if (globalConfig.driftEnv != 'devnet') { + throw new Error('Only devnet drift env is supported'); + } + + const hermesEndpointParts = globalConfig.hermesEndpoint.split('?token='); + this.wsClient = new PythLazerClient( + hermesEndpointParts[0], + hermesEndpointParts[1] + ); + + this.pythOracleClient = getOracleClient( + OracleSource.PYTH_LAZER, + driftClient.connection, + driftClient.program + ); + this.decodeFunc = + this.driftClient.program.account.pythLazerOracle.coder.accounts.decodeUnchecked.bind( + this.driftClient.program.account.pythLazerOracle.coder.accounts + ); + + this.blockhashSubscriber = new BlockhashSubscriber({ + connection: driftClient.connection, + }); + this.txSuccessRateThreshold = crankConfigs.txSuccessRateThreshold; + this.slotStalenessThresholdRestart = + crankConfigs.slotStalenessThresholdRestart; + } + + async init(): Promise { + logger.info(`Initializing ${this.name} bot`); + await this.blockhashSubscriber.subscribe(); + this.lookupTableAccounts.push( + await this.driftClient.fetchMarketLookupTableAccount() + ); + + const updateConfigs = this.crankConfigs.updateConfigs; + + let subscriptionId = 1; + for (const configChunk of chunks(Object.keys(updateConfigs), 11)) { + const priceFeedIds: number[] = configChunk.map((alias) => { + return updateConfigs[alias].feedId; + }); + + const sendMessage = () => + this.wsClient.send({ + type: 'subscribe', + subscriptionId, + priceFeedIds, + properties: ['price'], + chains: ['solana'], + deliveryFormat: 'json', + channel: 'fixed_rate@200ms', + jsonBinaryEncoding: 'hex', + }); + if (this.wsClient.ws.readyState != 1) { + this.wsClient.ws.addEventListener('open', () => { + sendMessage(); + }); + } else { + sendMessage(); + } + + this.wsClient.addMessageListener((message) => { + switch (message.type) { + case 'json': { + if (message.value.type == 'streamUpdated') { + if (message.value.solana?.data) + this.feedIdChunkToPriceMessage.set( + priceFeedIds, + message.value.solana.data + ); + } + break; + } + default: { + break; + } + } + }); + subscriptionId++; + } + + this.priorityFeeSubscriber?.updateAddresses( + Object.keys(this.feedIdChunkToPriceMessage) + .flat() + .map((feedId) => + getPythLazerOraclePublicKey( + this.driftClient.program.programId, + Number(feedId) + ) + ) + ); + } + + async reset(): Promise { + logger.info(`Resetting ${this.name} bot`); + this.blockhashSubscriber.unsubscribe(); + await this.driftClient.unsubscribe(); + this.wsClient.ws.close(); + } + + async startIntervalLoop(intervalMs = this.intervalMs): Promise { + logger.info(`Starting ${this.name} bot with interval ${intervalMs} ms`); + await sleepMs(5000); + await this.runCrankLoop(); + + setInterval(async () => { + await this.runCrankLoop(); + }, intervalMs); + } + + private async getBlockhashForTx(): Promise { + const cachedBlockhash = this.blockhashSubscriber.getLatestBlockhash(10); + if (cachedBlockhash) { + return cachedBlockhash.blockhash as string; + } + + const recentBlockhash = + await this.driftClient.connection.getLatestBlockhash({ + commitment: 'confirmed', + }); + + return recentBlockhash.blockhash; + } + + async runCrankLoop() { + for (const [ + feedIds, + priceMessage, + ] of this.feedIdChunkToPriceMessage.entries()) { + const ixs = [ + ComputeBudgetProgram.setComputeUnitLimit({ + units: 1_400_000, + }), + ]; + if (this.globalConfig.useJito) { + ixs.push(this.bundleSender!.getTipIx()); + const simResult = await simulateAndGetTxWithCUs({ + ixs, + connection: this.driftClient.connection, + payerPublicKey: this.driftClient.wallet.publicKey, + lookupTableAccounts: this.lookupTableAccounts, + cuLimitMultiplier: SIM_CU_ESTIMATE_MULTIPLIER, + doSimulation: true, + recentBlockhash: await this.getBlockhashForTx(), + }); + simResult.tx.sign([ + // @ts-ignore + this.driftClient.wallet.payer, + ]); + this.bundleSender?.sendTransactions( + [simResult.tx], + undefined, + undefined, + false + ); + } else { + const priorityFees = Math.floor( + (this.priorityFeeSubscriber?.getCustomStrategyResult() || 0) * + this.driftClient.txSender.getSuggestedPriorityFeeMultiplier() + ); + logger.info( + `Priority fees to use: ${priorityFees} with multiplier: ${this.driftClient.txSender.getSuggestedPriorityFeeMultiplier()}` + ); + ixs.push( + ComputeBudgetProgram.setComputeUnitPrice({ + microLamports: priorityFees, + }) + ); + } + const pythLazerIxs = + await this.driftClient.getPostPythLazerOracleUpdateIxs( + feedIds, + priceMessage, + ixs + ); + ixs.push(...pythLazerIxs); + const simResult = await simulateAndGetTxWithCUs({ + ixs, + connection: this.driftClient.connection, + payerPublicKey: this.driftClient.wallet.publicKey, + lookupTableAccounts: this.lookupTableAccounts, + cuLimitMultiplier: SIM_CU_ESTIMATE_MULTIPLIER, + doSimulation: true, + recentBlockhash: await this.getBlockhashForTx(), + }); + const startTime = Date.now(); + this.driftClient + .sendTransaction(simResult.tx) + .then((txSigAndSlot: TxSigAndSlot) => { + logger.info( + `Posted pyth lazer oracles for ${feedIds} update atomic tx: ${ + txSigAndSlot.txSig + }, took ${Date.now() - startTime}ms` + ); + }) + .catch((e) => { + console.log(e); + }); + } + } + + async healthCheck(): Promise { + return this.health; + } +} diff --git a/src/config.ts b/src/config.ts index b1721a26..d74de0ee 100644 --- a/src/config.ts +++ b/src/config.ts @@ -108,6 +108,17 @@ export type PythCrankerBotConfig = BaseBotConfig & { }; }; +export type PythLazerCrankerBotConfig = BaseBotConfig & { + slotStalenessThresholdRestart: number; + txSuccessRateThreshold: number; + intervalMs: number; + updateConfigs: { + [key: string]: { + feedId: number; + }; + }; +}; + export type SwitchboardCrankerBotConfig = BaseBotConfig & { intervalMs: number; queuePubkey: string; @@ -135,6 +146,7 @@ export type BotConfigMap = { userIdleFlipper?: BaseBotConfig; markTwapCrank?: BaseBotConfig; pythCranker?: PythCrankerBotConfig; + pythLazerCranker?: PythLazerCrankerBotConfig; switchboardCranker?: SwitchboardCrankerBotConfig; swiftTaker?: BaseBotConfig; swiftMaker?: BaseBotConfig; diff --git a/src/index.ts b/src/index.ts index a6a42d39..7fff67b7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -75,6 +75,7 @@ import { webhookMessage } from './webhook'; import { PythPriceFeedSubscriber } from './pythPriceFeedSubscriber'; import { PythCrankerBot } from './bots/pythCranker'; import { SwitchboardCrankerBot } from './bots/switchboardCranker'; +import { PythLazerCrankerBot } from './bots/pythLazerCranker'; require('dotenv').config(); const commitHash = process.env.COMMIT ?? ''; @@ -562,6 +563,19 @@ const runBot = async () => { ) ); } + if (configHasBot(config, 'pythLazerCranker')) { + needPriorityFeeSubscriber = true; + bots.push( + new PythLazerCrankerBot( + config.global, + config.botConfigs!.pythLazerCranker!, + driftClient, + priorityFeeSubscriber, + bundleSender, + [] + ) + ); + } if (configHasBot(config, 'switchboardCranker')) { needPriorityFeeSubscriber = true; needDriftStateWatcher = true; diff --git a/yarn.lock b/yarn.lock index a242d25c..26871db5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1138,7 +1138,15 @@ dependencies: bn.js "^5.2.1" -"@pythnetwork/pyth-solana-receiver@0.7.0": +"@pythnetwork/pyth-lazer-sdk@^0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@pythnetwork/pyth-lazer-sdk/-/pyth-lazer-sdk-0.1.1.tgz#5242c04f9b4f6ee0d3cc1aad228dfcb85b5e6498" + integrity sha512-/Zr9qbNi9YZb9Nl3ilkUKgeSQovevsXV57pIGrw04NFUmK4Ua92o2SyK8RRaqcw8zYtiDbseU1CgWHCfGYjRRQ== + dependencies: + isomorphic-ws "^5.0.0" + ws "^8.18.0" + +"@pythnetwork/pyth-solana-receiver@^0.7.0": version "0.7.0" resolved "https://registry.yarnpkg.com/@pythnetwork/pyth-solana-receiver/-/pyth-solana-receiver-0.7.0.tgz#253a0d15a135d625ceca7ba1b47940dd03b9cab6" integrity sha512-OoEAHh92RPRdKkfjkcKGrjC+t0F3SEL754iKFmixN9zyS8pIfZSVfFntmkHa9pWmqEMxdx/i925a8B5ny8Tuvg== @@ -3703,6 +3711,11 @@ isomorphic-ws@^4.0.1: resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== +isomorphic-ws@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" + integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== + jayson@^4.0.0, jayson@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.1.0.tgz#60dc946a85197317f2b1439d672a8b0a99cea2f9" @@ -5236,7 +5249,7 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@8.18.0: +ws@8.18.0, ws@^8.18.0: version "8.18.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== From 183fd46f05c0e018b0705e0f805656d279bcb0dd Mon Sep 17 00:00:00 2001 From: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 00:38:06 +0000 Subject: [PATCH 4/8] Bumping sdk and jit dependencies to 2.104.0-beta.33 and 0.12.20 --- package.json | 4 ++-- yarn.lock | 23 +++++++++++------------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 19c76068..c97f48bd 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "main": "lib/index.js", "license": "Apache-2.0", "dependencies": { - "@drift-labs/jit-proxy": "0.12.19", - "@drift-labs/sdk": "2.104.0-beta.32", + "@drift-labs/jit-proxy": "0.12.20", + "@drift-labs/sdk": "2.104.0-beta.33", "@opentelemetry/api": "1.7.0", "@opentelemetry/auto-instrumentations-node": "0.31.2", "@opentelemetry/exporter-prometheus": "0.31.0", diff --git a/yarn.lock b/yarn.lock index 26871db5..c8e57797 100644 --- a/yarn.lock +++ b/yarn.lock @@ -168,19 +168,19 @@ enabled "2.0.x" kuler "^2.0.0" -"@drift-labs/jit-proxy@0.12.19": - version "0.12.19" - resolved "https://registry.yarnpkg.com/@drift-labs/jit-proxy/-/jit-proxy-0.12.19.tgz#3cd6b3e9f3bae43fc8b250710f4073b8d5925b8b" - integrity sha512-w35uqL5TymBW3iZTw3mfYt2Gm8E8smqYf3s+yZyAEXDOQWkiusr/QLFZEYY07Pop4gzPszf9YvxFLf6/BIDFCg== +"@drift-labs/jit-proxy@0.12.20": + version "0.12.20" + resolved "https://registry.yarnpkg.com/@drift-labs/jit-proxy/-/jit-proxy-0.12.20.tgz#e6ac96a40048e6385d3d41cde766dc44fba58b83" + integrity sha512-+U2qCj3msonmLwVj0fh3GLzxckSksj7l9aWbTbxg4dUSTG2riyPjpnDy8E+k/+/TA7j2ZnrPV4ikqvPuPtijCw== dependencies: "@coral-xyz/anchor" "0.26.0" - "@drift-labs/sdk" "2.104.0-beta.32" + "@drift-labs/sdk" "2.104.0-beta.33" "@solana/web3.js" "1.91.7" -"@drift-labs/sdk@2.104.0-beta.32": - version "2.104.0-beta.32" - resolved "https://registry.yarnpkg.com/@drift-labs/sdk/-/sdk-2.104.0-beta.32.tgz#0065eb49089898fb9494ceb2728caef61c854510" - integrity sha512-G7XsghnJ9MugtXBo7kaOYdjToxFLPdN6+cfb8NXskfL/eMgwruoZSVuYK+Xv4Jscui+VDbWd1H/II6zBYcdjfw== +"@drift-labs/sdk@2.104.0-beta.33": + version "2.104.0-beta.33" + resolved "https://registry.yarnpkg.com/@drift-labs/sdk/-/sdk-2.104.0-beta.33.tgz#ea923408b7cf69efba1aefac135df966f4f44316" + integrity sha512-RPF9AiM6mn7/A8lBO6CqIdCOS0Wkn9nbOE7G8X0sJH5XNZZXML1EWLflKrkrQwVryBdXxmldyKVFCgGLDSkmfw== dependencies: "@coral-xyz/anchor" "0.29.0" "@coral-xyz/anchor-30" "npm:@coral-xyz/anchor@0.30.1" @@ -191,7 +191,6 @@ "@pythnetwork/client" "2.5.3" "@pythnetwork/price-service-sdk" "1.7.1" "@pythnetwork/pyth-solana-receiver" "0.7.0" - "@solana/buffer-layout" "4.0.1" "@solana/spl-token" "0.3.7" "@solana/web3.js" "1.92.3" "@switchboard-xyz/on-demand" "1.2.42" @@ -1146,7 +1145,7 @@ isomorphic-ws "^5.0.0" ws "^8.18.0" -"@pythnetwork/pyth-solana-receiver@^0.7.0": +"@pythnetwork/pyth-solana-receiver@0.7.0": version "0.7.0" resolved "https://registry.yarnpkg.com/@pythnetwork/pyth-solana-receiver/-/pyth-solana-receiver-0.7.0.tgz#253a0d15a135d625ceca7ba1b47940dd03b9cab6" integrity sha512-OoEAHh92RPRdKkfjkcKGrjC+t0F3SEL754iKFmixN9zyS8pIfZSVfFntmkHa9pWmqEMxdx/i925a8B5ny8Tuvg== @@ -1194,7 +1193,7 @@ bigint-buffer "^1.1.5" bignumber.js "^9.0.1" -"@solana/buffer-layout@4.0.1", "@solana/buffer-layout@^4.0.0", "@solana/buffer-layout@^4.0.1": +"@solana/buffer-layout@^4.0.0", "@solana/buffer-layout@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz#b996235eaec15b1e0b5092a8ed6028df77fa6c15" integrity sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA== From cc520183248370aadbd69647a338d82a4d5784d9 Mon Sep 17 00:00:00 2001 From: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 15:44:57 +0000 Subject: [PATCH 5/8] Bumping sdk and jit dependencies to 2.104.0-beta.34 and 0.12.21 --- package.json | 4 ++-- yarn.lock | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index c97f48bd..eb108a09 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "main": "lib/index.js", "license": "Apache-2.0", "dependencies": { - "@drift-labs/jit-proxy": "0.12.20", - "@drift-labs/sdk": "2.104.0-beta.33", + "@drift-labs/jit-proxy": "0.12.21", + "@drift-labs/sdk": "2.104.0-beta.34", "@opentelemetry/api": "1.7.0", "@opentelemetry/auto-instrumentations-node": "0.31.2", "@opentelemetry/exporter-prometheus": "0.31.0", diff --git a/yarn.lock b/yarn.lock index c8e57797..1b8936de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -168,19 +168,19 @@ enabled "2.0.x" kuler "^2.0.0" -"@drift-labs/jit-proxy@0.12.20": - version "0.12.20" - resolved "https://registry.yarnpkg.com/@drift-labs/jit-proxy/-/jit-proxy-0.12.20.tgz#e6ac96a40048e6385d3d41cde766dc44fba58b83" - integrity sha512-+U2qCj3msonmLwVj0fh3GLzxckSksj7l9aWbTbxg4dUSTG2riyPjpnDy8E+k/+/TA7j2ZnrPV4ikqvPuPtijCw== +"@drift-labs/jit-proxy@0.12.21": + version "0.12.21" + resolved "https://registry.yarnpkg.com/@drift-labs/jit-proxy/-/jit-proxy-0.12.21.tgz#7f4303b78966b7ef23d53cdd58ce252086b5a8ee" + integrity sha512-RQ5wvvzesYAgVXW+KhRGZNlEgQYF1TUoZAiUtT6vskuKronXMRI8HPzE9f8YeOAx2CsIWDBUhXqaduUMuy7EwQ== dependencies: "@coral-xyz/anchor" "0.26.0" - "@drift-labs/sdk" "2.104.0-beta.33" + "@drift-labs/sdk" "2.104.0-beta.34" "@solana/web3.js" "1.91.7" -"@drift-labs/sdk@2.104.0-beta.33": - version "2.104.0-beta.33" - resolved "https://registry.yarnpkg.com/@drift-labs/sdk/-/sdk-2.104.0-beta.33.tgz#ea923408b7cf69efba1aefac135df966f4f44316" - integrity sha512-RPF9AiM6mn7/A8lBO6CqIdCOS0Wkn9nbOE7G8X0sJH5XNZZXML1EWLflKrkrQwVryBdXxmldyKVFCgGLDSkmfw== +"@drift-labs/sdk@2.104.0-beta.34": + version "2.104.0-beta.34" + resolved "https://registry.yarnpkg.com/@drift-labs/sdk/-/sdk-2.104.0-beta.34.tgz#665ade52bc9af6333110246d597948e613e75fa3" + integrity sha512-ObXjbuAEP+hYzUVkvccMPCZbC00EwV6lEWPEb3fyHPqQUjjxklwTdZqpOJYyBBq/bKD/FYtoqw6PS4qgZ+m0wQ== dependencies: "@coral-xyz/anchor" "0.29.0" "@coral-xyz/anchor-30" "npm:@coral-xyz/anchor@0.30.1" From 8092561f043daf61215f6fc2b7247d4cfaf1d2c2 Mon Sep 17 00:00:00 2001 From: wphan Date: Thu, 19 Dec 2024 08:19:21 -0800 Subject: [PATCH 6/8] liquidator: use SOL routes when swapping LSTs (#322) --- src/bots/liquidator.ts | 26 ++++++++++++++++++++------ src/utils.ts | 11 +++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/bots/liquidator.ts b/src/bots/liquidator.ts index e088ef44..14c38f1c 100644 --- a/src/bots/liquidator.ts +++ b/src/bots/liquidator.ts @@ -82,6 +82,7 @@ import { calculateAccountValueUsd, checkIfAccountExists, handleSimResultError, + isSolLstToken, simulateAndGetTxWithCUs, SimulateAndGetTxWithCUsResponse, } from '../utils'; @@ -1259,10 +1260,17 @@ export class LiquidatorBot implements Bot { let outMarket: SpotMarketAccount | undefined; let inMarket: SpotMarketAccount | undefined; let amountIn: BN | undefined; + const spotMarketIsSolLst = isSolLstToken(spotMarketIndex); if (isVariant(orderDirection, 'long')) { - // sell USDC, buy spotMarketIndex - inMarket = this.driftClient.getSpotMarketAccount(0); - outMarket = this.driftClient.getSpotMarketAccount(spotMarketIndex); + if (spotMarketIsSolLst) { + // sell SOL, buy the LST + inMarket = this.driftClient.getSpotMarketAccount(1); + outMarket = this.driftClient.getSpotMarketAccount(spotMarketIndex); + } else { + // sell USDC, buy spotMarketIndex + inMarket = this.driftClient.getSpotMarketAccount(0); + outMarket = this.driftClient.getSpotMarketAccount(spotMarketIndex); + } if (!inMarket || !outMarket) { logger.error('failed to get spot markets'); return undefined; @@ -1274,9 +1282,15 @@ export class LiquidatorBot implements Bot { .mul(inPrecision) .div(PRICE_PRECISION.mul(outPrecision)); } else { - // sell spotMarketIndex, buy USDC - inMarket = this.driftClient.getSpotMarketAccount(spotMarketIndex); - outMarket = this.driftClient.getSpotMarketAccount(0); + if (spotMarketIsSolLst) { + // sell spotMarketIndex, buy SOL + inMarket = this.driftClient.getSpotMarketAccount(spotMarketIndex); + outMarket = this.driftClient.getSpotMarketAccount(1); + } else { + // sell spotMarketIndex, buy USDC + inMarket = this.driftClient.getSpotMarketAccount(spotMarketIndex); + outMarket = this.driftClient.getSpotMarketAccount(0); + } amountIn = baseAmountIn; } diff --git a/src/utils.ts b/src/utils.ts index b8bfe0f1..d442f263 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1553,3 +1553,14 @@ export function getMarketsAndOracleInfosToLoad( spotIndexes && spotIndexes.length > 0 ? spotIndexes : undefined, }; } + +export function isSolLstToken(spotMarketIndex: number): boolean { + return [ + 2, // mSOL + 6, // jitoSOL + 8, // bSOL + 16, // INF + 17, // dSOL + 25, // BNSOL + ].includes(spotMarketIndex); +} From 7b9ed59462ccd96d65a7d8301c044bd838cd919e Mon Sep 17 00:00:00 2001 From: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 17:11:27 +0000 Subject: [PATCH 7/8] Bumping sdk and jit dependencies to 2.104.0-beta.35 and 0.12.22 --- package.json | 4 ++-- yarn.lock | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index eb108a09..37148eb5 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "main": "lib/index.js", "license": "Apache-2.0", "dependencies": { - "@drift-labs/jit-proxy": "0.12.21", - "@drift-labs/sdk": "2.104.0-beta.34", + "@drift-labs/jit-proxy": "0.12.22", + "@drift-labs/sdk": "2.104.0-beta.35", "@opentelemetry/api": "1.7.0", "@opentelemetry/auto-instrumentations-node": "0.31.2", "@opentelemetry/exporter-prometheus": "0.31.0", diff --git a/yarn.lock b/yarn.lock index 1b8936de..1d5f97c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -168,19 +168,19 @@ enabled "2.0.x" kuler "^2.0.0" -"@drift-labs/jit-proxy@0.12.21": - version "0.12.21" - resolved "https://registry.yarnpkg.com/@drift-labs/jit-proxy/-/jit-proxy-0.12.21.tgz#7f4303b78966b7ef23d53cdd58ce252086b5a8ee" - integrity sha512-RQ5wvvzesYAgVXW+KhRGZNlEgQYF1TUoZAiUtT6vskuKronXMRI8HPzE9f8YeOAx2CsIWDBUhXqaduUMuy7EwQ== +"@drift-labs/jit-proxy@0.12.22": + version "0.12.22" + resolved "https://registry.yarnpkg.com/@drift-labs/jit-proxy/-/jit-proxy-0.12.22.tgz#76682541b6af0642153c16309f63badd53228982" + integrity sha512-y0qcfBN0ENde7OsaRCNSOtCGY7A6JYOuBY/C/s3zyJcjNzibhPR8GtrvU27zViu1vrusV3BUHRZnItGf88Jndw== dependencies: "@coral-xyz/anchor" "0.26.0" - "@drift-labs/sdk" "2.104.0-beta.34" + "@drift-labs/sdk" "2.104.0-beta.35" "@solana/web3.js" "1.91.7" -"@drift-labs/sdk@2.104.0-beta.34": - version "2.104.0-beta.34" - resolved "https://registry.yarnpkg.com/@drift-labs/sdk/-/sdk-2.104.0-beta.34.tgz#665ade52bc9af6333110246d597948e613e75fa3" - integrity sha512-ObXjbuAEP+hYzUVkvccMPCZbC00EwV6lEWPEb3fyHPqQUjjxklwTdZqpOJYyBBq/bKD/FYtoqw6PS4qgZ+m0wQ== +"@drift-labs/sdk@2.104.0-beta.35": + version "2.104.0-beta.35" + resolved "https://registry.yarnpkg.com/@drift-labs/sdk/-/sdk-2.104.0-beta.35.tgz#4dacbea1fa58ec86731859064cb88ac1e953ee8c" + integrity sha512-2KpU9fKtjTFjMPIKnL1CRbSggePl3sVxN2eY5m3yd8v3oc1v1SCW31bCj8M6ESur1kf9E6N0mABuFE3uzsv6KA== dependencies: "@coral-xyz/anchor" "0.29.0" "@coral-xyz/anchor-30" "npm:@coral-xyz/anchor@0.30.1" From 28cb4ff6de56b016a6e8b86b6efaf5d819111101 Mon Sep 17 00:00:00 2001 From: wphan Date: Thu, 19 Dec 2024 14:24:30 -0800 Subject: [PATCH 8/8] fillers: fix multimaker retry logic (#325) * fillers: fix multimaker retry logic * add missing tip ix --- src/bots/filler.ts | 33 +++--- src/bots/spotFiller.ts | 34 +++--- .../filler/fillerMultithreaded.ts | 107 +++++++++--------- .../spotFiller/spotFillerMultithreaded.ts | 40 +++---- 4 files changed, 110 insertions(+), 104 deletions(-) diff --git a/src/bots/filler.ts b/src/bots/filler.ts index d6d90130..5ba0f3ac 100644 --- a/src/bots/filler.ts +++ b/src/bots/filler.ts @@ -1427,22 +1427,6 @@ export class FillerBot extends TxThreaded implements Bot { nodeToFill: NodeToFill, buildForBundle: boolean ): Promise { - const ixs: Array = [ - ComputeBudgetProgram.setComputeUnitLimit({ - units: 1_400_000, - }), - ]; - if (!buildForBundle) { - ixs.push( - ComputeBudgetProgram.setComputeUnitPrice({ - microLamports: Math.floor( - this.priorityFeeSubscriber.getCustomStrategyResult() * - this.driftClient.txSender.getSuggestedPriorityFeeMultiplier() - ), - }) - ); - } - try { const { makerInfos, @@ -1477,6 +1461,23 @@ export class FillerBot extends TxThreaded implements Bot { ixs: Array; simResult: SimulateAndGetTxWithCUsResponse; }> => { + const ixs: Array = [ + ComputeBudgetProgram.setComputeUnitLimit({ + units: 1_400_000, + }), + ]; + if (buildForBundle) { + ixs.push(this.bundleSender!.getTipIx()); + } else { + ixs.push( + ComputeBudgetProgram.setComputeUnitPrice({ + microLamports: Math.floor( + this.priorityFeeSubscriber.getCustomStrategyResult() * + this.driftClient.txSender.getSuggestedPriorityFeeMultiplier() + ), + }) + ); + } ixs.push( await this.driftClient.getFillPerpOrderIx( await getUserAccountPublicKey( diff --git a/src/bots/spotFiller.ts b/src/bots/spotFiller.ts index 34ae5d59..ae57e4f3 100644 --- a/src/bots/spotFiller.ts +++ b/src/bots/spotFiller.ts @@ -1741,23 +1741,6 @@ export class SpotFillerBot implements Bot { buildForBundle: boolean, spotPrecision: BN ): Promise { - const ixs: Array = [ - ComputeBudgetProgram.setComputeUnitLimit({ - units: 1_400_000, - }), - ]; - if (buildForBundle) { - ixs.push(this.bundleSender!.getTipIx()); - } else { - ixs.push( - ComputeBudgetProgram.setComputeUnitPrice({ - microLamports: Math.floor( - this.priorityFeeSubscriber.getCustomStrategyResult() - ), - }) - ); - } - try { const { makerInfos, @@ -1788,6 +1771,23 @@ export class SpotFillerBot implements Bot { const buildTxWithMakerInfos = async ( makers: DataAndSlot[] ): Promise => { + const ixs: Array = [ + ComputeBudgetProgram.setComputeUnitLimit({ + units: 1_400_000, + }), + ]; + if (buildForBundle) { + ixs.push(this.bundleSender!.getTipIx()); + } else { + ixs.push( + ComputeBudgetProgram.setComputeUnitPrice({ + microLamports: Math.floor( + this.priorityFeeSubscriber.getCustomStrategyResult() + ), + }) + ); + } + ixs.push( await this.driftClient.getFillSpotOrderIx( new PublicKey(takerUserPubKey), diff --git a/src/experimental-bots/filler/fillerMultithreaded.ts b/src/experimental-bots/filler/fillerMultithreaded.ts index 5b52ac85..8a224775 100644 --- a/src/experimental-bots/filler/fillerMultithreaded.ts +++ b/src/experimental-bots/filler/fillerMultithreaded.ts @@ -1546,12 +1546,6 @@ export class FillerMultithreaded { fillTxId: number, nodeToFill: NodeToFillWithBuffer ): Promise { - let ixs: Array = [ - ComputeBudgetProgram.setComputeUnitLimit({ - units: 1_400_000, - }), - ]; - try { const { makerInfos, @@ -1563,60 +1557,69 @@ export class FillerMultithreaded { fillerRewardEstimate, } = await this.getNodeFillInfo(nodeToFill); - let removeLastIxPostSim = this.revertOnFailure; - if ( - this.pythPriceSubscriber && - ((makerInfos.length === 2 && !referrerInfo) || makerInfos.length < 2) - ) { - const pythIxs = await this.getPythIxsFromNode(nodeToFill); - ixs.push(...pythIxs); - removeLastIxPostSim = false; - } - - const priorityFeePrice = Math.floor( - this.priorityFeeSubscriber.getPriorityFees( - 'perp', - nodeToFill.node.order!.marketIndex! - )!.high * this.driftClient.txSender.getSuggestedPriorityFeeMultiplier() - ); const buildForBundle = this.shouldBuildForBundle(); - - if (buildForBundle) { - ixs.push(this.bundleSender!.getTipIx()); - } else { - ixs.push( - getPriorityFeeInstruction( - priorityFeePrice, - this.driftClient.getOracleDataForPerpMarket(0).price, - this.config.bidToFillerReward ? fillerRewardEstimate : undefined, - this.globalConfig.priorityFeeMultiplier - ) - ); - } - - logMessageForNodeToFill( - nodeToFill, - takerUserPubKey, - takerUserSlot, - makerInfos, - this.slotSubscriber.getSlot(), - fillTxId, - 'multiMakerFill', - this.revertOnFailure ?? false, - removeLastIxPostSim ?? false - ); - - if (!isVariant(marketType, 'perp')) { - throw new Error('expected perp market type'); - } - let makerInfosToUse = makerInfos; + const buildTxWithMakerInfos = async ( makers: DataAndSlot[] ): Promise => { if (makers.length === 0) { return undefined; } + + let ixs: Array = [ + ComputeBudgetProgram.setComputeUnitLimit({ + units: 1_400_000, + }), + ]; + + let removeLastIxPostSim = this.revertOnFailure; + if ( + this.pythPriceSubscriber && + ((makerInfos.length === 2 && !referrerInfo) || makerInfos.length < 2) + ) { + const pythIxs = await this.getPythIxsFromNode(nodeToFill); + ixs.push(...pythIxs); + removeLastIxPostSim = false; + } + + const priorityFeePrice = Math.floor( + this.priorityFeeSubscriber.getPriorityFees( + 'perp', + nodeToFill.node.order!.marketIndex! + )!.high * + this.driftClient.txSender.getSuggestedPriorityFeeMultiplier() + ); + + if (buildForBundle) { + ixs.push(this.bundleSender!.getTipIx()); + } else { + ixs.push( + getPriorityFeeInstruction( + priorityFeePrice, + this.driftClient.getOracleDataForPerpMarket(0).price, + this.config.bidToFillerReward ? fillerRewardEstimate : undefined, + this.globalConfig.priorityFeeMultiplier + ) + ); + } + + logMessageForNodeToFill( + nodeToFill, + takerUserPubKey, + takerUserSlot, + makerInfos, + this.slotSubscriber.getSlot(), + fillTxId, + 'multiMakerFill', + this.revertOnFailure ?? false, + removeLastIxPostSim ?? false + ); + + if (!isVariant(marketType, 'perp')) { + throw new Error('expected perp market type'); + } + ixs.push( await this.driftClient.getFillPerpOrderIx( await getUserAccountPublicKey( diff --git a/src/experimental-bots/spotFiller/spotFillerMultithreaded.ts b/src/experimental-bots/spotFiller/spotFillerMultithreaded.ts index db87e563..54ea7dd0 100644 --- a/src/experimental-bots/spotFiller/spotFillerMultithreaded.ts +++ b/src/experimental-bots/spotFiller/spotFillerMultithreaded.ts @@ -948,25 +948,6 @@ export class SpotFillerMultithreaded { )!.decimals ) ); - const ixs: Array = [ - ComputeBudgetProgram.setComputeUnitLimit({ - units: 1_400_000, - }), - ]; - if (buildForBundle) { - ixs.push(this.bundleSender!.getTipIx()); - } else { - ixs.push( - ComputeBudgetProgram.setComputeUnitPrice({ - microLamports: Math.floor( - this.priorityFeeSubscriber.getPriorityFees( - 'spot', - nodeToFill.node.order!.marketIndex - )!.high - ), - }) - ); - } try { const { @@ -1002,6 +983,27 @@ export class SpotFillerMultithreaded { if (makers.length === 0) { return undefined; } + + const ixs: Array = [ + ComputeBudgetProgram.setComputeUnitLimit({ + units: 1_400_000, + }), + ]; + if (buildForBundle) { + ixs.push(this.bundleSender!.getTipIx()); + } else { + ixs.push( + ComputeBudgetProgram.setComputeUnitPrice({ + microLamports: Math.floor( + this.priorityFeeSubscriber.getPriorityFees( + 'spot', + nodeToFill.node.order!.marketIndex + )!.high + ), + }) + ); + } + ixs.push( await this.driftClient.getFillSpotOrderIx( new PublicKey(takerUserPubKey),