Swap State Machine
Understanding swap states and transitions
LendaSwap swaps progress through a well-defined state machine that ensures atomicity and proper handling of all scenarios.
State Overview
┌──────────┐
│ Pending │
└────┬─────┘
│
┌──────────┴──────────┐
│ │
(User pays BTC) (Timeout: 30 min)
│ │
▼ ▼
┌───────────────┐ ┌──────────┐
│ ClientFunded │ │ Expired │
└───────┬───────┘ └──────────┘
│
┌─────────┴──────────┐
│ │
(Service creates HTLC) (User refunds)
│ │
▼ ▼
┌───────────────┐ ┌─────────────────┐
│ ServerFunded │ │ ClientRefunded │
└───────┬───────┘ └─────────────────┘
│
┌───────┴────────┐
│ │
(User claims) (HTLC timeout)
│ │
▼ ▼
┌────────────┐ ┌──────────────────────────┐
│ Done │ │ ClientFundedServerRefunded│
└────────────┘ └──────────────────────────┘States Explained
| Code | State | Description | Action Required |
|---|---|---|---|
| 0 | Pending | Swap created, waiting for BTC payment | Pay BTC |
| 1 | ClientFunded | BTC received, preparing HTLC | Wait |
| 2 | ServerFunded | HTLC created on Polygon, ready to claim | Claim now |
| 3 | Done | Swap complete, user received USDC | None |
| 4 | Expired | 30 min timeout, no payment received | None |
| 5 | ClientRefunded | User refunded before HTLC created | None |
| 6 | ClientFundedServerRefunded | HTLC timeout, service reclaimed WBTC | Refund |
Flow Examples
Success Flow (~95% of swaps)
Pending → ClientFunded → ServerFunded → Done- User creates swap request
- User pays BTC via Lightning (~10 seconds)
- Service creates HTLC on Polygon (~30 seconds)
- User claims USDC (gasless) (~10 seconds)
Total time: ~50 seconds
Timeout Flow (~2% of swaps)
Pending → ClientFunded → ServerFunded → ClientFundedServerRefundedUser paid BTC but didn't claim USDC within 10 minutes. Service refunds WBTC, user keeps BTC.
Expiration Flow (~5% of swaps)
Pending → ExpiredUser never paid within 30 minutes. No funds locked.
Transition Rules
| From | Event | To | Probability |
|---|---|---|---|
| Pending | User pays BTC | ClientFunded | ~95% |
| Pending | 30 min timeout | Expired | ~5% |
| ClientFunded | HTLC created | ServerFunded | ~99% |
| ServerFunded | User claims | Done | ~98% |
| ServerFunded | HTLC timeout | ClientFundedServerRefunded | ~2% |
Handling Each Status
const swaps = await client.listAllSwaps();
for (const stored of swaps) {
const swap = stored.response;
switch (swap.status) {
case "serverfunded":
console.log(`Swap ${stored.swapId}: Ready to claim!`);
await client.claim(stored.swapId);
break;
case "clientfundedserverrefunded":
console.log(`Swap ${stored.swapId}: Needs refund`);
break;
case "clientredeemed":
console.log(`Swap ${stored.swapId}: Complete`);
break;
default:
console.log(`Swap ${stored.swapId}: ${swap.status}`);
}
}On-chain BTC → Arkade States
1. Pending - Swap created, waiting for BTC
2. ClientFunded - BTC received, waiting for confirmations
3. ServerFunded - Arkade VHTLC created, ready to claim
4. Done - VTXOs claimed successfullyBest Practices
- Monitor
Pendingswaps - Prompt users to pay before timeout - Auto-claim
ServerFunded- Claim immediately when ready - Handle timeouts gracefully - Show appropriate messages for expired swaps
- Track terminal states - Clean up UI for completed/expired swaps