Skip to main content
KaleidoSwap currently supports two swap models depending on the client:
ModelUsed byTrust requiredSettlement
Atomic swapDesktop appNone — cryptographic guaranteeHTLC on Lightning Network
Order-based swapWeb app / APIMaker fulfillment during execution windowMaker sends asset after payment
Roadmap: Order-based swaps will become atomic in a future release, bringing the same trustless guarantees to web and API integrations.

Atomic Swaps (Desktop App)

The desktop app uses Hash Time-Locked Contracts (HTLCs) to execute swaps atomically over the Lightning Network. Both sides lock their assets simultaneously — either the full swap completes or both sides get their funds back. There is no counterparty risk.

How It Works

  1. The taker streams a live price from the maker over WebSocket (receives an rfq_id with each quote).
  2. The taker calls POST /api/v1/swaps/init — the maker locks the exchange rate and returns a swapstring and payment_hash.
  3. The taker’s RGB Lightning Node whitelists the swapstring (authorising it to route through the node).
  4. The taker calls POST /api/v1/swaps/execute — the maker initiates the HTLC.
  5. The Lightning Network routes the HTLC: the maker reveals the preimage to claim BTC, which simultaneously releases the RGB asset to the taker.
  6. If either party fails to complete within the HTLC timeout, both sides’ funds are returned automatically.

Sequence Diagram

Taker Client                         Maker (RGB-LSP)                   Taker RLN Node
     |                                      |                                 |
     |──── WebSocket connect ──────────────>|                                 |
     |──── quote_request (BTC/USDT) ───────>|                                 |
     |<─── quote_response (price, rfq_id) ──|                                 |
     |                                      |                                 |
     |──── POST /api/v1/swaps/init ────────>|                                 |
     |       (rfq_id, from, to, amounts)    |                                 |
     |<─── { swapstring, payment_hash } ────|                                 |
     |                                      |                                 |
     |──── whitelist_swap(swapstring) ──────────────────────────────────────>|
     |<─── swap whitelisted ───────────────────────────────────────────────  |
     |                                      |                                 |
     |──── POST /api/v1/swaps/execute ─────>|                                 |
     |       (swapstring, taker_pubkey,     |                                 |
     |        payment_hash)                 |                                 |
     |<─── 200 OK ──────────────────────── |                                 |
     |          ← HTLC resolves atomically on Lightning Network →             |
     |                                      |                                 |
     |──── GET /api/v1/swaps/status ───────>|                                 |
     |<─── { status: "Succeeded" } ─────── |                                 |

Endpoints Used

StepEndpoint
Stream pricesWebSocket wss://api.signet.kaleidoswap.com/ws/{client_id}
Lock ratePOST /api/v1/swaps/init
Execute swapPOST /api/v1/swaps/execute
Check statusGET /api/v1/swaps/status

WebSocket Environments

EnvironmentURL
Regtestwss://api.regtest.kaleidoswap.com/ws/{client_id}
Signetwss://api.signet.kaleidoswap.com/ws/{client_id}
Mainnetwss://api.kaleidoswap.com/ws/{client_id} (coming soon)
Replace {client_id} with a unique identifier for your session.

SDK Integration

The SDK handles the WebSocket, init, and execute steps for you:
import { KaleidoClient } from 'kaleidoswap-sdk';

const client = KaleidoClient.create({
  baseUrl: 'https://api.signet.kaleidoswap.com',
  nodeUrl: 'http://localhost:3001',  // required for atomic swaps
});

// Stream a live quote
client.maker.enableWebSocket('wss://api.signet.kaleidoswap.com/ws/my-client');

const unsubscribe = await client.maker.streamQuotesByTicker(
  'BTC', 'USDT', 100000,
  async (quote) => {
    // Use the rfq_id from the latest quote to init + execute
    const result = await client.maker.initSwap({
      rfq_id: quote.rfq_id,
      from_asset: 'BTC',
      from_amount: quote.from_amount,
      to_asset: 'USDT',
      to_amount: quote.to_amount,
    });
    // Whitelist on your node, then execute...
  }
);

