Skip to main content
Arkade provides seamless integration with the Lightning Network through Boltz submarine swaps, allowing users to move funds between Arkade and Lightning channels.

Overview

The BoltzSwapProvider library extends Arkade’s functionality by enabling:
  1. Lightning to Arkade swaps - Receive funds from Lightning payments into your Arkade wallet
  2. Arkade to Lightning swaps - Send funds from your Arkade wallet to Lightning invoices
This integration is built on top of the Boltz submarine swap protocol, providing a reliable and secure way to bridge the gap between Arkade and the Lightning Network.

Installation

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

Basic Usage

Initializing the Lightning Swap Provider

import { Wallet } from '@arkade-os/sdk'
import { ArkadeSwaps, BoltzSwapProvider } from '@arkade-os/boltz-swap'

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

// Initialize the Lightning swap provider
const swapProvider = new BoltzSwapProvider({
  apiUrl: 'https://api.ark.boltz.exchange',
  network: 'bitcoin',
})

// Create the lightningSwaps instance
const lightningSwaps = new ArkadeSwaps({
  wallet,
  swapProvider,
})

Swap Management

Enable background swap monitoring with the swapManager option:
const lightningSwaps = new ArkadeSwaps({
  wallet,
  swapProvider,
  swapManager: true, // enable with defaults
});

// Query pending swaps
const pendingPaymentsToLightning = lightningSwaps.getPendingSubmarineSwaps();
const pendingPaymentsFromLightning = lightningSwaps.getPendingReverseSwaps();

Receiving Lightning Payments

To receive a Lightning payment into your Arkade wallet:
// Create a Lightning invoice that will deposit funds to your Arkade wallet
const result = await lightningSwaps.createLightningInvoice({
  amount: 50000, // 50,000 sats
  description: 'Payment to my Arkade wallet',
});

console.log('Receive amount:', result.amount);
console.log('Expiry (seconds):', result.expiry);
console.log('Lightning Invoice:', result.invoice);
console.log('Payment Hash:', result.paymentHash);
console.log('Pending swap', result.pendingSwap);
console.log('Preimage', result.preimage);

// The invoice can now be shared with the payer
// When paid, funds will appear in your Arkade wallet
Response shape:
interface CreateLightningInvoiceResponse {
  amount: number                    // invoice amount in satoshis
  expiry: number                    // invoice expiry timestamp in unix seconds
  invoice: string                   // BOLT11 Lightning invoice
  paymentHash: string               // payment hash (hex-encoded)
  pendingSwap: BoltzReverseSwap     // the pending reverse swap for monitoring, pass to waitAndClaim()
  preimage: string                  // generated upfront by the receiver; hash goes into the invoice
}

Monitoring Incoming Lightning Payments

You must monitor the status of incoming Lightning payments. It will automatically claim the payment when it’s available.
// Monitor the payment, it will resolve when the payment is received
const { txid } = await lightningSwaps.waitAndClaim(result.pendingSwap);

console.log('Receival successful!');
console.log('Transaction ID:', txid);

Sending Lightning Payments

To send a payment from your Arkade wallet to a Lightning invoice:
import { decodeInvoice } from '@arkade-os/boltz-swap';

// Parse a Lightning invoice
const details = decodeInvoice(
  'lnbc500u1pj...' // Lightning invoice string
);

console.log('Invoice amount:', details.amountSats, 'sats');
console.log('Description:', details.description);
console.log('Payment Hash:', details.paymentHash);

// Pay the Lightning invoice from your Arkade wallet
const result = await lightningSwaps.sendLightningPayment({
  invoice: 'lnbc500u1pj...', // Lightning invoice string
});
// => { amount: number, preimage: string, txid: string }

console.log('Payment successful!');
console.log('Amount:', result.amount);
console.log('Preimage:', result.preimage);
console.log('Transaction ID:', result.txid);

Error Handling

The library provides detailed error types to help you handle different failure scenarios:
import {
  SwapError,
  SchemaError,
  NetworkError,
  SwapExpiredError,
  InvoiceExpiredError,
  InvoiceFailedToPayError,
  InsufficientFundsError,
  TransactionFailedError,
} from '@arkade-os/boltz-swap';

try {
  await lightningSwaps.sendLightningPayment({
    invoice: 'lnbc500u1pj...',
  });
} catch (error) {
  if (error instanceof InvoiceExpiredError) {
    console.error('The invoice has expired. Please request a new one.');
  } else if (error instanceof InvoiceFailedToPayError) {
    console.error('The provider failed to pay the invoice. Please request a new one.');
  } else if (error instanceof InsufficientFundsError) {
    console.error('Not enough funds available:', error.message);
  } else if (error instanceof NetworkError) {
    console.error('Network issue. Please try again later:', error.message);
  } else if (error instanceof SchemaError) {
    console.error('Invalid response from API. Please try again later.');
  } else if (error instanceof SwapExpiredError) {
    console.error('The swap has expired. Please request a new invoice.');
  } else if (error instanceof SwapError) {
    console.error('Swap failed:', error.message);
  } else if (error instanceof TransactionFailedError) {
    console.error('Transaction failed. Please try again later');
  } else {
    console.error('Unknown error:', error);
  }

  // You might be able to claim a refund
  if (error.isRefundable && error.pendingSwap) {
    const { txid } = await lightningSwaps.refundVHTLC(error.pendingSwap);
    console.log('Refund claimed:', txid);
  }
}