Skip to main content
Move funds between Bitcoin on-chain UTXOs and Arkade VTXOs through Boltz chain swaps. ArkadeSwaps handles both directions (ARK to BTC and BTC to ARK), with automatic background monitoring via SwapManager.

Installation

npm install @arkade-os/sdk @arkade-os/boltz-swap

Initialization

Chain swaps use the same ArkadeSwaps instance as Lightning swaps. Network and swap provider are auto-detected from your wallet.
import { Wallet } from '@arkade-os/sdk';
import { ArkadeSwaps } from '@arkade-os/boltz-swap';

const wallet = await Wallet.create({
  identity,
  arkServerUrl: 'https://arkade.computer',
});

const swaps = await ArkadeSwaps.create({ wallet });

Fees and limits

const fees = await swaps.getFees('ARK', 'BTC');
console.log('Fee:', fees.percentage, '%');
console.log('Server miner fee:', fees.minerFees.server);
console.log('User claim fee:', fees.minerFees.user.claim);
console.log('User lockup fee:', fees.minerFees.user.lockup);

const limits = await swaps.getLimits('ARK', 'BTC');
console.log('Min:', limits.min, 'sats');
console.log('Max:', limits.max, 'sats');

Sending to Bitcoin (Arkade to BTC)

Send funds from your Arkade wallet to a Bitcoin on-chain address. When specifying amounts, choose one:
  • senderLockAmount — you send exactly this amount, receiver gets less after fees
  • receiverLockAmount — receiver gets exactly this amount, you pay more including fees
const result = await swaps.arkToBtc({
  btcAddress: 'bc1q...',
  senderLockAmount: 100000, // OR receiverLockAmount: 95000
});

console.log('ARK lockup address:', result.arkAddress);
console.log('Amount to pay:', result.amountToPay);
console.log('Swap ID:', result.pendingSwap.id);

// Send funds to the lockup address
await wallet.sendBitcoin({
  address: result.arkAddress,
  amount: result.amountToPay,
});

Waiting for BTC claim

With SwapManager enabled (default), BTC claiming happens automatically. You can block until completion:
const { txid } = await swaps.waitAndClaimBtc(result.pendingSwap);
console.log('BTC claimed:', txid);

Receiving from Bitcoin (BTC to Arkade)

Receive Bitcoin on-chain funds into your Arkade wallet.
const result = await swaps.btcToArk({
  receiverLockAmount: 100000, // OR senderLockAmount: 105000
});

console.log('BTC deposit address:', result.btcAddress);
console.log('Amount to pay:', result.amountToPay);
console.log('Swap ID:', result.pendingSwap.id);

Waiting for ARK claim

const { txid } = await swaps.waitAndClaimArk(result.pendingSwap);
console.log('ARK claimed:', txid);

Swap status

const status = await swaps.getSwapStatus('swap_id');
console.log('Status:', status.status);

Storage and history

Swap records are persisted via SwapRepository (same as Lightning swaps):
const history = await swaps.getSwapHistory();
const pendingChain = await swaps.getPendingChainSwaps();

Cleanup

await swaps.dispose();

Error handling

With SwapManager, refunds for ARK-to-BTC swaps are automatic. Without it, handle errors manually:
import {
  SwapError,
  SchemaError,
  NetworkError,
  SwapExpiredError,
  InsufficientFundsError,
  TransactionFailedError,
  isPendingChainSwap,
} from '@arkade-os/boltz-swap';

try {
  const result = await swaps.arkToBtc({
    btcAddress: 'bc1q...',
    senderLockAmount: 100000,
  });

  await wallet.sendBitcoin({
    address: result.arkAddress,
    amount: result.amountToPay,
  });

  await swaps.waitAndClaimBtc(result.pendingSwap);
} catch (error) {
  if (error instanceof InsufficientFundsError) {
    console.error('Insufficient funds:', error.message);
  } else if (error instanceof NetworkError) {
    console.error('Network issue:', error.message);
  } else if (error instanceof SchemaError) {
    console.error('Invalid provider response.');
  } else if (error instanceof SwapExpiredError) {
    console.error('Swap expired.');
  } else if (error instanceof TransactionFailedError) {
    console.error('Transaction failed.');
  } else if (error instanceof SwapError) {
    console.error('Swap failed:', error.message);
  } else {
    console.error('Unknown error:', error);
  }

  // Refund ARK if applicable (only for ARK -> BTC direction)
  if (error.isRefundable && error.pendingSwap && isPendingChainSwap(error.pendingSwap)) {
    await swaps.refundArk(error.pendingSwap);
  }
}