Pindai untuk Mengunduh Aplikasi Gate
qrCode
Opsi Unduhan Lainnya
Jangan ingatkan saya lagi hari ini

Pengembangan sistem dompet pertukaran—menghubungkan ke jaringan Solana

Dalam artikel sebelumnya, kami melengkapi sistem pengendalian risiko di bursa, dan kali ini kami akan membahas integrasi dompet bursa dengan rantai Solana. Model akun, penyimpanan log, dan mekanisme konfirmasi Solana sangat berbeda dari rantai berbasis Ethereum. Jika kita mengikuti pola Ethereum, sangat mudah tersandung masalah. Berikut kami rangkum pemikiran keseluruhan tentang Solana.

Memahami Keunikan Solana

Model Akun Solana

Solana menggunakan model yang memisahkan program dan data, dimana program dapat digunakan bersama, sedangkan data program disimpan secara terpisah melalui akun PDA (Program Derived Address). Karena program bersifat bersama, diperlukan Token Mint untuk membedakan berbagai Token. Akun Token Mint menyimpan metadata global token seperti izin pencetakan (mint_authority), total pasokan (supply), dan jumlah desimal (decimals).
Setiap token memiliki alamat akun Mint unik sebagai pengenal, misalnya USD Coin (USDC) di jaringan utama Solana memiliki alamat Mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v.

Di Solana terdapat dua program Token, yaitu SPL Token dan SPL Token-2022. Setiap SPL Token memiliki ATA (Associated Token Account) yang terpisah untuk menyimpan saldo pengguna. Saat transfer token, sebenarnya yang dilakukan adalah memanggil program terkait untuk memindahkan token antar akun ATA.

Pembatasan Log Solana

Di Ethereum, log transfer digunakan untuk mendapatkan data transfer token melalui parsing log transaksi. Di Solana, log eksekusi secara default tidak disimpan secara permanen, dan tidak termasuk dalam status buku besar (ledger) (juga tidak memiliki filter Bloom untuk log), serta output log bisa dipotong selama eksekusi.
Oleh karena itu, kita tidak bisa melakukan rekonsiliasi deposit dengan memindai log, melainkan harus menggunakan getBlock atau getSignaturesForAddress untuk menganalisis instruksi.

Konfirmasi dan Reorganisasi Solana

Waktu blok Solana sekitar 400ms, dan setelah 32 konfirmasi (~12 detik), blok dianggap final (finalized). Jika kebutuhan real-time tidak tinggi, cukup percaya pada blok yang sudah final.
Untuk tingkat real-time lebih tinggi, perlu mempertimbangkan kemungkinan reorganisasi blok, meskipun jarang terjadi. Karena konsensus Solana tidak bergantung pada parentBlockHash untuk membentuk rantai, tidak bisa menggunakan metode seperti Ethereum yang membandingkan parentBlockHash dan hash blok di database untuk mendeteksi fork.
Bagaimana cara mendeteksi reorganisasi?
Saat melakukan scan lokal, kita harus merekam blockhash dari slot tertentu. Jika terjadi perubahan pada blockhash untuk slot yang sama, berarti terjadi rollback.

Memahami Perbedaan Solana, selanjutnya kita bisa mulai melakukan implementasi, dimulai dari modifikasi database:

Desain Tabel Database

Karena Solana memiliki dua tipe Token, maka di tabel tokens perlu ditambahkan kolom token_type untuk membedakan SPL Token dan SPL Token-2022.

Alamat Solana meskipun berbeda dari Ethereum, tetap bisa diproses melalui derivasi BIP32/BIP44, hanya jalurnya berbeda. Oleh karena itu, tabel wallets yang ada bisa digunakan kembali, namun untuk mendukung pemetaan ATA dan pelacakan scan blok Solana, perlu menambahkan tiga tabel berikut:

Nama Tabel Kolom Kunci Penjelasan
solana_slots slot, block_hash, status, parent_slot Menyimpan data slot secara redundan, memudahkan deteksi fork dan rollback
solana_transactions tx_hash, slot, to_addr, token_mint, amount, type Menyimpan detail transaksi deposit/withdrawal, tx_hash unik untuk tracking double signature
solana_token_accounts wallet_id, wallet_address, token_mint, ata_address Mencatat pemetaan ATA pengguna, scan module dapat melakukan pencarian balik berdasarkan ata_address

Keterangan:

  • solana_slots merekam status confirmed/finalized/skipped, scanner akan memutuskan penyimpanan atau rollback berdasarkan status.
  • solana_transactions menyimpan jumlah dalam lamports atau unit terkecil token, dengan kolom type untuk membedakan deposit/withdraw, dan tetap membutuhkan tanda tangan dari sistem risiko.
  • solana_token_accounts menghubungkan wallet dan pengguna dengan memastikan keunikan ATA (wallet_address + token_mint), ini adalah indeks utama untuk logika scan.

