Explorar o código

Merge pull request #93 from TheoBrigitte/mutable

Add mutable filter
Filip Dunđer hai 1 ano
pai
achega
54317de112
Modificáronse 9 ficheiros con 126 adicións e 2 borrados
  1. 2 1
      .env.copy
  2. 1 0
      README.md
  3. 1 0
      filters/index.ts
  4. 29 0
      filters/mutable.filter.ts
  5. 7 1
      filters/pool-filters.ts
  6. 1 0
      helpers/constants.ts
  7. 1 0
      index.ts
  8. 83 0
      package-lock.json
  9. 1 0
      package.json

+ 2 - 1
.env.copy

@@ -42,8 +42,9 @@ SNIPE_LIST_REFRESH_INTERVAL=30000
 FILTER_CHECK_DURATION=60000
 FILTER_CHECK_INTERVAL=2000
 CONSECUTIVE_FILTER_MATCHES=3
+CHECK_IF_MUTABLE=false
 CHECK_IF_MINT_IS_RENOUNCED=true
-CHECK_IF_FREEZABLE=true
+CHECK_IF_FREEZABLE=false
 CHECK_IF_BURNED=true
 MIN_POOL_SIZE=5
 MAX_POOL_SIZE=50

+ 1 - 0
README.md

@@ -84,6 +84,7 @@ Note: When using snipe list filters below will be disabled.
   - Set to zero to disable 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
