# Statische wallets

> Permanente stortingsadressen gekoppeld aan een specifieke order of gebruiker, perfect voor terugkerende en langlopende betalingen.

Statische wallets zijn permanente adressen voor het ontvangen van crypto-betalingen. Ze zijn gekoppeld aan een specifieke `order_id` en zijn uniek op de combinatie `project_id + order_id + currency + network`.

Gebruik statische wallets voor:

- Terugkerende stortingen van dezelfde gebruiker
- Langetermijn-betalingsadressen die op een gebruikersprofiel worden weergegeven
- Hoge volumes aan stortingen waarbij je een stabiel adres per gebruiker wilt

## Statische wallet aanmaken

`POST /v1/static-wallet`

### Verzoekparameters

| Veld | Type | Vereist | Beschrijving |
|------|------|---------|--------------|
| `currency` | string | ja | Cryptovaluta (USDT, BTC, ETH, enz.) |
| `network` | string | ja | Netwerkcode |
| `order_id` | string | ja | Je order-/gebruikers-ID (max. 255 tekens) |
| `label` | string | nee | Wallet-label (max. 255 tekens) |
| `url_callback` | string | ja | URL voor webhook-meldingen |
| `invite_code` | string | nee | Verwijzerscode |

### Voorbeeld van een verzoek

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

### Voorbeeld van een response

```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..."
  }
}
```

## Walletinformatie

Haal informatie over een statische wallet op met `uuid` of `address`.

`POST /v1/static-wallet/info`

### Verzoekparameters

| Veld | Type | Vereist | Beschrijving |
|------|------|---------|--------------|
| `uuid` | string | ja* | UUID van statische wallet |
| `address` | string | ja* | Blockchain-walletadres |

> **INFO:** Ten minste één van `uuid` of `address` is vereist.

### Voorbeeld van een response

```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` — som van alle stortingen die deze wallet heeft ontvangen, in `currency`.
- `transactions_count` — aantal tot nu toe ontvangen stortingen.
- `qr` — base64-gecodeerde QR data URI van het stortingsadres (altijd aanwezig voor statische wallets, het adres wordt bij het aanmaken toegewezen).

## Walletlijst

`POST /v1/static-wallet/list`

### Verzoekparameters

| Veld | Type | Vereist | Beschrijving |
|------|------|---------|--------------|
| `status` | string | nee | Filteren op status (`active`, `inactive`) |
| `currency` | string | nee | Filteren op valuta |
| `network` | string | nee | Filteren op netwerk |
| `order_id` | string | nee | Filteren op order_id |
| `page` | int | nee | Paginanummer (standaard: 1) |
| `per_page` | int | nee | Items per pagina (standaard: 20, max: 100) |

### Voorbeeld van een response

```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
    }
  }
}
```

## Wallet inschakelen / uitschakelen

Schakel in of uit of een statische wallet nieuwe betalingen accepteert.

`POST /v1/static-wallet/disable`

`POST /v1/static-wallet/enable`

### Verzoek

Beide endpoints nemen één enkele parameter:

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

### Voorbeeld van een response

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

Voor `enable` is `status` `"active"` en luidt `message` `"Static wallet enabled successfully"`.

## Wallet-transacties

Haal een lijst op van alle stortingen die een statische wallet heeft ontvangen.

`POST /v1/static-wallet/transactions`

### Verzoekparameters

| Veld | Type | Vereist | Beschrijving |
|------|------|---------|--------------|
| `uuid` | string | ja | UUID van statische wallet |
| `date_from` | date | nee | Begindatum (YYYY-MM-DD) |
| `date_to` | date | nee | Einddatum (YYYY-MM-DD) |
| `page` | int | nee | Paginanummer (standaard: 1) |
| `per_page` | int | nee | Items per pagina (standaard: 15, max: 5000) |

### Voorbeeld van een response

```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` — platformfee die van deze storting is afgetrokken, in `currency`.
- `net_amount` — bedrag dat na de fee aan het merchantsaldo is toegevoegd.

## Webhooks voor statische wallets

Wanneer er een betaling wordt ontvangen op een statische wallet, stuurt het systeem een webhook naar `url_callback`.

> **WARNING:** Het webhook-formaat voor statische wallets verschilt van het formaat van gewone betalingswebhooks. In het bijzonder bevatten webhooks van statische wallets een veld `merchant_amount` dat je moet gebruiken om bij te boeken.

### Webhook-payload

