Skip to main content
Move funds between Bitcoin onchain 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 onchain 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 onchain 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);
  }
}