mirror of
https://github.com/fdundjer/solana-sniper-bot.git
synced 2026-06-22 04:11:27 +10:00
Merge pull request #31 from fdundjer/feature/remove-open-book-cache
fix: remove open book cache, improve startup speed
This commit is contained in:
@@ -3,7 +3,6 @@ import {
|
|||||||
LIQUIDITY_STATE_LAYOUT_V4,
|
LIQUIDITY_STATE_LAYOUT_V4,
|
||||||
LiquidityPoolKeys,
|
LiquidityPoolKeys,
|
||||||
LiquidityStateV4,
|
LiquidityStateV4,
|
||||||
MARKET_STATE_LAYOUT_V2,
|
|
||||||
MARKET_STATE_LAYOUT_V3,
|
MARKET_STATE_LAYOUT_V3,
|
||||||
MarketStateV3,
|
MarketStateV3,
|
||||||
Token,
|
Token,
|
||||||
@@ -31,7 +30,7 @@ import {
|
|||||||
createPoolKeys,
|
createPoolKeys,
|
||||||
} from './liquidity';
|
} from './liquidity';
|
||||||
import { retrieveEnvVariable } from './utils';
|
import { retrieveEnvVariable } from './utils';
|
||||||
import { getAllMarketsV3, MinimalMarketLayoutV3 } from './market';
|
import { getMinimalMarketV3, MinimalMarketLayoutV3 } from './market';
|
||||||
import pino from 'pino';
|
import pino from 'pino';
|
||||||
import bs58 from 'bs58';
|
import bs58 from 'bs58';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
@@ -144,17 +143,6 @@ async function init(): Promise<void> {
|
|||||||
`Script will buy all new tokens using ${QUOTE_MINT}. Amount that will be used to buy each token is: ${quoteAmount.toFixed().toString()}`,
|
`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
|
// check existing wallet for associated token account of quote mint
|
||||||
const tokenAccounts = await getTokenAccounts(
|
const tokenAccounts = await getTokenAccounts(
|
||||||
solanaConnection,
|
solanaConnection,
|
||||||
@@ -187,6 +175,21 @@ async function init(): Promise<void> {
|
|||||||
loadSnipeList();
|
loadSnipeList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function saveTokenAccount(mint: PublicKey, accountData: MinimalMarketLayoutV3) {
|
||||||
|
const ata = getAssociatedTokenAddressSync(mint, wallet.publicKey);
|
||||||
|
const tokenAccount = <MinimalTokenAccountData>{
|
||||||
|
address: ata,
|
||||||
|
mint: mint,
|
||||||
|
market: <MinimalMarketLayoutV3>{
|
||||||
|
bids: accountData.bids,
|
||||||
|
asks: accountData.asks,
|
||||||
|
eventQueue: accountData.eventQueue,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
existingTokenAccounts.set(mint.toString(), tokenAccount);
|
||||||
|
return tokenAccount;
|
||||||
|
}
|
||||||
|
|
||||||
export async function processRaydiumPool(
|
export async function processRaydiumPool(
|
||||||
id: PublicKey,
|
id: PublicKey,
|
||||||
poolState: LiquidityStateV4,
|
poolState: LiquidityStateV4,
|
||||||
@@ -216,21 +219,7 @@ export async function processOpenBookMarket(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ata = getAssociatedTokenAddressSync(
|
saveTokenAccount(accountData.baseMint, accountData);
|
||||||
accountData.baseMint,
|
|
||||||
wallet.publicKey,
|
|
||||||
);
|
|
||||||
existingTokenAccounts.set(accountData.baseMint.toString(), <
|
|
||||||
MinimalTokenAccountData
|
|
||||||
>{
|
|
||||||
address: ata,
|
|
||||||
mint: accountData.baseMint,
|
|
||||||
market: <MinimalMarketLayoutV3>{
|
|
||||||
bids: accountData.bids,
|
|
||||||
asks: accountData.asks,
|
|
||||||
eventQueue: accountData.eventQueue,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error({ ...accountData, error: e }, `Failed to process market`);
|
logger.error({ ...accountData, error: e }, `Failed to process market`);
|
||||||
}
|
}
|
||||||
@@ -240,12 +229,16 @@ async function buy(
|
|||||||
accountId: PublicKey,
|
accountId: PublicKey,
|
||||||
accountData: LiquidityStateV4,
|
accountData: LiquidityStateV4,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const tokenAccount = existingTokenAccounts.get(
|
let tokenAccount = existingTokenAccounts.get(accountData.baseMint.toString());
|
||||||
accountData.baseMint.toString(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!tokenAccount) {
|
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(
|
tokenAccount.poolKeys = createPoolKeys(
|
||||||
@@ -378,10 +371,10 @@ const runListener = async () => {
|
|||||||
},
|
},
|
||||||
commitment,
|
commitment,
|
||||||
[
|
[
|
||||||
{ dataSize: MARKET_STATE_LAYOUT_V2.span },
|
{ dataSize: MARKET_STATE_LAYOUT_V3.span },
|
||||||
{
|
{
|
||||||
memcmp: {
|
memcmp: {
|
||||||
offset: MARKET_STATE_LAYOUT_V2.offsetOf('quoteMint'),
|
offset: MARKET_STATE_LAYOUT_V3.offsetOf('quoteMint'),
|
||||||
bytes: quoteToken.mint.toBase58(),
|
bytes: quoteToken.mint.toBase58(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
+12
-35
@@ -1,46 +1,23 @@
|
|||||||
import { Commitment, Connection, PublicKey } from '@solana/web3.js';
|
import { Commitment, Connection, PublicKey } from '@solana/web3.js';
|
||||||
import {
|
import { GetStructureSchema, MARKET_STATE_LAYOUT_V3 } from '@raydium-io/raydium-sdk';
|
||||||
GetStructureSchema,
|
import { MINIMAL_MARKET_STATE_LAYOUT_V3 } from '../liquidity';
|
||||||
MARKET_STATE_LAYOUT_V3,
|
|
||||||
} from '@raydium-io/raydium-sdk';
|
|
||||||
import {
|
|
||||||
MINIMAL_MARKET_STATE_LAYOUT_V3,
|
|
||||||
OPENBOOK_PROGRAM_ID,
|
|
||||||
} from '../liquidity';
|
|
||||||
|
|
||||||
export type MinimalOpenBookAccountData = {
|
|
||||||
id: PublicKey;
|
|
||||||
programId: PublicKey;
|
|
||||||
};
|
|
||||||
export type MinimalMarketStateLayoutV3 = typeof MINIMAL_MARKET_STATE_LAYOUT_V3;
|
export type MinimalMarketStateLayoutV3 = typeof MINIMAL_MARKET_STATE_LAYOUT_V3;
|
||||||
export type MinimalMarketLayoutV3 =
|
export type MinimalMarketLayoutV3 =
|
||||||
GetStructureSchema<MinimalMarketStateLayoutV3>;
|
GetStructureSchema<MinimalMarketStateLayoutV3>;
|
||||||
|
|
||||||
export async function getAllMarketsV3(
|
export async function getMinimalMarketV3(
|
||||||
connection: Connection,
|
connection: Connection,
|
||||||
quoteMint: PublicKey,
|
marketId: PublicKey,
|
||||||
commitment?: Commitment,
|
commitment?: Commitment,
|
||||||
): Promise<MinimalOpenBookAccountData[]> {
|
): Promise<MinimalMarketLayoutV3> {
|
||||||
const { span } = MARKET_STATE_LAYOUT_V3;
|
const marketInfo = await connection.getAccountInfo(marketId, {
|
||||||
const accounts = await connection.getProgramAccounts(OPENBOOK_PROGRAM_ID, {
|
commitment,
|
||||||
dataSlice: { offset: 0, length: 0 },
|
dataSlice: {
|
||||||
commitment: commitment,
|
offset: MARKET_STATE_LAYOUT_V3.offsetOf('eventQueue'),
|
||||||
filters: [
|
length: 32 * 3,
|
||||||
{ dataSize: span },
|
},
|
||||||
{
|
|
||||||
memcmp: {
|
|
||||||
offset: MARKET_STATE_LAYOUT_V3.offsetOf('quoteMint'),
|
|
||||||
bytes: quoteMint.toBase58(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return accounts.map(
|
return MINIMAL_MARKET_STATE_LAYOUT_V3.decode(marketInfo!.data);
|
||||||
(info) =>
|
|
||||||
<MinimalOpenBookAccountData>{
|
|
||||||
id: info.pubkey,
|
|
||||||
programId: OPENBOOK_PROGRAM_ID,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user