# Dompet Statis

> Alamat deposit permanen yang terikat pada pesanan atau pengguna tertentu, sempurna untuk pembayaran berulang dan jangka panjang.

Dompet statis adalah alamat permanen untuk menerima pembayaran kripto. Mereka ditautkan ke `order_id` tertentu dan unik berdasarkan kombinasi `project_id + order_id + currency + network`.

Gunakan dompet statis untuk:

- Deposit berulang dari pengguna yang sama
- Alamat pembayaran jangka panjang yang ditampilkan di profil pengguna
- Alur deposit volume tinggi di mana Anda menginginkan alamat stabil per pengguna

## Buat dompet statis

`POST /v1/static-wallet`

### Parameter permintaan

| Field | Tipe | Wajib | Deskripsi |
|-------|------|----------|-------------|
| `currency` | string | ya | Kripto (USDT, BTC, ETH, dll.) |
| `network` | string | ya | Kode jaringan |
| `order_id` | string | ya | ID pesanan/pengguna Anda (hingga 255 karakter) |
| `label` | string | tidak | Label dompet (hingga 255 karakter) |
| `url_callback` | string | ya | URL untuk notifikasi webhook |
| `invite_code` | string | tidak | Kode referral |

### Contoh permintaan

```json
{
  "currency": "USDT",
  "network": "TRX-TRC20",
  "order_id": "USER-123",
  "label": "User deposit #123",
  "url_callback": "https://your-site.com/webhook/static"
}
```

### Contoh respon

```json
{
  "state": 0,
  "result": {
    "uuid": "019b2265-34d8-7001-a230-8f97de90d481",
    "address": "TXYZabc123...",
    "currency": "USDT",
    "network": "TRX-TRC20",
    "label": "User deposit #123",
    "order_id": "USER-123",
    "status": "active",
    "url": "https://go.2328.io/static/019b2265-34d8-7001-a230-8f97de90d481",
    "created_at": "2026-01-20T12:00:00Z",
    "qr": "data:image/png;base64,iVBORw0..."
  }
}
```

## Info dompet

Dapatkan informasi dompet statis berdasarkan `uuid` atau `address`.

`POST /v1/static-wallet/info`

### Parameter permintaan

| Field | Tipe | Wajib | Deskripsi |
|-------|------|----------|-------------|
| `uuid` | string | ya* | UUID dompet statis |
| `address` | string | ya* | Alamat dompet blockchain |

> **INFO:** Setidaknya salah satu dari `uuid` atau `address` wajib diisi.

### Contoh respon

```json
{
  "state": 0,
  "result": {
    "uuid": "019b2265-34d8-7001-a230-8f97de90d481",
    "address": "TXYZabc123...",
    "currency": "USDT",
    "network": "TRX-TRC20",
    "status": "active",
    "total_received": "1250.50",
    "transactions_count": 3,
    "created_at": "2026-01-20T12:00:00Z",
    "qr": "data:image/png;base64,iVBORw0..."
  }
}
```

- `total_received` — jumlah semua deposit yang diterima oleh dompet ini, dalam `currency`.
- `transactions_count` — jumlah deposit yang diterima sejauh ini.
- `qr` — data URI QR berenkode Base64 dari alamat deposit (selalu hadir untuk dompet statis, alamat ditetapkan saat pembuatan).

## Daftar dompet

`POST /v1/static-wallet/list`

### Parameter permintaan

| Field | Tipe | Wajib | Deskripsi |
|-------|------|----------|-------------|
| `status` | string | tidak | Filter berdasarkan status (`active`, `inactive`) |
| `currency` | string | tidak | Filter berdasarkan mata uang |
| `network` | string | tidak | Filter berdasarkan jaringan |
| `order_id` | string | tidak | Filter berdasarkan order_id |
| `page` | int | tidak | Nomor halaman (default: 1) |
| `per_page` | int | tidak | Item per halaman (default: 20, maks: 100) |

### Contoh respon

```json
{
  "state": 0,
  "result": {
    "items": [
      {
        "uuid": "019b2265-...",
        "address": "TXYZabc123...",
        "currency": "USDT",
        "network": "TRX-TRC20",
        "status": "active",
        "total_received": "1250.50",
        "transactions_count": 3
      }
    ],
    "paginate": {
      "count": 1,
      "current_page": 1,
      "per_page": 20,
      "total": 1,
      "total_pages": 1,
      "has_more": false
    }
  }
}
```

## Aktifkan / nonaktifkan dompet

Atur apakah dompet statis menerima pembayaran baru.

`POST /v1/static-wallet/disable`

`POST /v1/static-wallet/enable`

### Permintaan

Kedua endpoint mengambil satu parameter:

```json
{
  "uuid": "019b2265-34d8-7001-a230-8f97de90d481"
}
```

### Contoh respon

