BARU: Helius mengakuisisi Light Protocol
Cara Memantau Transaksi Solana Menggunakan Geyser Enhanced Websockets
Blog/Pengembangan

Cara Memantau Transaksi Solana Menggunakan Geyser Enhanced Websockets

Engineer Integrasizerkerzzz di X
Bacaan 7 menit

Pendahuluan

Sudah lama saya penasaran bagaimana semua aplikasi pemantauan dan bot ini bekerja. Setelah pencarian yang tidak mudah, saya menemukan Geyser Enhanced Websockets dari Helius. Meskipun penggunaannya tidak gratis (Anda memerlukan paket Business atau Professional), ini adalah alat sangat canggih yang dapat Anda gunakan.

Menggunakan Geyser Enhanced Websockets dengan Helius sangat mudah — tempel alamat yang ingin Anda pantau, lalu jalankan kode. Anda dapat memantau apa pun: NFT, dompet, program, platform, dan benar-benar apa saja. Anda dapat membuat pelacak dompet, pelacak token, pemantau jual-beli, pemantau volume, dan sebagainya.

API dan alat semacam ini terkadang dapat berharga hingga ribuan dolar, tetapi artikel ini akan menampilkan beberapa contoh hal yang dapat dibuat dengan biaya jauh lebih rendah. Dengan $499 (paket Business), ROI dari membuat alat sendiri tidak terbatas; membagikan alat tersebut kepada orang lain atau menggunakannya sendiri akan memberi Anda keunggulan dan berbagai cara tanpa batas untuk memanfaatkan data langsung Solana.

Jika Anda baru menggunakan Helius Geyser WebSockets, baca artikel blog dan dokumentasi ini. Anda dapat mengikutinya karena contoh pertama ini cukup mudah dipahami.

Pemantau Pool Baru untuk Raydium

Kode
const WebSocket = require('ws');

// Create a WebSocket connection
const ws = new WebSocket('wss://atlas-mainnet.helius-rpc.com?api-key=YOUR_API_KEY');

// Function to send a request to the WebSocket server
function sendRequest(ws) {
    const request = {
        jsonrpc: "2.0",
        id: 420,
        method: "transactionSubscribe",
        params: [
            {   failed: false,
                accountInclude:    ["675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"]
            },
            {
                commitment: "confirmed",
                encoding: "jsonParsed",
                transactionDetails: "full",
                maxSupportedTransactionVersion: 0
            }
        ]
    };
    ws.send(JSON.stringify(request));
}

Bagian pertama cuplikan kode ini sangat sederhana. Kita menetapkan kunci API dan mengirim permintaan dengan akun yang ingin dipantau, yang dalam contoh ini adalah 675kPX9…, alias program on-chain Raydium. Dengan permintaan ini, kita akan mendapatkan semua transaksi terkonfirmasi dan tidak gagal yang berinteraksi dengan Raydium. Mengirim permintaan ini biasanya akan menghasilkan ribuan transaksi setiap detik, jadi mari fokus pada cara sederhana untuk menyaring gangguan tersebut.

Menyaring Gangguan

Cuplikan kode di bawah ini merupakan logika pemfilteran utama untuk penanganan peristiwa. Fungsi on message mengurai data yang dikembalikan dari transaksi berdasarkan log. Dalam contoh ini, kita melihat semua transaksi dengan log “initialize2: InitializeInstruction2” — log tersebut memberi tahu kita saat pengguna membuat pool likuiditas baru di Raydium. Anda juga dapat menggunakan log lain sesuai dengan hal yang ingin dipantau. Saya sarankan membuat transaksi uji untuk aktivitas yang ingin dipantau. Misalnya, Anda dapat menambahkan likuiditas ke sebuah pool dan melihat tampilan log transaksi tersebut, lalu memfilter log itu untuk mendapatkan semua transaksi yang menambahkan likuiditas.

