@arkade-os/boltz-swap 0.3.44 → 0.3.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{arkade-swaps-DwgfLCMY.d.cts → arkade-swaps-D-L0_0Ri.d.cts} +8 -1
- package/dist/{arkade-swaps-2q3VSgb4.d.ts → arkade-swaps-fmdCFjif.d.ts} +8 -1
- package/dist/{chunk-QVXFEX5F.js → chunk-GXO2EB6C.js} +84 -20
- package/dist/{chunk-PHF6C2NE.js → chunk-UJXW5JBT.js} +1 -1
- package/dist/expo/background.cjs +86 -19
- package/dist/expo/background.d.cts +3 -3
- package/dist/expo/background.d.ts +3 -3
- package/dist/expo/background.js +9 -4
- package/dist/expo/index.cjs +79 -17
- package/dist/expo/index.d.cts +4 -4
- package/dist/expo/index.d.ts +4 -4
- package/dist/expo/index.js +2 -2
- package/dist/index.cjs +80 -18
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/repositories/realm/index.d.cts +1 -1
- package/dist/repositories/realm/index.d.ts +1 -1
- package/dist/repositories/sqlite/index.d.cts +1 -1
- package/dist/repositories/sqlite/index.d.ts +1 -1
- package/dist/{swapsPollProcessor-CGMXUKPe.d.cts → swapsPollProcessor-B98F6MQF.d.cts} +1 -1
- package/dist/{swapsPollProcessor-CuDM6sxV.d.ts → swapsPollProcessor-Ov-wp17v.d.ts} +1 -1
- package/dist/{types-8NrCdOpS.d.cts → types-CS62-oEy.d.cts} +19 -2
- package/dist/{types-8NrCdOpS.d.ts → types-CS62-oEy.d.ts} +19 -2
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IWallet, ArkProvider, IndexerProvider, ArkInfo, Identity, ArkTxInput, VHTLC } from '@arkade-os/sdk';
|
|
2
|
-
import { r as BoltzSwapProvider, y as SwapManager, m as SwapRepository, q as ArkadeSwapsCreateConfig, A as ArkadeSwapsConfig, n as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, b as BoltzReverseSwap, S as SendLightningPaymentRequest, o as SendLightningPaymentResponse, O as OptimisticSendLightningPaymentResponse, c as BoltzSubmarineSwap, f as SubmarineRefundOutcome, g as SubmarineRecoveryInfo, h as SubmarineRecoveryResult, j as ArkToBtcResponse, a as BoltzChainSwap, l as ChainArkRefundOutcome, k as BtcToArkResponse, d as Chain, F as FeesResponse, i as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from './types-
|
|
2
|
+
import { r as BoltzSwapProvider, y as SwapManager, m as SwapRepository, q as ArkadeSwapsCreateConfig, A as ArkadeSwapsConfig, n as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, b as BoltzReverseSwap, S as SendLightningPaymentRequest, o as SendLightningPaymentResponse, O as OptimisticSendLightningPaymentResponse, c as BoltzSubmarineSwap, f as SubmarineRefundOutcome, g as SubmarineRecoveryInfo, h as SubmarineRecoveryResult, j as ArkToBtcResponse, a as BoltzChainSwap, l as ChainArkRefundOutcome, k as BtcToArkResponse, d as Chain, F as FeesResponse, i as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from './types-CS62-oEy.cjs';
|
|
3
3
|
import { TransactionOutput } from '@scure/btc-signer/psbt.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -415,6 +415,13 @@ declare class ArkadeSwaps {
|
|
|
415
415
|
swap: BoltzChainSwap;
|
|
416
416
|
arkInfo: ArkInfo;
|
|
417
417
|
}): Promise<boolean>;
|
|
418
|
+
/**
|
|
419
|
+
* Verifies the BTC-side Taproot HTLC of a chain swap before funds are
|
|
420
|
+
* committed: the lockup address must bind to MuSig2(boltz, user) over
|
|
421
|
+
* Boltz's leaves, and those leaves must enforce the agreed preimage hash,
|
|
422
|
+
* direction-specific keys, leaf version, and absolute refund CLTV.
|
|
423
|
+
*/
|
|
424
|
+
private verifyBtcChainHtlc;
|
|
418
425
|
/**
|
|
419
426
|
* Renegotiates the quote for an existing chain swap. Convenience wrapper
|
|
420
427
|
* over `getSwapQuote` + `acceptSwapQuote` with a safety floor.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IWallet, ArkProvider, IndexerProvider, ArkInfo, Identity, ArkTxInput, VHTLC } from '@arkade-os/sdk';
|
|
2
|
-
import { r as BoltzSwapProvider, y as SwapManager, m as SwapRepository, q as ArkadeSwapsCreateConfig, A as ArkadeSwapsConfig, n as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, b as BoltzReverseSwap, S as SendLightningPaymentRequest, o as SendLightningPaymentResponse, O as OptimisticSendLightningPaymentResponse, c as BoltzSubmarineSwap, f as SubmarineRefundOutcome, g as SubmarineRecoveryInfo, h as SubmarineRecoveryResult, j as ArkToBtcResponse, a as BoltzChainSwap, l as ChainArkRefundOutcome, k as BtcToArkResponse, d as Chain, F as FeesResponse, i as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from './types-
|
|
2
|
+
import { r as BoltzSwapProvider, y as SwapManager, m as SwapRepository, q as ArkadeSwapsCreateConfig, A as ArkadeSwapsConfig, n as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, b as BoltzReverseSwap, S as SendLightningPaymentRequest, o as SendLightningPaymentResponse, O as OptimisticSendLightningPaymentResponse, c as BoltzSubmarineSwap, f as SubmarineRefundOutcome, g as SubmarineRecoveryInfo, h as SubmarineRecoveryResult, j as ArkToBtcResponse, a as BoltzChainSwap, l as ChainArkRefundOutcome, k as BtcToArkResponse, d as Chain, F as FeesResponse, i as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from './types-CS62-oEy.js';
|
|
3
3
|
import { TransactionOutput } from '@scure/btc-signer/psbt.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -415,6 +415,13 @@ declare class ArkadeSwaps {
|
|
|
415
415
|
swap: BoltzChainSwap;
|
|
416
416
|
arkInfo: ArkInfo;
|
|
417
417
|
}): Promise<boolean>;
|
|
418
|
+
/**
|
|
419
|
+
* Verifies the BTC-side Taproot HTLC of a chain swap before funds are
|
|
420
|
+
* committed: the lockup address must bind to MuSig2(boltz, user) over
|
|
421
|
+
* Boltz's leaves, and those leaves must enforce the agreed preimage hash,
|
|
422
|
+
* direction-specific keys, leaf version, and absolute refund CLTV.
|
|
423
|
+
*/
|
|
424
|
+
private verifyBtcChainHtlc;
|
|
418
425
|
/**
|
|
419
426
|
* Renegotiates the quote for an existing chain swap. Convenience wrapper
|
|
420
427
|
* over `getSwapQuote` + `acceptSwapQuote` with a safety floor.
|
|
@@ -571,20 +571,26 @@ var BoltzSwapProvider = class {
|
|
|
571
571
|
invoiceAmount,
|
|
572
572
|
claimPublicKey,
|
|
573
573
|
preimageHash,
|
|
574
|
-
description
|
|
574
|
+
description,
|
|
575
|
+
descriptionHash
|
|
575
576
|
}) {
|
|
576
577
|
if (claimPublicKey.length != 66) {
|
|
577
578
|
throw new SwapError({
|
|
578
579
|
message: "claimPublicKey must be a compressed public key"
|
|
579
580
|
});
|
|
580
581
|
}
|
|
582
|
+
if (descriptionHash !== void 0 && !/^[0-9a-fA-F]{64}$/.test(descriptionHash)) {
|
|
583
|
+
throw new SwapError({
|
|
584
|
+
message: "descriptionHash must be a 32-byte SHA256 (64 hex chars)"
|
|
585
|
+
});
|
|
586
|
+
}
|
|
581
587
|
const requestBody = {
|
|
582
588
|
from: "BTC",
|
|
583
589
|
to: "ARK",
|
|
584
590
|
invoiceAmount,
|
|
585
591
|
claimPublicKey,
|
|
586
592
|
preimageHash,
|
|
587
|
-
description: description?.trim() || "Send to Arkade address",
|
|
593
|
+
...descriptionHash ? { descriptionHash } : { description: description?.trim() || "Send to Arkade address" },
|
|
588
594
|
...this.referralId ? { referralId: this.referralId } : {}
|
|
589
595
|
};
|
|
590
596
|
const response = await this.request(
|
|
@@ -997,6 +1003,12 @@ var decodeInvoice = (invoice) => {
|
|
|
997
1003
|
expiry: decoded.expiry ?? 3600,
|
|
998
1004
|
amountSats: Number(millisats / 1000n),
|
|
999
1005
|
description: decoded.sections.find((s) => s.name === "description")?.value ?? "",
|
|
1006
|
+
// description_hash (BOLT11 `h`) is missing from light-bolt11-decoder's
|
|
1007
|
+
// Section union even though the decoder emits it. Widen just this lookup
|
|
1008
|
+
// rather than patch the library's types (separate repo, out of scope).
|
|
1009
|
+
descriptionHash: decoded.sections.find(
|
|
1010
|
+
(s) => s.name === "description_hash"
|
|
1011
|
+
)?.value ?? "",
|
|
1000
1012
|
paymentHash: decoded.sections.find((s) => s.name === "payment_hash")?.value ?? ""
|
|
1001
1013
|
};
|
|
1002
1014
|
};
|
|
@@ -2364,14 +2376,16 @@ var IndexedDbSwapRepository = class {
|
|
|
2364
2376
|
// src/arkade-swaps.ts
|
|
2365
2377
|
import {
|
|
2366
2378
|
ArkAddress as ArkAddress2,
|
|
2367
|
-
isRecoverable
|
|
2379
|
+
isRecoverable,
|
|
2380
|
+
getNetwork as getNetwork2
|
|
2368
2381
|
} from "@arkade-os/sdk";
|
|
2369
2382
|
import { sha256 as sha2563 } from "@noble/hashes/sha2.js";
|
|
2383
|
+
import { ripemd160 as ripemd1602 } from "@noble/hashes/legacy.js";
|
|
2370
2384
|
import { hex as hex8 } from "@scure/base";
|
|
2371
2385
|
import { secp256k1 as secp256k12 } from "@noble/curves/secp256k1.js";
|
|
2372
2386
|
import { randomBytes } from "@noble/hashes/utils.js";
|
|
2373
2387
|
import { Address as Address2, OutScript as OutScript2, SigHash as SigHash2, Transaction as Transaction6 } from "@scure/btc-signer";
|
|
2374
|
-
import {
|
|
2388
|
+
import { equalBytes as equalBytes3 } from "@scure/btc-signer/utils.js";
|
|
2375
2389
|
|
|
2376
2390
|
// src/utils/musig.ts
|
|
2377
2391
|
import { secp256k1 } from "@noble/curves/secp256k1.js";
|
|
@@ -2593,21 +2607,9 @@ var create = (privateKey, publicKeys) => {
|
|
|
2593
2607
|
// src/utils/boltz-swap-tx.ts
|
|
2594
2608
|
import { schnorr } from "@noble/curves/secp256k1.js";
|
|
2595
2609
|
import { hex as hex4 } from "@scure/base";
|
|
2596
|
-
import { Script, Transaction as Transaction2 } from "@scure/btc-signer";
|
|
2610
|
+
import { Script, ScriptNum, Transaction as Transaction2 } from "@scure/btc-signer";
|
|
2597
2611
|
import { tapLeafHash } from "@scure/btc-signer/payment.js";
|
|
2598
2612
|
import { compareBytes, equalBytes as equalBytes2 } from "@scure/btc-signer/utils.js";
|
|
2599
|
-
var REGTEST_NETWORK = {
|
|
2600
|
-
bech32: "bcrt",
|
|
2601
|
-
pubKeyHash: 111,
|
|
2602
|
-
scriptHash: 196,
|
|
2603
|
-
wif: 239
|
|
2604
|
-
};
|
|
2605
|
-
var MUTINYNET_NETWORK = {
|
|
2606
|
-
bech32: "tb",
|
|
2607
|
-
pubKeyHash: 111,
|
|
2608
|
-
scriptHash: 196,
|
|
2609
|
-
wif: 239
|
|
2610
|
-
};
|
|
2611
2613
|
var deserializeLeaf = (leaf) => ({
|
|
2612
2614
|
version: leaf.version,
|
|
2613
2615
|
output: hex4.decode(leaf.output)
|
|
@@ -2641,6 +2643,19 @@ var deserializeSwapTree = (tree) => {
|
|
|
2641
2643
|
])
|
|
2642
2644
|
};
|
|
2643
2645
|
};
|
|
2646
|
+
var TAPLEAF_V1 = 192;
|
|
2647
|
+
var PUSH_32 = Uint8Array.of(32);
|
|
2648
|
+
var decodeScriptNum = (data) => data instanceof Uint8Array && data.length > 0 ? Number(ScriptNum(5, true).decode(data)) : void 0;
|
|
2649
|
+
var assertChainHtlcLeaves = (tree, expected) => {
|
|
2650
|
+
if (tree.claimLeaf.version !== TAPLEAF_V1 || tree.refundLeaf.version !== TAPLEAF_V1)
|
|
2651
|
+
throw new Error("unexpected leaf version");
|
|
2652
|
+
const claim = Script.decode(tree.claimLeaf.output);
|
|
2653
|
+
if (claim.length !== 8 || claim[0] !== "SIZE" || !(claim[1] instanceof Uint8Array) || !equalBytes2(claim[1], PUSH_32) || claim[2] !== "EQUALVERIFY" || claim[3] !== "HASH160" || !(claim[4] instanceof Uint8Array) || !equalBytes2(claim[4], expected.preimageHash160) || claim[5] !== "EQUALVERIFY" || !(claim[6] instanceof Uint8Array) || !equalBytes2(claim[6], expected.claimXOnly) || claim[7] !== "CHECKSIG")
|
|
2654
|
+
throw new Error("unexpected claim leaf");
|
|
2655
|
+
const refund = Script.decode(tree.refundLeaf.output);
|
|
2656
|
+
if (refund.length !== 4 || !(refund[0] instanceof Uint8Array) || !equalBytes2(refund[0], expected.refundXOnly) || refund[1] !== "CHECKSIGVERIFY" || decodeScriptNum(refund[2]) !== expected.timeoutBlockHeight || refund[3] !== "CHECKLOCKTIMEVERIFY")
|
|
2657
|
+
throw new Error("unexpected refund leaf");
|
|
2658
|
+
};
|
|
2644
2659
|
var taprootHashTree = (tree) => {
|
|
2645
2660
|
if (!Array.isArray(tree)) {
|
|
2646
2661
|
return {
|
|
@@ -2792,6 +2807,7 @@ import {
|
|
|
2792
2807
|
buildOffchainTx,
|
|
2793
2808
|
getSequence as getSequence2,
|
|
2794
2809
|
Intent,
|
|
2810
|
+
getNetwork,
|
|
2795
2811
|
networks,
|
|
2796
2812
|
VHTLC,
|
|
2797
2813
|
VtxoScript as VtxoScript2,
|
|
@@ -2978,7 +2994,7 @@ var createVHTLCScript = (args) => {
|
|
|
2978
2994
|
)
|
|
2979
2995
|
});
|
|
2980
2996
|
if (!vhtlcScript.claimScript) throw new Error("Failed to create VHTLC script");
|
|
2981
|
-
const hrp = network
|
|
2997
|
+
const hrp = getNetwork(network).hrp;
|
|
2982
2998
|
const vhtlcAddress = vhtlcScript.address(hrp, serverXOnlyPublicKey).encode();
|
|
2983
2999
|
return { vhtlcScript, vhtlcAddress };
|
|
2984
3000
|
};
|
|
@@ -3440,7 +3456,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3440
3456
|
invoiceAmount: args.amount,
|
|
3441
3457
|
claimPublicKey,
|
|
3442
3458
|
preimageHash,
|
|
3443
|
-
...args.description?.trim() ? { description: args.description.trim() } : {}
|
|
3459
|
+
...args.descriptionHash !== void 0 ? { descriptionHash: args.descriptionHash } : args.description?.trim() ? { description: args.description.trim() } : {}
|
|
3444
3460
|
};
|
|
3445
3461
|
const swapResponse = await this.swapProvider.createReverseSwap(swapRequest);
|
|
3446
3462
|
const decodedInvoice = decodeInvoice(swapResponse.invoice);
|
|
@@ -4395,7 +4411,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4395
4411
|
throw new Error(`Swap ${pendingSwap.id}: BTC transaction hex is required`);
|
|
4396
4412
|
const lockupTx = Transaction6.fromRaw(hex8.decode(swapStatus.transaction.hex));
|
|
4397
4413
|
const arkInfo = await this.arkProvider.getInfo();
|
|
4398
|
-
const network = arkInfo.network
|
|
4414
|
+
const network = getNetwork2(arkInfo.network);
|
|
4399
4415
|
const swapTree = deserializeSwapTree(pendingSwap.response.claimDetails.swapTree);
|
|
4400
4416
|
const musig = tweakMusig(
|
|
4401
4417
|
create(hex8.decode(pendingSwap.ephemeralKey), [
|
|
@@ -4935,8 +4951,56 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4935
4951
|
message: "Boltz is trying to scam us (invalid address)"
|
|
4936
4952
|
});
|
|
4937
4953
|
}
|
|
4954
|
+
this.verifyBtcChainHtlc({ to, swap, arkNetwork: arkInfo.network });
|
|
4938
4955
|
return true;
|
|
4939
4956
|
}
|
|
4957
|
+
/**
|
|
4958
|
+
* Verifies the BTC-side Taproot HTLC of a chain swap before funds are
|
|
4959
|
+
* committed: the lockup address must bind to MuSig2(boltz, user) over
|
|
4960
|
+
* Boltz's leaves, and those leaves must enforce the agreed preimage hash,
|
|
4961
|
+
* direction-specific keys, leaf version, and absolute refund CLTV.
|
|
4962
|
+
*/
|
|
4963
|
+
verifyBtcChainHtlc(args) {
|
|
4964
|
+
const { to, swap, arkNetwork } = args;
|
|
4965
|
+
const btcDetails = to === "ARK" ? swap.response.lockupDetails : swap.response.claimDetails;
|
|
4966
|
+
if (!btcDetails.swapTree)
|
|
4967
|
+
throw new SwapError({ message: `Swap ${swap.id}: missing swap tree in BTC details` });
|
|
4968
|
+
if (!btcDetails.serverPublicKey)
|
|
4969
|
+
throw new SwapError({
|
|
4970
|
+
message: `Swap ${swap.id}: missing server public key in BTC details`
|
|
4971
|
+
});
|
|
4972
|
+
if (typeof btcDetails.timeoutBlockHeight !== "number")
|
|
4973
|
+
throw new SwapError({
|
|
4974
|
+
message: `Swap ${swap.id}: missing timeout block height in BTC details`
|
|
4975
|
+
});
|
|
4976
|
+
const network = getNetwork2(arkNetwork);
|
|
4977
|
+
const swapTree = deserializeSwapTree(btcDetails.swapTree);
|
|
4978
|
+
const ephemeralPub = secp256k12.getPublicKey(hex8.decode(swap.ephemeralKey));
|
|
4979
|
+
const musig = tweakMusig(
|
|
4980
|
+
create(hex8.decode(swap.ephemeralKey), [
|
|
4981
|
+
hex8.decode(btcDetails.serverPublicKey),
|
|
4982
|
+
ephemeralPub
|
|
4983
|
+
]),
|
|
4984
|
+
swapTree.tree
|
|
4985
|
+
);
|
|
4986
|
+
const expectedScript = OutScript2.encode(Address2(network).decode(btcDetails.lockupAddress));
|
|
4987
|
+
if (!equalBytes3(p2trScript(musig.aggPubkey), expectedScript))
|
|
4988
|
+
throw new SwapError({ message: "Boltz is trying to scam us (invalid BTC address)" });
|
|
4989
|
+
const boltzXOnly = toXOnly(hex8.decode(btcDetails.serverPublicKey));
|
|
4990
|
+
const userXOnly = toXOnly(ephemeralPub);
|
|
4991
|
+
try {
|
|
4992
|
+
assertChainHtlcLeaves(swapTree, {
|
|
4993
|
+
preimageHash160: ripemd1602(hex8.decode(swap.request.preimageHash)),
|
|
4994
|
+
claimXOnly: to === "ARK" ? boltzXOnly : userXOnly,
|
|
4995
|
+
refundXOnly: to === "ARK" ? userXOnly : boltzXOnly,
|
|
4996
|
+
timeoutBlockHeight: btcDetails.timeoutBlockHeight
|
|
4997
|
+
});
|
|
4998
|
+
} catch (err) {
|
|
4999
|
+
throw new SwapError({
|
|
5000
|
+
message: `Boltz is trying to scam us (invalid BTC HTLC: ${err.message})`
|
|
5001
|
+
});
|
|
5002
|
+
}
|
|
5003
|
+
}
|
|
4940
5004
|
/**
|
|
4941
5005
|
* Renegotiates the quote for an existing chain swap. Convenience wrapper
|
|
4942
5006
|
* over `getSwapQuote` + `acceptSwapQuote` with a safety floor.
|
package/dist/expo/background.cjs
CHANGED
|
@@ -544,20 +544,26 @@ var BoltzSwapProvider = class {
|
|
|
544
544
|
invoiceAmount,
|
|
545
545
|
claimPublicKey,
|
|
546
546
|
preimageHash,
|
|
547
|
-
description
|
|
547
|
+
description,
|
|
548
|
+
descriptionHash
|
|
548
549
|
}) {
|
|
549
550
|
if (claimPublicKey.length != 66) {
|
|
550
551
|
throw new SwapError({
|
|
551
552
|
message: "claimPublicKey must be a compressed public key"
|
|
552
553
|
});
|
|
553
554
|
}
|
|
555
|
+
if (descriptionHash !== void 0 && !/^[0-9a-fA-F]{64}$/.test(descriptionHash)) {
|
|
556
|
+
throw new SwapError({
|
|
557
|
+
message: "descriptionHash must be a 32-byte SHA256 (64 hex chars)"
|
|
558
|
+
});
|
|
559
|
+
}
|
|
554
560
|
const requestBody = {
|
|
555
561
|
from: "BTC",
|
|
556
562
|
to: "ARK",
|
|
557
563
|
invoiceAmount,
|
|
558
564
|
claimPublicKey,
|
|
559
565
|
preimageHash,
|
|
560
|
-
description: description?.trim() || "Send to Arkade address",
|
|
566
|
+
...descriptionHash ? { descriptionHash } : { description: description?.trim() || "Send to Arkade address" },
|
|
561
567
|
...this.referralId ? { referralId: this.referralId } : {}
|
|
562
568
|
};
|
|
563
569
|
const response = await this.request(
|
|
@@ -963,6 +969,7 @@ var BoltzSwapProvider = class {
|
|
|
963
969
|
// src/arkade-swaps.ts
|
|
964
970
|
var import_sdk8 = require("@arkade-os/sdk");
|
|
965
971
|
var import_sha23 = require("@noble/hashes/sha2.js");
|
|
972
|
+
var import_legacy2 = require("@noble/hashes/legacy.js");
|
|
966
973
|
var import_base9 = require("@scure/base");
|
|
967
974
|
var import_secp256k13 = require("@noble/curves/secp256k1.js");
|
|
968
975
|
var import_utils3 = require("@noble/hashes/utils.js");
|
|
@@ -1186,18 +1193,6 @@ var import_base3 = require("@scure/base");
|
|
|
1186
1193
|
var import_btc_signer = require("@scure/btc-signer");
|
|
1187
1194
|
var import_payment = require("@scure/btc-signer/payment.js");
|
|
1188
1195
|
var import_utils2 = require("@scure/btc-signer/utils.js");
|
|
1189
|
-
var REGTEST_NETWORK = {
|
|
1190
|
-
bech32: "bcrt",
|
|
1191
|
-
pubKeyHash: 111,
|
|
1192
|
-
scriptHash: 196,
|
|
1193
|
-
wif: 239
|
|
1194
|
-
};
|
|
1195
|
-
var MUTINYNET_NETWORK = {
|
|
1196
|
-
bech32: "tb",
|
|
1197
|
-
pubKeyHash: 111,
|
|
1198
|
-
scriptHash: 196,
|
|
1199
|
-
wif: 239
|
|
1200
|
-
};
|
|
1201
1196
|
var deserializeLeaf = (leaf) => ({
|
|
1202
1197
|
version: leaf.version,
|
|
1203
1198
|
output: import_base3.hex.decode(leaf.output)
|
|
@@ -1231,6 +1226,19 @@ var deserializeSwapTree = (tree) => {
|
|
|
1231
1226
|
])
|
|
1232
1227
|
};
|
|
1233
1228
|
};
|
|
1229
|
+
var TAPLEAF_V1 = 192;
|
|
1230
|
+
var PUSH_32 = Uint8Array.of(32);
|
|
1231
|
+
var decodeScriptNum = (data) => data instanceof Uint8Array && data.length > 0 ? Number((0, import_btc_signer.ScriptNum)(5, true).decode(data)) : void 0;
|
|
1232
|
+
var assertChainHtlcLeaves = (tree, expected) => {
|
|
1233
|
+
if (tree.claimLeaf.version !== TAPLEAF_V1 || tree.refundLeaf.version !== TAPLEAF_V1)
|
|
1234
|
+
throw new Error("unexpected leaf version");
|
|
1235
|
+
const claim = import_btc_signer.Script.decode(tree.claimLeaf.output);
|
|
1236
|
+
if (claim.length !== 8 || claim[0] !== "SIZE" || !(claim[1] instanceof Uint8Array) || !(0, import_utils2.equalBytes)(claim[1], PUSH_32) || claim[2] !== "EQUALVERIFY" || claim[3] !== "HASH160" || !(claim[4] instanceof Uint8Array) || !(0, import_utils2.equalBytes)(claim[4], expected.preimageHash160) || claim[5] !== "EQUALVERIFY" || !(claim[6] instanceof Uint8Array) || !(0, import_utils2.equalBytes)(claim[6], expected.claimXOnly) || claim[7] !== "CHECKSIG")
|
|
1237
|
+
throw new Error("unexpected claim leaf");
|
|
1238
|
+
const refund = import_btc_signer.Script.decode(tree.refundLeaf.output);
|
|
1239
|
+
if (refund.length !== 4 || !(refund[0] instanceof Uint8Array) || !(0, import_utils2.equalBytes)(refund[0], expected.refundXOnly) || refund[1] !== "CHECKSIGVERIFY" || decodeScriptNum(refund[2]) !== expected.timeoutBlockHeight || refund[3] !== "CHECKLOCKTIMEVERIFY")
|
|
1240
|
+
throw new Error("unexpected refund leaf");
|
|
1241
|
+
};
|
|
1234
1242
|
var taprootHashTree = (tree) => {
|
|
1235
1243
|
if (!Array.isArray(tree)) {
|
|
1236
1244
|
return {
|
|
@@ -1312,6 +1320,12 @@ var decodeInvoice = (invoice) => {
|
|
|
1312
1320
|
expiry: decoded.expiry ?? 3600,
|
|
1313
1321
|
amountSats: Number(millisats / 1000n),
|
|
1314
1322
|
description: decoded.sections.find((s) => s.name === "description")?.value ?? "",
|
|
1323
|
+
// description_hash (BOLT11 `h`) is missing from light-bolt11-decoder's
|
|
1324
|
+
// Section union even though the decoder emits it. Widen just this lookup
|
|
1325
|
+
// rather than patch the library's types (separate repo, out of scope).
|
|
1326
|
+
descriptionHash: decoded.sections.find(
|
|
1327
|
+
(s) => s.name === "description_hash"
|
|
1328
|
+
)?.value ?? "",
|
|
1315
1329
|
paymentHash: decoded.sections.find((s) => s.name === "payment_hash")?.value ?? ""
|
|
1316
1330
|
};
|
|
1317
1331
|
};
|
|
@@ -2921,7 +2935,7 @@ var createVHTLCScript = (args) => {
|
|
|
2921
2935
|
)
|
|
2922
2936
|
});
|
|
2923
2937
|
if (!vhtlcScript.claimScript) throw new Error("Failed to create VHTLC script");
|
|
2924
|
-
const hrp = network
|
|
2938
|
+
const hrp = (0, import_sdk7.getNetwork)(network).hrp;
|
|
2925
2939
|
const vhtlcAddress = vhtlcScript.address(hrp, serverXOnlyPublicKey).encode();
|
|
2926
2940
|
return { vhtlcScript, vhtlcAddress };
|
|
2927
2941
|
};
|
|
@@ -3383,7 +3397,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3383
3397
|
invoiceAmount: args.amount,
|
|
3384
3398
|
claimPublicKey,
|
|
3385
3399
|
preimageHash,
|
|
3386
|
-
...args.description?.trim() ? { description: args.description.trim() } : {}
|
|
3400
|
+
...args.descriptionHash !== void 0 ? { descriptionHash: args.descriptionHash } : args.description?.trim() ? { description: args.description.trim() } : {}
|
|
3387
3401
|
};
|
|
3388
3402
|
const swapResponse = await this.swapProvider.createReverseSwap(swapRequest);
|
|
3389
3403
|
const decodedInvoice = decodeInvoice(swapResponse.invoice);
|
|
@@ -4338,7 +4352,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4338
4352
|
throw new Error(`Swap ${pendingSwap.id}: BTC transaction hex is required`);
|
|
4339
4353
|
const lockupTx = import_btc_signer5.Transaction.fromRaw(import_base9.hex.decode(swapStatus.transaction.hex));
|
|
4340
4354
|
const arkInfo = await this.arkProvider.getInfo();
|
|
4341
|
-
const network =
|
|
4355
|
+
const network = (0, import_sdk8.getNetwork)(arkInfo.network);
|
|
4342
4356
|
const swapTree = deserializeSwapTree(pendingSwap.response.claimDetails.swapTree);
|
|
4343
4357
|
const musig = tweakMusig(
|
|
4344
4358
|
create(import_base9.hex.decode(pendingSwap.ephemeralKey), [
|
|
@@ -4878,8 +4892,56 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4878
4892
|
message: "Boltz is trying to scam us (invalid address)"
|
|
4879
4893
|
});
|
|
4880
4894
|
}
|
|
4895
|
+
this.verifyBtcChainHtlc({ to, swap, arkNetwork: arkInfo.network });
|
|
4881
4896
|
return true;
|
|
4882
4897
|
}
|
|
4898
|
+
/**
|
|
4899
|
+
* Verifies the BTC-side Taproot HTLC of a chain swap before funds are
|
|
4900
|
+
* committed: the lockup address must bind to MuSig2(boltz, user) over
|
|
4901
|
+
* Boltz's leaves, and those leaves must enforce the agreed preimage hash,
|
|
4902
|
+
* direction-specific keys, leaf version, and absolute refund CLTV.
|
|
4903
|
+
*/
|
|
4904
|
+
verifyBtcChainHtlc(args) {
|
|
4905
|
+
const { to, swap, arkNetwork } = args;
|
|
4906
|
+
const btcDetails = to === "ARK" ? swap.response.lockupDetails : swap.response.claimDetails;
|
|
4907
|
+
if (!btcDetails.swapTree)
|
|
4908
|
+
throw new SwapError({ message: `Swap ${swap.id}: missing swap tree in BTC details` });
|
|
4909
|
+
if (!btcDetails.serverPublicKey)
|
|
4910
|
+
throw new SwapError({
|
|
4911
|
+
message: `Swap ${swap.id}: missing server public key in BTC details`
|
|
4912
|
+
});
|
|
4913
|
+
if (typeof btcDetails.timeoutBlockHeight !== "number")
|
|
4914
|
+
throw new SwapError({
|
|
4915
|
+
message: `Swap ${swap.id}: missing timeout block height in BTC details`
|
|
4916
|
+
});
|
|
4917
|
+
const network = (0, import_sdk8.getNetwork)(arkNetwork);
|
|
4918
|
+
const swapTree = deserializeSwapTree(btcDetails.swapTree);
|
|
4919
|
+
const ephemeralPub = import_secp256k13.secp256k1.getPublicKey(import_base9.hex.decode(swap.ephemeralKey));
|
|
4920
|
+
const musig = tweakMusig(
|
|
4921
|
+
create(import_base9.hex.decode(swap.ephemeralKey), [
|
|
4922
|
+
import_base9.hex.decode(btcDetails.serverPublicKey),
|
|
4923
|
+
ephemeralPub
|
|
4924
|
+
]),
|
|
4925
|
+
swapTree.tree
|
|
4926
|
+
);
|
|
4927
|
+
const expectedScript = import_btc_signer5.OutScript.encode((0, import_btc_signer5.Address)(network).decode(btcDetails.lockupAddress));
|
|
4928
|
+
if (!(0, import_utils4.equalBytes)(p2trScript(musig.aggPubkey), expectedScript))
|
|
4929
|
+
throw new SwapError({ message: "Boltz is trying to scam us (invalid BTC address)" });
|
|
4930
|
+
const boltzXOnly = toXOnly(import_base9.hex.decode(btcDetails.serverPublicKey));
|
|
4931
|
+
const userXOnly = toXOnly(ephemeralPub);
|
|
4932
|
+
try {
|
|
4933
|
+
assertChainHtlcLeaves(swapTree, {
|
|
4934
|
+
preimageHash160: (0, import_legacy2.ripemd160)(import_base9.hex.decode(swap.request.preimageHash)),
|
|
4935
|
+
claimXOnly: to === "ARK" ? boltzXOnly : userXOnly,
|
|
4936
|
+
refundXOnly: to === "ARK" ? userXOnly : boltzXOnly,
|
|
4937
|
+
timeoutBlockHeight: btcDetails.timeoutBlockHeight
|
|
4938
|
+
});
|
|
4939
|
+
} catch (err) {
|
|
4940
|
+
throw new SwapError({
|
|
4941
|
+
message: `Boltz is trying to scam us (invalid BTC HTLC: ${err.message})`
|
|
4942
|
+
});
|
|
4943
|
+
}
|
|
4944
|
+
}
|
|
4883
4945
|
/**
|
|
4884
4946
|
* Renegotiates the quote for an existing chain swap. Convenience wrapper
|
|
4885
4947
|
* over `getSwapQuote` + `acceptSwapQuote` with a safety floor.
|
|
@@ -5537,14 +5599,19 @@ function createBackgroundWalletShim(args) {
|
|
|
5537
5599
|
getVtxos: async () => notImplemented("getVtxos"),
|
|
5538
5600
|
getBoardingUtxos: async () => notImplemented("getBoardingUtxos"),
|
|
5539
5601
|
getTransactionHistory: async () => notImplemented("getTransactionHistory"),
|
|
5602
|
+
getActivityHistory: async () => notImplemented("getActivityHistory"),
|
|
5540
5603
|
getContractManager: async () => notImplemented("getContractManager"),
|
|
5541
5604
|
getDelegateManager: async () => notImplemented("getDelegateManager"),
|
|
5542
5605
|
getDelegatorManager: async () => notImplemented("getDelegatorManager"),
|
|
5543
5606
|
sendBitcoin: async () => notImplemented("sendBitcoin"),
|
|
5544
5607
|
send: async () => notImplemented("send"),
|
|
5545
5608
|
settle: async () => notImplemented("settle"),
|
|
5609
|
+
clear: async () => notImplemented("clear"),
|
|
5546
5610
|
assetManager: new Proxy({}, {
|
|
5547
5611
|
get: () => notImplemented("assetManager")
|
|
5612
|
+
}),
|
|
5613
|
+
activity: new Proxy({}, {
|
|
5614
|
+
get: () => notImplemented("activity")
|
|
5548
5615
|
})
|
|
5549
5616
|
};
|
|
5550
5617
|
}
|
|
@@ -5566,13 +5633,13 @@ function defineExpoSwapBackgroundTask(taskName, options) {
|
|
|
5566
5633
|
const wallet = createBackgroundWalletShim({
|
|
5567
5634
|
identity,
|
|
5568
5635
|
getAddress: async () => {
|
|
5569
|
-
const { ArkAddress: ArkAddress3 } = await import("@arkade-os/sdk");
|
|
5636
|
+
const { ArkAddress: ArkAddress3, getNetwork: getNetwork3 } = await import("@arkade-os/sdk");
|
|
5570
5637
|
const { hex: hex9 } = await import("@scure/base");
|
|
5571
5638
|
const info = await arkProvider.getInfo();
|
|
5572
5639
|
const pubkey = await identity.xOnlyPublicKey();
|
|
5573
5640
|
const serverPubKey = hex9.decode(info.signerPubkey);
|
|
5574
5641
|
const xOnlyServerPubKey = serverPubKey.length === 33 ? serverPubKey.slice(1) : serverPubKey;
|
|
5575
|
-
const hrp = info.network
|
|
5642
|
+
const hrp = getNetwork3(info.network).hrp;
|
|
5576
5643
|
return new ArkAddress3(xOnlyServerPubKey, pubkey, hrp).encode();
|
|
5577
5644
|
}
|
|
5578
5645
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { D as DefineSwapBackgroundTaskOptions } from '../swapsPollProcessor-
|
|
2
|
-
export { P as PersistedSwapBackgroundConfig, S as SWAP_POLL_TASK_TYPE, a as SwapTaskDependencies, s as swapsPollProcessor } from '../swapsPollProcessor-
|
|
1
|
+
import { D as DefineSwapBackgroundTaskOptions } from '../swapsPollProcessor-B98F6MQF.cjs';
|
|
2
|
+
export { P as PersistedSwapBackgroundConfig, S as SWAP_POLL_TASK_TYPE, a as SwapTaskDependencies, s as swapsPollProcessor } from '../swapsPollProcessor-B98F6MQF.cjs';
|
|
3
3
|
import '@arkade-os/sdk/worker/expo';
|
|
4
4
|
import '@arkade-os/sdk';
|
|
5
|
-
import '../types-
|
|
5
|
+
import '../types-CS62-oEy.cjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Define the Expo background task handler for swap polling.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { D as DefineSwapBackgroundTaskOptions } from '../swapsPollProcessor-
|
|
2
|
-
export { P as PersistedSwapBackgroundConfig, S as SWAP_POLL_TASK_TYPE, a as SwapTaskDependencies, s as swapsPollProcessor } from '../swapsPollProcessor-
|
|
1
|
+
import { D as DefineSwapBackgroundTaskOptions } from '../swapsPollProcessor-Ov-wp17v.js';
|
|
2
|
+
export { P as PersistedSwapBackgroundConfig, S as SWAP_POLL_TASK_TYPE, a as SwapTaskDependencies, s as swapsPollProcessor } from '../swapsPollProcessor-Ov-wp17v.js';
|
|
3
3
|
import '@arkade-os/sdk/worker/expo';
|
|
4
4
|
import '@arkade-os/sdk';
|
|
5
|
-
import '../types-
|
|
5
|
+
import '../types-CS62-oEy.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Define the Expo background task handler for swap polling.
|
package/dist/expo/background.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SWAP_POLL_TASK_TYPE,
|
|
3
3
|
swapsPollProcessor
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-UJXW5JBT.js";
|
|
5
5
|
import {
|
|
6
6
|
BoltzSwapProvider
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-GXO2EB6C.js";
|
|
8
8
|
import "../chunk-SJQJQO7P.js";
|
|
9
9
|
|
|
10
10
|
// src/expo/background.ts
|
|
@@ -27,14 +27,19 @@ function createBackgroundWalletShim(args) {
|
|
|
27
27
|
getVtxos: async () => notImplemented("getVtxos"),
|
|
28
28
|
getBoardingUtxos: async () => notImplemented("getBoardingUtxos"),
|
|
29
29
|
getTransactionHistory: async () => notImplemented("getTransactionHistory"),
|
|
30
|
+
getActivityHistory: async () => notImplemented("getActivityHistory"),
|
|
30
31
|
getContractManager: async () => notImplemented("getContractManager"),
|
|
31
32
|
getDelegateManager: async () => notImplemented("getDelegateManager"),
|
|
32
33
|
getDelegatorManager: async () => notImplemented("getDelegatorManager"),
|
|
33
34
|
sendBitcoin: async () => notImplemented("sendBitcoin"),
|
|
34
35
|
send: async () => notImplemented("send"),
|
|
35
36
|
settle: async () => notImplemented("settle"),
|
|
37
|
+
clear: async () => notImplemented("clear"),
|
|
36
38
|
assetManager: new Proxy({}, {
|
|
37
39
|
get: () => notImplemented("assetManager")
|
|
40
|
+
}),
|
|
41
|
+
activity: new Proxy({}, {
|
|
42
|
+
get: () => notImplemented("activity")
|
|
38
43
|
})
|
|
39
44
|
};
|
|
40
45
|
}
|
|
@@ -56,13 +61,13 @@ function defineExpoSwapBackgroundTask(taskName, options) {
|
|
|
56
61
|
const wallet = createBackgroundWalletShim({
|
|
57
62
|
identity,
|
|
58
63
|
getAddress: async () => {
|
|
59
|
-
const { ArkAddress } = await import("@arkade-os/sdk");
|
|
64
|
+
const { ArkAddress, getNetwork } = await import("@arkade-os/sdk");
|
|
60
65
|
const { hex } = await import("@scure/base");
|
|
61
66
|
const info = await arkProvider.getInfo();
|
|
62
67
|
const pubkey = await identity.xOnlyPublicKey();
|
|
63
68
|
const serverPubKey = hex.decode(info.signerPubkey);
|
|
64
69
|
const xOnlyServerPubKey = serverPubKey.length === 33 ? serverPubKey.slice(1) : serverPubKey;
|
|
65
|
-
const hrp = info.network
|
|
70
|
+
const hrp = getNetwork(info.network).hrp;
|
|
66
71
|
return new ArkAddress(xOnlyServerPubKey, pubkey, hrp).encode();
|
|
67
72
|
}
|
|
68
73
|
});
|
package/dist/expo/index.cjs
CHANGED
|
@@ -535,20 +535,26 @@ var BoltzSwapProvider = class {
|
|
|
535
535
|
invoiceAmount,
|
|
536
536
|
claimPublicKey,
|
|
537
537
|
preimageHash,
|
|
538
|
-
description
|
|
538
|
+
description,
|
|
539
|
+
descriptionHash
|
|
539
540
|
}) {
|
|
540
541
|
if (claimPublicKey.length != 66) {
|
|
541
542
|
throw new SwapError({
|
|
542
543
|
message: "claimPublicKey must be a compressed public key"
|
|
543
544
|
});
|
|
544
545
|
}
|
|
546
|
+
if (descriptionHash !== void 0 && !/^[0-9a-fA-F]{64}$/.test(descriptionHash)) {
|
|
547
|
+
throw new SwapError({
|
|
548
|
+
message: "descriptionHash must be a 32-byte SHA256 (64 hex chars)"
|
|
549
|
+
});
|
|
550
|
+
}
|
|
545
551
|
const requestBody = {
|
|
546
552
|
from: "BTC",
|
|
547
553
|
to: "ARK",
|
|
548
554
|
invoiceAmount,
|
|
549
555
|
claimPublicKey,
|
|
550
556
|
preimageHash,
|
|
551
|
-
description: description?.trim() || "Send to Arkade address",
|
|
557
|
+
...descriptionHash ? { descriptionHash } : { description: description?.trim() || "Send to Arkade address" },
|
|
552
558
|
...this.referralId ? { referralId: this.referralId } : {}
|
|
553
559
|
};
|
|
554
560
|
const response = await this.request(
|
|
@@ -953,6 +959,7 @@ var BoltzSwapProvider = class {
|
|
|
953
959
|
|
|
954
960
|
// src/arkade-swaps.ts
|
|
955
961
|
var import_sha23 = require("@noble/hashes/sha2.js");
|
|
962
|
+
var import_legacy2 = require("@noble/hashes/legacy.js");
|
|
956
963
|
var import_base9 = require("@scure/base");
|
|
957
964
|
var import_secp256k13 = require("@noble/curves/secp256k1.js");
|
|
958
965
|
var import_utils3 = require("@noble/hashes/utils.js");
|
|
@@ -1176,18 +1183,6 @@ var import_base3 = require("@scure/base");
|
|
|
1176
1183
|
var import_btc_signer = require("@scure/btc-signer");
|
|
1177
1184
|
var import_payment = require("@scure/btc-signer/payment.js");
|
|
1178
1185
|
var import_utils2 = require("@scure/btc-signer/utils.js");
|
|
1179
|
-
var REGTEST_NETWORK = {
|
|
1180
|
-
bech32: "bcrt",
|
|
1181
|
-
pubKeyHash: 111,
|
|
1182
|
-
scriptHash: 196,
|
|
1183
|
-
wif: 239
|
|
1184
|
-
};
|
|
1185
|
-
var MUTINYNET_NETWORK = {
|
|
1186
|
-
bech32: "tb",
|
|
1187
|
-
pubKeyHash: 111,
|
|
1188
|
-
scriptHash: 196,
|
|
1189
|
-
wif: 239
|
|
1190
|
-
};
|
|
1191
1186
|
var deserializeLeaf = (leaf) => ({
|
|
1192
1187
|
version: leaf.version,
|
|
1193
1188
|
output: import_base3.hex.decode(leaf.output)
|
|
@@ -1221,6 +1216,19 @@ var deserializeSwapTree = (tree) => {
|
|
|
1221
1216
|
])
|
|
1222
1217
|
};
|
|
1223
1218
|
};
|
|
1219
|
+
var TAPLEAF_V1 = 192;
|
|
1220
|
+
var PUSH_32 = Uint8Array.of(32);
|
|
1221
|
+
var decodeScriptNum = (data) => data instanceof Uint8Array && data.length > 0 ? Number((0, import_btc_signer.ScriptNum)(5, true).decode(data)) : void 0;
|
|
1222
|
+
var assertChainHtlcLeaves = (tree, expected) => {
|
|
1223
|
+
if (tree.claimLeaf.version !== TAPLEAF_V1 || tree.refundLeaf.version !== TAPLEAF_V1)
|
|
1224
|
+
throw new Error("unexpected leaf version");
|
|
1225
|
+
const claim = import_btc_signer.Script.decode(tree.claimLeaf.output);
|
|
1226
|
+
if (claim.length !== 8 || claim[0] !== "SIZE" || !(claim[1] instanceof Uint8Array) || !(0, import_utils2.equalBytes)(claim[1], PUSH_32) || claim[2] !== "EQUALVERIFY" || claim[3] !== "HASH160" || !(claim[4] instanceof Uint8Array) || !(0, import_utils2.equalBytes)(claim[4], expected.preimageHash160) || claim[5] !== "EQUALVERIFY" || !(claim[6] instanceof Uint8Array) || !(0, import_utils2.equalBytes)(claim[6], expected.claimXOnly) || claim[7] !== "CHECKSIG")
|
|
1227
|
+
throw new Error("unexpected claim leaf");
|
|
1228
|
+
const refund = import_btc_signer.Script.decode(tree.refundLeaf.output);
|
|
1229
|
+
if (refund.length !== 4 || !(refund[0] instanceof Uint8Array) || !(0, import_utils2.equalBytes)(refund[0], expected.refundXOnly) || refund[1] !== "CHECKSIGVERIFY" || decodeScriptNum(refund[2]) !== expected.timeoutBlockHeight || refund[3] !== "CHECKLOCKTIMEVERIFY")
|
|
1230
|
+
throw new Error("unexpected refund leaf");
|
|
1231
|
+
};
|
|
1224
1232
|
var taprootHashTree = (tree) => {
|
|
1225
1233
|
if (!Array.isArray(tree)) {
|
|
1226
1234
|
return {
|
|
@@ -1302,6 +1310,12 @@ var decodeInvoice = (invoice) => {
|
|
|
1302
1310
|
expiry: decoded.expiry ?? 3600,
|
|
1303
1311
|
amountSats: Number(millisats / 1000n),
|
|
1304
1312
|
description: decoded.sections.find((s) => s.name === "description")?.value ?? "",
|
|
1313
|
+
// description_hash (BOLT11 `h`) is missing from light-bolt11-decoder's
|
|
1314
|
+
// Section union even though the decoder emits it. Widen just this lookup
|
|
1315
|
+
// rather than patch the library's types (separate repo, out of scope).
|
|
1316
|
+
descriptionHash: decoded.sections.find(
|
|
1317
|
+
(s) => s.name === "description_hash"
|
|
1318
|
+
)?.value ?? "",
|
|
1305
1319
|
paymentHash: decoded.sections.find((s) => s.name === "payment_hash")?.value ?? ""
|
|
1306
1320
|
};
|
|
1307
1321
|
};
|
|
@@ -2911,7 +2925,7 @@ var createVHTLCScript = (args) => {
|
|
|
2911
2925
|
)
|
|
2912
2926
|
});
|
|
2913
2927
|
if (!vhtlcScript.claimScript) throw new Error("Failed to create VHTLC script");
|
|
2914
|
-
const hrp = network
|
|
2928
|
+
const hrp = (0, import_sdk7.getNetwork)(network).hrp;
|
|
2915
2929
|
const vhtlcAddress = vhtlcScript.address(hrp, serverXOnlyPublicKey).encode();
|
|
2916
2930
|
return { vhtlcScript, vhtlcAddress };
|
|
2917
2931
|
};
|
|
@@ -3373,7 +3387,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3373
3387
|
invoiceAmount: args.amount,
|
|
3374
3388
|
claimPublicKey,
|
|
3375
3389
|
preimageHash,
|
|
3376
|
-
...args.description?.trim() ? { description: args.description.trim() } : {}
|
|
3390
|
+
...args.descriptionHash !== void 0 ? { descriptionHash: args.descriptionHash } : args.description?.trim() ? { description: args.description.trim() } : {}
|
|
3377
3391
|
};
|
|
3378
3392
|
const swapResponse = await this.swapProvider.createReverseSwap(swapRequest);
|
|
3379
3393
|
const decodedInvoice = decodeInvoice(swapResponse.invoice);
|
|
@@ -4328,7 +4342,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4328
4342
|
throw new Error(`Swap ${pendingSwap.id}: BTC transaction hex is required`);
|
|
4329
4343
|
const lockupTx = import_btc_signer5.Transaction.fromRaw(import_base9.hex.decode(swapStatus.transaction.hex));
|
|
4330
4344
|
const arkInfo = await this.arkProvider.getInfo();
|
|
4331
|
-
const network =
|
|
4345
|
+
const network = (0, import_sdk8.getNetwork)(arkInfo.network);
|
|
4332
4346
|
const swapTree = deserializeSwapTree(pendingSwap.response.claimDetails.swapTree);
|
|
4333
4347
|
const musig = tweakMusig(
|
|
4334
4348
|
create(import_base9.hex.decode(pendingSwap.ephemeralKey), [
|
|
@@ -4868,8 +4882,56 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4868
4882
|
message: "Boltz is trying to scam us (invalid address)"
|
|
4869
4883
|
});
|
|
4870
4884
|
}
|
|
4885
|
+
this.verifyBtcChainHtlc({ to, swap, arkNetwork: arkInfo.network });
|
|
4871
4886
|
return true;
|
|
4872
4887
|
}
|
|
4888
|
+
/**
|
|
4889
|
+
* Verifies the BTC-side Taproot HTLC of a chain swap before funds are
|
|
4890
|
+
* committed: the lockup address must bind to MuSig2(boltz, user) over
|
|
4891
|
+
* Boltz's leaves, and those leaves must enforce the agreed preimage hash,
|
|
4892
|
+
* direction-specific keys, leaf version, and absolute refund CLTV.
|
|
4893
|
+
*/
|
|
4894
|
+
verifyBtcChainHtlc(args) {
|
|
4895
|
+
const { to, swap, arkNetwork } = args;
|
|
4896
|
+
const btcDetails = to === "ARK" ? swap.response.lockupDetails : swap.response.claimDetails;
|
|
4897
|
+
if (!btcDetails.swapTree)
|
|
4898
|
+
throw new SwapError({ message: `Swap ${swap.id}: missing swap tree in BTC details` });
|
|
4899
|
+
if (!btcDetails.serverPublicKey)
|
|
4900
|
+
throw new SwapError({
|
|
4901
|
+
message: `Swap ${swap.id}: missing server public key in BTC details`
|
|
4902
|
+
});
|
|
4903
|
+
if (typeof btcDetails.timeoutBlockHeight !== "number")
|
|
4904
|
+
throw new SwapError({
|
|
4905
|
+
message: `Swap ${swap.id}: missing timeout block height in BTC details`
|
|
4906
|
+
});
|
|
4907
|
+
const network = (0, import_sdk8.getNetwork)(arkNetwork);
|
|
4908
|
+
const swapTree = deserializeSwapTree(btcDetails.swapTree);
|
|
4909
|
+
const ephemeralPub = import_secp256k13.secp256k1.getPublicKey(import_base9.hex.decode(swap.ephemeralKey));
|
|
4910
|
+
const musig = tweakMusig(
|
|
4911
|
+
create(import_base9.hex.decode(swap.ephemeralKey), [
|
|
4912
|
+
import_base9.hex.decode(btcDetails.serverPublicKey),
|
|
4913
|
+
ephemeralPub
|
|
4914
|
+
]),
|
|
4915
|
+
swapTree.tree
|
|
4916
|
+
);
|
|
4917
|
+
const expectedScript = import_btc_signer5.OutScript.encode((0, import_btc_signer5.Address)(network).decode(btcDetails.lockupAddress));
|
|
4918
|
+
if (!(0, import_utils4.equalBytes)(p2trScript(musig.aggPubkey), expectedScript))
|
|
4919
|
+
throw new SwapError({ message: "Boltz is trying to scam us (invalid BTC address)" });
|
|
4920
|
+
const boltzXOnly = toXOnly(import_base9.hex.decode(btcDetails.serverPublicKey));
|
|
4921
|
+
const userXOnly = toXOnly(ephemeralPub);
|
|
4922
|
+
try {
|
|
4923
|
+
assertChainHtlcLeaves(swapTree, {
|
|
4924
|
+
preimageHash160: (0, import_legacy2.ripemd160)(import_base9.hex.decode(swap.request.preimageHash)),
|
|
4925
|
+
claimXOnly: to === "ARK" ? boltzXOnly : userXOnly,
|
|
4926
|
+
refundXOnly: to === "ARK" ? userXOnly : boltzXOnly,
|
|
4927
|
+
timeoutBlockHeight: btcDetails.timeoutBlockHeight
|
|
4928
|
+
});
|
|
4929
|
+
} catch (err) {
|
|
4930
|
+
throw new SwapError({
|
|
4931
|
+
message: `Boltz is trying to scam us (invalid BTC HTLC: ${err.message})`
|
|
4932
|
+
});
|
|
4933
|
+
}
|
|
4934
|
+
}
|
|
4873
4935
|
/**
|
|
4874
4936
|
* Renegotiates the quote for an existing chain swap. Convenience wrapper
|
|
4875
4937
|
* over `getSwapQuote` + `acceptSwapQuote` with a safety floor.
|
package/dist/expo/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { I as IArkadeSwaps, A as ArkadeSwaps, Q as QuoteSwapOptions, V as VhtlcTimeouts } from '../arkade-swaps-
|
|
2
|
-
import { n as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, S as SendLightningPaymentRequest, o as SendLightningPaymentResponse, O as OptimisticSendLightningPaymentResponse, c as BoltzSubmarineSwap, b as BoltzReverseSwap, f as SubmarineRefundOutcome, g as SubmarineRecoveryInfo, h as SubmarineRecoveryResult, F as FeesResponse, a as BoltzChainSwap, j as ArkToBtcResponse, l as ChainArkRefundOutcome, k as BtcToArkResponse, d as Chain, i as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from '../types-
|
|
3
|
-
import { E as ExpoArkadeSwapsConfig } from '../swapsPollProcessor-
|
|
4
|
-
export { D as DefineSwapBackgroundTaskOptions, b as ExpoArkadeLightningConfig, c as ExpoSwapBackgroundConfig, P as PersistedSwapBackgroundConfig, S as SWAP_POLL_TASK_TYPE, a as SwapTaskDependencies } from '../swapsPollProcessor-
|
|
1
|
+
import { I as IArkadeSwaps, A as ArkadeSwaps, Q as QuoteSwapOptions, V as VhtlcTimeouts } from '../arkade-swaps-D-L0_0Ri.cjs';
|
|
2
|
+
import { n as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, S as SendLightningPaymentRequest, o as SendLightningPaymentResponse, O as OptimisticSendLightningPaymentResponse, c as BoltzSubmarineSwap, b as BoltzReverseSwap, f as SubmarineRefundOutcome, g as SubmarineRecoveryInfo, h as SubmarineRecoveryResult, F as FeesResponse, a as BoltzChainSwap, j as ArkToBtcResponse, l as ChainArkRefundOutcome, k as BtcToArkResponse, d as Chain, i as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from '../types-CS62-oEy.cjs';
|
|
3
|
+
import { E as ExpoArkadeSwapsConfig } from '../swapsPollProcessor-B98F6MQF.cjs';
|
|
4
|
+
export { D as DefineSwapBackgroundTaskOptions, b as ExpoArkadeLightningConfig, c as ExpoSwapBackgroundConfig, P as PersistedSwapBackgroundConfig, S as SWAP_POLL_TASK_TYPE, a as SwapTaskDependencies } from '../swapsPollProcessor-B98F6MQF.cjs';
|
|
5
5
|
import { ArkInfo, Identity, ArkTxInput, VHTLC } from '@arkade-os/sdk';
|
|
6
6
|
import { TransactionOutput } from '@scure/btc-signer/psbt.js';
|
|
7
7
|
import '@arkade-os/sdk/worker/expo';
|
package/dist/expo/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { I as IArkadeSwaps, A as ArkadeSwaps, Q as QuoteSwapOptions, V as VhtlcTimeouts } from '../arkade-swaps-
|
|
2
|
-
import { n as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, S as SendLightningPaymentRequest, o as SendLightningPaymentResponse, O as OptimisticSendLightningPaymentResponse, c as BoltzSubmarineSwap, b as BoltzReverseSwap, f as SubmarineRefundOutcome, g as SubmarineRecoveryInfo, h as SubmarineRecoveryResult, F as FeesResponse, a as BoltzChainSwap, j as ArkToBtcResponse, l as ChainArkRefundOutcome, k as BtcToArkResponse, d as Chain, i as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from '../types-
|
|
3
|
-
import { E as ExpoArkadeSwapsConfig } from '../swapsPollProcessor-
|
|
4
|
-
export { D as DefineSwapBackgroundTaskOptions, b as ExpoArkadeLightningConfig, c as ExpoSwapBackgroundConfig, P as PersistedSwapBackgroundConfig, S as SWAP_POLL_TASK_TYPE, a as SwapTaskDependencies } from '../swapsPollProcessor-
|
|
1
|
+
import { I as IArkadeSwaps, A as ArkadeSwaps, Q as QuoteSwapOptions, V as VhtlcTimeouts } from '../arkade-swaps-fmdCFjif.js';
|
|
2
|
+
import { n as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, S as SendLightningPaymentRequest, o as SendLightningPaymentResponse, O as OptimisticSendLightningPaymentResponse, c as BoltzSubmarineSwap, b as BoltzReverseSwap, f as SubmarineRefundOutcome, g as SubmarineRecoveryInfo, h as SubmarineRecoveryResult, F as FeesResponse, a as BoltzChainSwap, j as ArkToBtcResponse, l as ChainArkRefundOutcome, k as BtcToArkResponse, d as Chain, i as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from '../types-CS62-oEy.js';
|
|
3
|
+
import { E as ExpoArkadeSwapsConfig } from '../swapsPollProcessor-Ov-wp17v.js';
|
|
4
|
+
export { D as DefineSwapBackgroundTaskOptions, b as ExpoArkadeLightningConfig, c as ExpoSwapBackgroundConfig, P as PersistedSwapBackgroundConfig, S as SWAP_POLL_TASK_TYPE, a as SwapTaskDependencies } from '../swapsPollProcessor-Ov-wp17v.js';
|
|
5
5
|
import { ArkInfo, Identity, ArkTxInput, VHTLC } from '@arkade-os/sdk';
|
|
6
6
|
import { TransactionOutput } from '@scure/btc-signer/psbt.js';
|
|
7
7
|
import '@arkade-os/sdk/worker/expo';
|
package/dist/expo/index.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -95,7 +95,7 @@ __export(index_exports, {
|
|
|
95
95
|
module.exports = __toCommonJS(index_exports);
|
|
96
96
|
|
|
97
97
|
// package.json
|
|
98
|
-
var version = "0.3.
|
|
98
|
+
var version = "0.3.46";
|
|
99
99
|
|
|
100
100
|
// src/errors.ts
|
|
101
101
|
var SwapError = class extends Error {
|
|
@@ -667,20 +667,26 @@ var BoltzSwapProvider = class {
|
|
|
667
667
|
invoiceAmount,
|
|
668
668
|
claimPublicKey,
|
|
669
669
|
preimageHash,
|
|
670
|
-
description
|
|
670
|
+
description,
|
|
671
|
+
descriptionHash
|
|
671
672
|
}) {
|
|
672
673
|
if (claimPublicKey.length != 66) {
|
|
673
674
|
throw new SwapError({
|
|
674
675
|
message: "claimPublicKey must be a compressed public key"
|
|
675
676
|
});
|
|
676
677
|
}
|
|
678
|
+
if (descriptionHash !== void 0 && !/^[0-9a-fA-F]{64}$/.test(descriptionHash)) {
|
|
679
|
+
throw new SwapError({
|
|
680
|
+
message: "descriptionHash must be a 32-byte SHA256 (64 hex chars)"
|
|
681
|
+
});
|
|
682
|
+
}
|
|
677
683
|
const requestBody = {
|
|
678
684
|
from: "BTC",
|
|
679
685
|
to: "ARK",
|
|
680
686
|
invoiceAmount,
|
|
681
687
|
claimPublicKey,
|
|
682
688
|
preimageHash,
|
|
683
|
-
description: description?.trim() || "Send to Arkade address",
|
|
689
|
+
...descriptionHash ? { descriptionHash } : { description: description?.trim() || "Send to Arkade address" },
|
|
684
690
|
...this.referralId ? { referralId: this.referralId } : {}
|
|
685
691
|
};
|
|
686
692
|
const response = await this.request(
|
|
@@ -1085,6 +1091,7 @@ var BoltzSwapProvider = class {
|
|
|
1085
1091
|
|
|
1086
1092
|
// src/arkade-swaps.ts
|
|
1087
1093
|
var import_sha23 = require("@noble/hashes/sha2.js");
|
|
1094
|
+
var import_legacy2 = require("@noble/hashes/legacy.js");
|
|
1088
1095
|
var import_base9 = require("@scure/base");
|
|
1089
1096
|
var import_secp256k13 = require("@noble/curves/secp256k1.js");
|
|
1090
1097
|
var import_utils3 = require("@noble/hashes/utils.js");
|
|
@@ -1308,18 +1315,6 @@ var import_base3 = require("@scure/base");
|
|
|
1308
1315
|
var import_btc_signer = require("@scure/btc-signer");
|
|
1309
1316
|
var import_payment = require("@scure/btc-signer/payment.js");
|
|
1310
1317
|
var import_utils2 = require("@scure/btc-signer/utils.js");
|
|
1311
|
-
var REGTEST_NETWORK = {
|
|
1312
|
-
bech32: "bcrt",
|
|
1313
|
-
pubKeyHash: 111,
|
|
1314
|
-
scriptHash: 196,
|
|
1315
|
-
wif: 239
|
|
1316
|
-
};
|
|
1317
|
-
var MUTINYNET_NETWORK = {
|
|
1318
|
-
bech32: "tb",
|
|
1319
|
-
pubKeyHash: 111,
|
|
1320
|
-
scriptHash: 196,
|
|
1321
|
-
wif: 239
|
|
1322
|
-
};
|
|
1323
1318
|
var deserializeLeaf = (leaf) => ({
|
|
1324
1319
|
version: leaf.version,
|
|
1325
1320
|
output: import_base3.hex.decode(leaf.output)
|
|
@@ -1353,6 +1348,19 @@ var deserializeSwapTree = (tree) => {
|
|
|
1353
1348
|
])
|
|
1354
1349
|
};
|
|
1355
1350
|
};
|
|
1351
|
+
var TAPLEAF_V1 = 192;
|
|
1352
|
+
var PUSH_32 = Uint8Array.of(32);
|
|
1353
|
+
var decodeScriptNum = (data) => data instanceof Uint8Array && data.length > 0 ? Number((0, import_btc_signer.ScriptNum)(5, true).decode(data)) : void 0;
|
|
1354
|
+
var assertChainHtlcLeaves = (tree, expected) => {
|
|
1355
|
+
if (tree.claimLeaf.version !== TAPLEAF_V1 || tree.refundLeaf.version !== TAPLEAF_V1)
|
|
1356
|
+
throw new Error("unexpected leaf version");
|
|
1357
|
+
const claim = import_btc_signer.Script.decode(tree.claimLeaf.output);
|
|
1358
|
+
if (claim.length !== 8 || claim[0] !== "SIZE" || !(claim[1] instanceof Uint8Array) || !(0, import_utils2.equalBytes)(claim[1], PUSH_32) || claim[2] !== "EQUALVERIFY" || claim[3] !== "HASH160" || !(claim[4] instanceof Uint8Array) || !(0, import_utils2.equalBytes)(claim[4], expected.preimageHash160) || claim[5] !== "EQUALVERIFY" || !(claim[6] instanceof Uint8Array) || !(0, import_utils2.equalBytes)(claim[6], expected.claimXOnly) || claim[7] !== "CHECKSIG")
|
|
1359
|
+
throw new Error("unexpected claim leaf");
|
|
1360
|
+
const refund = import_btc_signer.Script.decode(tree.refundLeaf.output);
|
|
1361
|
+
if (refund.length !== 4 || !(refund[0] instanceof Uint8Array) || !(0, import_utils2.equalBytes)(refund[0], expected.refundXOnly) || refund[1] !== "CHECKSIGVERIFY" || decodeScriptNum(refund[2]) !== expected.timeoutBlockHeight || refund[3] !== "CHECKLOCKTIMEVERIFY")
|
|
1362
|
+
throw new Error("unexpected refund leaf");
|
|
1363
|
+
};
|
|
1356
1364
|
var taprootHashTree = (tree) => {
|
|
1357
1365
|
if (!Array.isArray(tree)) {
|
|
1358
1366
|
return {
|
|
@@ -1434,6 +1442,12 @@ var decodeInvoice = (invoice) => {
|
|
|
1434
1442
|
expiry: decoded.expiry ?? 3600,
|
|
1435
1443
|
amountSats: Number(millisats / 1000n),
|
|
1436
1444
|
description: decoded.sections.find((s) => s.name === "description")?.value ?? "",
|
|
1445
|
+
// description_hash (BOLT11 `h`) is missing from light-bolt11-decoder's
|
|
1446
|
+
// Section union even though the decoder emits it. Widen just this lookup
|
|
1447
|
+
// rather than patch the library's types (separate repo, out of scope).
|
|
1448
|
+
descriptionHash: decoded.sections.find(
|
|
1449
|
+
(s) => s.name === "description_hash"
|
|
1450
|
+
)?.value ?? "",
|
|
1437
1451
|
paymentHash: decoded.sections.find((s) => s.name === "payment_hash")?.value ?? ""
|
|
1438
1452
|
};
|
|
1439
1453
|
};
|
|
@@ -3064,7 +3078,7 @@ var createVHTLCScript = (args) => {
|
|
|
3064
3078
|
)
|
|
3065
3079
|
});
|
|
3066
3080
|
if (!vhtlcScript.claimScript) throw new Error("Failed to create VHTLC script");
|
|
3067
|
-
const hrp = network
|
|
3081
|
+
const hrp = (0, import_sdk7.getNetwork)(network).hrp;
|
|
3068
3082
|
const vhtlcAddress = vhtlcScript.address(hrp, serverXOnlyPublicKey).encode();
|
|
3069
3083
|
return { vhtlcScript, vhtlcAddress };
|
|
3070
3084
|
};
|
|
@@ -3526,7 +3540,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3526
3540
|
invoiceAmount: args.amount,
|
|
3527
3541
|
claimPublicKey,
|
|
3528
3542
|
preimageHash,
|
|
3529
|
-
...args.description?.trim() ? { description: args.description.trim() } : {}
|
|
3543
|
+
...args.descriptionHash !== void 0 ? { descriptionHash: args.descriptionHash } : args.description?.trim() ? { description: args.description.trim() } : {}
|
|
3530
3544
|
};
|
|
3531
3545
|
const swapResponse = await this.swapProvider.createReverseSwap(swapRequest);
|
|
3532
3546
|
const decodedInvoice = decodeInvoice(swapResponse.invoice);
|
|
@@ -4481,7 +4495,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4481
4495
|
throw new Error(`Swap ${pendingSwap.id}: BTC transaction hex is required`);
|
|
4482
4496
|
const lockupTx = import_btc_signer5.Transaction.fromRaw(import_base9.hex.decode(swapStatus.transaction.hex));
|
|
4483
4497
|
const arkInfo = await this.arkProvider.getInfo();
|
|
4484
|
-
const network =
|
|
4498
|
+
const network = (0, import_sdk8.getNetwork)(arkInfo.network);
|
|
4485
4499
|
const swapTree = deserializeSwapTree(pendingSwap.response.claimDetails.swapTree);
|
|
4486
4500
|
const musig = tweakMusig(
|
|
4487
4501
|
create(import_base9.hex.decode(pendingSwap.ephemeralKey), [
|
|
@@ -5021,8 +5035,56 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
5021
5035
|
message: "Boltz is trying to scam us (invalid address)"
|
|
5022
5036
|
});
|
|
5023
5037
|
}
|
|
5038
|
+
this.verifyBtcChainHtlc({ to, swap, arkNetwork: arkInfo.network });
|
|
5024
5039
|
return true;
|
|
5025
5040
|
}
|
|
5041
|
+
/**
|
|
5042
|
+
* Verifies the BTC-side Taproot HTLC of a chain swap before funds are
|
|
5043
|
+
* committed: the lockup address must bind to MuSig2(boltz, user) over
|
|
5044
|
+
* Boltz's leaves, and those leaves must enforce the agreed preimage hash,
|
|
5045
|
+
* direction-specific keys, leaf version, and absolute refund CLTV.
|
|
5046
|
+
*/
|
|
5047
|
+
verifyBtcChainHtlc(args) {
|
|
5048
|
+
const { to, swap, arkNetwork } = args;
|
|
5049
|
+
const btcDetails = to === "ARK" ? swap.response.lockupDetails : swap.response.claimDetails;
|
|
5050
|
+
if (!btcDetails.swapTree)
|
|
5051
|
+
throw new SwapError({ message: `Swap ${swap.id}: missing swap tree in BTC details` });
|
|
5052
|
+
if (!btcDetails.serverPublicKey)
|
|
5053
|
+
throw new SwapError({
|
|
5054
|
+
message: `Swap ${swap.id}: missing server public key in BTC details`
|
|
5055
|
+
});
|
|
5056
|
+
if (typeof btcDetails.timeoutBlockHeight !== "number")
|
|
5057
|
+
throw new SwapError({
|
|
5058
|
+
message: `Swap ${swap.id}: missing timeout block height in BTC details`
|
|
5059
|
+
});
|
|
5060
|
+
const network = (0, import_sdk8.getNetwork)(arkNetwork);
|
|
5061
|
+
const swapTree = deserializeSwapTree(btcDetails.swapTree);
|
|
5062
|
+
const ephemeralPub = import_secp256k13.secp256k1.getPublicKey(import_base9.hex.decode(swap.ephemeralKey));
|
|
5063
|
+
const musig = tweakMusig(
|
|
5064
|
+
create(import_base9.hex.decode(swap.ephemeralKey), [
|
|
5065
|
+
import_base9.hex.decode(btcDetails.serverPublicKey),
|
|
5066
|
+
ephemeralPub
|
|
5067
|
+
]),
|
|
5068
|
+
swapTree.tree
|
|
5069
|
+
);
|
|
5070
|
+
const expectedScript = import_btc_signer5.OutScript.encode((0, import_btc_signer5.Address)(network).decode(btcDetails.lockupAddress));
|
|
5071
|
+
if (!(0, import_utils4.equalBytes)(p2trScript(musig.aggPubkey), expectedScript))
|
|
5072
|
+
throw new SwapError({ message: "Boltz is trying to scam us (invalid BTC address)" });
|
|
5073
|
+
const boltzXOnly = toXOnly(import_base9.hex.decode(btcDetails.serverPublicKey));
|
|
5074
|
+
const userXOnly = toXOnly(ephemeralPub);
|
|
5075
|
+
try {
|
|
5076
|
+
assertChainHtlcLeaves(swapTree, {
|
|
5077
|
+
preimageHash160: (0, import_legacy2.ripemd160)(import_base9.hex.decode(swap.request.preimageHash)),
|
|
5078
|
+
claimXOnly: to === "ARK" ? boltzXOnly : userXOnly,
|
|
5079
|
+
refundXOnly: to === "ARK" ? userXOnly : boltzXOnly,
|
|
5080
|
+
timeoutBlockHeight: btcDetails.timeoutBlockHeight
|
|
5081
|
+
});
|
|
5082
|
+
} catch (err) {
|
|
5083
|
+
throw new SwapError({
|
|
5084
|
+
message: `Boltz is trying to scam us (invalid BTC HTLC: ${err.message})`
|
|
5085
|
+
});
|
|
5086
|
+
}
|
|
5087
|
+
}
|
|
5026
5088
|
/**
|
|
5027
5089
|
* Renegotiates the quote for an existing chain swap. Convenience wrapper
|
|
5028
5090
|
* over `getSwapQuote` + `acceptSwapQuote` with a safety floor.
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Q as QuoteSwapOptions, I as IArkadeSwaps, V as VhtlcTimeouts } from './arkade-swaps-
|
|
2
|
-
export { A as ArkadeSwaps } from './arkade-swaps-
|
|
3
|
-
import { B as BoltzSwap, D as DecodedInvoice, a as BoltzChainSwap, b as BoltzReverseSwap, c as BoltzSubmarineSwap, A as ArkadeSwapsConfig, N as Network, C as CreateLightningInvoiceRequest, S as SendLightningPaymentRequest, F as FeesResponse, d as Chain, e as CreateLightningInvoiceResponse, O as OptimisticSendLightningPaymentResponse, f as SubmarineRefundOutcome, g as SubmarineRecoveryInfo, h as SubmarineRecoveryResult, i as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, j as ArkToBtcResponse, k as BtcToArkResponse, l as ChainArkRefundOutcome, m as SwapRepository, n as SwapManagerClient, o as SendLightningPaymentResponse, p as GetSwapsFilter } from './types-
|
|
4
|
-
export { q as ArkadeSwapsCreateConfig, r as BoltzSwapProvider, s as BoltzSwapStatus, I as IncomingPaymentSubscription, P as PendingChainSwap, t as PendingReverseSwap, u as PendingSubmarineSwap, v as PendingSwap, w as SubmarineProgressionStatus, x as SubmarineRecoveryStatus, y as SwapManager, z as SwapManagerCallbacks, E as SwapManagerConfig, H as SwapManagerEvents, V as Vtxo, J as hasSubmarineStatusReached, K as isChainClaimableStatus, M as isChainFailedStatus, Q as isChainFinalStatus, R as isChainPendingStatus, T as isChainRefundableStatus, U as isChainSignableStatus, W as isChainSuccessStatus, X as isChainSwapClaimable, Y as isChainSwapRefundable, Z as isPendingChainSwap, _ as isPendingReverseSwap, $ as isPendingSubmarineSwap, a0 as isReverseClaimableStatus, a1 as isReverseFailedStatus, a2 as isReverseFinalStatus, a3 as isReversePendingStatus, a4 as isReverseSuccessStatus, a5 as isReverseSwapClaimable, a6 as isSubmarineFailedStatus, a7 as isSubmarineFinalStatus, a8 as isSubmarinePendingStatus, a9 as isSubmarineRefundableStatus, aa as isSubmarineSuccessStatus, ab as isSubmarineSwapRefundable } from './types-
|
|
1
|
+
import { Q as QuoteSwapOptions, I as IArkadeSwaps, V as VhtlcTimeouts } from './arkade-swaps-D-L0_0Ri.cjs';
|
|
2
|
+
export { A as ArkadeSwaps } from './arkade-swaps-D-L0_0Ri.cjs';
|
|
3
|
+
import { B as BoltzSwap, D as DecodedInvoice, a as BoltzChainSwap, b as BoltzReverseSwap, c as BoltzSubmarineSwap, A as ArkadeSwapsConfig, N as Network, C as CreateLightningInvoiceRequest, S as SendLightningPaymentRequest, F as FeesResponse, d as Chain, e as CreateLightningInvoiceResponse, O as OptimisticSendLightningPaymentResponse, f as SubmarineRefundOutcome, g as SubmarineRecoveryInfo, h as SubmarineRecoveryResult, i as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, j as ArkToBtcResponse, k as BtcToArkResponse, l as ChainArkRefundOutcome, m as SwapRepository, n as SwapManagerClient, o as SendLightningPaymentResponse, p as GetSwapsFilter } from './types-CS62-oEy.cjs';
|
|
4
|
+
export { q as ArkadeSwapsCreateConfig, r as BoltzSwapProvider, s as BoltzSwapStatus, I as IncomingPaymentSubscription, P as PendingChainSwap, t as PendingReverseSwap, u as PendingSubmarineSwap, v as PendingSwap, w as SubmarineProgressionStatus, x as SubmarineRecoveryStatus, y as SwapManager, z as SwapManagerCallbacks, E as SwapManagerConfig, H as SwapManagerEvents, V as Vtxo, J as hasSubmarineStatusReached, K as isChainClaimableStatus, M as isChainFailedStatus, Q as isChainFinalStatus, R as isChainPendingStatus, T as isChainRefundableStatus, U as isChainSignableStatus, W as isChainSuccessStatus, X as isChainSwapClaimable, Y as isChainSwapRefundable, Z as isPendingChainSwap, _ as isPendingReverseSwap, $ as isPendingSubmarineSwap, a0 as isReverseClaimableStatus, a1 as isReverseFailedStatus, a2 as isReverseFinalStatus, a3 as isReversePendingStatus, a4 as isReverseSuccessStatus, a5 as isReverseSwapClaimable, a6 as isSubmarineFailedStatus, a7 as isSubmarineFinalStatus, a8 as isSubmarinePendingStatus, a9 as isSubmarineRefundableStatus, aa as isSubmarineSuccessStatus, ab as isSubmarineSwapRefundable } from './types-CS62-oEy.cjs';
|
|
5
5
|
import { Transaction } from '@scure/btc-signer';
|
|
6
6
|
import { MessageHandler, RequestEnvelope, ArkInfo, ResponseEnvelope, IWallet, IReadonlyWallet, VHTLC, Identity, ArkTxInput } from '@arkade-os/sdk';
|
|
7
7
|
import { TransactionOutput } from '@scure/btc-signer/psbt.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Q as QuoteSwapOptions, I as IArkadeSwaps, V as VhtlcTimeouts } from './arkade-swaps-
|
|
2
|
-
export { A as ArkadeSwaps } from './arkade-swaps-
|
|
3
|
-
import { B as BoltzSwap, D as DecodedInvoice, a as BoltzChainSwap, b as BoltzReverseSwap, c as BoltzSubmarineSwap, A as ArkadeSwapsConfig, N as Network, C as CreateLightningInvoiceRequest, S as SendLightningPaymentRequest, F as FeesResponse, d as Chain, e as CreateLightningInvoiceResponse, O as OptimisticSendLightningPaymentResponse, f as SubmarineRefundOutcome, g as SubmarineRecoveryInfo, h as SubmarineRecoveryResult, i as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, j as ArkToBtcResponse, k as BtcToArkResponse, l as ChainArkRefundOutcome, m as SwapRepository, n as SwapManagerClient, o as SendLightningPaymentResponse, p as GetSwapsFilter } from './types-
|
|
4
|
-
export { q as ArkadeSwapsCreateConfig, r as BoltzSwapProvider, s as BoltzSwapStatus, I as IncomingPaymentSubscription, P as PendingChainSwap, t as PendingReverseSwap, u as PendingSubmarineSwap, v as PendingSwap, w as SubmarineProgressionStatus, x as SubmarineRecoveryStatus, y as SwapManager, z as SwapManagerCallbacks, E as SwapManagerConfig, H as SwapManagerEvents, V as Vtxo, J as hasSubmarineStatusReached, K as isChainClaimableStatus, M as isChainFailedStatus, Q as isChainFinalStatus, R as isChainPendingStatus, T as isChainRefundableStatus, U as isChainSignableStatus, W as isChainSuccessStatus, X as isChainSwapClaimable, Y as isChainSwapRefundable, Z as isPendingChainSwap, _ as isPendingReverseSwap, $ as isPendingSubmarineSwap, a0 as isReverseClaimableStatus, a1 as isReverseFailedStatus, a2 as isReverseFinalStatus, a3 as isReversePendingStatus, a4 as isReverseSuccessStatus, a5 as isReverseSwapClaimable, a6 as isSubmarineFailedStatus, a7 as isSubmarineFinalStatus, a8 as isSubmarinePendingStatus, a9 as isSubmarineRefundableStatus, aa as isSubmarineSuccessStatus, ab as isSubmarineSwapRefundable } from './types-
|
|
1
|
+
import { Q as QuoteSwapOptions, I as IArkadeSwaps, V as VhtlcTimeouts } from './arkade-swaps-fmdCFjif.js';
|
|
2
|
+
export { A as ArkadeSwaps } from './arkade-swaps-fmdCFjif.js';
|
|
3
|
+
import { B as BoltzSwap, D as DecodedInvoice, a as BoltzChainSwap, b as BoltzReverseSwap, c as BoltzSubmarineSwap, A as ArkadeSwapsConfig, N as Network, C as CreateLightningInvoiceRequest, S as SendLightningPaymentRequest, F as FeesResponse, d as Chain, e as CreateLightningInvoiceResponse, O as OptimisticSendLightningPaymentResponse, f as SubmarineRefundOutcome, g as SubmarineRecoveryInfo, h as SubmarineRecoveryResult, i as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, j as ArkToBtcResponse, k as BtcToArkResponse, l as ChainArkRefundOutcome, m as SwapRepository, n as SwapManagerClient, o as SendLightningPaymentResponse, p as GetSwapsFilter } from './types-CS62-oEy.js';
|
|
4
|
+
export { q as ArkadeSwapsCreateConfig, r as BoltzSwapProvider, s as BoltzSwapStatus, I as IncomingPaymentSubscription, P as PendingChainSwap, t as PendingReverseSwap, u as PendingSubmarineSwap, v as PendingSwap, w as SubmarineProgressionStatus, x as SubmarineRecoveryStatus, y as SwapManager, z as SwapManagerCallbacks, E as SwapManagerConfig, H as SwapManagerEvents, V as Vtxo, J as hasSubmarineStatusReached, K as isChainClaimableStatus, M as isChainFailedStatus, Q as isChainFinalStatus, R as isChainPendingStatus, T as isChainRefundableStatus, U as isChainSignableStatus, W as isChainSuccessStatus, X as isChainSwapClaimable, Y as isChainSwapRefundable, Z as isPendingChainSwap, _ as isPendingReverseSwap, $ as isPendingSubmarineSwap, a0 as isReverseClaimableStatus, a1 as isReverseFailedStatus, a2 as isReverseFinalStatus, a3 as isReversePendingStatus, a4 as isReverseSuccessStatus, a5 as isReverseSwapClaimable, a6 as isSubmarineFailedStatus, a7 as isSubmarineFinalStatus, a8 as isSubmarinePendingStatus, a9 as isSubmarineRefundableStatus, aa as isSubmarineSuccessStatus, ab as isSubmarineSwapRefundable } from './types-CS62-oEy.js';
|
|
5
5
|
import { Transaction } from '@scure/btc-signer';
|
|
6
6
|
import { MessageHandler, RequestEnvelope, ArkInfo, ResponseEnvelope, IWallet, IReadonlyWallet, VHTLC, Identity, ArkTxInput } from '@arkade-os/sdk';
|
|
7
7
|
import { TransactionOutput } from '@scure/btc-signer/psbt.js';
|
package/dist/index.js
CHANGED
|
@@ -53,14 +53,14 @@ import {
|
|
|
53
53
|
updateReverseSwapStatus,
|
|
54
54
|
updateSubmarineSwapStatus,
|
|
55
55
|
verifySignatures
|
|
56
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-GXO2EB6C.js";
|
|
57
57
|
import {
|
|
58
58
|
applyCreatedAtOrder,
|
|
59
59
|
applySwapsFilter
|
|
60
60
|
} from "./chunk-SJQJQO7P.js";
|
|
61
61
|
|
|
62
62
|
// package.json
|
|
63
|
-
var version = "0.3.
|
|
63
|
+
var version = "0.3.46";
|
|
64
64
|
|
|
65
65
|
// src/serviceWorker/arkade-swaps-message-handler.ts
|
|
66
66
|
import { RestArkProvider, RestIndexerProvider } from "@arkade-os/sdk";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RealmLike } from '@arkade-os/sdk/repositories/realm';
|
|
2
|
-
import { m as SwapRepository, B as BoltzSwap, p as GetSwapsFilter } from '../../types-
|
|
2
|
+
import { m as SwapRepository, B as BoltzSwap, p as GetSwapsFilter } from '../../types-CS62-oEy.cjs';
|
|
3
3
|
import '@arkade-os/sdk';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RealmLike } from '@arkade-os/sdk/repositories/realm';
|
|
2
|
-
import { m as SwapRepository, B as BoltzSwap, p as GetSwapsFilter } from '../../types-
|
|
2
|
+
import { m as SwapRepository, B as BoltzSwap, p as GetSwapsFilter } from '../../types-CS62-oEy.js';
|
|
3
3
|
import '@arkade-os/sdk';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SQLExecutor } from '@arkade-os/sdk/repositories/sqlite';
|
|
2
|
-
import { m as SwapRepository, B as BoltzSwap, p as GetSwapsFilter } from '../../types-
|
|
2
|
+
import { m as SwapRepository, B as BoltzSwap, p as GetSwapsFilter } from '../../types-CS62-oEy.cjs';
|
|
3
3
|
import '@arkade-os/sdk';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SQLExecutor } from '@arkade-os/sdk/repositories/sqlite';
|
|
2
|
-
import { m as SwapRepository, B as BoltzSwap, p as GetSwapsFilter } from '../../types-
|
|
2
|
+
import { m as SwapRepository, B as BoltzSwap, p as GetSwapsFilter } from '../../types-CS62-oEy.js';
|
|
3
3
|
import '@arkade-os/sdk';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AsyncStorageTaskQueue, TaskProcessor } from '@arkade-os/sdk/worker/expo';
|
|
2
2
|
import { Identity, ArkProvider, IndexerProvider, IWallet } from '@arkade-os/sdk';
|
|
3
|
-
import { m as SwapRepository, N as Network, r as BoltzSwapProvider, A as ArkadeSwapsConfig } from './types-
|
|
3
|
+
import { m as SwapRepository, N as Network, r as BoltzSwapProvider, A as ArkadeSwapsConfig } from './types-CS62-oEy.cjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Dependencies injected into every swap processor at runtime.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AsyncStorageTaskQueue, TaskProcessor } from '@arkade-os/sdk/worker/expo';
|
|
2
2
|
import { Identity, ArkProvider, IndexerProvider, IWallet } from '@arkade-os/sdk';
|
|
3
|
-
import { m as SwapRepository, N as Network, r as BoltzSwapProvider, A as ArkadeSwapsConfig } from './types-
|
|
3
|
+
import { m as SwapRepository, N as Network, r as BoltzSwapProvider, A as ArkadeSwapsConfig } from './types-CS62-oEy.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Dependencies injected into every swap processor at runtime.
|
|
@@ -144,6 +144,12 @@ type CreateReverseSwapRequest = {
|
|
|
144
144
|
preimageHash: string;
|
|
145
145
|
/** Optional description for the BOLT11 invoice. */
|
|
146
146
|
description?: string;
|
|
147
|
+
/**
|
|
148
|
+
* Optional SHA256 description hash (hex, 32 bytes / 64 chars) to commit
|
|
149
|
+
* into the invoice instead of a plaintext description. BOLT11 carries one
|
|
150
|
+
* or the other, never both; when set, `description` is omitted.
|
|
151
|
+
*/
|
|
152
|
+
descriptionHash?: string;
|
|
147
153
|
};
|
|
148
154
|
/** Response from creating a reverse swap. */
|
|
149
155
|
type CreateReverseSwapResponse = {
|
|
@@ -345,7 +351,7 @@ declare class BoltzSwapProvider {
|
|
|
345
351
|
/** Creates a submarine swap (Arkade → Lightning) on Boltz. */
|
|
346
352
|
createSubmarineSwap({ invoice, refundPublicKey, }: CreateSubmarineSwapRequest): Promise<CreateSubmarineSwapResponse>;
|
|
347
353
|
/** Creates a reverse swap (Lightning → Arkade) on Boltz. */
|
|
348
|
-
createReverseSwap({ invoiceAmount, claimPublicKey, preimageHash, description, }: CreateReverseSwapRequest): Promise<CreateReverseSwapResponse>;
|
|
354
|
+
createReverseSwap({ invoiceAmount, claimPublicKey, preimageHash, description, descriptionHash, }: CreateReverseSwapRequest): Promise<CreateReverseSwapResponse>;
|
|
349
355
|
/** Creates a chain swap (ARK ↔ BTC) on Boltz. */
|
|
350
356
|
createChainSwap({ to, from, preimageHash, feeSatsPerByte, claimPublicKey, refundPublicKey, serverLockAmount, userLockAmount, }: CreateChainSwapRequest): Promise<CreateChainSwapResponse>;
|
|
351
357
|
/** Requests Boltz co-signature for a submarine swap refund. Returns signed transaction + checkpoint. */
|
|
@@ -915,6 +921,15 @@ interface CreateLightningInvoiceRequest {
|
|
|
915
921
|
amount: number;
|
|
916
922
|
/** Optional description embedded in the BOLT11 invoice. */
|
|
917
923
|
description?: string;
|
|
924
|
+
/**
|
|
925
|
+
* Optional SHA256 description hash (hex, 32 bytes) to commit into the
|
|
926
|
+
* BOLT11 invoice instead of a plaintext description. A BOLT11 invoice
|
|
927
|
+
* carries either a description or a description hash, never both, so when
|
|
928
|
+
* this is set `description` is ignored. Use this for flows that must bind
|
|
929
|
+
* the invoice to an external document — e.g. NIP-57 zaps, where the hash
|
|
930
|
+
* is SHA256 of the zap request and the receipt later proves the match.
|
|
931
|
+
*/
|
|
932
|
+
descriptionHash?: string;
|
|
918
933
|
}
|
|
919
934
|
/** Response containing the created Lightning invoice and swap details. */
|
|
920
935
|
interface CreateLightningInvoiceResponse {
|
|
@@ -1161,8 +1176,10 @@ interface DecodedInvoice {
|
|
|
1161
1176
|
expiry: number;
|
|
1162
1177
|
/** Invoice amount in satoshis. */
|
|
1163
1178
|
amountSats: number;
|
|
1164
|
-
/** Invoice description string. */
|
|
1179
|
+
/** Invoice description string (BOLT11 `d` field; "" if none). */
|
|
1165
1180
|
description: string;
|
|
1181
|
+
/** Invoice description hash (BOLT11 `h` field, hex; "" if none). */
|
|
1182
|
+
descriptionHash: string;
|
|
1166
1183
|
/** Payment hash (hex-encoded). */
|
|
1167
1184
|
paymentHash: string;
|
|
1168
1185
|
}
|
|
@@ -144,6 +144,12 @@ type CreateReverseSwapRequest = {
|
|
|
144
144
|
preimageHash: string;
|
|
145
145
|
/** Optional description for the BOLT11 invoice. */
|
|
146
146
|
description?: string;
|
|
147
|
+
/**
|
|
148
|
+
* Optional SHA256 description hash (hex, 32 bytes / 64 chars) to commit
|
|
149
|
+
* into the invoice instead of a plaintext description. BOLT11 carries one
|
|
150
|
+
* or the other, never both; when set, `description` is omitted.
|
|
151
|
+
*/
|
|
152
|
+
descriptionHash?: string;
|
|
147
153
|
};
|
|
148
154
|
/** Response from creating a reverse swap. */
|
|
149
155
|
type CreateReverseSwapResponse = {
|
|
@@ -345,7 +351,7 @@ declare class BoltzSwapProvider {
|
|
|
345
351
|
/** Creates a submarine swap (Arkade → Lightning) on Boltz. */
|
|
346
352
|
createSubmarineSwap({ invoice, refundPublicKey, }: CreateSubmarineSwapRequest): Promise<CreateSubmarineSwapResponse>;
|
|
347
353
|
/** Creates a reverse swap (Lightning → Arkade) on Boltz. */
|
|
348
|
-
createReverseSwap({ invoiceAmount, claimPublicKey, preimageHash, description, }: CreateReverseSwapRequest): Promise<CreateReverseSwapResponse>;
|
|
354
|
+
createReverseSwap({ invoiceAmount, claimPublicKey, preimageHash, description, descriptionHash, }: CreateReverseSwapRequest): Promise<CreateReverseSwapResponse>;
|
|
349
355
|
/** Creates a chain swap (ARK ↔ BTC) on Boltz. */
|
|
350
356
|
createChainSwap({ to, from, preimageHash, feeSatsPerByte, claimPublicKey, refundPublicKey, serverLockAmount, userLockAmount, }: CreateChainSwapRequest): Promise<CreateChainSwapResponse>;
|
|
351
357
|
/** Requests Boltz co-signature for a submarine swap refund. Returns signed transaction + checkpoint. */
|
|
@@ -915,6 +921,15 @@ interface CreateLightningInvoiceRequest {
|
|
|
915
921
|
amount: number;
|
|
916
922
|
/** Optional description embedded in the BOLT11 invoice. */
|
|
917
923
|
description?: string;
|
|
924
|
+
/**
|
|
925
|
+
* Optional SHA256 description hash (hex, 32 bytes) to commit into the
|
|
926
|
+
* BOLT11 invoice instead of a plaintext description. A BOLT11 invoice
|
|
927
|
+
* carries either a description or a description hash, never both, so when
|
|
928
|
+
* this is set `description` is ignored. Use this for flows that must bind
|
|
929
|
+
* the invoice to an external document — e.g. NIP-57 zaps, where the hash
|
|
930
|
+
* is SHA256 of the zap request and the receipt later proves the match.
|
|
931
|
+
*/
|
|
932
|
+
descriptionHash?: string;
|
|
918
933
|
}
|
|
919
934
|
/** Response containing the created Lightning invoice and swap details. */
|
|
920
935
|
interface CreateLightningInvoiceResponse {
|
|
@@ -1161,8 +1176,10 @@ interface DecodedInvoice {
|
|
|
1161
1176
|
expiry: number;
|
|
1162
1177
|
/** Invoice amount in satoshis. */
|
|
1163
1178
|
amountSats: number;
|
|
1164
|
-
/** Invoice description string. */
|
|
1179
|
+
/** Invoice description string (BOLT11 `d` field; "" if none). */
|
|
1165
1180
|
description: string;
|
|
1181
|
+
/** Invoice description hash (BOLT11 `h` field, hex; "" if none). */
|
|
1182
|
+
descriptionHash: string;
|
|
1166
1183
|
/** Payment hash (hex-encoded). */
|
|
1167
1184
|
paymentHash: string;
|
|
1168
1185
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arkade-os/boltz-swap",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.46",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A production-ready TypeScript package that brings Boltz submarine-swaps to Arkade.",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"@scure/btc-signer": "2.0.1",
|
|
77
77
|
"bip68": "1.0.4",
|
|
78
78
|
"light-bolt11-decoder": "3.2.0",
|
|
79
|
-
"@arkade-os/sdk": "0.4.
|
|
79
|
+
"@arkade-os/sdk": "0.4.41"
|
|
80
80
|
},
|
|
81
81
|
"peerDependencies": {
|
|
82
82
|
"expo-task-manager": ">=3.0.0",
|