mirror of
https://github.com/fdundjer/solana-sniper-bot.git
synced 2025-11-10 04:22:05 +10:00
Merge pull request #92 from fdundjer/master
fix: disable filters when snipe list is on
This commit is contained in:
12
README.md
12
README.md
@ -67,6 +67,15 @@ You should see the following output:
|
|||||||
- Stop loss is calculated based on quote mint.
|
- Stop loss is calculated based on quote mint.
|
||||||
- `SELL_SLIPPAGE` - Slippage %.
|
- `SELL_SLIPPAGE` - Slippage %.
|
||||||
|
|
||||||
|
#### Snipe list
|
||||||
|
- `USE_SNIPE_LIST` - Set to `true` to enable buying only tokens listed in `snipe-list.txt`.
|
||||||
|
- Pool must not exist before the bot starts.
|
||||||
|
- If token can be traded before bot starts nothing will happen. Bot will not buy the token.
|
||||||
|
- `SNIPE_LIST_REFRESH_INTERVAL` - Interval in milliseconds to refresh the snipe list.
|
||||||
|
- You can update snipe list while bot is running. It will pickup the new changes each time it does refresh.
|
||||||
|
|
||||||
|
Note: When using snipe list filters below will be disabled.
|
||||||
|
|
||||||
#### Filters
|
#### Filters
|
||||||
- `FILTER_CHECK_INTERVAL` - Interval in milliseconds for checking if pool match the filters.
|
- `FILTER_CHECK_INTERVAL` - Interval in milliseconds for checking if pool match the filters.
|
||||||
- Set to zero to disable filters.
|
- Set to zero to disable filters.
|
||||||
@ -75,9 +84,6 @@ You should see the following output:
|
|||||||
- Set to zero to disable filters.
|
- Set to zero to disable filters.
|
||||||
- `CONSECUTIVE_FILTER_MATCHES` - How many times in a row pool needs to match the filters.
|
- `CONSECUTIVE_FILTER_MATCHES` - How many times in a row pool needs to match the filters.
|
||||||
- This is useful because when pool is burned (and rugged), other filters may not report the same behavior. eg. pool size may still have old value
|
- This is useful because when pool is burned (and rugged), other filters may not report the same behavior. eg. pool size may still have old value
|
||||||
- `USE_SNIPE_LIST` - Set to `true` to enable buying only tokens listed in `snipe-list.txt`.
|
|
||||||
- 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_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_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.
|
- `CHECK_IF_BURNED` - Set to `true` to buy tokens only if their liquidity pool is burned.
|
||||||
|
|||||||
20
bot.ts
20
bot.ts
@ -100,7 +100,7 @@ export class Bot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async buy(accountId: PublicKey, poolState: LiquidityStateV4) {
|
public async buy(accountId: PublicKey, poolState: LiquidityStateV4) {
|
||||||
logger.trace({ mint: poolState.baseMint }, `Processing buy...`);
|
logger.trace({ mint: poolState.baseMint }, `Processing new pool...`);
|
||||||
|
|
||||||
if (this.config.useSnipeList && !this.snipeListCache?.isInList(poolState.baseMint.toString())) {
|
if (this.config.useSnipeList && !this.snipeListCache?.isInList(poolState.baseMint.toString())) {
|
||||||
logger.debug({ mint: poolState.baseMint.toString() }, `Skipping buy because token is not in a snipe list`);
|
logger.debug({ mint: poolState.baseMint.toString() }, `Skipping buy because token is not in a snipe list`);
|
||||||
@ -131,11 +131,13 @@ export class Bot {
|
|||||||
]);
|
]);
|
||||||
const poolKeys: LiquidityPoolKeysV4 = createPoolKeys(accountId, poolState, market);
|
const poolKeys: LiquidityPoolKeysV4 = createPoolKeys(accountId, poolState, market);
|
||||||
|
|
||||||
const match = await this.filterMatch(poolKeys);
|
if (!this.config.useSnipeList) {
|
||||||
|
const match = await this.filterMatch(poolKeys);
|
||||||
|
|
||||||
if (!match) {
|
if (!match) {
|
||||||
logger.trace({ mint: poolKeys.baseMint.toString() }, `Skipping buy because pool doesn't match filters`);
|
logger.trace({ mint: poolKeys.baseMint.toString() }, `Skipping buy because pool doesn't match filters`);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < this.config.maxBuyRetries; i++) {
|
for (let i = 0; i < this.config.maxBuyRetries; i++) {
|
||||||
@ -170,7 +172,7 @@ export class Bot {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug(
|
logger.info(
|
||||||
{
|
{
|
||||||
mint: poolState.baseMint.toString(),
|
mint: poolState.baseMint.toString(),
|
||||||
signature: result.signature,
|
signature: result.signature,
|
||||||
@ -197,7 +199,7 @@ export class Bot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
logger.trace({ mint: rawAccount.mint }, `Processing sell...`);
|
logger.trace({ mint: rawAccount.mint }, `Processing new token...`);
|
||||||
|
|
||||||
const poolData = await this.poolStorage.get(rawAccount.mint.toString());
|
const poolData = await this.poolStorage.get(rawAccount.mint.toString());
|
||||||
|
|
||||||
@ -269,7 +271,7 @@ export class Bot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.debug({ mint: rawAccount.mint.toString(), error }, `Failed to sell token`);
|
logger.error({ mint: rawAccount.mint.toString(), error }, `Failed to sell token`);
|
||||||
} finally {
|
} finally {
|
||||||
if (this.config.oneTokenAtATime) {
|
if (this.config.oneTokenAtATime) {
|
||||||
this.sellExecutionCount--;
|
this.sellExecutionCount--;
|
||||||
@ -351,7 +353,7 @@ export class Bot {
|
|||||||
|
|
||||||
private async filterMatch(poolKeys: LiquidityPoolKeysV4) {
|
private async filterMatch(poolKeys: LiquidityPoolKeysV4) {
|
||||||
if (this.config.filterCheckInterval === 0 || this.config.filterCheckDuration === 0) {
|
if (this.config.filterCheckInterval === 0 || this.config.filterCheckDuration === 0) {
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const timesToCheck = this.config.filterCheckDuration / this.config.filterCheckInterval;
|
const timesToCheck = this.config.filterCheckDuration / this.config.filterCheckInterval;
|
||||||
|
|||||||
25
index.ts
25
index.ts
@ -109,17 +109,24 @@ function printDetails(wallet: Keypair, quoteToken: Token, bot: Bot) {
|
|||||||
logger.info(`Take profit: ${botConfig.takeProfit}%`);
|
logger.info(`Take profit: ${botConfig.takeProfit}%`);
|
||||||
logger.info(`Stop loss: ${botConfig.stopLoss}%`);
|
logger.info(`Stop loss: ${botConfig.stopLoss}%`);
|
||||||
|
|
||||||
logger.info('- Filters -');
|
logger.info('- Snipe list -');
|
||||||
logger.info(`Snipe list: ${botConfig.useSnipeList}`);
|
logger.info(`Snipe list: ${botConfig.useSnipeList}`);
|
||||||
logger.info(`Snipe list refresh interval: ${SNIPE_LIST_REFRESH_INTERVAL} ms`);
|
logger.info(`Snipe list refresh interval: ${SNIPE_LIST_REFRESH_INTERVAL} ms`);
|
||||||
logger.info(`Filter check interval: ${botConfig.filterCheckInterval} ms`);
|
|
||||||
logger.info(`Filter check duration: ${botConfig.filterCheckDuration} ms`);
|
if (botConfig.useSnipeList) {
|
||||||
logger.info(`Consecutive filter matches: ${botConfig.consecutiveMatchCount} ms`);
|
logger.info('- Filters -');
|
||||||
logger.info(`Check renounced: ${botConfig.checkRenounced}`);
|
logger.info(`Filters are disabled when snipe list is on`);
|
||||||
logger.info(`Check freezable: ${botConfig.checkFreezable}`);
|
} else {
|
||||||
logger.info(`Check burned: ${botConfig.checkBurned}`);
|
logger.info('- Filters -');
|
||||||
logger.info(`Min pool size: ${botConfig.minPoolSize.toFixed()}`);
|
logger.info(`Filter check interval: ${botConfig.filterCheckInterval} ms`);
|
||||||
logger.info(`Max pool size: ${botConfig.maxPoolSize.toFixed()}`);
|
logger.info(`Filter check duration: ${botConfig.filterCheckDuration} ms`);
|
||||||
|
logger.info(`Consecutive filter matches: ${botConfig.consecutiveMatchCount}`);
|
||||||
|
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()}`);
|
||||||
|
}
|
||||||
|
|
||||||
logger.info('------- CONFIGURATION END -------');
|
logger.info('------- CONFIGURATION END -------');
|
||||||
|
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "warp-solana-bot",
|
"name": "warp-solana-bot",
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "warp-solana-bot",
|
"name": "warp-solana-bot",
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@raydium-io/raydium-sdk": "^1.3.1-beta.47",
|
"@raydium-io/raydium-sdk": "^1.3.1-beta.47",
|
||||||
"@solana/spl-token": "^0.4.0",
|
"@solana/spl-token": "^0.4.0",
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
"name": "warp-solana-bot",
|
"name": "warp-solana-bot",
|
||||||
"author": "Filip Dundjer",
|
"author": "Filip Dundjer",
|
||||||
"homepage": "https://warp.id",
|
"homepage": "https://warp.id",
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "ts-node index.ts",
|
"start": "ts-node index.ts",
|
||||||
"tsc": "tsc --noEmit"
|
"tsc": "tsc --noEmit"
|
||||||
|
|||||||
Reference in New Issue
Block a user