Kode
ws.on('open', function open() {
    console.log('WebSocket is open');
    sendRequest(ws);  // Send a request once the WebSocket is open
});

ws.on('message', async function incoming(data) {
    const messageStr = data.toString('utf8');
    try {
        const messageObj = JSON.parse(messageStr);

        const result = messageObj.params.result;
        const logs = result.transaction.meta.logMessages;
        const signature = result.signature; // Extract the signature
        const accountKeys = result.transaction.transaction.message.accountKeys.map(ak => ak.pubkey); // Extract only pubkeys

        if (logs && logs.some(log => log.includes("initialize2: InitializeInstruction2"))) {
            // Log the signature, and the public keys of the AMM ID
            console.log('Transaction signature:', signature);
            console.log('AMM ID:', accountKeys[2]); // Corrected to the third account for AMM ID
        }
    } catch (e) {
        
    }
});

ws.on('error', function error(err) {
    console.error('WebSocket error:', err);
});

ws.on('close', function close() {
    console.log('WebSocket is closed');
});

Setelah mengetahui bahwa transaksi tersebut memiliki log yang dimaksud, kita mengekstrak dua hal: signature agar dapat membandingkan dan memverifikasi akurasi program kita, serta kunci akun yang merupakan AMM ID (yaitu alamat AMM dari pool tersebut), karena banyak bot/sniper menggunakan AMM ID untuk memulai perdagangan.

Anda juga dapat mengekstrak lebih banyak data jika diperlukan. Misalnya, Anda dapat memperoleh kreator (biasanya public key ke-17 di accountKeys), token yang digunakan untuk membuat pool (baik dari saldo token sebelum/sesudah maupun instruksi internal), jumlah token, dan bahkan token LP yang diterima kreator. Jumlah token LP yang diterima kreator dapat digunakan untuk membuat pemantau pembakaran likuiditas. Saat kreator pool membakar token LP miliknya, yang pada dasarnya merupakan token bukti atas porsi mereka di pool, kreator tersebut mencabut kemampuannya untuk menghapus likuiditas (berhati-hatilah jika mint authority masih berada di tangan mereka karena mereka dapat mencetak lebih banyak token dan menjualnya ke pool).

Struktur JSON

Untuk mendapatkan lebih banyak data, Anda dapat melihat struktur JSON transaksi yang tersedia di dokumentasi resmi Solana. Sebagai alternatif, Anda dapat menyimpan respons JSON dan menggunakan pemformat ini untuk melihat strukturnya. Hal ini cukup penting karena setelah memahami struktur umum transaksi, Anda dapat mengekstrak data apa pun yang biasanya terlihat saat menggunakan block explorer.

Di bawah ini adalah JSON umum yang berisi dua objek penting dengan struktur bertingkat dalam: Transaction dan Meta. Di dalam Transaction, terdapat objek message yang menyimpan blockhash terbaru, accountKeys, dan instructions. Di dalam Meta, terdapat Balances sebelum/sesudah (saldo lamport), innerInstructions, logMessages, dan token balances sebelum/sesudah.

Contoh Pemantau Pump.Fun

Melihat tren meme coin saat ini di Solana, saya membuat pemantau pump.fun yang sangat sederhana. Cukup ganti alamat yang kita pantau menjadi “6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P”, yaitu program on-chain pump.fun, lalu gunakan fungsi on message berikut:

Kode
ws.on('message', function incoming(data) {
    const messageStr = data.toString('utf8');
    try {
        const messageObj = JSON.parse(messageStr);

        const result = messageObj.params.result;
        const logs = result.transaction.meta.logMessages;
        const signature = result.signature; // Extract the signature
        const accountKeys = result.transaction.transaction.message.accountKeys.map(ak => ak.pubkey);

        if (logs && logs.some(log => log.includes('Program log: Instruction: InitializeMint2'))) {
            console.log('New pump.fun token!');
            console.log('tx:', signature);
            console.log('Creator:', accountKeys[0]);
            console.log('Token:', accountKeys[1]);

            // Log the first and second account keys if they exist
          
        }
    } catch (e) {
        
    }
});

