Phoenix Wallet

Reservations

Holds and authorizations for two-phase transactions

Reservations are temporary holds on wallet funds that enable two-phase transaction patterns. They're essential for scenarios where you need to guarantee funds before completing an operation, such as payment authorizations, order processing, or gaming wagers.

Reservation Structure

FieldTypeDescription
idstringUnique identifier (UUID)
wallet_idstringWallet being reserved from
asset_codestringAsset type being reserved
amountstringReserved amount
statusenumCurrent state (see below)
expires_attimestampAuto-release time
metadataobjectCustom key-value pairs
created_attimestampCreation timestamp
updated_attimestampLast state change

Reservation States

Reservations follow a defined state machine:

                         ┌─────────────────────┐
                         │                     │
            create()     │      PENDING        │
         ───────────────▶│                     │
                         │  Funds are held     │
                         └─────────────────────┘

              ┌────────────────────┼────────────────────┐
              │                    │                    │
              ▼                    ▼                    ▼
    ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
    │                 │  │                 │  │                 │
    │   COMMITTED     │  │   RELEASED      │  │    EXPIRED      │
    │                 │  │                 │  │                 │
    │ Funds debited   │  │ Funds returned  │  │ Auto-released   │
    │ from wallet     │  │ to available    │  │ after timeout   │
    └─────────────────┘  └─────────────────┘  └─────────────────┘
         commit()           release()           (automatic)

State Descriptions

StateDescriptionFunds Location
PENDINGActive holdReserved (not available)
COMMITTEDPermanently deductedRemoved from wallet
RELEASEDHold cancelledReturned to available
EXPIREDAuto-released after timeoutReturned to available

All terminal states (COMMITTED, RELEASED, EXPIRED) are final. Once a reservation reaches a terminal state, it cannot be modified.

Use Cases

Payment Authorization

1. User initiates checkout for $50
2. Create reservation for $50 → PENDING
3. User confirms payment
4. Commit reservation → COMMITTED (funds deducted)

Alternative: User cancels
4. Release reservation → RELEASED (funds returned)

Gaming Wagers

1. Player places $10 bet
2. Create reservation for $10 → PENDING
3. Game resolves
   - Player wins: Release reservation, credit winnings
   - Player loses: Commit reservation (house keeps funds)

Order Fulfillment

1. Customer orders items totaling $75
2. Create reservation for $75 → PENDING
3. Items ship
4. Commit reservation → COMMITTED

Alternative: Item out of stock
4. Partial release, adjust reservation amount

Creating a Reservation

curl -X POST https://api.phoenixwallet.io/v1/reservations \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "wallet_id": "wal_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
    "asset_code": "USD",
    "amount": "5000",
    "intent": "purchase",
    "expires_at": "2024-01-16T10:30:00Z",
    "metadata": {
      "order_id": "ord_12345",
      "description": "Shopping cart checkout"
    },
    "idempotency_key": "reserve_order_12345"
  }'

Response:

{
  "id": "rsv_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
  "wallet_id": "wal_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
  "asset_code": "USD",
  "amount": "5000",
  "status": "PENDING",
  "intent": "purchase",
  "expires_at": "2024-01-16T10:30:00Z",
  "metadata": {
    "order_id": "ord_12345",
    "description": "Shopping cart checkout"
  },
  "lots": [
    {
      "lot_id": "lot_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
      "amount": "5000"
    }
  ],
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z"
}

Committing a Reservation

When you're ready to finalize the transaction:

curl -X POST https://api.phoenixwallet.io/v1/reservations/rsv_01HV8X.../commit \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "5000",
    "metadata": {
      "payment_reference": "pay_98765"
    }
  }'

You can commit a partial amount. If the original reservation was for $50 but the final charge is $45, commit only $45 and the remaining $5 is automatically released.

Releasing a Reservation

To cancel a hold and return funds to available:

curl -X POST https://api.phoenixwallet.io/v1/reservations/rsv_01HV8X.../release \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Order cancelled by customer"
  }'

Reservation Expiry

Reservations automatically expire if not committed or released within the specified time:

{
  "expires_at": "2024-01-16T10:30:00Z"
}

When a reservation expires:

  1. Status changes to EXPIRED
  2. Reserved funds return to available balance
  3. A reservation.expired event is emitted

Always set appropriate expiration times. Short expirations (15-30 minutes) work well for checkout flows. Longer expirations (24-72 hours) suit order fulfillment patterns.

Lot Selection for Reservations

When creating a reservation, Phoenix Wallet selects lots based on:

  1. Policy compatibility - Lots must allow the specified intent
  2. Available balance - Lots must have sufficient unreserved funds
  3. Depletion order - FIFO, FEFO, or custom ordering

The reservation response includes which lots were selected:

{
  "lots": [
    {
      "lot_id": "lot_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
      "amount": "3000"
    },
    {
      "lot_id": "lot_02HV8X9Y2KPQRS3T4UV5WX6YZ8",
      "amount": "2000"
    }
  ]
}

Querying Reservations

List Active Reservations

curl "https://api.phoenixwallet.io/v1/wallets/wal_01HV8X.../reservations?status=PENDING" \
  -H "Authorization: Bearer $API_KEY"

Get Reservation Details

curl "https://api.phoenixwallet.io/v1/reservations/rsv_01HV8X..." \
  -H "Authorization: Bearer $API_KEY"

Impact on Balances

Reservations affect the reserved portion of wallet balances:

{
  "wallet_id": "wal_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
  "balances": [
    {
      "asset_code": "USD",
      "available": "10000",
      "reserved": "5000",
      "total": "15000"
    }
  ]
}

In this example:

  • User has $150 total
  • $50 is reserved (held for pending transactions)
  • $100 is available for new transactions
  • Wallets - Understanding available vs reserved balances
  • Lots - How reservations select and hold lot funds
  • Policies - Rules that affect reservation creation
  • Ledger - How reservations are recorded