# Riset teknis: Everted Hand Swarm

**Tujuan.** Dokumen ini merancang *Everted Hand Swarm* (EHS), dashboard analitik Solana waktu-nyata untuk menemukan kandidat pembeli memecoin, memantau dompet, dan memberi sinyal akumulasi. Produk ini **read-only**: tidak meminta seed phrase/private key, tidak mengeksekusi perdagangan, dan tidak menyatakan sinyal sebagai nasihat investasi. Tanggal riset: 16 Oktober 2026.

## Cara membaca dan tingkat kepastian

- **[Fakta]** adalah perilaku/dokumentasi sumber yang dapat ditautkan.
- **[Rancangan]** adalah keputusan teknis yang direkomendasikan untuk EHS, bukan kemampuan yang sudah ada atau fakta dari penyedia.
- **[Batas/ketidakpastian]** adalah hal yang tidak boleh dipresentasikan sebagai pasti.
- **[Pertanyaan terbuka]** perlu diputuskan pemilik produk sebelum produksi.

Istilah “kontrak token” pada UI berarti **alamat mint SPL**, bukan alamat smart-contract EVM. Solana mendeskripsikan mint sebagai akun yang mengidentifikasi token tertentu; kepemilikan individual berada pada token account. [Fakta; dokumentasi Solana](https://solana.com/docs/tokens).

## 1. Kesimpulan arsitektur yang direkomendasikan

**[Rancangan]** Bangun empat jalur yang terpisah agar angka UI dapat diaudit dan kegagalan satu jalur tidak mengubah data menjadi palsu.

```text
PublicNode HTTPS                  PublicNode WSS
getTransaction / balances         logsSubscribe / accountSubscribe
          \                         /
           -> Ingestor + decoder + idempotent queue
                         |
      PostgreSQL: raw_tx, fills, lots, snapshots, alerts
                         |
       API read model / SSE atau WebSocket aplikasi
                         |
          dashboard web + watchlist + notifikasi

DEX Screener REST -> cache harga/pair -> pricing service --/
```

**[Fakta]** PublicNode menampilkan endpoint mainnet `https://solana-rpc.publicnode.com`, menyediakan kategori RPC dan WS RPC, dan menyatakan Yellowstone gRPC membutuhkan token gratis. [PublicNode](https://solana.publicnode.com/). Konfigurasikan `RPC_HTTP=https://solana-rpc.publicnode.com` dan, sesuai kebutuhan brief, `RPC_WSS=wss://solana-rpc.publicnode.com`; lakukan *health probe* saat bootstrap dan jangan anggap dukungan fitur/retensi sama dengan endpoint berbayar.

**[Fakta]** RPC Solana mendukung membaca state, transaksi, simulasi, serta subscription pembaruan langsung. [Solana RPC overview](https://solana.com/docs/rpc). `getTransaction` menerima signature dan dapat mengembalikan `null` bila transaksi tidak ditemukan atau belum terkonfirmasi. [Dokumentasi `getTransaction`](https://solana.com/docs/rpc/http/gettransaction). Maka WSS hanya menjadi pemicu; rekaman transaksi final selalu diambil ulang dari HTTPS dan disimpan bersama signature/slot.

**[Rancangan – stack gratis dahulu]**

| Lapisan | Pilihan | Alasan dan batas |
|---|---|---|
| Ingestor/API | TypeScript (Node.js) dengan worker terpisah; REST untuk query historis, SSE untuk feed browser | Satu bahasa untuk parser/validasi dan UI. Worker tidak boleh berjalan di browser atau mengekspos kredensial DB. |
| Antrean | tabel PostgreSQL `jobs` dengan `FOR UPDATE SKIP LOCKED` pada MVP; tambah Redis hanya jika metrik menunjukkan perlu | Menghindari layanan tambahan. Antrean harus memiliki idempotency key `signature:wallet:mint`. |
| Data primer | PostgreSQL terkelola pada free tier yang benar-benar tersedia saat deploy, atau PostgreSQL lokal untuk pengembangan | Data relasional (lot, fill, alert, kepemilikan) dan indeks cocok untuk query leaderboard. Hindari menyebut tier gratis tertentu permanen: kuota/ketentuan berubah. |
| Cache | memori proses dengan TTL pendek pada MVP; Redis gratis/terkelola hanya bila ada kapasitas | Cache DEX Screener tidak pernah menjadi sumber transaksi. |
| Web | Next.js/React atau SPA statis + API; desain responsif | Keputusan implementasi, bukan ketergantungan pada penyedia berbayar. |
| Observabilitas | log JSON terstruktur, tabel `ingestion_runs`, metrik lag/429/reconnect, dan endpoint `/health` internal | Membuktikan kesegaran/kelengkapan, bukan sekadar membuat grafik. |

**[Fakta]** PostgreSQL Row-Level Security dapat membatasi baris per pengguna; ketika RLS aktif dan tidak ada kebijakan yang berlaku, akses normal bersifat *default deny*. [PostgreSQL RLS](https://www.postgresql.org/docs/17/ddl-rowsecurity.html). **[Rancangan]** aktifkan RLS pada `watchlists`, `alert_rules`, `notification_endpoints`, dan data pengguna; data on-chain agregat dapat dibaca publik melalui view yang tidak memuat informasi privat pengguna.

## 2. Kontrak data, asal data, dan kebenaran

**[Rancangan]** Setiap objek yang keluar ke UI membawa `source`, `source_url/endpoint`, `observed_at`, `slot`, `commitment`, `signature` (bila ada), `decoder_version`, `price_source`, dan `verification_state` (`pending | confirmed | finalized | rejected | incomplete`). Jangan pernah mengisi nilai yang tidak diketahui dengan 0: gunakan `null`, `N/A`, dan alasan.

Tabel minimum:

```text
tokens(mint PK, token_program, decimals, first_seen_at, risk_flags jsonb)
pairs(pair_address PK, mint, dex_id, quote_mint, dex_url, last_price_usd, observed_at)
raw_transactions(signature PK, slot, block_time, message_json, meta_json, fetched_at, commitment)
wallet_events(signature, wallet, mint, side, token_delta, quote_delta, fee_lamports,
              price_usd, price_source, slot, state, decoder_version,
              PRIMARY KEY(signature,wallet,mint))
lots(wallet,mint, lot_id, acquired_qty, remaining_qty, cost_usd, opened_at)
wallet_snapshots(wallet,mint, qty, cost_basis_usd, realized_pnl_usd, unrealized_pnl_usd, as_of_slot)
watchlists(owner_user_id, wallet, mode, reason, enabled); alerts(...); audit_log(...)
```

Simpan angka token sebagai integer unit dasar/`numeric`, bukan `float`; simpan lamports sebagai integer dan timestamp UTC. Harga USD dapat desimal, tetapi semua pembulatan terjadi di lapisan tampilan. Signature unik dan *upsert* membuat pengiriman ulang WSS/retry aman.

## 3. Penemuan otomatis: dompet dan buy/sell yang benar

### 3.1 Menemukan token/pair kandidat

**[Fakta]** DEX Screener mendokumentasikan profil token terbaru/boost dengan batas 60 request/menit dan endpoint pair/token (`/token-pairs/v1/{chainId}/{tokenAddress}`, `/tokens/v1/{chainId}/{tokenAddresses}`) dengan batas 300 request/menit; respons pair mencakup `pairAddress`, token dasar/kuotasi, `priceUsd`, `txns`, `volume`, `liquidity`, dan waktu pair dibuat. [Referensi DEX Screener](https://docs.dexscreener.com/api/reference). Metadata/profil atau boost hanyalah sinyal penemuan, **bukan** bukti keamanan atau volume riil.

**[Rancangan]** Poll kandidat dengan token-bucket lokal (mis. 45 rpm untuk kelas 60 dan 240 rpm untuk kelas 300 sebagai headroom), cache per mint 30–60 detik, *jitter*, dan `Retry-After` bila tersedia. Filter awal yang dapat dikonfigurasi: `chainId=solana`, pair masih muda, likuiditas minimum, volume 5m minimum, dan quote token yang diizinkan. Pilih pair kanonis secara deterministik: likuiditas USD tertinggi yang segar, lalu volume; simpan semua pair agar pilihan dapat ditinjau. Jangan menyebut token “memecoin” hanya dari nama/simbol.

**[Batas/ketidakpastian]** DEX Screener adalah sumber harga/pair pihak ketiga, bukan ledger Solana. Harga `priceUsd` bisa kosong, terlambat, berubah karena pair berganti, atau bukan harga fill seorang wallet. Tidak boleh menghitung transaksi on-chain dari nilai `txns.buys/sells` DEX Screener; itu statistik pair, bukan identitas wallet.

### 3.2 Mengambil aktivitas on-chain

**[Fakta]** `logsSubscribe` dapat berlangganan log transaksi, tetapi filter `mentions` hanya menerima **satu** pubkey per panggilan; `all` mengecualikan vote sederhana. [Dokumentasi Solana `logsSubscribe`](https://solana.com/docs/rpc/websocket/logssubscribe). `accountSubscribe` mengirim notifikasi ketika lamports atau data akun berubah dan menerima `processed`, `confirmed`, atau `finalized`. [Dokumentasi `accountSubscribe`](https://solana.com/docs/rpc/websocket/accountsubscribe). `getSignaturesForAddress` mengembalikan signature transaksi terkonfirmasi yang mereferensikan alamat dan `getTransaction` mengembalikan transaksi menurut signature. [Daftar metode HTTP Solana](https://solana.com/docs/rpc/http).

**[Rancangan – dua lintasan]**

1. **Discovery/backfill:** untuk setiap mint/pool/program DEX yang masuk daftar, ambil signature berhalaman dengan `getSignaturesForAddress` dan checkpoint `before`/slot terakhir. Fetch `getTransaction(signature, {encoding:"jsonParsed", maxSupportedTransactionVersion:0, commitment:"confirmed"})`; antrikan kembali `null` atau status sementara, jangan ciptakan event.
2. **Live watchlist:** buka satu `logsSubscribe({mentions:[wallet]})` per wallet yang dipantau, karena batas satu mention. Notifikasi memberi signature; ambil transaksi lengkap lalu decode. Untuk 100 wallet, *shard* koneksi/subscription, batasi concurrent fetch, dan simpan checkpoint per wallet.
3. **Cakupan luas yang murah:** jangan subscribe `all` di PublicNode untuk mengklaim “seluruh Solana”. Gunakan daftar pool/mint/program yang eksplisit dan sampling/backfill. Jika kelak membutuhkan seluruh blok/program secara andal, evaluasi indeks/Geyser berbayar—bukan memalsukan kelengkapan dari endpoint gratis.
4. **Rekonsiliasi:** setiap 1–5 menit, gunakan `getSignaturesForAddress` sejak checkpoint untuk menutup pesan WSS yang hilang; deduplikasi berdasarkan signature. Setelah `finalized`, perbarui state; event `processed` di UI harus berlabel sementara.

**[Fakta]** `processed` adalah blok terbaru tetapi dapat di-*rollback*; `confirmed` telah dipilih supermayoritas; `finalized` adalah status terkuat. [Solana commitment](https://solana.com/docs/rpc). **[Rancangan]** feed cepat memakai `confirmed` dengan badge “belum final”, leaderboard/alert finansial memakai `finalized` atau memperlihatkan kolom komitmen. Ini mencegah PnL dari fork sementara tampak final.

### 3.3 Klasifikasi buy/sell, bukan tebakan dari transfer

**[Fakta]** Transfer SPL hanya memindahkan token antar token account dan tidak mengubah suplai. [Solana transfer token](https://solana.com/docs/tokens/basics/transfer-tokens). Karena itu transfer token sendiri **bukan bukti buy atau sell**. Transaksi dengan token account baru tidak memasukkan akun tersebut di `preTokenBalances`; saldo awal harus diperlakukan nol. [Panduan integrasi transaksi Solana](https://solana.com/docs/defi/exchange).

**[Rancangan – decoder konservatif]**

1. Terima hanya transaksi dengan `meta.err === null`; simpan signature, slot, `pre/postTokenBalances`, `pre/postBalances`, `innerInstructions`, `logMessages`, dan account keys.
2. Petakan setiap token account ke `owner`, `mint`, `decimals`; hitung delta bersih per `(owner,mint)` dari pre/post. Account yang hanya ada di post bernilai pre=0; account tertutup post=0. Kenali Token Program asli dan Token-2022—Solana memiliki keduanya, dan token program memengaruhi derivasi ATA. [Solana token programs](https://solana.com/docs/payments/how-payments-work).
3. Tentukan *actor wallet* hanya bila signer/fee payer atau owner cocok dengan wallet yang dipantau. Jangan mengatribusikan vault pool, PDA, atau token account langsung sebagai trader.
4. Kenali program DEX/router melalui *allowlist versioned* dari ID yang telah direview; parse instruksi + inner transfer. Jika wallet mendapat `+X` mint target dan membayar `-Y` quote (SOL/wSOL/USDC atau quote pair yang terverifikasi) dalam swap yang sama, klasifikasikan `BUY`; kebalikannya `SELL`. Jika dua aset target atau transfer langsung, `TRANSFER/UNKNOWN`.
5. Hitung `qty=abs(delta target)`, `quote=abs(delta quote)`, `execution_price=quote/qty`; simpan fee jaringan dan, jika terdeteksi secara andal, transfer fee. Bila lebih dari satu pool/rute, tandai `multi-hop` dan simpan seluruh kaki, bukan memaksa satu harga.
6. Jika parser tidak mengenal program, `meta` tidak lengkap, arah ambigu, atau tidak ada quote yang terverifikasi, simpan transaksi mentah dan tampilkan **Unclassified—needs decoder**. Ia tidak masuk PnL/leaderboard.

Ini merupakan pendekatan yang lebih aman daripada menyebut setiap penerimaan token sebagai pembelian. **[Batas]** airdrop, mint, burn, transfer OTC, wrap/unwrap SOL, LP deposit/withdraw, aggregator multi-hop, Token-2022 fee/hook, dan saldo rahasia dapat menyerupai trade. Solana secara eksplisit menyebut Token-2022 memiliki transfer hook, transfer fee, dan confidential balances. [Dokumentasi Token-2022](https://solana.com/docs/payments/how-payments-work). Untuk jenis ini, berikan reason code dan jangan masukkan hasil yang ambigu.

### 3.4 Skor kandidat “smart money”

**[Rancangan]** “Smart money” adalah label heuristik yang dapat dijelaskan, bukan identitas/keahlian seseorang. Gunakan dua skor terpisah:

- `quality_score` (0–100): jumlah trade final yang terklasifikasi, usia riwayat, win rate setelah minimum sampel, realised PnL bersih fee, median hold time, dan konsistensi lintas token;
- `discovery_score`: pembelian awal setelah pair terdeteksi, nilai pembelian relatif terhadap likuiditas, dan akumulasi bersih yang belum dipindahkan.

Tampilkan komponen, jendela waktu, min-sample, versi formula, dan status data. Gunakan *shrinkage* (mis. win rate dibobotkan ke baseline sampai >=20 closed lots) sehingga satu kemenangan tidak menang leaderboard. Hindari fitur yang mengimplikasikan sebab-akibat (“wallet ini membuat harga naik”) dan label legal/identitas tanpa bukti.

## 4. Watchlist top-N dan manual

**[Rancangan]** `watchlists` memiliki mode `manual`, `auto_top_10`, `auto_top_50`, `auto_top_100`, sumber skor, `pinned`, `excluded`, `effective_from/to`, serta alasan perubahan. Satu wallet adalah pubkey yang tervalidasi base58/panjang; UI menolak duplikasi dan alamat token account bila pengguna bermaksud wallet.

| Kebutuhan | Mekanisme |
|---|---|
| Manual | Pengguna menambah wallet, label privat, ambang alert, dan menghapusnya. Validasi format, query kepemilikan token opsional, lalu tulis audit log; tidak melakukan panggilan transaksi dari UI. |
| Top 10/50/100 | Pekerjaan periodik menghitung ranking dari event **finalized**, universe/token/time window yang jelas. Gunakan *hysteresis*: kandidat baru harus mengungguli posisi terbawah selama dua run, kecuali risiko tinggi. |
| Stabilitas | `pinned` tidak dapat dihapus otomatis; `excluded` tidak dapat masuk auto. Snapshot ranking berisi input/version agar hasil masa lalu dapat direproduksi. |
| Beban | Saat N=10 gunakan WSS per wallet + rekonsiliasi; N=50/100 lakukan sharding, concurrency cap, batch HTTP bila aman, dan turunkan refresh non-kritis lebih dahulu. Tampilkan `coverage: 97/100 connected`, bukan “real-time” bila 3 subscription gagal. |

**[Fakta]** `getTokenAccountsByOwner` mengembalikan akun SPL yang owner-nya sesuai alamat dan mendukung pemfilteran mint atau program ID. [Dokumentasi Solana](https://solana.com/docs/rpc/http/gettokenaccountsbyowner). **[Rancangan]** panggil saat snapshot/rekonsiliasi untuk holdings wallet, bukan sebagai pengganti ledger transaksi; pagination/retensi dan biaya request tetap harus diukur.

## 5. Feed transaksi live, harga, volume, dan PnL

### Kontrak UI event

Setiap baris menampilkan: waktu blok dan umur data; wallet dipendekkan + salin + tautan explorer; side (`BUY/SELL/TRANSFER/UNKNOWN`); mint dan pair; quantity; quote/volume; harga eksekusi; harga referensi saat ini; realised/unrealised PnL; fee; signature; source/commitment; dan badge `verified`, `pending`, `incomplete`, atau `unclassified`.

**[Rancangan harga]** `execution_price` berasal dari delta quote/token transaksi yang sudah terklasifikasi. `mark_price` dari pair kanonis DEX Screener yang dicache beserta `pair_address`, `observed_at`, dan `priceUsd`. `volume_usd = abs(quote_amount) × harga quote saat eksekusi`; apabila quote=USDC dapat dianggap sekitar USD **hanya jika kebijakan produk mengizinkannya**, selain itu gunakan harga snapshot berstempel waktu. Jangan gunakan *harga sekarang* untuk volume/PnL historis tanpa label estimasi.

Rumus (semua setelah penyesuaian decimals):

```text
cost_lot = qty_beli × harga_eksekusi_USD + fee_USD
proceeds_jual = qty_jual × harga_eksekusi_USD - fee_USD
realisedPnL = Σ(proceeds_jual - cost_basis_qty_yang_terjual)
unrealisedPnL = qty_tersisa × mark_price_USD - cost_basis_qty_tersisa
totalPnL = realisedPnL + unrealisedPnL
ROI = totalPnL / modal_yang_dialokasikan  (null jika modal=0)
```

Pilih FIFO sebagai default dan tulis `cost_method=FIFO` di setiap hasil; alternatif LIFO/average-cost akan menghasilkan angka berbeda. Buat lot saat BUY final; SELL mengurangi lot tertua dan tidak boleh membuat lot negatif—jika riwayat dimulai terlambat, tandai `unknown_cost_basis` dan tampilkan PnL `N/A`, bukan profit fiktif. PnL tidak menghitung slippage implisit, pajak, CEX/off-chain trade, atau harga yang hilang.

## 6. Leaderboard dan alert akumulasi whale

**[Rancangan]** Semua leaderboard memiliki selector waktu, universe, commitment, metode PnL, min-sample, *last updated*, cakupan, dan ekspor CSV berisi signature. Peringkat berikut tidak dicampur:

| Papan | Metrik | Guardrail |
|---|---|---|
| Profit | realised PnL final bersih fee (utama); unrealised dipisah | Hanya lot ber-cost basis diketahui; minimum trade dan modal; jangan urutkan % ROI kecil tanpa minimum modal. |
| Most-held | jumlah wallet unik dengan saldo > 0 per mint dan/atau exposure USD | Bedakan wallet vs token account; kepemilikan melalui CEX/vault dapat membuat hitungan menipu. |
| Akumulasi whale | jumlah wallet qualifying, `net_buy_usd`, delta holding, konsentrasi, dan jendela 5m/1h/24h | “Whale” didefinisikan konfigurabel (mis. notional/percentile), bukan klaim identitas. |

Alert contoh: *>=3 wallet qualifying berbeda melakukan net buy final >= ambang USD dalam 15 menit, total net buy >= ambang, pair liquidity >= minimum, dan tidak ada stale-data flag*. Lalu dedupe `(mint, rule, window)`, cooldown, dan kirim notifikasi berisi hitungan/cakupan/signature, bukan “beli sekarang”. Alarm `distribution` memakai kondisi kebalikannya. Cegah *sybil*: kelompokkan hanya melalui bukti eksplisit yang direview; jangan menggabungkan alamat berdasar tebakan.

## 7. UX dark cyberpunk yang tetap dapat dipakai

**[Rancangan]** Gunakan latar charcoal/navy (`#080B12`), panel `#101827`, teks off-white dengan rasio kontras memadai, satu aksen cyan untuk data netral, hijau/merah **plus ikon dan label** untuk buy/sell, dan magenta hanya untuk alert. Efek glow/scanline tipis serta opsi `prefers-reduced-motion`; jangan menjadikan neon sebagai satu-satunya pembawa makna.

- Desktop: bar atas (status RPC: connected/lag/last slot), sidebar filter/watchlist, tabel feed utama, panel kanan alert. Mobile: filter sebagai drawer, kolom non-kritis disembunyikan, baris membuka detail/bukti; tombol sentuh >=44px.
- Panel detail menampilkan proses klasifikasi, raw signature/slot, commitment, pair/harga source, lot FIFO dan alasan `N/A`. Ini lebih berharga daripada animasi bagi trust.
- Toast untuk success/error operasi pengguna; notification center untuk alert yang disimpan. Pengaturan notifikasi *opt-in*, *rate limited*, dapat dibisukan per token, dan selalu memberi timestamp serta “data may be pending”.
- Jangan memuat gambar/logo token pihak ketiga tanpa allowlist proxy/CSP dan fallback; nama/simbol dapat dipalsukan, jadi mint selalu terlihat/dapat disalin.

## 8. RPC gratis: reconnect, kuota, dan kejujuran operasional

**[Fakta]** Dokumentasi Solana menyatakan endpoint publik adalah infrastruktur bersama yang tidak ditujukan untuk aplikasi produksi, dapat memberi `429` ketika melampaui rate limit dan `403` ketika trafik diblokir. Dokumentasi pemilihan provider meminta pengecekan limit request/metode/ukuran respons/bandwidth/batch/WS/koneksi serta retensi histori; endpoint terkait dapat memiliki state tertinggal satu sama lain. [Solana RPC overview](https://solana.com/docs/rpc) dan [panduan memilih provider](https://solana.com/docs/rpc/providers). PublicNode menyatakan archive data tersedia namun akses archive berbeda, dan gRPC memerlukan token gratis; jangan menyimpulkan semua histori tersedia lewat endpoint umum. [PublicNode](https://solana.publicnode.com/).

**[Rancangan koneksi]**

1. State machine: `CONNECTING → SUBSCRIBING → LIVE → BACKOFF → RECOVERING`; simpan daftar subscription logis, bukan ID subscription lama.
2. Ping/heartbeat, batas waktu respons, dan *exponential backoff with full jitter* (mis. 1 s, 2 s, 4 s… maksimum 60 s), satu reconnect inflight. Pada `429/503` hormati `Retry-After`; pada `403` hentikan retry agresif dan tampilkan degraded/error.
3. Setelah reconnect: buka socket baru, subscribe ulang seluruh daftar, lalu backfill signature dari `last_finalized_slot/signature` sampai head. Dedupe signature di database; bandingkan slot/checkpoint. Jangan menganggap pesan saat putus telah diterima.
4. Per-wallet/per-mint token bucket dan global concurrency limit; gabungkan request yang dapat dibatch; cache hasil immutable; turunkan urutan kerja: gambar/metadata → harga → discovery → watchlist final. Transaksi/PnL tidak dibuang demi mempercantik UI.
5. *Circuit breaker* bila error ratio tinggi; tandai feed `STALE` dengan durasi dan cakupan, berhenti mengirim alert trading pada data stale. Dashboard menampilkan latensi p50/p95, last WSS event, last reconciled slot, count `429`, coverage, dan backlog.

**[Batas/ketidakpastian]** Tidak ada SLA, limit numerik PublicNode, retensi historis, koneksi WS maksimum, atau dukungan subscription tertentu yang dapat dibuktikan dari halaman publik yang ditinjau. Ini harus diukur dalam *staging* tanpa mengasumsikan nilai tertentu. Cadangan endpoint hanya boleh ditambahkan setelah persetujuan/ketentuan layanan diverifikasi; endpoint cadangan bukan lisensi untuk menghindari limit.

## 9. Keamanan, akurasi, dan anti-data-palsu

**[Rancangan]**

- **Sumber primer:** transaksi, saldo, owner, dan finality berasal dari RPC; harga/pair dari DEX Screener diberi label sekunder. Persilangkan signature/slot dan akun program dengan node yang sama/sehat; ketika ada konflik, tampilkan konflik dan tahan alert, bukan pilih nilai yang menguntungkan.
- **Validasi input:** validasi base58/panjang pubkey, allowlist `chainId=solana`, batas panjang/kuota filter, parameterized SQL, schema validation pada respons RPC/DEX, dan batas ukuran JSON. Tidak ada URL pihak ketiga yang di-fetch server berdasarkan input token (cegah SSRF).
- **Provenance dan immutabilitas:** `raw_transactions` append-only; hash payload terkanonisasi, `decoder_version`, timestamp, dan audit log perubahan watchlist/rule. Perubahan parser memicu reprocess ke tabel hasil baru, bukan menulis ulang bukti tanpa jejak.
- **Akses:** autentikasi pada endpoint mutasi; otorisasi ownership di API **dan** RLS; service-role DB hanya di worker backend; cookie aman/HttpOnly/SameSite atau token pendek; rotasi secret, TLS, CSP ketat, CORS allowlist, CSRF untuk cookie, dan rate limit per user/IP.
- **Dompet:** tidak pernah meminta/menyimpan seed phrase/private key. “Connect wallet” (jika ada) hanya untuk membuktikan kepemilikan alamat via pesan non-transaksional yang ber-domain/nonce/expiry; tidak perlu untuk melihat data publik.
- **Pencegahan manipulasi:** mint adalah identitas, bukan simbol; tampilkan authority/risk flag jika parser memverifikasi; dedupe signature; tolak transaksi gagal; gunakan `finalized` untuk klaim leaderboard; sampling audit manual signature→explorer; label setiap angka estimasi/stale/unknown.

**[Fakta]** OWASP merekomendasikan inventaris host/integrasi API dan dokumentasi autentikasi, error, redirect, rate limit, CORS, endpoint, request, serta respons. [OWASP API9:2023](https://api-security.owasp.org/editions/2023/en/0xa9-improper-inventory-management/). Terapkan daftar tersebut sebagai *API inventory* di repositori dan uji kontrak, bukan hanya dokumentasi wiki.

## 10. Rencana audit, simulasi, dan validasi tombol

### Definisi selesai yang dapat diuji

**[Rancangan]** Bangun “simulation mode” dengan fixture yang direkam dan disanitasi dari respons RPC/DEX, tanpa jaringan. Ia harus menggunakan parser dan jalur UI yang sama dengan produksi, tetapi bertanda `SIMULATED` permanen. Tidak boleh menggantikan data live atau mengisi leaderboard nyata.

| Area | Uji otomatis | Pemeriksaan audit/manual |
|---|---|---|
| Decoder | Fixture BUY, SELL, transfer, account baru (pre=0), transaksi gagal, multi-hop, Token-2022, tx `null`; assertion side/delta/fee/reason | Cocokkan sampel acak hasil dengan signature di explorer/RPC dan review program allowlist. |
| PnL | Unit test FIFO: partial sell, fee, unknown basis, rounding, harga null; property test: remaining qty tidak negatif | Bandingkan rekalkulasi dari `wallet_events` dengan snapshot/materialized view. |
| Ingestion | Socket disconnect/reconnect, pesan duplikat/out-of-order, gap/backfill, `429`, `403`, `5xx`, DEX timeout | Chaos test interval pendek; pastikan badge stale dan alert suppression muncul. |
| API/DB | contract/schema test, authz antar pengguna, RLS negative test, SQL injection/SSRF payload, idempotent upsert | Review migrasi/index/backup/retensi dan hak DB minimum. |
| UI/tombol | Playwright/Cypress: add/edit/delete/pin/exclude wallet, change N 10/50/100, filter, sort, copy mint/signature, detail, mute/unmute alert, reconnect banner | Keyboard-only, screen reader, mobile 320px, reduced-motion, error/loading/empty states. |
| Anti-fake | Uji UI tidak menampilkan angka `0` untuk null, source/slot/signature wajib, tamper fixture harus gagal hash/schema | Reviewer independen mengikuti 10 signature dari UI sampai payload raw. |

Setiap tombol mempunyai kontrak: aksi, validasi, request, state sukses/gagal, log audit, dan tes E2E. Tombol yang belum terhubung diberi `disabled` + alasan—tidak boleh tampil aktif lalu membuat toast sukses palsu. Simpan hasil test (versi fixture, commit, waktu, pass/fail) di CI; test browser tidak perlu akses PublicNode.

### Fase peluncuran

1. **MVP read-only:** 10 manual wallet, parser allowlist sempit, confirmation badge, raw evidence, no push alert.
2. **Pilot:** auto top-10, FIFO PnL, reconciliation/observability, alert yang hanya diin-app dan cukup ketat.
3. **Scale berhati-hati:** 50 lalu 100 hanya bila p95 lag, gap rate, `429`, dan kelengkapan backfill memenuhi SLO yang didefinisikan. Ini keputusan metrik, bukan target kosmetik.
4. **Production:** evaluasi private/dedicated indexer/RPC bila cakupan penuh atau SLA diperlukan; dokumen Solana sendiri menempatkan endpoint publik terutama untuk pengembangan. [Panduan provider](https://solana.com/docs/rpc/providers).

## 11. Keterbatasan yang harus terlihat di produk

- Free/shared RPC dapat putus, di-rate-limit, diblokir, tertinggal, atau tidak menyimpan riwayat yang dibutuhkan. Tidak ada klaim “semua transaksi” tanpa metrik coverage/backfill.
- WSS memberi notifikasi, bukan bukti final; fork/reorg dan transaksi `null` harus diatasi. Feed cepat dan hasil final sengaja dapat berbeda sesaat.
- DEX Screener tidak menggantikan data eksekusi on-chain dan harga/likuiditasnya dapat kosong/terlambat; cache membuatnya makin tua.
- Kepemilikan wallet publik bukan identitas manusia. Wallet CEX, vault, bot, atau cluster alamat dapat mengubah arti “holder” dan “whale”.
- PnL hanya pada aktivitas yang berhasil diindeks dan diklasifikasikan; tidak mencakup off-chain transfer, pajak, token yang dikirim dari luar jendela, atau basis biaya tak diketahui.
- Memecoin mudah dimanipulasi. Akumulasi/volume bukan prediksi return dan bukan rekomendasi membeli/menjual.

## 12. Pertanyaan terbuka untuk pemilik produk

1. Apa definisi universe token (semua pair Solana, daftar program DEX tertentu, atau filter likuiditas/umur) dan ambang “whale” dalam USD/percentile?
2. Apakah PnL harus FIFO saja, metode pajak lokal tertentu, atau multi-metode? Apakah USDC dapat diperlakukan USD untuk tampilan?
3. Berapa SLO yang diterima untuk lag, gap, dan cakupan pada N=10/50/100, serta berapa retensi raw transaksi yang diizinkan secara biaya?
4. DEX/program mana yang masuk allowlist parser pada rilis pertama? Tanpa daftar ini, klasifikasi universal akan terlalu berisiko.
5. Apakah data watchlist/alert bersifat privat per akun, dan kanal notifikasi mana yang disetujui (in-app, email, push)?

## Referensi primer

1. [PublicNode — Solana RPC Gateway](https://solana.publicnode.com/) — endpoint, kategori WS RPC, archive/gRPC disclosure.
2. [Solana — RPC Overview dan commitment](https://solana.com/docs/rpc) — kemampuan RPC, definisi processed/confirmed/finalized, peringatan endpoint publik.
3. [Solana — Choosing an RPC Provider](https://solana.com/docs/rpc/providers) — kriteria limit, retensi, freshness, dan rekomendasi akses private untuk produksi.
4. [Solana — HTTP RPC methods](https://solana.com/docs/rpc/http), [getTransaction](https://solana.com/docs/rpc/http/gettransaction), dan [logsSubscribe](https://solana.com/docs/rpc/websocket/logssubscribe) — kontrak pengambilan dan subscription.
5. [Solana — Token accounts](https://solana.com/docs/tokens), [transfer token](https://solana.com/docs/tokens/basics/transfer-tokens), dan [integrasi transaksi](https://solana.com/docs/defi/exchange) — model mint/account dan edge case balance baru.
6. [DEX Screener API Reference](https://docs.dexscreener.com/api/reference) — endpoint, field pair, dan rate limit yang dipublikasikan.
7. [PostgreSQL — Row Security Policies](https://www.postgresql.org/docs/17/ddl-rowsecurity.html) — perilaku RLS/default deny.
8. [OWASP API9:2023](https://api-security.owasp.org/editions/2023/en/0xa9-improper-inventory-management/) — inventaris dan dokumentasi API/integrasi.

**Status bukti.** Referensi diakses pada 16 Oktober 2026. Rekomendasi, ambang, schema, interval, dan stack adalah rancangan yang harus diuji terhadap beban nyata; tidak ada hasil benchmark PublicNode, audit keamanan independen, atau identifikasi smart-money yang diklaim oleh laporan ini.