Serupa dengan pendekatan kita pada Raydium, kita melihat semua transaksi yang berinteraksi dengan program pump.fun dan memfilternya berdasarkan log yang diinginkan (polanya jelas: log, log, log). Setelah mendapatkan transaksi dengan log yang diinginkan, kita mengekstrak signature, kreator, dan token itu sendiri!

Anda dapat melihat bahwa accountKeys dan signature tersusun di lokasi yang sama dalam JSON seperti pada contoh Raydium, sehingga kreator, token, dan signature mudah diperoleh. Struktur JSON pada dasarnya sama untuk sebagian besar transaksi, tetapi beberapa nilai mungkin berada di lokasi berbeda atau memiliki urutan berbeda  — Anda akan melihatnya dalam contoh berikutnya.

Intinya, ini adalah pemantau yang cukup sederhana untuk token pump.fun baru. Dengan informasi ini, Anda dapat membeli token tersebut atau sekadar mengetahui keberadaannya untuk keperluan pemantauan. Anda juga dapat menggabungkannya dengan berbagai Helius DAS API untuk membuat alat yang lebih canggih, misalnya guna memperoleh metadata atau informasi mengenai kreator.

Pemantau DCA Jupiter

Contoh ini relatif spesifik, tetapi menunjukkan bahwa Anda dapat melihat semuanya melalui log. Dengan permintaan berikut, kita akan melihat program DCA (Dollar-Cost Average) Jupiter dan, lebih khusus lagi, setiap pembelian DCA yang dilakukan menggunakan Jupiter. Contoh ini dapat digunakan dalam perhitungan perdagangan arbitrase atau untuk melihat potensi dampak terhadap pasar. Data pembelian DCA masih sangat jarang dimanfaatkan untuk menilai potensi dampak terhadap pasar.

Seperti yang Anda lihat, sejauh ini tidak ada hal rumit yang dilakukan. Kita menambahkan impor base58 di bagian atas dan mengubah alamat ke program DCA Jupiter. Bagian berikutnya mungkin terlihat cukup rumit, dan memang agak rumit, tetapi menurut saya penting untuk menyertakan contoh yang sedikit lebih kompleks.

Kode
const WebSocket = require("ws");
const bs58 = require("bs58");
// Create a WebSocket connection
const ws = new WebSocket(
  "wss://atlas-mainnet.helius-rpc.com?api-key=YOUR_API_KEY"
);

// Function to send a request to the WebSocket server
function sendRequest(ws) {
  const request = {
    jsonrpc: "2.0",
    id: 420,
    method: "transactionSubscribe",
    params: [
      {
        failed: false,
        accountInclude: ["DCA265Vj8a9CEuX1eb1LWRnDT7uK6q1xMipnNyatn23M"],
      },
      {
        commitment: "confirmed",
        encoding: "jsonParsed",
        transactionDetails: "full",
        maxSupportedTransactionVersion: 0,
      },
    ],
  };
  ws.send(JSON.stringify(request));
}

Berikut yang kita lakukan:

  • Menggunakan log DCA untuk memfilter hanya jenis transaksi ini.
  • Mengekstrak User, Input Mint, dan Output Mint dari transaksi.
  • Mengambil Instruction Data Raw dan mengonversi byte menjadi argumen input, seperti jumlah yang dimasukkan pengguna, seberapa sering mereka menjual, dan berapa banyak yang dijual setiap kali.
