阿卡德交换
使用 Boltz 转换 Arkade 的闪电和链路
@arkade-os/boltz-swap 通过博尔茨互换提供与闪电网络和比特币在链上的无缝集成,允许用户在Arkade,闪电,比特币之间移动资金.
概览
库允许四种互换类型:
- 闪电到 Arkade - 从闪电支付接受资金进入你的Arkade钱包
- Arkade 到闪电 - 从你的阿卡德钱包里寄钱给闪电发票
- ARK 转到 BTC - 将资金从Arkade转到链上比特币地址
- BTC 到 ARK - 把钱从链上比特币转到你的阿卡德钱包
建于博尔茨互换协议上方,通过SwapManager自动进行背景监测.
安装
npm install @arkade-os/sdk @arkade-os/boltz-swap
基本用途
初始化
import { Wallet, MnemonicIdentity } from '@arkade-os/sdk';
import { ArkadeSwaps } from '@arkade-os/boltz-swap';
// Create an identity
const identity = MnemonicIdentity.fromMnemonic('your twelve word mnemonic phrase ...', { isMainnet: true });
// Initialize your Arkade wallet
const wallet = await Wallet.create({
identity,
arkServerUrl: 'https://arkade.computer',
});
// Initialize swaps (network auto-detected from wallet, SwapManager enabled by default)
const swaps = await ArkadeSwaps.create({ wallet });
[注] 从 v1 升级
StorageAdapter看到了吗 交换仓库迁移。 。 。 .
接收闪电
const result = await swaps.createLightningInvoice({ amount: 50000 });
console.log('Invoice:', result.invoice);
// SwapManager auto-claims when paid
发送闪电
const result = await swaps.sendLightningPayment({ invoice: 'lnbc500u1pj...' });
console.log('Paid:', result.txid);
// SwapManager auto-refunds if payment fails
默认情况下,只有在互换完全结算后,调用才能解决(transaction.claimed, (中文(简体) ),
也就是在Boltz扫过HTLC之后. 以示乐观的"同意"状态
付款在飞行中——就像大多数闪电钱包一样——通过 waitFor: 'funded'数字 :
const result = await swaps.sendLightningPayment({
invoice: 'lnbc500u1pj...',
waitFor: 'funded',
});
// Resolves as soon as the lockup transaction is observed: the funds are
// committed and the swap is refundable from here. result.preimage is not
// reported on this path — the proof of payment is persisted to the stored
// swap once it settles. Monitoring continues in the
// background and keeps the stored swap up to date until a terminal status,
// but a late failure no longer rejects — keep the SwapManager enabled so
// auto-refunds are handled for you. With the SwapManager disabled, a late
// failure is only persisted as refundable and the funds stay locked until
// you recover them via restoreSwaps()/recoverSubmarineFunds().
同样的里程碑被曝光 交换你已经持有
waitForSwapFunded(pendingSwap),同时 waitForSwapSettlement(pendingSwap)。 。 。 .
如果应用程序在互换解决前重新启动, 进程内监控就消失了 — call
refreshSwapsStatus() * 开始调和:每一次待定的互换投票,并持续进行
最新状态,包括应用程序时解决的互换假想
关闭。 从寄存器读取回换( 例如 ) . getSwapHistory()来翻转一个
待UI行为"已完成".
ARK 转到 BTC
const result = await swaps.arkToBtc({
btcAddress: 'bc1q...',
senderLockAmount: 100000,
});
// SwapManager auto-claims BTC when ready
BTC 到 ARK
const result = await swaps.btcToArk({ receiverLockAmount: 100000 });
console.log('Pay to:', result.btcAddress, 'Amount:', result.amountToPay);
// SwapManager auto-claims ARK when ready
正在收听更新
const manager = swaps.getSwapManager();
// Global listeners
manager.onSwapCompleted((swap) => console.log(`${swap.id} completed`));
manager.onSwapFailed((swap, error) => console.error(`${swap.id} failed`, error));
manager.onSwapUpdate((swap, oldStatus) => console.log(`${swap.id}: ${oldStatus} → ${swap.status}`));
// Wait for a specific swap
const result = await swaps.createLightningInvoice({ amount: 50000 });
const unsubscribe = manager.subscribeToSwapUpdates(result.pendingSwap.id, (swap, oldStatus) => {
console.log(`${oldStatus} → ${swap.status}`);
});
// Or block until a specific swap completes
const { txid } = await manager.waitForSwapCompletion(result.pendingSwap.id);
收费和限额
// Lightning
const fees = await swaps.getFees();
const limits = await swaps.getLimits();
// Chain swaps
const chainFees = await swaps.getFees('ARK', 'BTC');
const chainLimits = await swaps.getLimits('ARK', 'BTC');
交换历史
const history = await swaps.getSwapHistory();
const pending = await swaps.getPendingReverseSwaps();
高级使用
链式交换金额
当创建连锁互换时, 指定一个:
senderLockAmount: 发送者发送这一确切金额, 接收者得到的减少( 金额 - 费用)receiverLockAmount:接收者得到这一确切数额,发送者支付更多(金额+费用)
重新谈判引文
如果发送的金额与预期的不同:
const newAmount = await swaps.quoteSwap(pendingSwap.id);
挡住交换
即使使用交换管理器,也可以屏蔽,直到特定交换完成:
const result = await swaps.createLightningInvoice({ amount: 50000 });
const { txid } = await swaps.waitAndClaim(result.pendingSwap);
不交换管理器( 手工模式)
如果您禁用交换管理器, 您必须手动监视和操作交换 :
const swaps = await ArkadeSwaps.create({ wallet, swapManager: false });
const result = await swaps.createLightningInvoice({ amount: 50000 });
await swaps.waitAndClaim(result.pendingSwap); // blocks until complete
交换管理器配置
const swaps = await ArkadeSwaps.create({
wallet,
swapManager: {
enableAutoActions: true, // Auto claim/refund (default: true)
autoStart: true, // Auto-start on init (default: true)
pollInterval: 30000, // Failsafe poll interval (default)
events: {
onSwapCompleted: (swap) => {},
onSwapFailed: (swap, error) => {},
onSwapUpdate: (swap, oldStatus) => {},
onActionExecuted: (swap, action) => {},
onWebSocketConnected: () => {},
onWebSocketDisconnected: (error?) => {},
}
},
});
双向UI钩
const result = await swaps.createLightningInvoice({ amount: 50000 });
const manager = swaps.getSwapManager();
const unsubscribe = manager.subscribeToSwapUpdates(
result.pendingSwap.id,
(swap, oldStatus) => {
if (swap.status === 'invoice.settled') showNotification('Payment received!');
}
);
潜艇基金回收
如果闪电支付失败,资金被困入VHTLC,你可以手动回收:
// Scan all local swaps for recoverable funds
const candidates = await swaps.scanRecoverableSubmarineSwaps();
// candidates[i].status: "recoverable" | "pre_cltv" | "none" | "already_spent" | "invalid_swap"
// Recover all at once
const results = await swaps.recoverAllSubmarineFunds(candidates.map(c => c.swap));
// Or inspect / recover a single swap
const info = await swaps.inspectSubmarineRecovery(swap);
if (info.status === 'recoverable') {
await swaps.recoverSubmarineFunds(swap);
}
[注] 这只扫描存储在您本地仓库中的互换 。 它没有发现在 Boltz 上存在的互换,而是在当地缺失.
清理
// Manual
await swaps.dispose();
// Automatic (TypeScript 5.2+)
{
await using swaps = await ArkadeSwaps.create({ wallet });
// ...
} // auto-disposed
交换仓库
在浏览器中将存储默认交换到索引DB. 其他平台:
// SQLite (React Native / Node.js)
import { SQLiteSwapRepository } from '@arkade-os/boltz-swap/repositories/sqlite';
// Realm (React Native)
import { RealmSwapRepository, BoltzRealmSchemas } from '@arkade-os/boltz-swap/repositories/realm';
自定义执行必须设置 readonly version = 1 ——TypeScript被撞出后会出错,信号需要更新.
[尖叫声] 如果您先前使用 v1 则
StorageAdapter- 基于储存库,迁移 使用前的数据.migrateToSwapRepository复制遗赠reverseSwaps财务报告和审定财务报表submarineSwaps旧的收藏ContractRepository输入新SwapRepository它写着自己的互换特殊移民旗帜,所以它是 能够安全地召唤每一个启动者 钱包侧getMigrationStatus。 。 。 .import { IndexedDbSwapRepository, migrateToSwapRepository } from '@arkade-os/boltz-swap' import { IndexedDBStorageAdapter } from '@arkade-os/sdk/adapters/indexedDB' const oldStorage = new IndexedDBStorageAdapter('arkade-service-worker', 1) await migrateToSwapRepository(oldStorage, new IndexedDbSwapRepository())
博览会/ 反应原生
Expo/React Introduct不能运行长寿的服务工作员,背景工作由OS执行一个短窗口(通常每~15+分). 实现最佳背景索赔/交换退款,使用 ExpoArkadeLightning 加上在全球范围界定的背景任务.
[尖叫声] 自0.3.30起的变化 - 修理 136号。 。 。 .
背景任务助手从
@arkade-os/boltz-swap/expo改为@arkade-os/boltz-swap/expo/background操作系统级注册为无 执行时间较长ExpoArkadeSwaps.setup()- 说得很清楚.
在此之前 之后 import { defineExpoSwapBackgroundTask } from "@arkade-os/boltz-swap/expo"import { defineExpoSwapBackgroundTask } from "@arkade-os/boltz-swap/expo/background"background: { taskName, taskQueue, minimumBackgroundInterval, foregroundIntervalMs }background: { taskQueue, foregroundIntervalMs }+ 显式await registerExpoSwapBackgroundTask(taskName, { minimumInterval })dispose()未注册的OS任务打电话 unregisterExpoSwapBackgroundTask(taskName)你自己来TypeScript呼叫器在已删除的字段中获得编译错误. JS 呼叫者必须手动更新 ——老字段被默默地忽略,OS任务永远不会运行.
先决条件
- 安装 Expo 背景任务依赖性 :
npx expo install expo-task-manager expo-background-task
npx expo install @react-native-async-storage/async-storage expo-secure-store
npx expo install expo-crypto
npx expo install expo-sqlite
-
对于博览会的持久性,更喜欢SQLite后置的寄存器 (单位:千美元)
@arkade-os/boltz-swap/repositories/sqlite财务报告和审定财务报表@arkade-os/sdk/repositories/sqlite在顶部expo-sqlite,或王国 顶端的仓库realm。没有 SDK 发送索引DB 帮助器 为博览会. -
博览会需要
crypto.getRandomValues()密码操作的多填充 :
import * as Crypto from "expo-crypto";
if (!global.crypto) global.crypto = {} as any;
global.crypto.getRandomValues = Crypto.getRandomValues;
(1) 界定背景任务(全球范围)
TaskManager.defineTask() 必须在模块范围中调用,然后进行回放.
// App entry point (e.g., _layout.tsx) — GLOBAL SCOPE
import AsyncStorage from "@react-native-async-storage/async-storage";
import * as SecureStore from "expo-secure-store";
import * as SQLite from "expo-sqlite";
import { SingleKey } from "@arkade-os/sdk";
import { AsyncStorageTaskQueue } from "@arkade-os/sdk/worker/expo";
import { SQLiteSwapRepository } from "@arkade-os/boltz-swap/repositories/sqlite";
import { defineExpoSwapBackgroundTask } from "@arkade-os/boltz-swap/expo/background";
const swapTaskQueue = new AsyncStorageTaskQueue(AsyncStorage, "ark:swap-queue");
const swapDb = SQLite.openDatabaseSync("ark-swaps.db");
const swapRepository = new SQLiteSwapRepository({
run: (sql, params) => swapDb.runAsync(sql, params ?? []),
get: (sql, params) => swapDb.getFirstAsync(sql, params ?? []),
all: (sql, params) => swapDb.getAllAsync(sql, params ?? []),
});
defineExpoSwapBackgroundTask("ark-swap-poll", {
taskQueue: swapTaskQueue,
swapRepository,
identityFactory: async () => {
const key = await SecureStore.getItemAsync("ark-private-key");
if (!key) throw new Error("Missing private key in SecureStore");
return SingleKey.fromHex(key);
},
});
(2) 设置 ExpoArkadeLightning (构成部分/提供者)
使用一个 IWallet 执行《公约》的情况 arkProvider 财务报告和审定财务报表 indexerProvider (例如 ExpoWallet 从 @arkade-os/sdk/wallet/expo,或 Wallet.create() 与 ExpoArkProvider 编号 : ExpoIndexerProvider) (中文(简体) ).
import AsyncStorage from "@react-native-async-storage/async-storage";
import { ExpoWallet } from "@arkade-os/sdk/wallet/expo";
import { AsyncStorageTaskQueue } from "@arkade-os/sdk/worker/expo";
import { BoltzSwapProvider } from "@arkade-os/boltz-swap";
import { ExpoArkadeLightning } from "@arkade-os/boltz-swap/expo";
import { registerExpoSwapBackgroundTask } from "@arkade-os/boltz-swap/expo/background";
// Used by ExpoWallet's background task (defined via @arkade-os/sdk/wallet/expo)
const walletTaskQueue = new AsyncStorageTaskQueue(AsyncStorage, "ark:wallet-queue");
const wallet = await ExpoWallet.setup({
identity, // same identity used by identityFactory()
arkServerUrl: "https://mutinynet.arkade.sh",
storage: { walletRepository, contractRepository },
background: {
taskName: "ark-wallet-poll",
taskQueue: walletTaskQueue,
foregroundIntervalMs: 20_000,
minimumBackgroundInterval: 15,
},
});
const swapProvider = new BoltzSwapProvider({
apiUrl: "https://api.boltz.mutinynet.arkade.sh",
network: "mutinynet",
});
const arkLn = await ExpoArkadeLightning.setup({
wallet,
swapProvider,
swapRepository, // must match the one used in defineExpoSwapBackgroundTask
background: {
taskQueue: swapTaskQueue, // must match the one used in defineExpoSwapBackgroundTask
foregroundIntervalMs: 20_000,
},
});
// Activate the OS scheduler (Expo Android/iOS only).
// Must use the same task name passed to defineExpoSwapBackgroundTask above.
await registerExpoSwapBackgroundTask("ark-swap-poll", { minimumInterval: 15 });
await arkLn.createLightningInvoice({ amount: 1000 });
// On logout / wallet reset / app teardown:
import { unregisterExpoSwapBackgroundTask } from "@arkade-os/boltz-swap/expo/background";
await arkLn.dispose();
await unregisterExpoSwapBackgroundTask("ark-swap-poll");
[大 OS 任务助手( O)
defineExpoSwapBackgroundTask, (中文(简体) ),registerExpoSwapBackgroundTask, (中文(简体) ),unregisterExpoSwapBackgroundTask(中文(简体) ) 住在楼下@arkade-os/boltz-swap/expo/background。这个子路径是 页:1 仅限 模块expo-task-manager编号 :expo-background-task; 保持隔离让反应-内生网和 节点消费者使用/expo没有那些本地的包裹.
处理错误
与交换管理员,退款是自动的——听 onSwapFailed 用于通知。 没有它, 手动处理错误 :
import { isPendingSubmarineSwap, isPendingChainSwap } from '@arkade-os/boltz-swap';
try {
await swaps.sendLightningPayment({ invoice: 'lnbc500u1pj...' });
} catch (error) {
if (error.isRefundable && error.pendingSwap) {
if (isPendingChainSwap(error.pendingSwap)) {
await swaps.refundArk(error.pendingSwap);
} else if (isPendingSubmarineSwap(error.pendingSwap)) {
await swaps.refundVHTLC(error.pendingSwap);
}
}
}
错误类型 : InvoiceExpiredError, (中文(简体) ), InvoiceFailedToPayError, (中文(简体) ), InsufficientFundsError, (中文(简体) ), NetworkError, (中文(简体) ), SchemaError, (中文(简体) ), SwapExpiredError, (中文(简体) ), TransactionFailedError。 。 。 .
类型警卫
import {
isPendingReverseSwap, isPendingSubmarineSwap, isPendingChainSwap,
isChainSwapClaimable, isChainSwapRefundable,
} from '@arkade-os/boltz-swap';
释放
软件包本地发行被禁用 。 从单列波根放出并被套件扫描: pnpm run release -- boltz-swap patch 颠倒并出版 @arkade-os/boltz-swap 带有 @arkade-os/boltz-swap/<version> 标签,对照当前发布的 @arkade-os/sdk 版本。 见 根读取 满旗和 pnpm run release -- --help。 。 。 .
许可证
麻省理工学院