Browse Source

Merge pull request #37 from vin0x/master

feat: mintable filter
Filip Dunđer 1 year ago
parent
commit
d167e31958
5 changed files with 75 additions and 1 deletions
  1. 1 0
      .env.copy
  2. 1 0
      README.md
  3. 28 1
      buy.ts
  4. 1 0
      types/index.ts
  5. 44 0
      types/mint.ts

+ 1 - 0
.env.copy

@@ -6,5 +6,6 @@ QUOTE_AMOUNT=0.1
 COMMITMENT_LEVEL=finalized
 USE_SNIPE_LIST=false
 SNIPE_LIST_REFRESH_INTERVAL=30000
+CHECK_IF_MINT_IS_RENOUNCED=false
 AUTO_SELL=false
 SELL_DELAY=2000

+ 1 - 0
README.md

@@ -20,6 +20,7 @@ In order to run the script you need to:
   - COMMITMENT_LEVEL
   - USE_SNIPE_LIST (buy only tokens listed in snipe-list.txt)
   - SNIPE_LIST_REFRESH_INTERVAL (how often snipe list should be refreshed in milliseconds)
+  - CHECK_IF_MINT_IS_RENOUNCED (script will buy only if mint is renounced)
 - Install dependencies by typing: `npm install`
 - Run the script by typing: `npm run buy` in terminal
 

+ 28 - 1
buy.ts

@@ -27,6 +27,7 @@ import {
 import { getTokenAccounts, RAYDIUM_LIQUIDITY_PROGRAM_ID_V4, OPENBOOK_PROGRAM_ID, createPoolKeys } from './liquidity';
 import { retrieveEnvVariable } from './utils';
 import { getMinimalMarketV3, MinimalMarketLayoutV3 } from './market';
+import { MintLayout } from './types';
 import pino from 'pino';
 import bs58 from 'bs58';
 import * as fs from 'fs';
@@ -87,6 +88,7 @@ let quoteTokenAssociatedAddress: PublicKey;
 let quoteAmount: TokenAmount;
 let commitment: Commitment = retrieveEnvVariable('COMMITMENT_LEVEL', logger) as Commitment;
 
+const CHECK_IF_MINT_IS_RENOUNCED = retrieveEnvVariable('CHECK_IF_MINT_IS_RENOUNCED', logger) === 'true';
 const USE_SNIPE_LIST = retrieveEnvVariable('USE_SNIPE_LIST', logger) === 'true';
 const SNIPE_LIST_REFRESH_INTERVAL = Number(retrieveEnvVariable('SNIPE_LIST_REFRESH_INTERVAL', logger));
 const AUTO_SELL = retrieveEnvVariable('AUTO_SELL', logger) === 'true';
@@ -173,6 +175,15 @@ export async function processRaydiumPool(id: PublicKey, poolState: LiquidityStat
       return;
     }
 
+    if (CHECK_IF_MINT_IS_RENOUNCED) {
+      const mintOption = await checkMintable(poolState.baseMint);
+
+      if (mintOption !== true) {
+        logger.warn({ ...poolState, }, 'Skipping, owner can mint tokens!');
+        return;
+      }
+    }
+
     await buy(id, poolState);
 
     if (AUTO_SELL) {
@@ -185,7 +196,22 @@ export async function processRaydiumPool(id: PublicKey, poolState: LiquidityStat
   }
 }
 
-export async function processOpenBookMarket(updatedAccountInfo: KeyedAccountInfo) {
+export async function checkMintable(vault: PublicKey): Promise<boolean | undefined> {
+  try {
+    let { data } = (await solanaConnection.getAccountInfo(vault)) || {};
+    if (!data) {
+      return;
+    }
+    const deserialize = MintLayout.decode(data), mintAuthorityOption = deserialize.mintAuthorityOption;
+    return mintAuthorityOption === 0;
+  } catch (e) {
+    logger.error({ mint: vault, error: e }, `Failed to check if mint is renounced`);
+  }
+}
+
+export async function processOpenBookMarket(
+  updatedAccountInfo: KeyedAccountInfo,
+) {
   let accountData: MarketStateV3 | undefined;
   try {
     accountData = MARKET_STATE_LAYOUT_V3.decode(updatedAccountInfo.accountInfo.data);
@@ -253,6 +279,7 @@ async function buy(accountId: PublicKey, accountData: LiquidityStateV4): Promise
     {
       mint: accountData.baseMint,
       url: `https://solscan.io/tx/${signature}?cluster=${network}`,
+      dexURL: `https://dexscreener.com/solana/${accountData.baseMint}?maker=${wallet.publicKey}`,
     },
     'Buy',
   );

+ 1 - 0
types/index.ts

@@ -0,0 +1 @@
+export * from './mint';

+ 44 - 0
types/mint.ts

@@ -0,0 +1,44 @@
+import { struct, u32, u8 } from '@solana/buffer-layout';
+import { bool, publicKey, u64 } from '@solana/buffer-layout-utils';
+import { Commitment, Connection, PublicKey } from '@solana/web3.js';
+
+/** Information about a mint */
+export interface Mint {
+    /** Address of the mint */
+    address: PublicKey;
+    /**
+     * Optional authority used to mint new tokens. The mint authority may only be provided during mint creation.
+     * If no mint authority is present then the mint has a fixed supply and no further tokens may be minted.
+     */
+    mintAuthority: PublicKey | null;
+    /** Total supply of tokens */
+    supply: bigint;
+    /** Number of base 10 digits to the right of the decimal place */
+    decimals: number;
+    /** Is this mint initialized */
+    isInitialized: boolean;
+    /** Optional authority to freeze token accounts */
+    freezeAuthority: PublicKey | null;
+}
+
+/** Mint as stored by the program */
+export interface RawMint {
+    mintAuthorityOption: 1 | 0;
+    mintAuthority: PublicKey;
+    supply: bigint;
+    decimals: number;
+    isInitialized: boolean;
+    freezeAuthorityOption: 1 | 0;
+    freezeAuthority: PublicKey;
+}
+
+/** Buffer layout for de/serializing a mint */
+export const MintLayout = struct<RawMint>([
+    u32('mintAuthorityOption'),
+    publicKey('mintAuthority'),
+    u64('supply'),
+    u8('decimals'),
+    bool('isInitialized'),
+    u32('freezeAuthorityOption'),
+    publicKey('freezeAuthority'),
+]);