# Statyczne portfele

> Trwałe adresy depozytowe powiązane z konkretnym zamówieniem lub użytkownikiem, idealne do płatności cyklicznych i długoterminowych.

Statyczne portfele to trwałe adresy do otrzymywania płatności kryptowalutowych. Są one powiązane z konkretnym `order_id` i są unikalne dla kombinacji `project_id + order_id + currency + network`.

Statycznych portfeli używaj do:

- Cyklicznych depozytów od tego samego użytkownika
- Długoterminowych adresów płatności wyświetlanych w profilu użytkownika
- Procesów depozytowych o dużym wolumenie, w których zależy Ci na stabilnym adresie dla każdego użytkownika

## Utwórz statyczny portfel

`POST /v1/static-wallet`

### Parametry żądania

| Pole | Typ | Wymagane | Opis |
|------|-----|----------|------|
| `currency` | string | tak | Kryptowaluta (USDT, BTC, ETH itp.) |
| `network` | string | tak | Kod sieci |
| `order_id` | string | tak | Twój identyfikator zamówienia/użytkownika (do 255 znaków) |
| `label` | string | nie | Etykieta portfela (do 255 znaków) |
| `url_callback` | string | tak | URL powiadomień webhook |
| `invite_code` | string | nie | Kod osoby polecającej |

### Przykład żądania

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

### Przykład odpowiedzi

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

## Informacje o portfelu

Pobierz informacje o statycznym portfelu po `uuid` lub `address`.

`POST /v1/static-wallet/info`

### Parametry żądania

| Pole | Typ | Wymagane | Opis |
|------|-----|----------|------|
| `uuid` | string | tak* | UUID statycznego portfela |
| `address` | string | tak* | Adres portfela blockchain |

> **INFO:** Wymagany jest co najmniej jeden z parametrów `uuid` lub `address`.

### Przykład odpowiedzi

```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` — suma wszystkich depozytów otrzymanych przez ten portfel, w walucie `currency`.
- `transactions_count` — liczba dotychczas otrzymanych depozytów.
- `qr` — kod QR (data URI) zakodowany w base64, prezentujący adres depozytowy (zawsze obecny w przypadku statycznych portfeli, ponieważ adres jest przypisywany w momencie utworzenia).

## Lista portfeli

`POST /v1/static-wallet/list`

### Parametry żądania

| Pole | Typ | Wymagane | Opis |
|------|-----|----------|------|
| `status` | string | nie | Filtrowanie według statusu (`active`, `inactive`) |
| `currency` | string | nie | Filtrowanie według waluty |
| `network` | string | nie | Filtrowanie według sieci |
| `order_id` | string | nie | Filtrowanie według order_id |
| `page` | int | nie | Numer strony (domyślnie: 1) |
| `per_page` | int | nie | Liczba elementów na stronę (domyślnie: 20, maks.: 100) |

### Przykład odpowiedzi

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

## Włącz / wyłącz portfel

Przełącz, czy statyczny portfel akceptuje nowe płatności.

`POST /v1/static-wallet/disable`

`POST /v1/static-wallet/enable`

### Żądanie

Oba endpointy przyjmują pojedynczy parametr:

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

### Przykład odpowiedzi

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

W przypadku `enable`, `status` ma wartość `"active"`, a `message` brzmi `"Static wallet enabled successfully"`.

## Transakcje portfela

Pobierz listę wszystkich depozytów otrzymanych przez statyczny portfel.

`POST /v1/static-wallet/transactions`

### Parametry żądania

| Pole | Typ | Wymagane | Opis |
|------|-----|----------|------|
| `uuid` | string | tak | UUID statycznego portfela |
| `date_from` | date | nie | Data początkowa (YYYY-MM-DD) |
| `date_to` | date | nie | Data końcowa (YYYY-MM-DD) |
| `page` | int | nie | Numer strony (domyślnie: 1) |
| `per_page` | int | nie | Liczba elementów na stronę (domyślnie: 15, maks.: 5000) |

### Przykład odpowiedzi

```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` — opłata platformy potrącona z tego depozytu, w walucie `currency`.
- `net_amount` — kwota zaksięgowana na saldzie sprzedawcy po potrąceniu opłaty.

## Webhooki statycznych portfeli

Gdy na statyczny portfel wpłynie płatność, system wysyła webhook pod adres `url_callback`.

> **WARNING:** Format webhooka dla statycznych portfeli różni się od standardowych webhooków płatności. W szczególności webhooki statycznych portfeli zawierają pole `merchant_amount`, którego należy używać do księgowania.

### Payload webhooka