```json
{
  "state": 0,
  "result": {
    "uuid": "019b2265-34d8-7001-a230-8f97de90d481",
    "status": "inactive",
    "message": "Static wallet disabled successfully"
  }
}
```

Untuk `enable`, `status` adalah `"active"` dan `message` berbunyi `"Static wallet enabled successfully"`.

## Transaksi dompet

Dapatkan daftar semua deposit yang diterima oleh sebuah dompet statis.

`POST /v1/static-wallet/transactions`

### Parameter permintaan

| Field | Tipe | Wajib | Deskripsi |
|-------|------|----------|-------------|
| `uuid` | string | ya | UUID dompet statis |
| `date_from` | date | tidak | Tanggal mulai (YYYY-MM-DD) |
| `date_to` | date | tidak | Tanggal akhir (YYYY-MM-DD) |
| `page` | int | tidak | Nomor halaman (default: 1) |
| `per_page` | int | tidak | Item per halaman (default: 15, maks: 5000) |

### Contoh respon

```json
{
  "state": 0,
  "result": {
    "items": [
      {
        "uuid": "abc123-def456-...",
        "order_id": "USER-123",
        "amount": "100.00",
        "currency": "USDT",
        "payment_status": "paid",
        "txid": "0xabc123def456...",
        "fee_amount": "3.00",
        "net_amount": "97.00",
        "created_at": "2026-01-20T15:30:00Z"
      }
    ],
    "paginate": {
      "count": 1,
      "hasPages": true,
      "perPage": 15,
      "page": 1
    }
  }
}
```

- `fee_amount` — biaya platform yang dikurangi dari deposit ini, dalam `currency`.
- `net_amount` — jumlah yang dikreditkan ke saldo merchant setelah biaya.

## Webhook dompet statis

Saat pembayaran diterima di sebuah dompet statis, sistem mengirim webhook ke `url_callback`.

> **WARNING:** Format webhook untuk dompet statis berbeda dari webhook pembayaran biasa. Khususnya, webhook dompet statis menyertakan field `merchant_amount` yang harus Anda gunakan untuk pengkreditan.

### Payload webhook

```json
{
  "uuid": "a28b293f-5c76-4053-8062-ae9ca4ab784b",
  "order_id": "USER-7666308594",
  "amount": "10.00000000",
  "currency": "USDT",
  "amount_usd": "10.00000000",
  "exchange_rate": "1.00000000",
  "payer_currency": "USDT",
  "payer_amount": "10.00000000",
  "network": "TRX-TRC20",
  "address": "TMU9Tgpchvgbywkbj5SdC8KJS73t5m3M7G",
  "payment_status": "paid",
  "txid": "8369ede26a0da05b1bae154b4bb4072eb2453db30ba86b21831902670929454f",
  "tx_explorer_url": "https://tronscan.org/#/transaction/8369ede26a0da05b1bae154b4bb4072eb2453db30ba86b21831902670929454f",
  "payment_amount": "10.00000000",
  "merchant_amount": "9.920000000000000000",
  "created_at": "2026-05-09T16:13:04+03:00",
  "sign": "dd958d1405febce670a9a196e9141784b9f2a5f39cd6d1832d6f3f68d0de1e10"
}
```

> **INFO:** Webhook dompet statis **tidak** menyertakan `url` atau `expires_at` (karena alamatnya permanen, bukan sebuah sesi). Mereka **menyertakan** `exchange_rate` dan `created_at`.

### Referensi field

| Field | Tipe | Deskripsi |
|-------|------|-------------|
| `uuid` | string | UUID transaksi (faktur) untuk deposit ini |
| `order_id` | string | `order_id` dompet statis Anda |
| `amount` | decimal (8 dp) | Jumlah kripto yang diterima |
| `currency` | string | Kripto yang diterima (cocok dengan `currency` dompet) |
| `amount_usd` | decimal (8 dp) | Nilai USD pada saat penerimaan |
| `exchange_rate` | decimal | Nilai tukar Kripto / USD yang digunakan |
| `payer_currency` | string | Sama dengan `currency` untuk dompet statis |
| `payer_amount` | decimal (8 dp) | Sama dengan `amount` untuk dompet statis |
| `network` | string | Jaringan blockchain |
| `address` | string | Alamat dompet statis |
| `payment_status` | string | Status deposit saat ini; biasanya `paid`, tetapi AML dapat menghasilkan `aml_lock` yang tidak boleh dikreditkan otomatis |
| `txid` | string | Hash transaksi blockchain |
| `tx_explorer_url` | string \| null | URL transaksi di penjelajah blockchain. Bernilai `null` jika `txid` tidak ada atau transfer merupakan P2P internal. |
| `payment_amount` | decimal (8 dp) | Sama dengan `amount` |
| `merchant_amount` | decimal (18 dp) | **Jumlah setelah pemotongan biaya** — gunakan ini untuk pengkreditan |
| `created_at` | string (ISO 8601) | Saat deposit diterima |
| `sign` | string (hex) | Tanda tangan HMAC-SHA256 dari payload |

