From 508e5214339ea38a4e8c9c2d5d24cc520bb63f76 Mon Sep 17 00:00:00 2001 From: Theo Brigitte Date: Fri, 19 Apr 2024 23:00:32 +0200 Subject: [PATCH 1/4] Add freezable filter Check if owner can freeze tokens --- .env.copy | 1 + bot.ts | 1 + filters/pool-filters.ts | 8 ++++---- filters/renounced.filter.ts | 19 ++++++++++++------- helpers/constants.ts | 1 + index.ts | 3 +++ 6 files changed, 22 insertions(+), 11 deletions(-) diff --git a/.env.copy b/.env.copy index 0bcb847..2a4bdfd 100644 --- a/.env.copy +++ b/.env.copy @@ -43,6 +43,7 @@ FILTER_CHECK_DURATION=60000 FILTER_CHECK_INTERVAL=2000 CONSECUTIVE_FILTER_MATCHES=3 CHECK_IF_MINT_IS_RENOUNCED=true +CHECK_IF_FREEZABLE=true CHECK_IF_BURNED=true MIN_POOL_SIZE=5 MAX_POOL_SIZE=50 diff --git a/bot.ts b/bot.ts index 7e80090..eaf307b 100644 --- a/bot.ts +++ b/bot.ts @@ -26,6 +26,7 @@ import { WarpTransactionExecutor } from './transactions/warp-transaction-executo export interface BotConfig { wallet: Keypair; checkRenounced: boolean; + checkFreezable: boolean; checkBurned: boolean; minPoolSize: TokenAmount; maxPoolSize: TokenAmount; diff --git a/filters/pool-filters.ts b/filters/pool-filters.ts index 9af1310..fc7d457 100644 --- a/filters/pool-filters.ts +++ b/filters/pool-filters.ts @@ -1,9 +1,9 @@ import { Connection } from '@solana/web3.js'; import { LiquidityPoolKeysV4, Token, TokenAmount } from '@raydium-io/raydium-sdk'; import { BurnFilter } from './burn.filter'; -import { RenouncedFilter } from './renounced.filter'; +import { RenouncedFreezeFilter } from './renounced.filter'; import { PoolSizeFilter } from './pool-size.filter'; -import { CHECK_IF_BURNED, CHECK_IF_MINT_IS_RENOUNCED, logger } from '../helpers'; +import { CHECK_IF_BURNED, CHECK_IF_FREEZABLE, CHECK_IF_MINT_IS_RENOUNCED, logger } from '../helpers'; export interface Filter { execute(poolKeysV4: LiquidityPoolKeysV4): Promise; @@ -31,8 +31,8 @@ export class PoolFilters { this.filters.push(new BurnFilter(connection)); } - if (CHECK_IF_MINT_IS_RENOUNCED) { - this.filters.push(new RenouncedFilter(connection)); + if (CHECK_IF_MINT_IS_RENOUNCED || CHECK_IF_FREEZABLE) { + this.filters.push(new RenouncedFreezeFilter(connection, CHECK_IF_MINT_IS_RENOUNCED, CHECK_IF_FREEZABLE)); } if (!args.minPoolSize.isZero() || !args.maxPoolSize.isZero()) { diff --git a/filters/renounced.filter.ts b/filters/renounced.filter.ts index c5d6884..ab828c1 100644 --- a/filters/renounced.filter.ts +++ b/filters/renounced.filter.ts @@ -4,23 +4,28 @@ import { Connection } from '@solana/web3.js'; import { LiquidityPoolKeysV4 } from '@raydium-io/raydium-sdk'; import { logger } from '../helpers'; -export class RenouncedFilter implements Filter { - constructor(private readonly connection: Connection) {} +export class RenouncedFreezeFilter implements Filter { + constructor(private readonly connection: Connection, private readonly checkRenounced: boolean, private readonly checkFreezable: boolean) {} async execute(poolKeys: LiquidityPoolKeysV4): Promise { try { const accountInfo = await this.connection.getAccountInfo(poolKeys.baseMint, this.connection.commitment); if (!accountInfo?.data) { - return { ok: false, message: 'Renounced -> Failed to fetch account data' }; + return { ok: false, message: 'Failed to fetch account data' }; } const deserialize = MintLayout.decode(accountInfo.data); - const renounced = deserialize.mintAuthorityOption === 0; - return { ok: renounced, message: renounced ? undefined : 'Renounced -> Creator can mint more tokens' }; + const renounced = !this.checkRenounced || deserialize.mintAuthorityOption === 0; + const freezable = !this.checkFreezable || deserialize.freezeAuthorityOption !== 0; + + const message = [ renounced ? undefined : 'mint', !freezable ? undefined : 'freeze' ].filter((e) => e !== undefined); + const ok = renounced && !freezable; + + return { ok: ok, message: ok ? undefined : `RenouncedFreeze -> Creator can ${message.join(' and ')} tokens` }; } catch (e) { - logger.error({ mint: poolKeys.baseMint }, `Failed to check if mint is renounced`); + logger.error({ mint: poolKeys.baseMint }, `Failed to check if mint is renounced and freezable`); } - return { ok: false, message: 'Renounced -> Failed to check if mint is renounced' }; + return { ok: false, message: 'Renounced -> Failed to check if mint is renounced and freezable' }; } } diff --git a/helpers/constants.ts b/helpers/constants.ts index 81f42e2..2e8da8f 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -55,6 +55,7 @@ export const FILTER_CHECK_INTERVAL = Number(retrieveEnvVariable('FILTER_CHECK_IN export const FILTER_CHECK_DURATION = Number(retrieveEnvVariable('FILTER_CHECK_DURATION', logger)); export const CONSECUTIVE_FILTER_MATCHES = Number(retrieveEnvVariable('CONSECUTIVE_FILTER_MATCHES', logger)); export const CHECK_IF_MINT_IS_RENOUNCED = retrieveEnvVariable('CHECK_IF_MINT_IS_RENOUNCED', logger) === 'true'; +export const CHECK_IF_FREEZABLE = retrieveEnvVariable('CHECK_IF_FREEZABLE', logger) === 'true'; export const CHECK_IF_BURNED = retrieveEnvVariable('CHECK_IF_BURNED', logger) === 'true'; export const MIN_POOL_SIZE = retrieveEnvVariable('MIN_POOL_SIZE', logger); export const MAX_POOL_SIZE = retrieveEnvVariable('MAX_POOL_SIZE', logger); diff --git a/index.ts b/index.ts index 3c27f75..39acf85 100644 --- a/index.ts +++ b/index.ts @@ -15,6 +15,7 @@ import { PRE_LOAD_EXISTING_MARKETS, LOG_LEVEL, CHECK_IF_MINT_IS_RENOUNCED, + CHECK_IF_FREEZABLE, CHECK_IF_BURNED, QUOTE_MINT, MAX_POOL_SIZE, @@ -115,6 +116,7 @@ function printDetails(wallet: Keypair, quoteToken: Token, bot: Bot) { logger.info(`Filter check duration: ${botConfig.filterCheckDuration} ms`); logger.info(`Consecutive filter matches: ${botConfig.consecutiveMatchCount} ms`); logger.info(`Check renounced: ${botConfig.checkRenounced}`); + logger.info(`Check freezable: ${botConfig.checkFreezable}`); logger.info(`Check burned: ${botConfig.checkBurned}`); logger.info(`Min pool size: ${botConfig.minPoolSize.toFixed()}`); logger.info(`Max pool size: ${botConfig.maxPoolSize.toFixed()}`); @@ -149,6 +151,7 @@ const runListener = async () => { wallet, quoteAta: getAssociatedTokenAddressSync(quoteToken.mint, wallet.publicKey), checkRenounced: CHECK_IF_MINT_IS_RENOUNCED, + checkFreezable: CHECK_IF_FREEZABLE, checkBurned: CHECK_IF_BURNED, minPoolSize: new TokenAmount(quoteToken, MIN_POOL_SIZE, false), maxPoolSize: new TokenAmount(quoteToken, MAX_POOL_SIZE, false), From ff0ebad6bd1f80a0609d238bbf78dd6796d411a5 Mon Sep 17 00:00:00 2001 From: Theo Brigitte Date: Sat, 20 Apr 2024 11:53:44 +0200 Subject: [PATCH 2/4] update error message --- filters/renounced.filter.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/filters/renounced.filter.ts b/filters/renounced.filter.ts index ab828c1..c2aca51 100644 --- a/filters/renounced.filter.ts +++ b/filters/renounced.filter.ts @@ -8,6 +8,7 @@ export class RenouncedFreezeFilter implements Filter { constructor(private readonly connection: Connection, private readonly checkRenounced: boolean, private readonly checkFreezable: boolean) {} async execute(poolKeys: LiquidityPoolKeysV4): Promise { + const errorMessage = [ this.checkRenounced ? 'mint' : undefined, this.checkFreezable ? 'freeze' : undefined ].filter((e) => e !== undefined); try { const accountInfo = await this.connection.getAccountInfo(poolKeys.baseMint, this.connection.commitment); if (!accountInfo?.data) { @@ -23,9 +24,9 @@ export class RenouncedFreezeFilter implements Filter { return { ok: ok, message: ok ? undefined : `RenouncedFreeze -> Creator can ${message.join(' and ')} tokens` }; } catch (e) { - logger.error({ mint: poolKeys.baseMint }, `Failed to check if mint is renounced and freezable`); + logger.error({ mint: poolKeys.baseMint }, `RenouncedFreeze -> Failed to check if creator can ${errorMessage.join(' and ')} tokens`); } - return { ok: false, message: 'Renounced -> Failed to check if mint is renounced and freezable' }; + return { ok: false, message: `RenouncedFreeze -> Failed to check if creator can ${errorMessage.join(' and ')} tokens` }; } } From b92a9ee128a9c5ba7aa34b21eec1504b49927c01 Mon Sep 17 00:00:00 2001 From: Theo Brigitte Date: Sun, 21 Apr 2024 13:56:01 +0200 Subject: [PATCH 3/4] update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8aaa878..799613b 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ You should see the following output: - Pool must not exist before the script starts. - `SNIPE_LIST_REFRESH_INTERVAL` - Interval in milliseconds to refresh the snipe list. - `CHECK_IF_MINT_IS_RENOUNCED` - Set to `true` to buy tokens only if their mint is renounced. +- `CHECK_IF_FREEZABLE` - Set to `true` to buy tokens only if they are not freezable. - `CHECK_IF_BURNED` - Set to `true` to buy tokens only if their liquidity pool is burned. - `MIN_POOL_SIZE` - Bot will buy only if the pool size is greater than or equal the specified amount. - Set `0` to disable. From 70ba5eed76b649e1da87b6d819e9b203d2942c74 Mon Sep 17 00:00:00 2001 From: Theo Brigitte Date: Sun, 21 Apr 2024 14:17:30 +0200 Subject: [PATCH 4/4] keep filter --- filters/renounced.filter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filters/renounced.filter.ts b/filters/renounced.filter.ts index c2aca51..b18ecbb 100644 --- a/filters/renounced.filter.ts +++ b/filters/renounced.filter.ts @@ -12,7 +12,7 @@ export class RenouncedFreezeFilter implements Filter { try { const accountInfo = await this.connection.getAccountInfo(poolKeys.baseMint, this.connection.commitment); if (!accountInfo?.data) { - return { ok: false, message: 'Failed to fetch account data' }; + return { ok: false, message: 'RenouncedFreeze -> Failed to fetch account data' }; } const deserialize = MintLayout.decode(accountInfo.data);