Order-Based Swaps (Web App / API)

The web app and direct API integrations use an order-based model. The taker creates a swap order, pays a deposit, and the maker sends the swapped asset to the recipient address after confirming payment. This model has a trust component during the execution window — you pay first, then wait for the maker to fulfil. If the maker fails to deliver, you can contact support for a refund.

How It Works

  1. The taker requests a price quote (POST /api/v1/market/quote) and receives an rfq_id.
  2. The taker creates a swap order, providing the rfq_id and a recipient address.
  3. The taker is shown a deposit address or Lightning invoice.
  4. The taker pays the deposit.
  5. The maker detects the payment, executes the swap, and sends the asset to the recipient address.
  6. The taker polls order status until FILLED.

Sequence Diagram

Web Client / API User                Maker (RGB-LSP)
        |                                  |
        |──── POST /api/v1/market/quote ──>|
        |       (from_asset, to_asset,     |
        |        from_amount)              |
        |<─── { rfq_id, price,  ──────────|
        |        to_amount, expires_at }   |
        |                                  |
        |──── POST /api/v1/swap-orders ───>|
        |       (rfq_id, receiver_address) |
        |<─── { order_id, status: ────────|
        |        AWAITING_DEPOSIT,         |
        |        deposit_address }         |
        |                                  |
        |──── Pay deposit ─────────────────────> Bitcoin / Lightning Network
        |                                  |
        |                    Maker detects payment
        |                    Maker sends asset to receiver_address
        |                                  |
        |──── GET /api/v1/swap-orders ────>|
        |       /{order_id}                |
        |<─── { status: FILLED } ─────────|

Order States

StateDescription
AWAITING_DEPOSITOrder created, waiting for payment
PAYMENT_CONFIRMEDPayment received, maker processing
EXECUTINGMaker sending the swapped asset
FILLEDSwap complete
EXPIREDDeposit window elapsed without payment
FAILEDExecution error — contact support
PENDING_RATE_DECISIONRate changed, taker must accept or reject

SDK Integration

import { KaleidoClient } from 'kaleidoswap-sdk';

const client = KaleidoClient.create({
  baseUrl: 'https://api.signet.kaleidoswap.com',
});

// 1. Get a quote
const quote = await client.maker.getQuote({
  from_asset: { asset_id: 'BTC', layer: 'BTC_LN', amount: 100000 },
  to_asset: { asset_id: 'USDT', layer: 'RGB_LN' },
});

// 2. Create swap order
const order = await client.maker.createSwapOrder({
  rfq_id: quote.rfq_id,
  from_asset: { asset_id: 'BTC', layer: 'BTC_LN', amount: quote.from_amount },
  to_asset: { asset_id: 'USDT', layer: 'RGB_LN', amount: quote.to_amount },
  receiver_address: 'lnbc1...',  // recipient Lightning invoice
});

console.log(`Pay: ${order.deposit_address}`);

// 3. Poll for completion
const completed = await client.maker.waitForSwapCompletion(order.order_id, {
  timeout: 600,
  onStatusUpdate: (s) => console.log(`Status: ${s}`)
});

Comparing the Two Models

Atomic SwapOrder-Based Swap
TrustNone — HTLC guaranteeMaker must fulfil after payment
SpeedMilliseconds (Lightning)Seconds to minutes
RequiredRGB Lightning Node (RLN)Any wallet or API client
Rate stabilityLocked at initMay change (rate decision flow)
Available onDesktop appWeb app, API
RoadmapLiveWill become atomic

Swap APIs

Endpoints for atomic swap init and execute

Market APIs

Endpoints for quotes and order-based swaps

SDK Examples

End-to-end code examples for both swap models

Error Handling

Handle swap failures and rate decisions