@arkade-os/boltz-swap 0.3.45 → 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-C8CmzknM.d.cts → arkade-swaps-D-L0_0Ri.d.cts} +7 -0
- package/dist/{arkade-swaps-gXHRbR09.d.ts → arkade-swaps-fmdCFjif.d.ts} +7 -0
- package/dist/{chunk-5GBBRBFS.js → chunk-GXO2EB6C.js} +69 -17
- package/dist/{chunk-WPAI2ECT.js → chunk-UJXW5JBT.js} +1 -1
- package/dist/expo/background.cjs +71 -16
- package/dist/expo/background.js +9 -4
- package/dist/expo/index.cjs +64 -14
- package/dist/expo/index.d.cts +1 -1
- package/dist/expo/index.d.ts +1 -1
- package/dist/expo/index.js +2 -2
- package/dist/index.cjs +65 -15
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/package.json +2 -2
|
@@ -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.
|
|
@@ -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.
|
|
@@ -2376,14 +2376,16 @@ var IndexedDbSwapRepository = class {
|
|
|
2376
2376
|
// src/arkade-swaps.ts
|
|
2377
2377
|
import {
|
|
2378
2378
|
ArkAddress as ArkAddress2,
|
|
2379
|
-
isRecoverable
|
|
2379
|
+
isRecoverable,
|
|
2380
|
+
getNetwork as getNetwork2
|
|
2380
2381
|
} from "@arkade-os/sdk";
|
|
2381
2382
|
import { sha256 as sha2563 } from "@noble/hashes/sha2.js";
|
|
2383
|
+
import { ripemd160 as ripemd1602 } from "@noble/hashes/legacy.js";
|
|
2382
2384
|
import { hex as hex8 } from "@scure/base";
|
|
2383
2385
|
import { secp256k1 as secp256k12 } from "@noble/curves/secp256k1.js";
|
|
2384
2386
|
import { randomBytes } from "@noble/hashes/utils.js";
|
|
2385
2387
|
import { Address as Address2, OutScript as OutScript2, SigHash as SigHash2, Transaction as Transaction6 } from "@scure/btc-signer";
|
|
2386
|
-
import {
|
|
2388
|
+
import { equalBytes as equalBytes3 } from "@scure/btc-signer/utils.js";
|
|
2387
2389
|
|
|
2388
2390
|
// src/utils/musig.ts
|
|
2389
2391
|
import { secp256k1 } from "@noble/curves/secp256k1.js";
|
|
@@ -2605,21 +2607,9 @@ var create = (privateKey, publicKeys) => {
|
|
|
2605
2607
|
// src/utils/boltz-swap-tx.ts
|
|
2606
2608
|
import { schnorr } from "@noble/curves/secp256k1.js";
|
|
2607
2609
|
import { hex as hex4 } from "@scure/base";
|
|
2608
|
-
import { Script, Transaction as Transaction2 } from "@scure/btc-signer";
|
|
2610
|
+
import { Script, ScriptNum, Transaction as Transaction2 } from "@scure/btc-signer";
|
|
2609
2611
|
import { tapLeafHash } from "@scure/btc-signer/payment.js";
|
|
2610
2612
|
import { compareBytes, equalBytes as equalBytes2 } from "@scure/btc-signer/utils.js";
|
|
2611
|
-
var REGTEST_NETWORK = {
|
|
2612
|
-
bech32: "bcrt",
|
|
2613
|
-
pubKeyHash: 111,
|
|
2614
|
-
scriptHash: 196,
|
|
2615
|
-
wif: 239
|
|
2616
|
-
};
|
|
2617
|
-
var MUTINYNET_NETWORK = {
|
|
2618
|
-
bech32: "tb",
|
|
2619
|
-
pubKeyHash: 111,
|
|
2620
|
-
scriptHash: 196,
|
|
2621
|
-
wif: 239
|
|
2622
|
-
};
|
|
2623
2613
|
var deserializeLeaf = (leaf) => ({
|
|
2624
2614
|
version: leaf.version,
|
|
2625
2615
|
output: hex4.decode(leaf.output)
|
|
@@ -2653,6 +2643,19 @@ var deserializeSwapTree = (tree) => {
|
|
|
2653
2643
|
])
|
|
2654
2644
|
};
|
|
2655
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
|
+
};
|
|
2656
2659
|
var taprootHashTree = (tree) => {
|
|
2657
2660
|
if (!Array.isArray(tree)) {
|
|
2658
2661
|
return {
|
|
@@ -2804,6 +2807,7 @@ import {
|
|
|
2804
2807
|
buildOffchainTx,
|
|
2805
2808
|
getSequence as getSequence2,
|
|
2806
2809
|
Intent,
|
|
2810
|
+
getNetwork,
|
|
2807
2811
|
networks,
|
|
2808
2812
|
VHTLC,
|
|
2809
2813
|
VtxoScript as VtxoScript2,
|
|
@@ -2990,7 +2994,7 @@ var createVHTLCScript = (args) => {
|
|
|
2990
2994
|
)
|
|
2991
2995
|
});
|
|
2992
2996
|
if (!vhtlcScript.claimScript) throw new Error("Failed to create VHTLC script");
|
|
2993
|
-
const hrp = network
|
|
2997
|
+
const hrp = getNetwork(network).hrp;
|
|
2994
2998
|
const vhtlcAddress = vhtlcScript.address(hrp, serverXOnlyPublicKey).encode();
|
|
2995
2999
|
return { vhtlcScript, vhtlcAddress };
|
|
2996
3000
|
};
|
|
@@ -4407,7 +4411,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4407
4411
|
throw new Error(`Swap ${pendingSwap.id}: BTC transaction hex is required`);
|
|
4408
4412
|
const lockupTx = Transaction6.fromRaw(hex8.decode(swapStatus.transaction.hex));
|
|
4409
4413
|
const arkInfo = await this.arkProvider.getInfo();
|
|
4410
|
-
const network = arkInfo.network
|
|
4414
|
+
const network = getNetwork2(arkInfo.network);
|
|
4411
4415
|
const swapTree = deserializeSwapTree(pendingSwap.response.claimDetails.swapTree);
|
|
4412
4416
|
const musig = tweakMusig(
|
|
4413
4417
|
create(hex8.decode(pendingSwap.ephemeralKey), [
|
|
@@ -4947,8 +4951,56 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4947
4951
|
message: "Boltz is trying to scam us (invalid address)"
|
|
4948
4952
|
});
|
|
4949
4953
|
}
|
|
4954
|
+
this.verifyBtcChainHtlc({ to, swap, arkNetwork: arkInfo.network });
|
|
4950
4955
|
return true;
|
|
4951
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
|
+
}
|
|
4952
5004
|
/**
|
|
4953
5005
|
* Renegotiates the quote for an existing chain swap. Convenience wrapper
|
|
4954
5006
|
* over `getSwapQuote` + `acceptSwapQuote` with a safety floor.
|
package/dist/expo/background.cjs
CHANGED
|
@@ -969,6 +969,7 @@ var BoltzSwapProvider = class {
|
|
|
969
969
|
// src/arkade-swaps.ts
|
|
970
970
|
var import_sdk8 = require("@arkade-os/sdk");
|
|
971
971
|
var import_sha23 = require("@noble/hashes/sha2.js");
|
|
972
|
+
var import_legacy2 = require("@noble/hashes/legacy.js");
|
|
972
973
|
var import_base9 = require("@scure/base");
|
|
973
974
|
var import_secp256k13 = require("@noble/curves/secp256k1.js");
|
|
974
975
|
var import_utils3 = require("@noble/hashes/utils.js");
|
|
@@ -1192,18 +1193,6 @@ var import_base3 = require("@scure/base");
|
|
|
1192
1193
|
var import_btc_signer = require("@scure/btc-signer");
|
|
1193
1194
|
var import_payment = require("@scure/btc-signer/payment.js");
|
|
1194
1195
|
var import_utils2 = require("@scure/btc-signer/utils.js");
|
|
1195
|
-
var REGTEST_NETWORK = {
|
|
1196
|
-
bech32: "bcrt",
|
|
1197
|
-
pubKeyHash: 111,
|
|
1198
|
-
scriptHash: 196,
|
|
1199
|
-
wif: 239
|
|
1200
|
-
};
|
|
1201
|
-
var MUTINYNET_NETWORK = {
|
|
1202
|
-
bech32: "tb",
|
|
1203
|
-
pubKeyHash: 111,
|
|
1204
|
-
scriptHash: 196,
|
|
1205
|
-
wif: 239
|
|
1206
|
-
};
|
|
1207
1196
|
var deserializeLeaf = (leaf) => ({
|
|
1208
1197
|
version: leaf.version,
|
|
1209
1198
|
output: import_base3.hex.decode(leaf.output)
|
|
@@ -1237,6 +1226,19 @@ var deserializeSwapTree = (tree) => {
|
|
|
1237
1226
|
])
|
|
1238
1227
|
};
|
|
1239
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
|
+
};
|
|
1240
1242
|
var taprootHashTree = (tree) => {
|
|
1241
1243
|
if (!Array.isArray(tree)) {
|
|
1242
1244
|
return {
|
|
@@ -2933,7 +2935,7 @@ var createVHTLCScript = (args) => {
|
|
|
2933
2935
|
)
|
|
2934
2936
|
});
|
|
2935
2937
|
if (!vhtlcScript.claimScript) throw new Error("Failed to create VHTLC script");
|
|
2936
|
-
const hrp = network
|
|
2938
|
+
const hrp = (0, import_sdk7.getNetwork)(network).hrp;
|
|
2937
2939
|
const vhtlcAddress = vhtlcScript.address(hrp, serverXOnlyPublicKey).encode();
|
|
2938
2940
|
return { vhtlcScript, vhtlcAddress };
|
|
2939
2941
|
};
|
|
@@ -4350,7 +4352,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4350
4352
|
throw new Error(`Swap ${pendingSwap.id}: BTC transaction hex is required`);
|
|
4351
4353
|
const lockupTx = import_btc_signer5.Transaction.fromRaw(import_base9.hex.decode(swapStatus.transaction.hex));
|
|
4352
4354
|
const arkInfo = await this.arkProvider.getInfo();
|
|
4353
|
-
const network =
|
|
4355
|
+
const network = (0, import_sdk8.getNetwork)(arkInfo.network);
|
|
4354
4356
|
const swapTree = deserializeSwapTree(pendingSwap.response.claimDetails.swapTree);
|
|
4355
4357
|
const musig = tweakMusig(
|
|
4356
4358
|
create(import_base9.hex.decode(pendingSwap.ephemeralKey), [
|
|
@@ -4890,8 +4892,56 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4890
4892
|
message: "Boltz is trying to scam us (invalid address)"
|
|
4891
4893
|
});
|
|
4892
4894
|
}
|
|
4895
|
+
this.verifyBtcChainHtlc({ to, swap, arkNetwork: arkInfo.network });
|
|
4893
4896
|
return true;
|
|
4894
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
|
+
}
|
|
4895
4945
|
/**
|
|
4896
4946
|
* Renegotiates the quote for an existing chain swap. Convenience wrapper
|
|
4897
4947
|
* over `getSwapQuote` + `acceptSwapQuote` with a safety floor.
|
|
@@ -5549,14 +5599,19 @@ function createBackgroundWalletShim(args) {
|
|
|
5549
5599
|
getVtxos: async () => notImplemented("getVtxos"),
|
|
5550
5600
|
getBoardingUtxos: async () => notImplemented("getBoardingUtxos"),
|
|
5551
5601
|
getTransactionHistory: async () => notImplemented("getTransactionHistory"),
|
|
5602
|
+
getActivityHistory: async () => notImplemented("getActivityHistory"),
|
|
5552
5603
|
getContractManager: async () => notImplemented("getContractManager"),
|
|
5553
5604
|
getDelegateManager: async () => notImplemented("getDelegateManager"),
|
|
5554
5605
|
getDelegatorManager: async () => notImplemented("getDelegatorManager"),
|
|
5555
5606
|
sendBitcoin: async () => notImplemented("sendBitcoin"),
|
|
5556
5607
|
send: async () => notImplemented("send"),
|
|
5557
5608
|
settle: async () => notImplemented("settle"),
|
|
5609
|
+
clear: async () => notImplemented("clear"),
|
|
5558
5610
|
assetManager: new Proxy({}, {
|
|
5559
5611
|
get: () => notImplemented("assetManager")
|
|
5612
|
+
}),
|
|
5613
|
+
activity: new Proxy({}, {
|
|
5614
|
+
get: () => notImplemented("activity")
|
|
5560
5615
|
})
|
|
5561
5616
|
};
|
|
5562
5617
|
}
|
|
@@ -5578,13 +5633,13 @@ function defineExpoSwapBackgroundTask(taskName, options) {
|
|
|
5578
5633
|
const wallet = createBackgroundWalletShim({
|
|
5579
5634
|
identity,
|
|
5580
5635
|
getAddress: async () => {
|
|
5581
|
-
const { ArkAddress: ArkAddress3 } = await import("@arkade-os/sdk");
|
|
5636
|
+
const { ArkAddress: ArkAddress3, getNetwork: getNetwork3 } = await import("@arkade-os/sdk");
|
|
5582
5637
|
const { hex: hex9 } = await import("@scure/base");
|
|
5583
5638
|
const info = await arkProvider.getInfo();
|
|
5584
5639
|
const pubkey = await identity.xOnlyPublicKey();
|
|
5585
5640
|
const serverPubKey = hex9.decode(info.signerPubkey);
|
|
5586
5641
|
const xOnlyServerPubKey = serverPubKey.length === 33 ? serverPubKey.slice(1) : serverPubKey;
|
|
5587
|
-
const hrp = info.network
|
|
5642
|
+
const hrp = getNetwork3(info.network).hrp;
|
|
5588
5643
|
return new ArkAddress3(xOnlyServerPubKey, pubkey, hrp).encode();
|
|
5589
5644
|
}
|
|
5590
5645
|
});
|
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
|
@@ -959,6 +959,7 @@ var BoltzSwapProvider = class {
|
|
|
959
959
|
|
|
960
960
|
// src/arkade-swaps.ts
|
|
961
961
|
var import_sha23 = require("@noble/hashes/sha2.js");
|
|
962
|
+
var import_legacy2 = require("@noble/hashes/legacy.js");
|
|
962
963
|
var import_base9 = require("@scure/base");
|
|
963
964
|
var import_secp256k13 = require("@noble/curves/secp256k1.js");
|
|
964
965
|
var import_utils3 = require("@noble/hashes/utils.js");
|
|
@@ -1182,18 +1183,6 @@ var import_base3 = require("@scure/base");
|
|
|
1182
1183
|
var import_btc_signer = require("@scure/btc-signer");
|
|
1183
1184
|
var import_payment = require("@scure/btc-signer/payment.js");
|
|
1184
1185
|
var import_utils2 = require("@scure/btc-signer/utils.js");
|
|
1185
|
-
var REGTEST_NETWORK = {
|
|
1186
|
-
bech32: "bcrt",
|
|
1187
|
-
pubKeyHash: 111,
|
|
1188
|
-
scriptHash: 196,
|
|
1189
|
-
wif: 239
|
|
1190
|
-
};
|
|
1191
|
-
var MUTINYNET_NETWORK = {
|
|
1192
|
-
bech32: "tb",
|
|
1193
|
-
pubKeyHash: 111,
|
|
1194
|
-
scriptHash: 196,
|
|
1195
|
-
wif: 239
|
|
1196
|
-
};
|
|
1197
1186
|
var deserializeLeaf = (leaf) => ({
|
|
1198
1187
|
version: leaf.version,
|
|
1199
1188
|
output: import_base3.hex.decode(leaf.output)
|
|
@@ -1227,6 +1216,19 @@ var deserializeSwapTree = (tree) => {
|
|
|
1227
1216
|
])
|
|
1228
1217
|
};
|
|
1229
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
|
+
};
|
|
1230
1232
|
var taprootHashTree = (tree) => {
|
|
1231
1233
|
if (!Array.isArray(tree)) {
|
|
1232
1234
|
return {
|
|
@@ -2923,7 +2925,7 @@ var createVHTLCScript = (args) => {
|
|
|
2923
2925
|
)
|
|
2924
2926
|
});
|
|
2925
2927
|
if (!vhtlcScript.claimScript) throw new Error("Failed to create VHTLC script");
|
|
2926
|
-
const hrp = network
|
|
2928
|
+
const hrp = (0, import_sdk7.getNetwork)(network).hrp;
|
|
2927
2929
|
const vhtlcAddress = vhtlcScript.address(hrp, serverXOnlyPublicKey).encode();
|
|
2928
2930
|
return { vhtlcScript, vhtlcAddress };
|
|
2929
2931
|
};
|
|
@@ -4340,7 +4342,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4340
4342
|
throw new Error(`Swap ${pendingSwap.id}: BTC transaction hex is required`);
|
|
4341
4343
|
const lockupTx = import_btc_signer5.Transaction.fromRaw(import_base9.hex.decode(swapStatus.transaction.hex));
|
|
4342
4344
|
const arkInfo = await this.arkProvider.getInfo();
|
|
4343
|
-
const network =
|
|
4345
|
+
const network = (0, import_sdk8.getNetwork)(arkInfo.network);
|
|
4344
4346
|
const swapTree = deserializeSwapTree(pendingSwap.response.claimDetails.swapTree);
|
|
4345
4347
|
const musig = tweakMusig(
|
|
4346
4348
|
create(import_base9.hex.decode(pendingSwap.ephemeralKey), [
|
|
@@ -4880,8 +4882,56 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4880
4882
|
message: "Boltz is trying to scam us (invalid address)"
|
|
4881
4883
|
});
|
|
4882
4884
|
}
|
|
4885
|
+
this.verifyBtcChainHtlc({ to, swap, arkNetwork: arkInfo.network });
|
|
4883
4886
|
return true;
|
|
4884
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
|
+
}
|
|
4885
4935
|
/**
|
|
4886
4936
|
* Renegotiates the quote for an existing chain swap. Convenience wrapper
|
|
4887
4937
|
* over `getSwapQuote` + `acceptSwapQuote` with a safety floor.
|
package/dist/expo/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I as IArkadeSwaps, A as ArkadeSwaps, Q as QuoteSwapOptions, V as VhtlcTimeouts } from '../arkade-swaps-
|
|
1
|
+
import { I as IArkadeSwaps, A as ArkadeSwaps, Q as QuoteSwapOptions, V as VhtlcTimeouts } from '../arkade-swaps-D-L0_0Ri.cjs';
|
|
2
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
3
|
import { E as ExpoArkadeSwapsConfig } from '../swapsPollProcessor-B98F6MQF.cjs';
|
|
4
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';
|
package/dist/expo/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I as IArkadeSwaps, A as ArkadeSwaps, Q as QuoteSwapOptions, V as VhtlcTimeouts } from '../arkade-swaps-
|
|
1
|
+
import { I as IArkadeSwaps, A as ArkadeSwaps, Q as QuoteSwapOptions, V as VhtlcTimeouts } from '../arkade-swaps-fmdCFjif.js';
|
|
2
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
3
|
import { E as ExpoArkadeSwapsConfig } from '../swapsPollProcessor-Ov-wp17v.js';
|
|
4
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';
|
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 {
|
|
@@ -1091,6 +1091,7 @@ var BoltzSwapProvider = class {
|
|
|
1091
1091
|
|
|
1092
1092
|
// src/arkade-swaps.ts
|
|
1093
1093
|
var import_sha23 = require("@noble/hashes/sha2.js");
|
|
1094
|
+
var import_legacy2 = require("@noble/hashes/legacy.js");
|
|
1094
1095
|
var import_base9 = require("@scure/base");
|
|
1095
1096
|
var import_secp256k13 = require("@noble/curves/secp256k1.js");
|
|
1096
1097
|
var import_utils3 = require("@noble/hashes/utils.js");
|
|
@@ -1314,18 +1315,6 @@ var import_base3 = require("@scure/base");
|
|
|
1314
1315
|
var import_btc_signer = require("@scure/btc-signer");
|
|
1315
1316
|
var import_payment = require("@scure/btc-signer/payment.js");
|
|
1316
1317
|
var import_utils2 = require("@scure/btc-signer/utils.js");
|
|
1317
|
-
var REGTEST_NETWORK = {
|
|
1318
|
-
bech32: "bcrt",
|
|
1319
|
-
pubKeyHash: 111,
|
|
1320
|
-
scriptHash: 196,
|
|
1321
|
-
wif: 239
|
|
1322
|
-
};
|
|
1323
|
-
var MUTINYNET_NETWORK = {
|
|
1324
|
-
bech32: "tb",
|
|
1325
|
-
pubKeyHash: 111,
|
|
1326
|
-
scriptHash: 196,
|
|
1327
|
-
wif: 239
|
|
1328
|
-
};
|
|
1329
1318
|
var deserializeLeaf = (leaf) => ({
|
|
1330
1319
|
version: leaf.version,
|
|
1331
1320
|
output: import_base3.hex.decode(leaf.output)
|
|
@@ -1359,6 +1348,19 @@ var deserializeSwapTree = (tree) => {
|
|
|
1359
1348
|
])
|
|
1360
1349
|
};
|
|
1361
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
|
+
};
|
|
1362
1364
|
var taprootHashTree = (tree) => {
|
|
1363
1365
|
if (!Array.isArray(tree)) {
|
|
1364
1366
|
return {
|
|
@@ -3076,7 +3078,7 @@ var createVHTLCScript = (args) => {
|
|
|
3076
3078
|
)
|
|
3077
3079
|
});
|
|
3078
3080
|
if (!vhtlcScript.claimScript) throw new Error("Failed to create VHTLC script");
|
|
3079
|
-
const hrp = network
|
|
3081
|
+
const hrp = (0, import_sdk7.getNetwork)(network).hrp;
|
|
3080
3082
|
const vhtlcAddress = vhtlcScript.address(hrp, serverXOnlyPublicKey).encode();
|
|
3081
3083
|
return { vhtlcScript, vhtlcAddress };
|
|
3082
3084
|
};
|
|
@@ -4493,7 +4495,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4493
4495
|
throw new Error(`Swap ${pendingSwap.id}: BTC transaction hex is required`);
|
|
4494
4496
|
const lockupTx = import_btc_signer5.Transaction.fromRaw(import_base9.hex.decode(swapStatus.transaction.hex));
|
|
4495
4497
|
const arkInfo = await this.arkProvider.getInfo();
|
|
4496
|
-
const network =
|
|
4498
|
+
const network = (0, import_sdk8.getNetwork)(arkInfo.network);
|
|
4497
4499
|
const swapTree = deserializeSwapTree(pendingSwap.response.claimDetails.swapTree);
|
|
4498
4500
|
const musig = tweakMusig(
|
|
4499
4501
|
create(import_base9.hex.decode(pendingSwap.ephemeralKey), [
|
|
@@ -5033,8 +5035,56 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
5033
5035
|
message: "Boltz is trying to scam us (invalid address)"
|
|
5034
5036
|
});
|
|
5035
5037
|
}
|
|
5038
|
+
this.verifyBtcChainHtlc({ to, swap, arkNetwork: arkInfo.network });
|
|
5036
5039
|
return true;
|
|
5037
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
|
+
}
|
|
5038
5088
|
/**
|
|
5039
5089
|
* Renegotiates the quote for an existing chain swap. Convenience wrapper
|
|
5040
5090
|
* over `getSwapQuote` + `acceptSwapQuote` with a safety floor.
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Q as QuoteSwapOptions, I as IArkadeSwaps, V as VhtlcTimeouts } from './arkade-swaps-
|
|
2
|
-
export { A as ArkadeSwaps } from './arkade-swaps-
|
|
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
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
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';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Q as QuoteSwapOptions, I as IArkadeSwaps, V as VhtlcTimeouts } from './arkade-swaps-
|
|
2
|
-
export { A as ArkadeSwaps } from './arkade-swaps-
|
|
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
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
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';
|
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";
|
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",
|