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
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:
Scan Signatures: getSignaturesForAddress
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.
// 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:
Ada dua tipe Token: SPL-Token dan SPL-Token-2022, dengan programID berbeda. Saat membangun instruksi, harus membedakan keduanya.
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
Pre-check ATA: Pastikan sebelum withdraw, ATA target sudah dibuat, jika belum, buat terlebih dahulu.
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.
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.
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:
Keterangan:
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:
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.
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)
2. Tahap scan (scanNewSlots)
3. Parsing blok (txParser.parseBlock)
4. Parsing instruksi (txParser.parseInstruction)
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:
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:
Alur withdraw:
Contoh kode utama:
Pengiriman transaksi ke jaringan:
Kode lengkap dan pengujian ada di:
Dua optimisasi yang perlu diimplementasikan:
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.