## Praktik terbaik

- **`order_id` unik** — Gunakan `order_id` unik untuk setiap pengguna atau pesanan
- **Idempotensi** — Periksa `txid` sebelum memproses untuk menghindari kredit duplikat
- **Verifikasi tanda tangan** — SELALU verifikasi tanda tangan `sign` sebelum mengkreditkan dana
- **Gunakan `merchant_amount`** — Kreditkan pengguna berdasarkan `merchant_amount`, bukan `payment_amount`

## Siklus hidup dan idempoten

Dompet statis adalah identitas deposit yang dapat digunakan kembali, bukan faktur. Ia tidak memiliki jumlah yang diharapkan dan tidak memiliki masa kedaluwarsa. Satu alamat dapat menghasilkan jumlah transaksi deposit berapa pun selama masa hidupnya.

Pembuatan bersifat idempoten untuk proyek pedagang yang sama, `order_id`, `currency`, dan `network`: dompet yang ada dikembalikan. Pertahankan tuple itu stabil dan simpan dompet yang dikembalikan `uuid`; jangan menggunakan `order_id` baru setiap kali pelanggan yang sama membuka layar deposit.

Idempoten deposit berbeda dari idempoten dompet:

- `order_id` mengidentifikasi pemetaan dompet/pelanggan yang dapat digunakan kembali;
- dompet `uuid` mengidentifikasi catatan dompet permanen;
- webhook `uuid` mengidentifikasi satu transaksi setoran yang terdeteksi;
- `txid` mengidentifikasi transfer on-chain dan merupakan kunci deduplikasi utama untuk mengkredit.

Gunakan batasan keunikan database untuk identitas chain/network/txid yang diproses dan klaim dalam transaksi yang sama yang mengkredit saldo internal pelanggan.

## Aktifkan dan nonaktifkan semantik

Menonaktifkan dompet mencegah aplikasi memprosesnya sebagai target setoran aktif; ini tidak menghapus alamat atau sejarahnya dan tidak dapat menghentikan transfer blockchain yang sudah dikirim oleh pengguna.

> **DANGER:** Jangan pernah memberi tahu pengguna bahwa dana yang dikirim ke alamat yang tidak aktif akan dikembalikan secara otomatis. Transfer blockchain tidak dapat dibatalkan. Nonaktifkan hanya setelah menghapus alamat dari antarmuka pengguna Anda, dan tetap pertahankan prosedur pemulihan operasional untuk deposito yang terlambat.

Mengaktifkan kembali mempertahankan identitas dompet dan alamat yang sama. Jangan membuat pengganti hanya untuk mengubah label; label bukanlah pengenal penyelesaian.

## Kasus tepi dompet statis

| Situasi | Penanganan yang benar |
|-----------|------------------|
| Permintaan pembuatan duplikat | Terima dompet yang ada yang dikembalikan dan verifikasi tuple yang tersimpan alih-alih mengharapkan alamat baru. |
| Beberapa deposito ke satu alamat | Buat baris deposit lokal terpisah untuk setiap transaksi `uuid`/`txid`; jangan pernah menandai dompet itu sendiri sebagai “dibayar.” |
| Webhook duplikat | Kembalikan HTTP 200 setelah menemukan txid yang sudah dikomit; jangan pernah mengkredit lagi. |
| Keterlambatan konfirmasi atau pengamatan ulang rantai | Tetap buat proses idempoten dan rekonsiliasi dari `/v1/static-wallet/transactions`. |
| Deposit di bawah minimum konversi otomatis | Harapkan kredit mata uang sumber tanpa blok `convert` yang selesai. |
| Konversi otomatis berhasil | Simpan nilai pembayaran sumber dan hasil `convert` target secara terpisah. |
| Token salah atau jaringan salah | Jangan membuat kredit secara palsu. Catat bukti dan tingkatkan ke dukungan/pemulihan karena kemampuan pemulihan tergantung pada rantai tertentu. |
| Rantai berbasis memo/tag | Tampilkan dan validasi setiap bidang tujuan yang dikembalikan oleh platform; alamat saja mungkin tidak cukup ketika memo diperlukan. |
| Kunci AML | Jangan memberikan kredit kepada pengguna akhir sampai status yang berwenang dirilis melalui proses kepatuhan. |
| Dompet dinonaktifkan setelah tampilan alamat | Hapus dari antarmuka pengguna segera, tetapi terus pantau peringatan operasional untuk transfer yang terlambat. |

## Model rekonsiliasi

Jalankan pekerjaan berkala yang menelusuri `/v1/static-wallet/transactions`, melakukan upsert deposit berdasarkan txid, dan membandingkan `merchant_amount`, status, dan hasil konversi opsional mereka dengan buku besar internal Anda. Pengiriman webhook harus membuat rekonsiliasi cepat, tetapi rekonsiliasi harus membuatnya lengkap.