npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@arkade-os/boltz-swap

v0.2.11

Published

A production-ready TypeScript package that brings Boltz submarine-swaps to Arkade.

Readme

Lightning Swaps

Integrate Lightning Network with Arkade using Submarine Swaps

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, SingleKey } from '@arkade-os/sdk';
import { ArkadeLightning, BoltzSwapProvider } from '@arkade-os/boltz-swap';

// Create an identity
const identity = SingleKey.fromHex('your_private_key_in_hex');

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

// Initialize the Lightning swap provider
const swapProvider = new BoltzSwapProvider({
  apiUrl: 'https://api.boltz.mutinynet.arkade.sh',
  network: 'mutinynet',
  referralId: 'arkade', // optional
});

// Create the ArkadeLightning instance
const arkadeLightning = new ArkadeLightning({
  wallet,
  swapProvider,
});

Create your Wallet

import { Wallet } from '@arkade-os/sdk';

const wallet = await Wallet.create({
  identity,
  arkServerUrl: 'https://mutinynet.arkade.sh',
  // storage defaults to in-memory
});

// Wallet may have built-in providers
const arkadeLightning = new ArkadeLightning({
  wallet,
  swapProvider
});

ServiceWorkerWallet with IndexDB

import { ServiceWorkerWallet, SingleKey, RestArkProvider, RestIndexerProvider } from '@arkade-os/sdk';
import { IndexedDBStorageAdapter } from '@arkade-os/sdk/storage';

// Create your identity
const identity = SingleKey.fromHex('your_private_key_hex');
// Or generate a new one:
// const identity = SingleKey.fromRandomBytes();

// Configure IndexedDB storage adapter for ServiceWorker
const storage = new IndexedDBStorageAdapter('arkade-service-worker-wallet', 1);

const wallet = await ServiceWorkerWallet.setup({
  serviceWorkerPath: '/service-worker.js',
  arkServerUrl: 'https://mutinynet.arkade.sh',
  identity,
  storage, // Pass the IndexedDB storage adapter
});

// Must provide external providers for ServiceWorkerWallet (it doesn't have them)
const arkadeLightning = new ArkadeLightning({
  wallet: serviceWorkerWallet,
  arkProvider: new RestArkProvider('https://mutinynet.arkade.sh'),
  indexerProvider: new RestIndexerProvider('https://mutinynet.arkade.sh'),
  swapProvider,
});

Storage Adapters: The Arkade SDK provides various storage adapters for different environments. For ServiceWorker environments, use IndexedDBStorageAdapter. For more storage options and adapters, see the Arkade SDK storage adapters documentation.

Checking Swap Limits

Before creating Lightning invoices or sending payments, you can check the minimum and maximum swap amounts supported by the Boltz service. This is useful to validate that your invoice amount is within the acceptable range.

// Get current swap limits (in satoshis)
const limits = await arkadeLightning.getLimits();

if (limits) {
  console.log('Minimum swap amount:', limits.min, 'sats');
  console.log('Maximum swap amount:', limits.max, 'sats');

  // Example: Validate invoice amount before creating
  const invoiceAmount = 50000; // 50,000 sats

  if (invoiceAmount < limits.min) {
    console.error(`Amount ${invoiceAmount} is below minimum ${limits.min} sats`);
  } else if (invoiceAmount > limits.max) {
    console.error(`Amount ${invoiceAmount} is above maximum ${limits.max} sats`);
  } else {
    console.log('Amount is within valid range');
    // Safe to proceed with creating invoice or payment
  }
} else {
  console.log('Unable to fetch limits - no swap provider configured');
}

Validating Lightning Invoice Amounts

import { decodeInvoice } from '@arkade-os/boltz-swap';

// Decode an incoming Lightning invoice to check its amount
const invoice = 'lnbc500u1pj...'; // Lightning invoice string
const decodedInvoice = decodeInvoice(invoice);

console.log('Invoice amount:', decodedInvoice.amountSats, 'sats');

// Check if the invoice amount is within swap limits
const limits = await arkadeLightning.getLimits();

if (limits && decodedInvoice.amountSats >= limits.min && decodedInvoice.amountSats <= limits.max) {
  // Amount is valid for swaps
  const paymentResult = await arkadeLightning.sendLightningPayment({
    invoice: invoice,
  });
  console.log('Payment successful!');
} else {
  console.error('Invoice amount is outside supported swap limits');
}

Checking Swap Fees

You can check the fee to pay for different swap amounts supported by the Boltz service. This is useful to validate the user is willing to pay the fees.

// Get current swap fees
const fees: FeesResponse | null = await arkadeLightning.getFees();
if (!fees) throw new Error('something went wrong');

const calcSubmarineSwapFee = (satoshis: number): number => {
  if (!satoshis) return 0;
  const { percentage, minerFees } = fees.submarine;
  return Math.ceil((satoshis * percentage) / 100 + minerFees);
};

const calcReverseSwapFee = (satoshis: number): number => {
  if (!satoshis) return 0;
  const { percentage, minerFees } = fees.reverse;
  return Math.ceil((satoshis * percentage) / 100 + minerFees.claim + minerFees.lockup);
};

Checking swap status

const response = await arkadeLightning.getSwapStatus('swap_id');
console.log('swap status = ', response.status);

Storage

This library automatically stores pending swaps using the wallet's built-in contract repository. All swap data is persisted automatically and can be retrieved using the following methods:

// Get all pending submarine swaps (those waiting for Lightning payment)
const pendingPaymentsToLightning = await arkadeLightning.getPendingSubmarineSwaps();

// Get all pending reverse swaps (those waiting for claim)
const pendingPaymentsFromLightning = await arkadeLightning.getPendingReverseSwaps();

// Get complete swap history (both completed and pending)
const swapHistory = await arkadeLightning.getSwapHistory();

Note: All swap data is automatically persisted and retrieved through the wallet's contract repository. No additional storage configuration is required.

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 arkadeLightning.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

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 receivalResult = await arkadeLightning.waitAndClaim(result.pendingSwap);
console.log('Receival successful!');
console.log('Transaction ID:', receivalResult.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 invoiceDetails = decodeInvoice(
  'lnbc500u1pj...' // Lightning invoice string
);

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

// Pay the Lightning invoice from your Arkade wallet
const paymentResult = await arkadeLightning.sendLightningPayment({
  invoice: 'lnbc500u1pj...', // Lightning invoice string
});

console.log('Payment successful!');
console.log('Amount:', paymentResult.amount);
console.log('Preimage:', paymentResult.preimage);
console.log('Transaction ID:', paymentResult.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 arkadeLightning.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 refundResult = await arkadeLightning.refundVHTLC(error.pendingSwap);
    console.log('Refund claimed:', refundResult.txid);
  }
}