Rincian definisi tabel dapat dilihat di db_gateway/database.md

Penanganan Deposit Pengguna

Untuk memproses deposit pengguna, perlu melakukan scan data chain Solana secara terus-menerus, dengan dua metode utama:

  1. Scan Signatures: getSignaturesForAddress
  2. Scan Blok: getBlock

Metode 1: Scan signature dari alamat tertentu, dengan memanggil getSignaturesForAddress(, { before, until, limit }), dan memasukkan alamat ATA yang dihasilkan untuk pengguna sebagai parameter. Alamat ini bisa juga programID (perhatikan bahwa instruksi transfer SPL-token tidak menyertakan alamat mint, dan dikontrol melalui parameter before/ until untuk menarik secara incremental). Setelah mendapatkan signature, gunakan getTransaction(signature untuk memperoleh data transaksi.

Metode ini cocok untuk volume data atau jumlah akun yang kecil. Jika jumlah akun sangat besar, metode scan blok lebih cocok, dan di sini kami menggunakan metode scan blok.

Metode 2: Scan blok dengan terus-menerus mendapatkan slot terbaru, lalu memanggil getBlock)slot( untuk mendapatkan detail transaksi lengkap, signature, dan akun terkait, kemudian memfilter berdasarkan instruksi dan akun yang relevan.

Catatan: Karena volume transaksi Solana tinggi dan TPS tinggi, dalam lingkungan produksi, parsing dan filtering bisa tertinggal. Oleh karena itu, disarankan menggunakan message queue, seperti Kafka/RabbitMQ, untuk mengirim semua transfer token yang berpotensi sebagai event deposit ke antrian, kemudian dikonsumsi secara terpisah untuk diproses dan disimpan ke database. Untuk mempercepat filter, data hotspot bisa disimpan di Redis. Jika pengguna sangat banyak, bisa dilakukan sharding berdasarkan ATA, dengan beberapa konsumen memantau shard berbeda.

Alternatif lain, bisa menggunakan layanan Indexer dari penyedia RPC pihak ketiga, yang menawarkan Webhook, monitoring akun, dan filtering tingkat tinggi, sehingga beban parsing data besar bisa ditangani di luar sistem utama.

Proses Scan Blok

Kami menggunakan metode kedua, dengan kode utama di modul scan/solana-scan, file blockScanner.ts dan txParser.ts, dengan alur sebagai berikut:

1. Sinkronisasi awal dan pengisian data historis (performInitialSync)

  • Mulai dari slot terakhir yang sudah diproses, scan ke slot terbaru
  • Setiap 100 slot, periksa apakah slot baru muncul, dan update target
  • Gunakan commitment confirmed untuk mendapatkan blok, agar tetap real-time

2. Tahap scan (scanNewSlots)

  • Terus-menerus cek muncul slot baru
  • Validasi ulang slot confirmed terakhir (deteksi rollback)

3. Parsing blok (txParser.parseBlock)

  • Panggil getBlock)slot) dengan parameter commitment: “confirmed” dan encoding: “jsonParsed”
  • Iterasi setiap transaksi, periksa instruksi dan meta
  • Hanya proses transaksi sukses (tx.meta.err === null)

4. Parsing instruksi (txParser.parseInstruction)

  • Transfer SOL: cocokkan program System (11111…) dan tipe ‘transfer’, cocokkan destination dengan daftar alamat yang dipantau
  • Transfer SPL Token: cocokkan program Token atau Token-2022, tipe ‘transfer’ atau ‘transferChecked’, destination adalah ATA, dan lakukan mapping ke wallet dan token mint dari database.

Penanganan rollback:
Program akan terus memantau finalizedSlot, jika slot ≤ finalizedSlot, maka blok dianggap final. Untuk blok yang masih di confirmed, periksa perubahan blockhash untuk mendeteksi rollback.

Contoh kode utama:

// blockScanner.ts - scan slot tunggal
async scanSingleSlot(slot: number) {
  const block = await solanaClient.getBlock(slot);
  if (!block) {
    await insertSlot({ slot, status: 'skipped' });
    return;
  }
  const finalizedSlot = await getCachedFinalizedSlot();
  const status = slot <= finalizedSlot ? 'finalized' : 'confirmed';
  await processBlock(slot, block, status);
}
// txParser.ts - parsing instruksi transfer
for (const tx of block.transactions) {
  if (tx.meta?.err) continue; // lewati transaksi gagal
  const instructions = [
    ...tx.transaction.message.instructions,
    ...(tx.meta.innerInstructions ?? []).flatMap(i => i.instructions)
  ];
  for (const ix of instructions) {
    // Transfer SOL
    if (ix.programId === SYSTEM_PROGRAM_ID && ix.parsed?.type === 'transfer') {
      if (monitoredAddresses.has)ix.parsed.info.destination() {
        // proses
      }
    }
    // Transfer Token
    if (ix.programId === TOKEN_PROGRAM_ID || ix.programId === TOKEN_2022_PROGRAM_ID) {
      if (ix.parsed?.type === 'transfer' || ix.parsed?.type === 'transferChecked'() {
        const ataAddress = ix.parsed.info.destination; // ATA
        const walletAddress = ataToWalletMap.get)ataAddress(; // mapping ke wallet
        if )walletAddress && monitoredAddresses.has(walletAddress)) {
          // proses
        }
      }
    }
  }
}

