From 050c83d6c84cb26315fed46b0819b18ca0dc0261 Mon Sep 17 00:00:00 2001 From: "Ricardo J. Mendez" Date: Wed, 25 Oct 2023 10:09:32 +0200 Subject: [PATCH 1/6] BUGFIX: uncrossArbBot was not obeying dry run setting --- src/bots/uncrossArbBot.ts | 87 +++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 36 deletions(-) diff --git a/src/bots/uncrossArbBot.ts b/src/bots/uncrossArbBot.ts index 8477a1f6..17fb43af 100644 --- a/src/bots/uncrossArbBot.ts +++ b/src/bots/uncrossArbBot.ts @@ -88,6 +88,10 @@ export class UncrossArbBot implements Bot { public async init(): Promise { logger.info(`${this.name} initing`); + if (this.dryRun) { + logger.warn(`${this.name} on DRY RUN. Will not place any transactions.`); + } + await this.dlobSubscriber.subscribe(); this.lookupTableAccount = await this.driftClient.fetchMarketLookupTableAccount(); @@ -215,46 +219,57 @@ export class UncrossArbBot implements Bot { 2 * driftUser.getMarketFees(MarketType.PERP, perpIdx).takerFee ) { try { - this.driftClient.txSender - .sendVersionedTransaction( - await this.driftClient.txSender.getVersionedTransaction( - [ - ComputeBudgetProgram.setComputeUnitLimit({ - units: 1_000_000, - }), - await this.jitProxyClient.getArbPerpIx({ - marketIndex: perpIdx, - makerInfos: [bidMakerInfo, askMakerInfo], - }), - ], - [this.lookupTableAccount!], + logger.info( + `Found arb opportunity @ midPrice $${midPrice.toFixed( + 4 + )} between Bid: $${bestBidPrice.toFixed( + 4 + )} Ask: $${bestAskPrice.toFixed(4)} ` + ); + if (!this.dryRun) { + this.driftClient.txSender + .sendVersionedTransaction( + await this.driftClient.txSender.getVersionedTransaction( + [ + ComputeBudgetProgram.setComputeUnitLimit({ + units: 1_000_000, + }), + await this.jitProxyClient.getArbPerpIx({ + marketIndex: perpIdx, + makerInfos: [bidMakerInfo, askMakerInfo], + }), + ], + [this.lookupTableAccount!], + [], + this.driftClient.opts + ), [], this.driftClient.opts - ), - [], - this.driftClient.opts - ) - .then((txResult) => { - logger.info( - `Potential arb with sig: ${txResult.txSig}. Check the blockchain for confirmation.` - ); - }) - .catch((e) => { - if (e.logs && e.logs.length > 0) { - let noArbOpError = false; - for (const log of e.logs) { - if (log.includes('NoArbOpportunity')) { - noArbOpError = true; - break; + ) + .then((txResult) => { + logger.info( + `Potential arb with sig: ${txResult.txSig}. Check the blockchain for confirmation.` + ); + }) + .catch((e) => { + if (e.logs && e.logs.length > 0) { + let noArbOpError = false; + for (const log of e.logs) { + if (log.includes('NoArbOpportunity')) { + noArbOpError = true; + break; + } } + console.error(`Not no arb opp error:\n`); + console.error(e); + } else { + console.error(`Caught unknown error:\n`); + console.error(e); } - console.error(`Not no arb opp error:\n`); - console.error(e); - } else { - console.error(`Caught unknown error:\n`); - console.error(e); - } - }); + }); + } else { + logger.warn(`DRY RUN - Did not place any transactions`); + } } catch (e) { if (e instanceof Error) { logger.error( From 9dba7357d8fd016355381da3edb23529d45bdf61 Mon Sep 17 00:00:00 2001 From: "Ricardo J. Mendez" Date: Wed, 25 Oct 2023 11:09:43 +0200 Subject: [PATCH 2/6] Removed unused imports from uncrossArbBot --- src/bots/uncrossArbBot.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/bots/uncrossArbBot.ts b/src/bots/uncrossArbBot.ts index 17fb43af..ed9cb699 100644 --- a/src/bots/uncrossArbBot.ts +++ b/src/bots/uncrossArbBot.ts @@ -9,9 +9,7 @@ import { DLOBSubscriber, UserMap, SlotSubscriber, - UserStatsMap, MakerInfo, - PerpMarkets, getUserStatsAccountPublicKey, } from '@drift-labs/sdk'; import { Mutex, tryAcquire, E_ALREADY_LOCKED } from 'async-mutex'; @@ -20,7 +18,6 @@ import { Bot } from '../types'; import { getBestLimitAskExcludePubKey, getBestLimitBidExcludePubKey, - sleepMs, } from '../utils'; import { JitProxyClient } from '@drift-labs/jit-proxy/lib'; import dotenv = require('dotenv'); @@ -29,7 +26,6 @@ dotenv.config(); import { BaseBotConfig } from 'src/config'; import { AddressLookupTableAccount, - ComputeBudgetInstruction, ComputeBudgetProgram, } from '@solana/web3.js'; From 927d7701313582a971ec0979f06a7e467b41ea6e Mon Sep 17 00:00:00 2001 From: "Ricardo J. Mendez" Date: Wed, 25 Oct 2023 11:22:45 +0200 Subject: [PATCH 3/6] Removed exception dump on NoArbOpportunity The client is already logging it, there's no need to do it twice. Also updated the error log, since there was a double negative. --- src/bots/uncrossArbBot.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bots/uncrossArbBot.ts b/src/bots/uncrossArbBot.ts index ed9cb699..a95887ac 100644 --- a/src/bots/uncrossArbBot.ts +++ b/src/bots/uncrossArbBot.ts @@ -256,8 +256,7 @@ export class UncrossArbBot implements Bot { break; } } - console.error(`Not no arb opp error:\n`); - console.error(e); + console.error(`NoArbOpportunity error`); } else { console.error(`Caught unknown error:\n`); console.error(e); From f4d28f5d0ce16dc826c9ed96597e760687d0d029 Mon Sep 17 00:00:00 2001 From: "Ricardo J. Mendez" Date: Wed, 25 Oct 2023 11:30:24 +0200 Subject: [PATCH 4/6] Adding priority fees to uncrossArbBot --- src/bots/uncrossArbBot.ts | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/bots/uncrossArbBot.ts b/src/bots/uncrossArbBot.ts index a95887ac..cdb19894 100644 --- a/src/bots/uncrossArbBot.ts +++ b/src/bots/uncrossArbBot.ts @@ -11,6 +11,7 @@ import { SlotSubscriber, MakerInfo, getUserStatsAccountPublicKey, + PriorityFeeCalculator, } from '@drift-labs/sdk'; import { Mutex, tryAcquire, E_ALREADY_LOCKED } from 'async-mutex'; import { logger } from '../logger'; @@ -24,10 +25,7 @@ import dotenv = require('dotenv'); dotenv.config(); import { BaseBotConfig } from 'src/config'; -import { - AddressLookupTableAccount, - ComputeBudgetProgram, -} from '@solana/web3.js'; +import { AddressLookupTableAccount } from '@solana/web3.js'; const TARGET_LEVERAGE_PER_ACCOUNT = 1; @@ -53,6 +51,7 @@ export class UncrossArbBot implements Bot { private dlobSubscriber: DLOBSubscriber; private slotSubscriber: SlotSubscriber; private userMap: UserMap; + private priorityFeeCalculator: PriorityFeeCalculator; constructor( driftClient: DriftClient, // driftClient needs to have correct number of subaccounts listed @@ -70,6 +69,8 @@ export class UncrossArbBot implements Bot { this.slotSubscriber = slotSubscriber; this.userMap = userMap; + this.priorityFeeCalculator = new PriorityFeeCalculator(Date.now()); + this.dlobSubscriber = new DLOBSubscriber({ dlobSource: this.userMap, slotSource: this.slotSubscriber, @@ -223,18 +224,27 @@ export class UncrossArbBot implements Bot { )} Ask: $${bestAskPrice.toFixed(4)} ` ); if (!this.dryRun) { + const usePriorityFee = + this.priorityFeeCalculator.updatePriorityFee( + Date.now(), + this.driftClient.txSender.getTimeoutCount() + ); + const ixs = + this.priorityFeeCalculator.generateComputeBudgetWithPriorityFeeIx( + 1_000_000, + usePriorityFee, + 1_000_000_000 // 1000 lamports + ); + ixs.push( + await this.jitProxyClient.getArbPerpIx({ + marketIndex: perpIdx, + makerInfos: [bidMakerInfo, askMakerInfo], + }) + ); this.driftClient.txSender .sendVersionedTransaction( await this.driftClient.txSender.getVersionedTransaction( - [ - ComputeBudgetProgram.setComputeUnitLimit({ - units: 1_000_000, - }), - await this.jitProxyClient.getArbPerpIx({ - marketIndex: perpIdx, - makerInfos: [bidMakerInfo, askMakerInfo], - }), - ], + ixs, [this.lookupTableAccount!], [], this.driftClient.opts From 04129c785042b60f263fe141714c0d0897d74aa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20J=2E=20Me=CC=81ndez?= Date: Mon, 30 Oct 2023 09:05:28 +0100 Subject: [PATCH 5/6] Fixed noArbOpError logging It wasn't logging the errors in the case where there were logs BUT it hadn't been a noArbOpError. --- src/bots/uncrossArbBot.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bots/uncrossArbBot.ts b/src/bots/uncrossArbBot.ts index cdb19894..5a60dfa8 100644 --- a/src/bots/uncrossArbBot.ts +++ b/src/bots/uncrossArbBot.ts @@ -258,14 +258,16 @@ export class UncrossArbBot implements Bot { ); }) .catch((e) => { + let noArbOpError = false; if (e.logs && e.logs.length > 0) { - let noArbOpError = false; for (const log of e.logs) { if (log.includes('NoArbOpportunity')) { noArbOpError = true; break; } } + } + if (noArbOpError) { console.error(`NoArbOpportunity error`); } else { console.error(`Caught unknown error:\n`); From 74b8847376520bf0883eaff9c4a7afb2377951f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20J=2E=20Me=CC=81ndez?= Date: Mon, 30 Oct 2023 09:30:12 +0100 Subject: [PATCH 6/6] Added optional fee multiplier to uncrossArbBot --- src/bots/uncrossArbBot.ts | 19 ++++++++++++++++--- src/config.ts | 4 ++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/bots/uncrossArbBot.ts b/src/bots/uncrossArbBot.ts index 5a60dfa8..853cfa88 100644 --- a/src/bots/uncrossArbBot.ts +++ b/src/bots/uncrossArbBot.ts @@ -24,7 +24,7 @@ import { JitProxyClient } from '@drift-labs/jit-proxy/lib'; import dotenv = require('dotenv'); dotenv.config(); -import { BaseBotConfig } from 'src/config'; +import { UncrossArbBotConfig } from 'src/config'; import { AddressLookupTableAccount } from '@solana/web3.js'; const TARGET_LEVERAGE_PER_ACCOUNT = 1; @@ -53,12 +53,14 @@ export class UncrossArbBot implements Bot { private userMap: UserMap; private priorityFeeCalculator: PriorityFeeCalculator; + private feeMultiplier: number; + constructor( driftClient: DriftClient, // driftClient needs to have correct number of subaccounts listed jitProxyClient: JitProxyClient, slotSubscriber: SlotSubscriber, userMap: UserMap, - config: BaseBotConfig, + config: UncrossArbBotConfig, driftEnv: DriftEnv ) { this.jitProxyClient = jitProxyClient; @@ -68,6 +70,7 @@ export class UncrossArbBot implements Bot { this.driftEnv = driftEnv; this.slotSubscriber = slotSubscriber; this.userMap = userMap; + this.feeMultiplier = config.feeMultiplier ?? 1; this.priorityFeeCalculator = new PriorityFeeCalculator(Date.now()); @@ -89,6 +92,14 @@ export class UncrossArbBot implements Bot { logger.warn(`${this.name} on DRY RUN. Will not place any transactions.`); } + if (this.feeMultiplier != 1) { + logger.info( + `${this.name} using ${this.feeMultiplier.toFixed( + 2 + )} as a fee multiplier` + ); + } + await this.dlobSubscriber.subscribe(); this.lookupTableAccount = await this.driftClient.fetchMarketLookupTableAccount(); @@ -213,7 +224,9 @@ export class UncrossArbBot implements Bot { const midPrice = (bestBidPrice + bestAskPrice) / 2; if ( (bestBidPrice - bestAskPrice) / midPrice > - 2 * driftUser.getMarketFees(MarketType.PERP, perpIdx).takerFee + this.feeMultiplier * + 2 * + driftUser.getMarketFees(MarketType.PERP, perpIdx).takerFee ) { try { logger.info( diff --git a/src/config.ts b/src/config.ts index 3a0ce09f..c285ae00 100644 --- a/src/config.ts +++ b/src/config.ts @@ -26,6 +26,10 @@ export type FillerConfig = BaseBotConfig & { revertOnFailure?: boolean; }; +export type UncrossArbBotConfig = BaseBotConfig & { + feeMultiplier?: number; +}; + export type SubaccountConfig = { [key: number]: Array; };