```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:** Webhooks van statische wallets bevatten **geen** `url` of `expires_at` (omdat het adres permanent is, geen sessie). Ze bevatten **wel** `exchange_rate` en `created_at`.

### Veldreferentie

| Veld | Type | Beschrijving |
|------|------|--------------|
| `uuid` | string | Transactie-UUID (factuur-UUID) voor deze storting |
| `order_id` | string | `order_id` van je statische wallet |
| `amount` | decimal (8 dp) | Ontvangen cryptobedrag |
| `currency` | string | Ontvangen crypto (komt overeen met de `currency` van de wallet) |
| `amount_usd` | decimal (8 dp) | USD-waarde op het moment van ontvangst |
| `exchange_rate` | decimal | Gebruikte crypto/USD-koers |
| `payer_currency` | string | Hetzelfde als `currency` voor statische wallets |
| `payer_amount` | decimal (8 dp) | Hetzelfde als `amount` voor statische wallets |
| `network` | string | Blockchain-netwerk |
| `address` | string | Adres van de statische wallet |
| `payment_status` | string | Huidige stortingsstatus; meestal `paid`, maar AML kan `aml_lock` opleveren, wat niet automatisch mag worden bijgeschreven |
| `txid` | string | Hash van de blockchain-transactie |
| `tx_explorer_url` | string \| null | URL van de transactie in de blockchainverkenner. `null` als `txid` ontbreekt of de overdracht intern P2P is. |
| `payment_amount` | decimal (8 dp) | Hetzelfde als `amount` |
| `merchant_amount` | decimal (18 dp) | **Bedrag na aftrek van fee** — gebruik dit om bij te boeken |
| `created_at` | string (ISO 8601) | Tijdstip waarop de storting werd ontvangen |
| `sign` | string (hex) | HMAC-SHA256-handtekening van de payload |

## Best practices

- **Unieke `order_id`** — Gebruik een unieke `order_id` voor elke gebruiker of order
- **Idempotentie** — Controleer `txid` voordat je verwerkt om dubbele bijboekingen te voorkomen
- **Verifieer handtekeningen** — Verifieer ALTIJD de `sign`-handtekening voordat je geld bijboekt
- **Gebruik `merchant_amount`** — Boek gebruikers bij op basis van `merchant_amount`, niet `payment_amount`

## Levenscyclus en idempotentie

Een statische portemonnee is een herbruikbare stortingsidentiteit, geen factuur. Het heeft geen verwacht bedrag en geen vervaldatum. Eén adres kan gedurende zijn levensduur een willekeurig aantal stortingstransacties genereren.

Aanmaak is idempotent voor hetzelfde handelaarproject, `order_id`, `currency`, en `network`: de bestaande portemonnee wordt geretourneerd. Houd die tuple stabiel en bewaar de geretourneerde portemonnee `uuid`; gebruik niet elke keer een nieuwe `order_id` wanneer dezelfde klant het stortingsscherm opent.

Idempotentie van stortingen verschilt van idempotentie van portemonnees:

- `order_id` identificeert de herbruikbare portemonnee/klantkoppeling;
- portemonnee `uuid` identificeert het permanente portemonneerecord;
- webhook `uuid` identificeert één gedetecteerde stortingstransactie;
- `txid` identificeert de on-chain overboeking en is de primaire deduplicatiesleutel voor het crediteren.

Gebruik een uniekheidsbeperking in de database voor de verwerkte chain/network/txid-identiteit en claim deze in dezelfde transactie die het interne saldo van de klant crediteert.

## In- en uitschakelsemantiek inschakelen

Het uitschakelen van een wallet voorkomt dat de applicatie deze verwerkt als een actief stortingsdoel; het wist het adres of de geschiedenis ervan niet en kan een blockchain-overboeking die al door een gebruiker is verzonden, niet stoppen.

> **DANGER:** Vertel gebruikers nooit dat middelen die naar een inactief adres zijn gestuurd automatisch worden teruggestuurd. Blockchain-transacties zijn onomkeerbaar. Schakel alleen uit nadat het adres uit je gebruikersinterface is verwijderd en houd een operationele herstelprocedure voor late stortingen bij.

Het opnieuw inschakelen behoudt dezelfde wallet-identiteit en hetzelfde adres. Maak geen vervanging alleen om het label te wijzigen; labels zijn geen afwikkelingsidentificatoren.

## Statische wallet-randgevallen

| Situatie | Correcte afhandeling |
|-----------|------------------|
| Duplicaat aanmaakverzoek | Accepteer de teruggestuurde bestaande wallet en controleer de bewaarde tuple in plaats van een nieuw adres te verwachten. |
| Meerdere stortingen naar één adres | Maak een aparte lokale stortingsregel voor iedere transactie `uuid`/`txid`; markeer de portemonnee zelf nooit als "betaald." |
| Duplicaat webhook | Stuur HTTP 200 terug nadat het reeds vastgelegde txid is gevonden; crediteer nooit opnieuw. |
| Bevestigingsvertraging of herbevestiging van de keten | Houd de verwerking idempotent en reconcilieer vanaf `/v1/static-wallet/transactions`. |
| Storting onder een automatisch converteer minimum | Verwacht bronvaluta-crediteer zonder een voltooid `convert`-blok. |
| Automatisch converteren slaagt | Sla bronbetalingswaarden en het doel `convert`-resultaat afzonderlijk op. |
| Verkeerde token of verkeerde netwerk | Maak geen tegoed aan. Leg bewijs vast en escaleer naar ondersteuning/herstel omdat herstelbaarheid ketenspecifiek is. |
| Memo/tag-gebaseerde keten | Toon en valideer elk bestemmingsveld dat door het platform wordt teruggegeven; een adres alleen kan onvoldoende zijn wanneer een memo vereist is. |
| AML-vergrendeling | Crediteer de eindgebruiker niet totdat de gezaghebbende status is vrijgegeven via het complianceproces. |
| Portemonnee uitgeschakeld na adresweergave | Verwijder het onmiddellijk uit de UI, maar blijf operationele waarschuwingen voor late overboekingen volgen. |

## Reconciliatiemodel

Voer een periodieke taak uit die door `/v1/static-wallet/transactions` bladert, stortingen bijwerkt op txid, en hun `merchant_amount`, status en optioneel conversieresultaat vergelijkt met uw interne grootboek. Webhook-levering moet het reconciliëren snel maken, maar reconciliatie moet het volledig maken.