+- `CHECK_IF_MUTABLE` - Set to `true` to buy tokens only if their metadata are not mutable.
 - `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.

+ 1 - 0
filters/index.ts

@@ -1,4 +1,5 @@
 export * from './burn.filter';
+export * from './mutable.filter';
 export * from './pool-filters';
 export * from './pool-size.filter';
 export * from './renounced.filter';

+ 29 - 0
filters/mutable.filter.ts

@@ -0,0 +1,29 @@
+import { Filter, FilterResult } from './pool-filters';
+import { Connection, PublicKey } from '@solana/web3.js';
+import { LiquidityPoolKeysV4 } from '@raydium-io/raydium-sdk';
+import { getPdaMetadataKey } from '@raydium-io/raydium-sdk';
+import { getMetadataAccountDataSerializer, MetadataAccountData, MetadataAccountDataArgs } from '@metaplex-foundation/mpl-token-metadata';
+import { Serializer } from '@metaplex-foundation/umi/serializers';
+import { logger } from '../helpers';
+
+export class MutableFilter implements Filter {
+  constructor(private readonly connection: Connection, private readonly metadataSerializer: Serializer<MetadataAccountDataArgs, MetadataAccountData>) {}
+
+  async execute(poolKeys: LiquidityPoolKeysV4): Promise<FilterResult> {
+    try {
+      const metadataPDA = getPdaMetadataKey(poolKeys.baseMint);
+      const metadataAccount = await this.connection.getAccountInfo(metadataPDA.publicKey);
+      if (!metadataAccount?.data) {
+        return { ok: false, message: 'Mutable -> Failed to fetch account data' };
+      }
+      const deserialize = this.metadataSerializer.deserialize(metadataAccount.data);
+      const mutable = deserialize[0].isMutable;
+
+      return { ok: !mutable, message: !mutable ? undefined : "Mutable -> Creator can change metadata" };
+    } catch (e: any) {
+      logger.error({ mint: poolKeys.baseMint }, `Mutable -> Failed to check if metadata are mutable`);
+    }
+
+    return { ok: false, message: 'Mutable -> Failed to check if metadata are mutable' };
+  }
+}

+ 7 - 1
filters/pool-filters.ts

@@ -1,9 +1,11 @@
 import { Connection } from '@solana/web3.js';
 import { LiquidityPoolKeysV4, Token, TokenAmount } from '@raydium-io/raydium-sdk';
+import { getMetadataAccountDataSerializer } from '@metaplex-foundation/mpl-token-metadata';
 import { BurnFilter } from './burn.filter';
+import { MutableFilter } from './mutable.filter';
 import { RenouncedFreezeFilter } from './renounced.filter';
 import { PoolSizeFilter } from './pool-size.filter';
-import { CHECK_IF_BURNED, CHECK_IF_FREEZABLE, CHECK_IF_MINT_IS_RENOUNCED, logger } from '../helpers';
+import { CHECK_IF_BURNED, CHECK_IF_FREEZABLE, CHECK_IF_MINT_IS_RENOUNCED, CHECK_IF_MUTABLE, logger } from '../helpers';
 
 export interface Filter {
   execute(poolKeysV4: LiquidityPoolKeysV4): Promise<FilterResult>;
@@ -35,6 +37,10 @@ export class PoolFilters {
       this.filters.push(new RenouncedFreezeFilter(connection, CHECK_IF_MINT_IS_RENOUNCED, CHECK_IF_FREEZABLE));
     }
 
+    if (CHECK_IF_MUTABLE) {
+      this.filters.push(new MutableFilter(connection, getMetadataAccountDataSerializer()));
+    }
+
     if (!args.minPoolSize.isZero() || !args.maxPoolSize.isZero()) {
       this.filters.push(new PoolSizeFilter(connection, args.quoteToken, args.minPoolSize, args.maxPoolSize));
     }

+ 1 - 0
helpers/constants.ts

@@ -54,6 +54,7 @@ export const SELL_SLIPPAGE = Number(retrieveEnvVariable('SELL_SLIPPAGE', logger)
 export const FILTER_CHECK_INTERVAL = Number(retrieveEnvVariable('FILTER_CHECK_INTERVAL', logger));
 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_MUTABLE = retrieveEnvVariable('CHECK_IF_MUTABLE', logger) === 'true';
 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';

+ 1 - 0
index.ts

@@ -14,6 +14,7 @@ import {
   RPC_WEBSOCKET_ENDPOINT,
   PRE_LOAD_EXISTING_MARKETS,
   LOG_LEVEL,
+  CHECK_IF_MUTABLE,
   CHECK_IF_MINT_IS_RENOUNCED,
   CHECK_IF_FREEZABLE,
   CHECK_IF_BURNED,

+ 83 - 0
package-lock.json

@@ -8,6 +8,7 @@
       "name": "warp-solana-bot",
       "version": "2.0.1",
       "dependencies": {
+        "@metaplex-foundation/mpl-token-metadata": "^3.2.1",
         "@raydium-io/raydium-sdk": "^1.3.1-beta.47",
         "@solana/spl-token": "^0.4.0",
         "@solana/web3.js": "^1.89.1",
@@ -75,6 +76,88 @@
         "@jridgewell/sourcemap-codec": "^1.4.10"
       }
     },
+    "node_modules/@metaplex-foundation/mpl-token-metadata": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/@metaplex-foundation/mpl-token-metadata/-/mpl-token-metadata-3.2.1.tgz",
+      "integrity": "sha512-26W1NhQwDWmLOg/pBRYut7x/vEs/5kFS2sWVEY5/X0f2jJOLhnd4NaZQcq+5u+XZsXvm1jq2AtrRGPNK43oqWQ==",
+      "dependencies": {
+        "@metaplex-foundation/mpl-toolbox": "^0.9.4"
+      },
+      "peerDependencies": {
+        "@metaplex-foundation/umi": ">= 0.8.2 < 1"
+      }
+    },
+    "node_modules/@metaplex-foundation/mpl-toolbox": {
+      "version": "0.9.4",
+      "resolved": "https://registry.npmjs.org/@metaplex-foundation/mpl-toolbox/-/mpl-toolbox-0.9.4.tgz",
+      "integrity": "sha512-fd6JxfoLbj/MM8FG2x91KYVy1U6AjBQw4qjt7+Da3trzQaWnSaYHDcYRG/53xqfvZ9qofY1T2t53GXPlD87lnQ==",
+      "peerDependencies": {
+        "@metaplex-foundation/umi": ">= 0.8.2 < 1"
+      }
+    },
+    "node_modules/@metaplex-foundation/umi": {
+      "version": "0.9.1",
+      "resolved": "https://registry.npmjs.org/@metaplex-foundation/umi/-/umi-0.9.1.tgz",
+      "integrity": "sha512-IhHoOvp4vfO/++YL+78+iVuLM53+FDwUOZDYgH6lx0jYXyQ27BeaieeR5i+q3A9dz4KxQo5Nzc5aCA1109QGCQ==",
+      "peer": true,
+      "dependencies": {
+        "@metaplex-foundation/umi-options": "^0.8.9",
+        "@metaplex-foundation/umi-public-keys": "^0.8.9",
+        "@metaplex-foundation/umi-serializers": "^0.9.0"
+      }
+    },
+    "node_modules/@metaplex-foundation/umi-options": {
+      "version": "0.8.9",
+      "resolved": "https://registry.npmjs.org/@metaplex-foundation/umi-options/-/umi-options-0.8.9.tgz",
+      "integrity": "sha512-jSQ61sZMPSAk/TXn8v8fPqtz3x8d0/blVZXLLbpVbo2/T5XobiI6/MfmlUosAjAUaQl6bHRF8aIIqZEFkJiy4A==",
+      "peer": true
+    },
+    "node_modules/@metaplex-foundation/umi-public-keys": {
+      "version": "0.8.9",
+      "resolved": "https://registry.npmjs.org/@metaplex-foundation/umi-public-keys/-/umi-public-keys-0.8.9.tgz",
+      "integrity": "sha512-CxMzN7dgVGOq9OcNCJe2casKUpJ3RmTVoOvDFyeoTQuK+vkZ1YSSahbqC1iGuHEtKTLSjtWjKvUU6O7zWFTw3Q==",
+      "peer": true,
+      "dependencies": {
+        "@metaplex-foundation/umi-serializers-encodings": "^0.8.9"
+      }
+    },
+    "node_modules/@metaplex-foundation/umi-serializers": {
+      "version": "0.9.0",
+      "resolved": "https://registry.npmjs.org/@metaplex-foundation/umi-serializers/-/umi-serializers-0.9.0.tgz",
+      "integrity": "sha512-hAOW9Djl4w4ioKeR4erDZl5IG4iJdP0xA19ZomdaCbMhYAAmG/FEs5khh0uT2mq53/MnzWcXSUPoO8WBN4Q+Vg==",
+      "peer": true,
+      "dependencies": {
+        "@metaplex-foundation/umi-options": "^0.8.9",
+        "@metaplex-foundation/umi-public-keys": "^0.8.9",
+        "@metaplex-foundation/umi-serializers-core": "^0.8.9",
+        "@metaplex-foundation/umi-serializers-encodings": "^0.8.9",
+        "@metaplex-foundation/umi-serializers-numbers": "^0.8.9"
+      }
+    },
+    "node_modules/@metaplex-foundation/umi-serializers-core": {
+      "version": "0.8.9",
+      "resolved": "https://registry.npmjs.org/@metaplex-foundation/umi-serializers-core/-/umi-serializers-core-0.8.9.tgz",
+      "integrity": "sha512-WT82tkiYJ0Qmscp7uTj1Hz6aWQPETwaKLAENAUN5DeWghkuBKtuxyBKVvEOuoXerJSdhiAk0e8DWA4cxcTTQ/w==",
+      "peer": true
+    },
+    "node_modules/@metaplex-foundation/umi-serializers-encodings": {
+      "version": "0.8.9",
+      "resolved": "https://registry.npmjs.org/@metaplex-foundation/umi-serializers-encodings/-/umi-serializers-encodings-0.8.9.tgz",
+      "integrity": "sha512-N3VWLDTJ0bzzMKcJDL08U3FaqRmwlN79FyE4BHj6bbAaJ9LEHjDQ9RJijZyWqTm0jE7I750fU7Ow5EZL38Xi6Q==",
+      "peer": true,
+      "dependencies": {
+        "@metaplex-foundation/umi-serializers-core": "^0.8.9"
+      }
+    },
+    "node_modules/@metaplex-foundation/umi-serializers-numbers": {
+      "version": "0.8.9",
+      "resolved": "https://registry.npmjs.org/@metaplex-foundation/umi-serializers-numbers/-/umi-serializers-numbers-0.8.9.tgz",
+      "integrity": "sha512-NtBf1fnVNQJHFQjLFzRu2i9GGnigb9hOm/Gfrk628d0q0tRJB7BOM3bs5C61VAs7kJs4yd+pDNVAERJkknQ7Lg==",
+      "peer": true,
+      "dependencies": {
+        "@metaplex-foundation/umi-serializers-core": "^0.8.9"
+      }
+    },
     "node_modules/@noble/curves": {
       "version": "1.3.0",
       "license": "MIT",

+ 1 - 0
package.json

@@ -8,6 +8,7 @@
     "tsc": "tsc --noEmit"
   },
   "dependencies": {
+    "@metaplex-foundation/mpl-token-metadata": "^3.2.1",
     "@raydium-io/raydium-sdk": "^1.3.1-beta.47",
     "@solana/spl-token": "^0.4.0",
     "@solana/web3.js": "^1.89.1",