From ab16a326f017bf4feaa7a1754d8b7bf89ecd15d4 Mon Sep 17 00:00:00 2001 From: Filip Dunder Date: Fri, 9 Feb 2024 17:19:57 +0100 Subject: [PATCH] fix: remove open book cache, improve startup speed --- buy.ts | 61 +++++++++++++++++++++--------------------------- market/market.ts | 47 ++++++++++--------------------------- 2 files changed, 39 insertions(+), 69 deletions(-) diff --git a/buy.ts b/buy.ts index fe69c62..8b3aa80 100644 --- a/buy.ts +++ b/buy.ts @@ -3,7 +3,6 @@ import { LIQUIDITY_STATE_LAYOUT_V4, LiquidityPoolKeys, LiquidityStateV4, - MARKET_STATE_LAYOUT_V2, MARKET_STATE_LAYOUT_V3, MarketStateV3, Token, @@ -31,7 +30,7 @@ import { createPoolKeys, } from './liquidity'; import { retrieveEnvVariable } from './utils'; -import { getAllMarketsV3, MinimalMarketLayoutV3 } from './market'; +import { getMinimalMarketV3, MinimalMarketLayoutV3 } from './market'; import pino from 'pino'; import bs58 from 'bs58'; import * as fs from 'fs'; @@ -144,17 +143,6 @@ async function init(): Promise { `Script will buy all new tokens using ${QUOTE_MINT}. Amount that will be used to buy each token is: ${quoteAmount.toFixed().toString()}`, ); - logger.info(`Loading existing markets...`); - // get all open-book markets - const allMarkets = await getAllMarketsV3( - solanaConnection, - quoteToken.mint, - commitment, - ); - existingOpenBookMarkets = new Set(allMarkets.map((p) => p.id.toString())); - logger.info( - `Loaded ${existingOpenBookMarkets.size} ${quoteToken.symbol} markets`, - ); // check existing wallet for associated token account of quote mint const tokenAccounts = await getTokenAccounts( solanaConnection, @@ -187,6 +175,21 @@ async function init(): Promise { loadSnipeList(); } +function saveTokenAccount(mint: PublicKey, accountData: MinimalMarketLayoutV3) { + const ata = getAssociatedTokenAddressSync(mint, wallet.publicKey); + const tokenAccount = { + address: ata, + mint: mint, + market: { + bids: accountData.bids, + asks: accountData.asks, + eventQueue: accountData.eventQueue, + }, + }; + existingTokenAccounts.set(mint.toString(), tokenAccount); + return tokenAccount; +} + export async function processRaydiumPool( id: PublicKey, poolState: LiquidityStateV4, @@ -216,21 +219,7 @@ export async function processOpenBookMarket( return; } - const ata = getAssociatedTokenAddressSync( - accountData.baseMint, - wallet.publicKey, - ); - existingTokenAccounts.set(accountData.baseMint.toString(), < - MinimalTokenAccountData - >{ - address: ata, - mint: accountData.baseMint, - market: { - bids: accountData.bids, - asks: accountData.asks, - eventQueue: accountData.eventQueue, - }, - }); + saveTokenAccount(accountData.baseMint, accountData); } catch (e) { logger.error({ ...accountData, error: e }, `Failed to process market`); } @@ -240,12 +229,16 @@ async function buy( accountId: PublicKey, accountData: LiquidityStateV4, ): Promise { - const tokenAccount = existingTokenAccounts.get( - accountData.baseMint.toString(), - ); + let tokenAccount = existingTokenAccounts.get(accountData.baseMint.toString()); if (!tokenAccount) { - return; + // it's possible that we didn't have time to fetch open book data + const market = await getMinimalMarketV3( + solanaConnection, + accountData.marketId, + commitment, + ); + tokenAccount = saveTokenAccount(accountData.baseMint, market); } tokenAccount.poolKeys = createPoolKeys( @@ -378,10 +371,10 @@ const runListener = async () => { }, commitment, [ - { dataSize: MARKET_STATE_LAYOUT_V2.span }, + { dataSize: MARKET_STATE_LAYOUT_V3.span }, { memcmp: { - offset: MARKET_STATE_LAYOUT_V2.offsetOf('quoteMint'), + offset: MARKET_STATE_LAYOUT_V3.offsetOf('quoteMint'), bytes: quoteToken.mint.toBase58(), }, }, diff --git a/market/market.ts b/market/market.ts index bff51f0..0593e35 100644 --- a/market/market.ts +++ b/market/market.ts @@ -1,46 +1,23 @@ import { Commitment, Connection, PublicKey } from '@solana/web3.js'; -import { - GetStructureSchema, - MARKET_STATE_LAYOUT_V3, -} from '@raydium-io/raydium-sdk'; -import { - MINIMAL_MARKET_STATE_LAYOUT_V3, - OPENBOOK_PROGRAM_ID, -} from '../liquidity'; +import { GetStructureSchema, MARKET_STATE_LAYOUT_V3 } from '@raydium-io/raydium-sdk'; +import { MINIMAL_MARKET_STATE_LAYOUT_V3 } from '../liquidity'; -export type MinimalOpenBookAccountData = { - id: PublicKey; - programId: PublicKey; -}; export type MinimalMarketStateLayoutV3 = typeof MINIMAL_MARKET_STATE_LAYOUT_V3; export type MinimalMarketLayoutV3 = GetStructureSchema; -export async function getAllMarketsV3( +export async function getMinimalMarketV3( connection: Connection, - quoteMint: PublicKey, + marketId: PublicKey, commitment?: Commitment, -): Promise { - const { span } = MARKET_STATE_LAYOUT_V3; - const accounts = await connection.getProgramAccounts(OPENBOOK_PROGRAM_ID, { - dataSlice: { offset: 0, length: 0 }, - commitment: commitment, - filters: [ - { dataSize: span }, - { - memcmp: { - offset: MARKET_STATE_LAYOUT_V3.offsetOf('quoteMint'), - bytes: quoteMint.toBase58(), - }, - }, - ], +): Promise { + const marketInfo = await connection.getAccountInfo(marketId, { + commitment, + dataSlice: { + offset: MARKET_STATE_LAYOUT_V3.offsetOf('eventQueue'), + length: 32 * 3, + }, }); - return accounts.map( - (info) => - { - id: info.pubkey, - programId: OPENBOOK_PROGRAM_ID, - }, - ); + return MINIMAL_MARKET_STATE_LAYOUT_V3.decode(marketInfo!.data); }