```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:** Webhooki statycznych portfeli **nie** zawierają pól `url` ani `expires_at` (ponieważ adres jest trwały, a nie sesyjny). **Zawierają** natomiast `exchange_rate` oraz `created_at`.

### Opis pól

| Pole | Typ | Opis |
|------|-----|------|
| `uuid` | string | UUID transakcji (faktury) tego depozytu |
| `order_id` | string | Twój `order_id` statycznego portfela |
| `amount` | decimal (8 dp) | Otrzymana kwota w kryptowalucie |
| `currency` | string | Otrzymana kryptowaluta (zgodna z `currency` portfela) |
| `amount_usd` | decimal (8 dp) | Wartość w USD w chwili otrzymania |
| `exchange_rate` | decimal | Użyty kurs krypto / USD |
| `payer_currency` | string | Tożsame z `currency` dla statycznych portfeli |
| `payer_amount` | decimal (8 dp) | Tożsame z `amount` dla statycznych portfeli |
| `network` | string | Sieć blockchain |
| `address` | string | Adres statycznego portfela |
| `payment_status` | string | Bie??cy status depozytu; zwykle `paid`, lecz kontrola AML mo?e da? `aml_lock`, kt?rego nie wolno automatycznie uznawa? |
| `txid` | string | Hash transakcji blockchain |
| `tx_explorer_url` | string \| null | Adres URL transakcji w eksploratorze blockchain. Wartość `null`, gdy brakuje `txid` lub przelew jest wewnętrznym P2P. |
| `payment_amount` | decimal (8 dp) | Tożsame z `amount` |
| `merchant_amount` | decimal (18 dp) | **Kwota po potrąceniu opłaty** — używaj jej do księgowania |
| `created_at` | string (ISO 8601) | Moment otrzymania depozytu |
| `sign` | string (hex) | Podpis HMAC-SHA256 payloadu |

## Dobre praktyki

- **Unikalny `order_id`** — używaj unikalnego `order_id` dla każdego użytkownika lub zamówienia
- **Idempotentność** — sprawdzaj `txid` przed przetworzeniem, aby uniknąć podwójnych zaksięgowań
- **Weryfikuj podpisy** — ZAWSZE weryfikuj podpis `sign` przed zaksięgowaniem środków
- **Używaj `merchant_amount`** — księguj użytkownikom kwotę z `merchant_amount`, a nie `payment_amount`

## Cykl życia i niezmienność

Statyczny portfel jest tożsamością depozytową wielokrotnego użytku, a nie fakturą. Nie ma oczekiwanej kwoty ani daty wygaśnięcia. Jeden adres może wygenerować dowolną liczbę transakcji depozytowych w ciągu swojego istnienia.

Tworzenie jest niezmienne dla tego samego projektu handlowca, `order_id`, `currency` i `network`: zwracany jest istniejący portfel. Zachowaj tę krotkę stabilną i przechowuj zwrócony portfel `uuid`; nie używaj nowego `order_id` za każdym razem, gdy ten sam klient otwiera ekran depozytu.

Niezmienność depozytu różni się od niezmienności portfela:

- `order_id` identyfikuje mapowanie wielokrotnego użytku portfela/klienta;
- portfel `uuid` identyfikuje permanentny zapis portfela;
- webhook `uuid` identyfikuje jedną wykrytą transakcję depozytu;
- `txid` identyfikuje transfer w blockchainie i jest głównym kluczem deduplikacji do zaliczenia na koncie.

Użyj ograniczenia unikalności w bazie danych dla przetworzonej tożsamości chain/network/txid i zgłoś ją w tej samej transakcji, która zalicza saldo wewnętrzne klienta.

## Włączanie i wyłączanie semantyki

Wyłączenie portfela uniemożliwia aplikacji jego przetwarzanie jako aktywnego celu depozytu; nie usuwa to adresu ani jego historii i nie może zatrzymać transferu blockchain już wysłanego przez użytkownika.

> **DANGER:** Nigdy nie informuj użytkowników, że środki wysłane na nieaktywny adres są automatycznie zwracane. Transakcje w blockchainie są nieodwracalne. Wyłączaj tylko po usunięciu adresu z interfejsu użytkownika i utrzymuj operacyjną procedurę odzyskiwania dla późnych wpłat.

Ponowne włączenie zachowuje tę samą tożsamość portfela i adres. Nie twórz zamiennika tylko po to, aby zmienić etykietę; etykiety nie są identyfikatorami rozliczeniowymi.

## Specjalne przypadki statycznego portfela

| Sytuacja | Prawidłowe postępowanie |
|-----------|------------------|
| Żądanie utworzenia duplikatu | Zaakceptuj zwrócony istniejący portfel i zweryfikuj jego uporządkowaną krotkę zamiast oczekiwać nowego adresu. |
| Wiele wpłat na jeden adres | Utwórz osobny lokalny wiersz depozytu dla każdej transakcji `uuid`/`txid`; nigdy nie oznaczaj samego portfela jako „opłaconego.” |
| Zduplikowany webhook | Zwróć HTTP 200 po znalezieniu już zatwierdzonego txid; nigdy nie księguj ponownie. |
| Opóźnienie potwierdzenia lub ponowne obserwowanie łańcucha | Utrzymuj przetwarzanie jako idempotentne i uzgadniaj z `/v1/static-wallet/transactions`. |
| Depozyt poniżej minimalnej kwoty do automatycznej konwersji | Oczekuj zaksięgowania w walucie źródłowej bez zakończonego bloku `convert`. |
| Automatyczna konwersja zakończona sukcesem | Przechowuj wartości płatności źródłowych i wynik docelowy `convert` osobno. |
| Zły token lub zła sieć | Nie twórz kredytu. Zarejestruj dowody i eskaluj do wsparcia/odzyskiwania, ponieważ możliwość odzyskania jest specyficzna dla łańcucha. |
| Łańcuch oparty na notatkach/tagach | Wyświetl i zweryfikuj każde pole docelowe zwracane przez platformę; sam adres może być niewystarczający, gdy wymagana jest notatka. |
| Blokada AML | Nie przyznawaj kredytu użytkownikowi końcowemu, dopóki status autorytatywny nie zostanie zwolniony w procesie zgodności. |
| Portfel wyłączony po wyświetleniu adresu | Usuń go natychmiast z interfejsu, ale nadal monitoruj alerty operacyjne dotyczące późnych transferów. |

## Model uzgadniania

Uruchom okresowe zadanie, które przegląda `/v1/static-wallet/transactions`, wstawia lub aktualizuje depozyty według txid i porównuje ich `merchant_amount`, status oraz opcjonalny wynik konwersji z twoim wewnętrznym rejestrem. Dostarczanie za pomocą webhooka powinno przyspieszyć uzgadnianie, ale uzgadnianie musi być kompletne.