Kode
ws.on("message", async function incoming(data) {
  const messageStr = data.toString("utf8");
  try {
    const messageObj = JSON.parse(messageStr);

    const instructions = messageObj.params.result.transaction.transaction.message.instructions;
    const result = messageObj.params.result;
    const logs = result.transaction.meta.logMessages;
    // Extract only pubkeys

    if (
      logs &&
      logs.some((log) => log.includes("Program log: Instruction: OpenDcaV2"))
    ) {
      instructions.forEach((instruction) => {
        if (instruction.programId.includes("DCA265")) {
          if (instruction.accounts.length === 13) {
            console.log("User:", instruction.accounts[2]);
            console.log("Input Mint:", instruction.accounts[3]);
            console.log("Output Mint:", instruction.accounts[4]);

            const data = instruction.data;
            const bytedata = bs58.decode(data);

            const hexString = bytedata.toString("hex");
            const inAmountbytes = hexString.substring(16 * 2, 24 * 2);
            const cycleFrequencyBytes = hexString.substring(32 * 2, (32 + 8) * 2);
            const inAmountPerCycleBytes = hexString.substring(24 * 2, 32 * 2);

            // Reverse the byte order for little-endian interpretation
            const reversedCycleFrequencyBytes = cycleFrequencyBytes
              .match(/.{1,2}/g)
              .reverse()
              .join("");
            const reversedInAmountBytes = inAmountbytes
              .match(/.{1,2}/g)
              .reverse()
              .join("");
            const reversedInAmountPerCycleBytes = inAmountPerCycleBytes
              .match(/.{1,2}/g)
              .reverse()
              .join("");
            const cycleFrequency = BigInt("0x" + reversedCycleFrequencyBytes);
            const inAmount = BigInt("0x" + reversedInAmountBytes);
            const inAmountPerCycle = BigInt("0x" + reversedInAmountPerCycleBytes);

            console.log("Cycle Frequency every", cycleFrequency.toString() + " seconds");
            console.log("Amount input:", inAmount.toString());
            console.log("Amount  per cycle:", inAmountPerCycle.toString());
          
          }
        }
      });
      
    }
  } catch (e) {}
});*

Mendekripsi Data Instruksi Mentah

Saat melihat data instruksi mentah, data tersebut biasanya sesuai dengan argumen input. Data ini tidak sulit diperoleh dengan cara tersebut, dan kita tidak perlu melakukan deserialisasi apa pun, yang sering kali terasa merepotkan bagi banyak orang.

Sebagai contoh, mari ambil data ini dari transaksi berikut:

8e772b6da2340bb12e783a66000000006d9415754e00000037ca8a3a270000003c00000000000000010000000000000000010000000000000000010000000000000000

Sekarang, buka hexed.it dan tempel data tersebut:

Sekarang, mari cari argumen input berikut:

Di sisi kanan, mari masukkan 336971797613 ke kolom pencarian. Klik find next untuk melihat lokasi nilai inAmount di dalam byte.

Seperti yang dapat Anda lihat, byte dari 6D hingga 00 terakhir sebelum 37 menyimpan nilai inAmount. Setiap transaksi DCA dengan format yang kita pantau memiliki inAmount pada posisi byte yang sama. Delapan pasangan byte berikutnya menyimpan nilai inAmountPerCycle. Ini adalah cara praktis untuk menemukan nilai yang biasanya tidak terlihat jelas dalam JSON transaksi karena JSON sebagian besar berisi alamat dan saldo, bukan argumen input.

Anda Berhasil!

Jika sudah sampai sejauh ini, Anda kini memiliki dasar yang sangat baik untuk mulai menggunakan Helius Geyser WebSockets. Bagian tersulit adalah memulai. Sekarang Anda dapat memantau dompet, program, pool, dan apa pun yang diinginkan. Anda tidak memerlukan API berharga sangat mahal atau hal semacamnya. Jika mengalami masalah atau memiliki pertanyaan, Anda selalu dapat menanyakannya di Discord Helius!

Referensi

Berlangganan Helius

Ikuti perkembangan terbaru dalam pengembangan Solana dan dapatkan pembaruan saat kami memublikasikan postingan

Gambar diperbesar