Setelah menemukan transaksi deposit, data akan diverifikasi dengan sistem risiko dan, jika valid, disimpan ke tabel transaksi dana.

Withdraw

Proses withdraw di Solana mirip dengan EVM, namun ada perbedaan dalam konstruksi transaksi:

  1. Ada dua tipe Token: SPL-Token dan SPL-Token-2022, dengan programID berbeda. Saat membangun instruksi, harus membedakan keduanya.
  2. Transaksi Solana terdiri dari signature (tanda tangan ed25519) dan message (berisi header, accountKeys, recentBlockhash, instructions). Message di-hash dan ditandatangani. Tidak ada nonce, melainkan recentBlockhash yang berlaku selama sekitar 150 blok (~1 menit). Setiap kali melakukan withdraw, recentBlockhash harus diambil dari chain secara real-time. Jika transaksi perlu review manual, recentBlockhash harus diperoleh ulang dan transaksi ditandatangani lagi.

Alur withdraw:

  • Bangun instruksi transfer SOL atau token sesuai tipe
  • Buat message transaksi menggunakan library @solana/kit
  • Tanda tangani transaksi dengan private key
  • Kirim transaksi ke jaringan melalui @solana/web3.js

Contoh kode utama:

// Instruksi transfer SOL
const instruction = getTransferSolInstruction({
  source: hotWalletSigner,
  destination: solanaAddress)to(,
  amount: BigInt(amount)
};

// Instruksi transfer Token
const instruction = getTransferInstruction){
  source: sourceAta,
  destination: destAta,
  authority: hotWalletSigner,
  amount: BigInt(amount)
};

// Membuat message transaksi
const transactionMessage = pipe(
  createTransactionMessage({ version: 0 }),
  tx => setTransactionMessageFeePayerSigner(hotWalletSigner, tx),
  tx => setTransactionMessageLifetimeUsingBlockhash){
    blockhash: blockhash,
    lastValidBlockHeight: BigInt(lastValidBlockHeight(
  }, tx),
  tx => appendTransactionMessageInstruction)instruction, tx(;

// Tanda tangan transaksi
const signedTx = await signTransactionMessageWithSigners(transactionMessage);

// Encode transaksi untuk pengiriman
const signedTransaction = getBase64EncodedWireTransaction(signedTx);

Pengiriman transaksi ke jaringan:

// Menggunakan @solana/web3.js
const solanaRpc = chainConfigManager.getSolanaRpc((;
const txSignature = await solanaRpc.sendTransaction)signedTransaction, ...;

Kode lengkap dan pengujian ada di:

  • Wallet: walletBusinessService.ts:405-754
  • Signer: solanaSigner.ts:29-122
  • Script pengujian: requestWithdrawOnSolana.ts

Dua optimisasi yang perlu diimplementasikan:

  1. Pre-check ATA: Pastikan sebelum withdraw, ATA target sudah dibuat, jika belum, buat terlebih dahulu.
  2. Biaya prioritas: Saat jaringan padat, atur computeUnitPrice untuk mempercepat transaksi.

Kesimpulan

Integrasi Solana ke sistem bursa secara arsitektur tidak banyak berbeda, hanya perlu menyesuaikan dengan model akun, struktur transaksi, dan mekanisme konfirmasi uniknya.
Dalam proses deposit, buat dan pelihara mapping ATA ke wallet, gunakan monitoring perubahan blockhash untuk deteksi reorganisasi, dan perbarui status transaksi secara dinamis dari confirmed ke finalized.
Dalam withdraw, ambil recentBlockhash secara real-time, dan bangun transaksi sesuai tipe token yang berbeda.

SOL-1.8%
ETH-1.41%
Lihat Asli
Halaman ini mungkin berisi konten pihak ketiga, yang disediakan untuk tujuan informasi saja (bukan pernyataan/jaminan) dan tidak boleh dianggap sebagai dukungan terhadap pandangannya oleh Gate, atau sebagai nasihat keuangan atau profesional. Lihat Penafian untuk detailnya.
  • Hadiah
  • Komentar
  • Posting ulang
  • Bagikan
Komentar
0/400
Tidak ada komentar
  • Sematkan
Perdagangkan Kripto Di Mana Saja Kapan Saja
qrCode
Pindai untuk mengunduh aplikasi Gate
Komunitas
Bahasa Indonesia
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)