Skip to main content
Satora Swaps swaps progress through a well-defined state machine that ensures atomicity and proper handling of all scenarios. The state machine is the same for both directions (BTC → EVM and EVM → BTC) - the difference is which addresses the client and server fund.

Who Funds What

The state machine is direction-agnostic. “Client funds” and “Server funds” refer to different addresses depending on the swap direction.

BTC → EVM (Client sends BTC, receives tokens)

EVM → BTC (Client sends tokens, receives BTC)

Gasless flow (recommended): Manual flow (with signer):
EVM → BTC gasless: The user sends stablecoins to client_evm_address, not to evm_htlc_address. The SDK derives client_evm_address from the swap’s secret key and uses Permit2 to relay tokens to the HTLC contract - the user never interacts with the HTLC directly.

State Overview


States Explained

Early exit: In the ClientFunded state, if the server hasn’t funded its side yet, you can refund immediately without waiting for the timelock. The swap transitions to ClientRefunded.

Flow Examples

BTC → EVM Success Flow

The full happy path passes through ClientRedeemed before reaching ServerRedeemed - the server only settles after the client’s claim is confirmed on-chain.
  1. Client generates secret S, shares hash H with service
  2. Client sends BTC to boltz_invoice (Lightning) / btc_vhtlc_address (Arkade) / btc_htlc_address (On-chain)
  3. Payment detected (ClientFundingSeen), then confirmed (ClientFunded)
  4. Service locks tokens in evm_htlc_address on EVM chain (ServerFunded)
  5. Client reveals S, claims tokens from evm_htlc_address via gasless EIP-712 (ClientRedeeming → ClientRedeemed)
  6. Service extracts S from blockchain, claims BTC (ServerRedeemed)

EVM → BTC Success Flow (Gasless)

  1. Client creates swap - receives client_evm_address (SDK-derived deposit address)
  2. Client sends stablecoins to client_evm_address (not the HTLC!)
  3. SDK calls fundSwapGasless() - signs Permit2, server relays tokens from client_evm_address → evm_htlc_address
  4. Funding detected (ClientFundingSeen), then confirmed (ClientFunded)
  5. Service sends BTC to client’s Arkade wallet / Lightning invoice / on-chain address (ServerFunded)
  6. Service reveals preimage (ClientRedeeming → ClientRedeemed) and claims tokens from evm_htlc_address (ServerRedeemed)

EVM → BTC Success Flow (Manual / With Signer)

  1. Client creates swap - receives evm_htlc_address and coordinator details
  2. Client approves token spend, then calls HTLCCoordinator.executeAndCreateWithPermit2() to lock tokens in evm_htlc_address (client pays gas)
  3. Funding detected (ClientFundingSeen), confirmed (ClientFunded)
  4. Service sends BTC (ServerFunded)
  5. Service reveals preimage (ClientRedeeming → ClientRedeemed) and claims tokens from evm_htlc_address (ServerRedeemed)

Timeout Flow

Client funded but didn’t claim/settle within the HTLC timelock (24 hours on mainnet). Server reclaims its funds. Client can refund their side.

Late Funding Flow

Client funded after the Lightning invoice / swap expired. Client refunds via locktime.

Expiration Flow

Client never funded within the pending timeout (~30 minutes by default; configurable via expire_pending_swaps). No funds locked.

Early Exit Flow

Client funded but requested a refund before the server funded its side.

Transition Rules


Handling Each Status


Terminal States

These states are final - no further transitions occur:
  • ServerRedeemed - Success (both parties received funds)
  • Expired - No payment was made
  • ClientRefunded - Client exited early
  • ClientFundedServerRefunded - EVM HTLC timed out
  • ClientRefundedServerRefunded - Both sides refunded
  • ClientRedeemedAndClientRefunded - Edge case resolved

Best Practices

  1. Monitor Pending swaps - Prompt users to pay before the ~30 minute timeout (default; configurable on the server)
  2. Auto-claim ServerFunded - Claim immediately when ready
  3. Handle ClientRedeeming - Show a loading state; claim is in progress
  4. Wait for ServerRedeemed - This is the true success terminal, not ClientRedeemed
  5. Track terminal states - Clean up UI for completed/expired swaps

Resources