@arkade-os/boltz-swap
Version:
A production-ready TypeScript package that brings Boltz submarine-swaps to Arkade.
317 lines (309 loc) • 11.6 kB
text/typescript
import { IWallet, Identity, RestArkProvider, RestIndexerProvider, VHTLC } from '@arkade-os/sdk';
interface StorageOptions {
storagePath?: string;
}
declare class Storage {
private storage;
private isBrowser;
private storagePath;
private localStorage;
private initPromise?;
private constructor();
static create(options?: StorageOptions): Promise<Storage>;
initializeFileStorage(): Promise<void>;
getItem(key: string): Promise<any>;
setItem(key: string, value: any): Promise<void>;
removeItem(key: string): Promise<void>;
clear(): Promise<void>;
save(): Promise<void>;
ensureInitialized(): Promise<void>;
}
declare class StorageProvider {
private storageInstance;
private storage;
constructor(instance: Storage);
static create(options?: StorageOptions): Promise<StorageProvider>;
getPendingReverseSwaps(): PendingReverseSwap[];
savePendingReverseSwap(swap: PendingReverseSwap): Promise<void>;
deletePendingReverseSwap(id: string): Promise<void>;
getPendingSubmarineSwaps(): PendingSubmarineSwap[];
savePendingSubmarineSwap(swap: PendingSubmarineSwap): Promise<void>;
deletePendingSubmarineSwap(id: string): Promise<void>;
private savePendingSwap;
private deletePendingSwap;
private setSwaps;
private set;
private get;
private initializeStorage;
}
interface SwapProviderConfig {
apiUrl?: string;
network: Network;
}
type LimitsResponse = {
min: number;
max: number;
};
type BoltzSwapStatus = 'invoice.expired' | 'invoice.failedToPay' | 'invoice.paid' | 'invoice.pending' | 'invoice.set' | 'invoice.settled' | 'swap.created' | 'swap.expired' | 'transaction.claim.pending' | 'transaction.claimed' | 'transaction.confirmed' | 'transaction.failed' | 'transaction.lockupFailed' | 'transaction.mempool' | 'transaction.refunded';
type GetSwapStatusResponse = {
status: string;
zeroConfRejected?: boolean;
transaction?: {
id: string;
hex: string;
preimage?: string;
};
};
type CreateSubmarineSwapRequest = {
invoice: string;
refundPublicKey: string;
};
type CreateSubmarineSwapResponse = {
id: string;
address: string;
expectedAmount: number;
claimPublicKey: string;
acceptZeroConf: boolean;
timeoutBlockHeights: {
refund: number;
unilateralClaim: number;
unilateralRefund: number;
unilateralRefundWithoutReceiver: number;
};
};
type CreateReverseSwapRequest = {
claimPublicKey: string;
invoiceAmount: number;
preimageHash: string;
};
type CreateReverseSwapResponse = {
id: string;
invoice: string;
onchainAmount: number;
lockupAddress: string;
refundPublicKey: string;
timeoutBlockHeights: {
refund: number;
unilateralClaim: number;
unilateralRefund: number;
unilateralRefundWithoutReceiver: number;
};
};
declare class BoltzSwapProvider {
private readonly wsUrl;
private readonly apiUrl;
private readonly network;
constructor(config: SwapProviderConfig);
getNetwork(): Network;
getLimits(): Promise<LimitsResponse>;
getSwapStatus(id: string): Promise<GetSwapStatusResponse>;
createSubmarineSwap({ invoice, refundPublicKey, }: CreateSubmarineSwapRequest): Promise<CreateSubmarineSwapResponse>;
createReverseSwap({ invoiceAmount, claimPublicKey, preimageHash, }: CreateReverseSwapRequest): Promise<CreateReverseSwapResponse>;
monitorSwap(swapId: string, update: (type: BoltzSwapStatus, data?: any) => void): Promise<void>;
private request;
}
interface Vtxo {
txid: string;
vout: number;
sats: number;
script: string;
tx: {
hex: string;
version: number;
locktime: number;
};
}
type Wallet = IWallet & Identity;
type Network = 'bitcoin' | 'mutinynet' | 'regtest' | 'testnet';
interface CreateLightningInvoiceRequest {
amount: number;
description?: string;
}
interface CreateLightningInvoiceResponse {
expiry: number;
invoice: string;
paymentHash: string;
pendingSwap: PendingReverseSwap;
preimage: string;
}
interface SendLightningPaymentRequest {
invoice: string;
maxFeeSats?: number;
}
interface SendLightningPaymentResponse {
amount: number;
preimage: string;
txid: string;
}
interface PendingReverseSwap {
preimage: string;
status: BoltzSwapStatus;
request: CreateReverseSwapRequest;
response: CreateReverseSwapResponse;
}
interface PendingSubmarineSwap {
status: BoltzSwapStatus;
request: CreateSubmarineSwapRequest;
response: CreateSubmarineSwapResponse;
}
interface RefundHandler {
onRefundNeeded: (swapData: PendingSubmarineSwap) => Promise<void>;
}
interface ArkadeLightningConfig {
wallet: Wallet;
arkProvider: RestArkProvider;
swapProvider: BoltzSwapProvider;
indexerProvider: RestIndexerProvider;
feeConfig?: Partial<FeeConfig>;
refundHandler?: RefundHandler;
storageProvider?: StorageProvider | null;
timeoutConfig?: Partial<TimeoutConfig>;
retryConfig?: Partial<RetryConfig>;
}
interface TimeoutConfig {
swapExpiryBlocks: number;
invoiceExpirySeconds: number;
claimDelayBlocks: number;
}
interface FeeConfig {
maxMinerFeeSats: number;
maxSwapFeeSats: number;
}
interface RetryConfig {
maxAttempts: number;
delayMs: number;
}
interface DecodedInvoice {
expiry: number;
amountSats: number;
description: string;
paymentHash: string;
}
interface IncomingPaymentSubscription {
on(event: 'pending', listener: () => void): this;
on(event: 'created', listener: () => void): this;
on(event: 'settled', listener: () => void): this;
on(event: 'failed', listener: (error: Error) => void): this;
unsubscribe(): void;
}
declare class ArkadeLightning {
private readonly wallet;
private readonly arkProvider;
private readonly swapProvider;
private readonly storageProvider;
private readonly indexerProvider;
private readonly config;
constructor(config: ArkadeLightningConfig);
createLightningInvoice(args: CreateLightningInvoiceRequest): Promise<CreateLightningInvoiceResponse>;
/**
* Sends a Lightning payment.
* 1. decode the invoice to get the amount and destination
* 2. create submarine swap with the decoded invoice
* 3. send the swap address and expected amount to the wallet to create a transaction
* 4. wait for the swap settlement and return the preimage and txid
* @param args - The arguments for sending a Lightning payment.
* @returns The result of the payment.
*/
sendLightningPayment(args: SendLightningPaymentRequest): Promise<SendLightningPaymentResponse>;
createSubmarineSwap(args: SendLightningPaymentRequest): Promise<PendingSubmarineSwap>;
createReverseSwap(args: CreateLightningInvoiceRequest): Promise<PendingReverseSwap>;
claimVHTLC(pendingSwap: PendingReverseSwap): Promise<void>;
refundVHTLC(pendingSwap: PendingSubmarineSwap): Promise<void>;
waitAndClaim(pendingSwap: PendingReverseSwap): Promise<{
txid: string;
}>;
/**
* Waits for the swap settlement.
* @param pendingSwap - The pending swap.
* @returns The status of the swap settlement.
*/
waitForSwapSettlement(pendingSwap: PendingSubmarineSwap): Promise<void>;
/**
* Waits for the swap settlement.
* @param swapData - The swap data to wait for.
* @returns The status of the swap settlement.
*/
waitForSwapSettlementold(swapData: PendingSubmarineSwap): Promise<GetSwapStatusResponse>;
/**
* Validates the final Ark transaction.
* checks that all inputs have a signature for the given pubkey
* and the signature is correct for the given tapscript leaf
* TODO: This is a simplified check, we should verify the actual signatures
* @param finalArkTx The final Ark transaction in PSBT format.
* @param _pubkey The public key of the user.
* @param _tapLeaves The taproot script leaves.
* @returns True if the final Ark transaction is valid, false otherwise.
*/
private validFinalArkTx;
/**
* Creates a VHTLC script for the swap.
* works for submarine swaps and reverse swaps
* it creates a VHTLC script that can be used to claim or refund the swap
* it validates the receiver, sender and server public keys are x-only
* it validates the VHTLC script matches the expected lockup address
* @param param0 - The parameters for creating the VHTLC script.
* @returns The created VHTLC script.
*/
createVHTLCScript({ network, preimageHash, receiverPubkey, senderPubkey, serverPubkey, timeoutBlockHeights, }: {
network: string;
preimageHash: Uint8Array;
receiverPubkey: string;
senderPubkey: string;
serverPubkey: string;
timeoutBlockHeights: {
refund: number;
unilateralClaim: number;
unilateralRefund: number;
unilateralRefundWithoutReceiver: number;
};
}): {
vhtlcScript: VHTLC.Script;
vhtlcAddress: string;
};
/**
* Retrieves all pending submarine swaps from the storage provider.
* This method filters the pending swaps to return only those with a status of 'invoice.set'.
* It is useful for checking the status of all pending submarine swaps in the system.
* @returns PendingSubmarineSwap[] or null if no storage provider is set.
* If no swaps are found, it returns an empty array.
*/
getPendingSubmarineSwaps(): PendingSubmarineSwap[] | null;
/**
* Retrieves all pending reverse swaps from the storage provider.
* This method filters the pending swaps to return only those with a status of 'swap.created'.
* It is useful for checking the status of all pending reverse swaps in the system.
* @returns PendingReverseSwap[] or null if no storage provider is set.
* If no swaps are found, it returns an empty array.
*/
getPendingReverseSwaps(): PendingReverseSwap[] | null;
}
interface ErrorOptions {
message?: string;
isClaimable?: boolean;
isRefundable?: boolean;
pendingSwap?: PendingReverseSwap | PendingSubmarineSwap;
}
declare class SwapError extends Error {
isClaimable: boolean;
isRefundable: boolean;
pendingSwap?: PendingReverseSwap | PendingSubmarineSwap;
constructor(options?: ErrorOptions);
}
declare class InvoiceExpiredError extends SwapError {
constructor(options: ErrorOptions);
}
declare class InsufficientFundsError extends SwapError {
constructor(options?: ErrorOptions);
}
declare class NetworkError extends Error {
constructor(message: string);
}
/**
* Decodes a Lightning invoice.
* @param invoice - The Lightning invoice to decode.
* @returns The decoded invoice.
*/
declare const decodeInvoice: (invoice: string) => DecodedInvoice;
declare const getInvoiceSatoshis: (invoice: string) => number;
declare const getInvoicePaymentHash: (invoice: string) => string;
export { ArkadeLightning, type ArkadeLightningConfig, BoltzSwapProvider, type CreateLightningInvoiceResponse, type DecodedInvoice, type FeeConfig, type IncomingPaymentSubscription, InsufficientFundsError, InvoiceExpiredError, type Network, NetworkError, type PendingReverseSwap, type PendingSubmarineSwap, type RefundHandler, type RetryConfig, type SendLightningPaymentRequest, type SendLightningPaymentResponse, StorageProvider, SwapError, type TimeoutConfig, type Vtxo, type Wallet, decodeInvoice, getInvoicePaymentHash, getInvoiceSatoshis };