@arkade-os/swap 0.0.3 → 0.0.4
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/README.md +88 -47
- package/dist/{chunk-HLMMA3LJ.js → chunk-DLM6BVTB.js} +54 -243
- package/dist/index.cjs +127 -278
- package/dist/index.d.cts +201 -9
- package/dist/index.d.ts +201 -9
- package/dist/index.js +87 -65
- package/dist/nostr.cjs +10 -14
- package/dist/nostr.d.cts +1 -2
- package/dist/nostr.d.ts +1 -2
- package/dist/nostr.js +2 -2
- package/dist/{rfq-CCAFoFtR.d.cts → rfq-DjZlesr4.d.cts} +15 -323
- package/dist/{rfq-CCAFoFtR.d.ts → rfq-DjZlesr4.d.ts} +15 -323
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -55,7 +55,6 @@ __export(index_exports, {
|
|
|
55
55
|
ONCHAIN_SEND_PAIR: () => ONCHAIN_SEND_PAIR,
|
|
56
56
|
QUOTE_OPTIONS: () => QUOTE_OPTIONS,
|
|
57
57
|
REFUND_MTP_LAG_SECONDS: () => REFUND_MTP_LAG_SECONDS,
|
|
58
|
-
RFQ_PREIMAGE_TAG: () => RFQ_PREIMAGE_TAG,
|
|
59
58
|
RFQ_RESOLVED_STATES: () => RFQ_RESOLVED_STATES,
|
|
60
59
|
RFQ_SWAP_TERMINAL_STATES: () => RFQ_SWAP_TERMINAL_STATES,
|
|
61
60
|
RFQ_TERMINAL_STATES: () => RFQ_TERMINAL_STATES,
|
|
@@ -66,7 +65,6 @@ __export(index_exports, {
|
|
|
66
65
|
SWAP_LOCKUP_CONTRACT_TYPE: () => SWAP_LOCKUP_CONTRACT_TYPE,
|
|
67
66
|
SwapRefusal: () => SwapRefusal,
|
|
68
67
|
addAssetSwap: () => addAssetSwap,
|
|
69
|
-
adoptSwapDescriptor: () => adoptSwapDescriptor,
|
|
70
68
|
arkadeSwapRequest: () => arkadeSwapRequest,
|
|
71
69
|
assertFundable: () => assertFundable,
|
|
72
70
|
assertReceivable: () => assertReceivable,
|
|
@@ -75,7 +73,6 @@ __export(index_exports, {
|
|
|
75
73
|
awaitRfqResolution: () => awaitRfqResolution,
|
|
76
74
|
buildHtlcClaim: () => buildHtlcClaim,
|
|
77
75
|
buildHtlcRefund: () => buildHtlcRefund,
|
|
78
|
-
buildPreimageMessage: () => buildPreimageMessage,
|
|
79
76
|
cancelOffer: () => cancelOffer,
|
|
80
77
|
claimOnchainFill: () => claimOnchainFill,
|
|
81
78
|
claimReceiveLockup: () => claimReceiveLockup,
|
|
@@ -87,8 +84,6 @@ __export(index_exports, {
|
|
|
87
84
|
deriveLightningReceive: () => deriveLightningReceive,
|
|
88
85
|
deriveOnchainReceive: () => deriveOnchainReceive,
|
|
89
86
|
deriveOnchainSend: () => deriveOnchainSend,
|
|
90
|
-
derivePreimage: () => derivePreimage,
|
|
91
|
-
deriveSwapSecrets: () => deriveSwapSecrets,
|
|
92
87
|
discoverMarkets: () => discoverMarkets,
|
|
93
88
|
encodeOffer: () => encodeOffer,
|
|
94
89
|
extractPreimage: () => extractPreimage,
|
|
@@ -97,7 +92,6 @@ __export(index_exports, {
|
|
|
97
92
|
getAssetSwaps: () => getAssetSwaps,
|
|
98
93
|
getAssetSwapsOrThrow: () => getAssetSwapsOrThrow,
|
|
99
94
|
httpTransport: () => httpTransport,
|
|
100
|
-
isDeterministicSigner: () => isDeterministicSigner,
|
|
101
95
|
isRfqSwapTerminal: () => isRfqSwapTerminal,
|
|
102
96
|
isRfqTerminal: () => isRfqTerminal,
|
|
103
97
|
lightningReceiveRequest: () => lightningReceiveRequest,
|
|
@@ -113,10 +107,8 @@ __export(index_exports, {
|
|
|
113
107
|
onchainReceiveRequest: () => onchainReceiveRequest,
|
|
114
108
|
onchainSendRequest: () => onchainSendRequest,
|
|
115
109
|
paymentHashOf: () => paymentHashOf,
|
|
116
|
-
preimageForRfqSecrets: () => preimageForRfqSecrets,
|
|
117
110
|
pushClaim: () => pushClaim,
|
|
118
111
|
pushRefundWithoutReceiver: () => pushRefundWithoutReceiver,
|
|
119
|
-
randomSwapSecrets: () => randomSwapSecrets,
|
|
120
112
|
readLockupFate: () => readLockupFate,
|
|
121
113
|
receiveVtxoScript: () => receiveVtxoScript,
|
|
122
114
|
refundIfUnresolved: () => refundIfUnresolved,
|
|
@@ -129,15 +121,12 @@ __export(index_exports, {
|
|
|
129
121
|
restoreAssetSwaps: () => restoreAssetSwaps,
|
|
130
122
|
retireSettledOfferContracts: () => retireSettledOfferContracts,
|
|
131
123
|
rfqPair: () => rfqPair,
|
|
132
|
-
rfqSecretsOfRecord: () => rfqSecretsOfRecord,
|
|
133
|
-
rfqSecretsToRecord: () => rfqSecretsToRecord,
|
|
134
124
|
sealClaimPacket: () => sealClaimPacket,
|
|
135
|
-
senderIdentityForRfqSecrets: () => senderIdentityForRfqSecrets,
|
|
136
125
|
senderIdentityForSwapRecord: () => senderIdentityForSwapRecord,
|
|
137
|
-
senderPubkeyForRfqSecrets: () => senderPubkeyForRfqSecrets,
|
|
138
126
|
spendTxidsOf: () => spendTxidsOf,
|
|
139
127
|
spendUpdate: () => spendUpdate,
|
|
140
128
|
swapPrograms: () => swapPrograms,
|
|
129
|
+
swapSecretsToRecord: () => swapSecretsToRecord,
|
|
141
130
|
unilateralClaimDelay: () => unilateralClaimDelay,
|
|
142
131
|
unilateralRefundDelay: () => unilateralRefundDelay,
|
|
143
132
|
unilateralRefundWithoutReceiverDelay: () => unilateralRefundWithoutReceiverDelay,
|
|
@@ -151,7 +140,7 @@ __export(index_exports, {
|
|
|
151
140
|
module.exports = __toCommonJS(index_exports);
|
|
152
141
|
|
|
153
142
|
// src/offer.ts
|
|
154
|
-
var
|
|
143
|
+
var import_base2 = require("@scure/base");
|
|
155
144
|
var import_utils = require("@scure/btc-signer/utils.js");
|
|
156
145
|
var import_sdk = require("@arkade-os/sdk");
|
|
157
146
|
|
|
@@ -283,6 +272,7 @@ async function retireSettledOfferContracts(manager, swaps) {
|
|
|
283
272
|
}
|
|
284
273
|
|
|
285
274
|
// src/store.ts
|
|
275
|
+
var import_base = require("@scure/base");
|
|
286
276
|
var BTC_ASSET_ID = "btc";
|
|
287
277
|
var byNewest = (a, b) => b.createdAt - a.createdAt;
|
|
288
278
|
var getAssetSwapsOrThrow = async (repository) => {
|
|
@@ -335,6 +325,10 @@ var updateAssetSwapBestEffort = async (repository, id, changes) => {
|
|
|
335
325
|
return { swaps, persisted: false };
|
|
336
326
|
}
|
|
337
327
|
};
|
|
328
|
+
var swapSecretsToRecord = (secrets) => ({
|
|
329
|
+
signingDescriptor: secrets.descriptor,
|
|
330
|
+
..."mustPersistPreimage" in secrets && secrets.mustPersistPreimage ? { preimageHex: import_base.hex.encode(secrets.preimage) } : {}
|
|
331
|
+
});
|
|
338
332
|
|
|
339
333
|
// src/offer.ts
|
|
340
334
|
var swapPrograms = {
|
|
@@ -472,14 +466,14 @@ async function registerOfferContract(wallet, arkServerUrl, network, binding, ser
|
|
|
472
466
|
contractManager
|
|
473
467
|
});
|
|
474
468
|
const contract = new import_sdk.arkade.ArkadeContract(client, program, args, keys);
|
|
475
|
-
if (
|
|
469
|
+
if (import_base2.hex.encode(contract.pkScript) !== import_base2.hex.encode(expectedPkScript)) {
|
|
476
470
|
throw new Error("derived covenant does not match the offer's swapPkScript");
|
|
477
471
|
}
|
|
478
472
|
await contract.register({
|
|
479
473
|
label: OFFER_CONTRACT_LABEL,
|
|
480
474
|
metadata: { genericallySpendable: false, kind: OFFER_CONTRACT_KIND }
|
|
481
475
|
});
|
|
482
|
-
await promoteOfferContract(contractManager,
|
|
476
|
+
await promoteOfferContract(contractManager, import_base2.hex.encode(expectedPkScript));
|
|
483
477
|
}
|
|
484
478
|
async function createOffer(wallet, arkServerUrl, params) {
|
|
485
479
|
if (Boolean(params.wantAsset) === Boolean(params.offerAsset)) {
|
|
@@ -490,9 +484,9 @@ async function createOffer(wallet, arkServerUrl, params) {
|
|
|
490
484
|
wallet.getAddress(),
|
|
491
485
|
wallet.identity.xOnlyPublicKey()
|
|
492
486
|
]);
|
|
493
|
-
const serverPubKey =
|
|
487
|
+
const serverPubKey = import_base2.hex.decode((0, import_sdk.toXOnlySignerHex)(info.signerPubkey));
|
|
494
488
|
const network = (0, import_sdk.getNetwork)(info.network);
|
|
495
|
-
const emuKey =
|
|
489
|
+
const emuKey = import_base2.hex.decode(
|
|
496
490
|
(0, import_sdk.toXOnlySignerHex)((0, import_sdk.resolveEmulatorPubkey)(network, params.emulatorPubkey))
|
|
497
491
|
);
|
|
498
492
|
const binding = {
|
|
@@ -515,7 +509,7 @@ async function createOffer(wallet, arkServerUrl, params) {
|
|
|
515
509
|
);
|
|
516
510
|
const payload = encodeOffer(offer);
|
|
517
511
|
return {
|
|
518
|
-
offerHex:
|
|
512
|
+
offerHex: import_base2.hex.encode(payload),
|
|
519
513
|
extension: { type: OFFER_PACKET_TYPE, payload },
|
|
520
514
|
// VtxoScript.address owns address construction; assembling an ArkAddress
|
|
521
515
|
// from tweakedPublicKey here would silently miss any future step it gains
|
|
@@ -525,7 +519,7 @@ async function createOffer(wallet, arkServerUrl, params) {
|
|
|
525
519
|
}
|
|
526
520
|
async function cancelOffer(wallet, arkServerUrl, offerHex, opts) {
|
|
527
521
|
const { repository, fundingTxid, swapAddress } = opts;
|
|
528
|
-
const offer = decodeOffer(
|
|
522
|
+
const offer = decodeOffer(import_base2.hex.decode(offerHex));
|
|
529
523
|
const contractManager = await wallet.getContractManager();
|
|
530
524
|
const client = await import_sdk.arkade.Arkade.connect({
|
|
531
525
|
arkade: new import_sdk.RestArkProvider(arkServerUrl),
|
|
@@ -542,7 +536,7 @@ async function cancelOffer(wallet, arkServerUrl, offerHex, opts) {
|
|
|
542
536
|
const serverKey = swapAddress ? import_sdk.ArkAddress.decode(swapAddress).serverPubKey : client.serverKey;
|
|
543
537
|
const { program, args, keys } = swapProgramBinding(offer, serverKey);
|
|
544
538
|
const rebuilt = new import_sdk.arkade.ArkadeProgramScript(program, args, keys);
|
|
545
|
-
if (
|
|
539
|
+
if (import_base2.hex.encode(rebuilt.pkScript) !== import_base2.hex.encode(offer.swapPkScript)) {
|
|
546
540
|
throw new Error(
|
|
547
541
|
"rebuilt covenant does not match the offer's swapPkScript \u2014 the server signing key has likely rotated since funding; pass swapAddress (the funded address) to pin the original key"
|
|
548
542
|
);
|
|
@@ -575,7 +569,7 @@ async function cancelOffer(wallet, arkServerUrl, offerHex, opts) {
|
|
|
575
569
|
spentTxid: txid
|
|
576
570
|
});
|
|
577
571
|
if (persisted) {
|
|
578
|
-
await retireOfferContract(contractManager, swaps,
|
|
572
|
+
await retireOfferContract(contractManager, swaps, import_base2.hex.encode(offer.swapPkScript));
|
|
579
573
|
}
|
|
580
574
|
}
|
|
581
575
|
return txid;
|
|
@@ -841,7 +835,7 @@ var IndexedDbAssetSwapRepository = class {
|
|
|
841
835
|
};
|
|
842
836
|
|
|
843
837
|
// src/restore.ts
|
|
844
|
-
var
|
|
838
|
+
var import_base3 = require("@scure/base");
|
|
845
839
|
var import_sdk4 = require("@arkade-os/sdk");
|
|
846
840
|
var TXS_PER_REQUEST = 50;
|
|
847
841
|
async function fetchParsedTxs(indexer, txids) {
|
|
@@ -858,7 +852,7 @@ async function fetchParsedTxs(indexer, txids) {
|
|
|
858
852
|
if (result.status !== "fulfilled") continue;
|
|
859
853
|
for (const psbt of result.value) {
|
|
860
854
|
try {
|
|
861
|
-
const parsed = import_sdk4.Transaction.fromPSBT(
|
|
855
|
+
const parsed = import_sdk4.Transaction.fromPSBT(import_base3.base64.decode(psbt));
|
|
862
856
|
parsedByTxid.set(parsed.id, parsed);
|
|
863
857
|
} catch {
|
|
864
858
|
}
|
|
@@ -873,7 +867,7 @@ function classifySpend(offer, serverPubkey, spendTx, deposit) {
|
|
|
873
867
|
let leaves;
|
|
874
868
|
try {
|
|
875
869
|
const script = offerVtxoScript(offer, serverPubkey);
|
|
876
|
-
if (
|
|
870
|
+
if (import_base3.hex.encode(script.pkScript) !== import_base3.hex.encode(offer.swapPkScript)) return "indeterminate";
|
|
877
871
|
leaves = {
|
|
878
872
|
cancel: script.functionByName("cancel")?.leafScript,
|
|
879
873
|
fulfill: script.functionByName("fulfill")?.leafScript
|
|
@@ -884,11 +878,11 @@ function classifySpend(offer, serverPubkey, spendTx, deposit) {
|
|
|
884
878
|
for (let i = 0; i < spendTx.inputsLength; i++) {
|
|
885
879
|
const input = spendTx.getInput(i);
|
|
886
880
|
if (!input.txid || input.index !== deposit.vout) continue;
|
|
887
|
-
if (
|
|
881
|
+
if (import_base3.hex.encode(input.txid) !== deposit.txid) continue;
|
|
888
882
|
for (const leaf of input.tapLeafScript ?? []) {
|
|
889
|
-
const spent =
|
|
890
|
-
if (leaves.cancel && spent ===
|
|
891
|
-
if (leaves.fulfill && spent ===
|
|
883
|
+
const spent = import_base3.hex.encode((0, import_sdk4.scriptFromTapLeafScript)(leaf));
|
|
884
|
+
if (leaves.cancel && spent === import_base3.hex.encode(leaves.cancel)) return "cancelled";
|
|
885
|
+
if (leaves.fulfill && spent === import_base3.hex.encode(leaves.fulfill)) return "fulfilled";
|
|
892
886
|
}
|
|
893
887
|
}
|
|
894
888
|
return "indeterminate";
|
|
@@ -923,13 +917,13 @@ async function restoreAssetSwaps(indexer, txs, existingIds, opts) {
|
|
|
923
917
|
found.push({
|
|
924
918
|
fundingTx,
|
|
925
919
|
offer: decodeOffer(payload),
|
|
926
|
-
offerHex:
|
|
920
|
+
offerHex: import_base3.hex.encode(payload)
|
|
927
921
|
});
|
|
928
922
|
} catch {
|
|
929
923
|
}
|
|
930
924
|
}
|
|
931
925
|
if (found.length === 0) return { restored: [], scannedTxids: fetchedTxids };
|
|
932
|
-
const scripts = [...new Set(found.map((f) =>
|
|
926
|
+
const scripts = [...new Set(found.map((f) => import_base3.hex.encode(f.offer.swapPkScript)))];
|
|
933
927
|
const { vtxos } = await indexer.getVtxos({ scripts });
|
|
934
928
|
const vtxoByScriptAndTxid = new Map(vtxos.map((v) => [`${v.script}:${v.txid}`, v]));
|
|
935
929
|
const txByAnyId = /* @__PURE__ */ new Map();
|
|
@@ -941,7 +935,7 @@ async function restoreAssetSwaps(indexer, txs, existingIds, opts) {
|
|
|
941
935
|
const spendTxids = /* @__PURE__ */ new Set();
|
|
942
936
|
for (const { fundingTx, offer } of found) {
|
|
943
937
|
const vtxo = vtxoByScriptAndTxid.get(
|
|
944
|
-
`${
|
|
938
|
+
`${import_base3.hex.encode(offer.swapPkScript)}:${fundingTx.redeemTxid}`
|
|
945
939
|
);
|
|
946
940
|
if (vtxo?.virtualStatus.state !== "spent") continue;
|
|
947
941
|
for (const txid of spendTxidsOf(vtxo)) spendTxids.add(txid);
|
|
@@ -950,7 +944,7 @@ async function restoreAssetSwaps(indexer, txs, existingIds, opts) {
|
|
|
950
944
|
const restored = [];
|
|
951
945
|
const unresolved = /* @__PURE__ */ new Set();
|
|
952
946
|
for (const { fundingTx, offer, offerHex } of found) {
|
|
953
|
-
const swapPkScript =
|
|
947
|
+
const swapPkScript = import_base3.hex.encode(offer.swapPkScript);
|
|
954
948
|
const vtxo = vtxoByScriptAndTxid.get(`${swapPkScript}:${fundingTx.redeemTxid}`);
|
|
955
949
|
if (!vtxo) {
|
|
956
950
|
unresolved.add(fundingTx.redeemTxid);
|
|
@@ -1007,7 +1001,7 @@ async function restoreAssetSwaps(indexer, txs, existingIds, opts) {
|
|
|
1007
1001
|
}
|
|
1008
1002
|
|
|
1009
1003
|
// src/watch.ts
|
|
1010
|
-
var
|
|
1004
|
+
var import_base4 = require("@scure/base");
|
|
1011
1005
|
var import_sdk5 = require("@arkade-os/sdk");
|
|
1012
1006
|
var TERMINAL = ["fulfilled", "cancelled", "recoverable"];
|
|
1013
1007
|
function spendUpdate(swap, spend) {
|
|
@@ -1042,9 +1036,9 @@ async function watchOfferSwaps({
|
|
|
1042
1036
|
if (candidates.length === 0) return "indeterminate";
|
|
1043
1037
|
const { txs } = await indexer.getVirtualTxs(candidates);
|
|
1044
1038
|
return classifyDepositSpend(
|
|
1045
|
-
decodeOffer(
|
|
1039
|
+
decodeOffer(import_base4.hex.decode(swap.offerHex)),
|
|
1046
1040
|
serverPubkey,
|
|
1047
|
-
txs.map((psbt) => import_sdk5.Transaction.fromPSBT(
|
|
1041
|
+
txs.map((psbt) => import_sdk5.Transaction.fromPSBT(import_base4.base64.decode(psbt))),
|
|
1048
1042
|
{ txid: vtxo.txid, vout: vtxo.vout }
|
|
1049
1043
|
);
|
|
1050
1044
|
} catch {
|
|
@@ -1088,10 +1082,10 @@ async function watchOfferSwaps({
|
|
|
1088
1082
|
// src/rfq.ts
|
|
1089
1083
|
var import_base8 = require("@scure/base");
|
|
1090
1084
|
var import_legacy2 = require("@noble/hashes/legacy.js");
|
|
1091
|
-
var
|
|
1085
|
+
var import_sdk7 = require("@arkade-os/sdk");
|
|
1092
1086
|
|
|
1093
1087
|
// src/onchainHtlc.ts
|
|
1094
|
-
var
|
|
1088
|
+
var import_base5 = require("@scure/base");
|
|
1095
1089
|
var import_sha2 = require("@noble/hashes/sha2.js");
|
|
1096
1090
|
var import_legacy = require("@noble/hashes/legacy.js");
|
|
1097
1091
|
var btc = __toESM(require("@scure/btc-signer"), 1);
|
|
@@ -1101,8 +1095,8 @@ var MAX_MIN_CONFIRMATIONS = 6;
|
|
|
1101
1095
|
var ONCHAIN_SECONDS_PER_BLOCK = 600;
|
|
1102
1096
|
var ONCHAIN_DUST_SATS = BigInt(330);
|
|
1103
1097
|
var newPreimage = () => crypto.getRandomValues(new Uint8Array(32));
|
|
1104
|
-
var paymentHashOf = (preimage) =>
|
|
1105
|
-
var h160FromPaymentHash = (paymentHash) => (0, import_legacy.ripemd160)(
|
|
1098
|
+
var paymentHashOf = (preimage) => import_base5.hex.encode((0, import_sha2.sha256)(preimage));
|
|
1099
|
+
var h160FromPaymentHash = (paymentHash) => (0, import_legacy.ripemd160)(import_base5.hex.decode(paymentHash));
|
|
1106
1100
|
var L1_NETWORKS = {
|
|
1107
1101
|
bitcoin: btc.NETWORK,
|
|
1108
1102
|
testnet: btc.TEST_NETWORK,
|
|
@@ -1143,7 +1137,7 @@ function onchainHtlcScript(params, network) {
|
|
|
1143
1137
|
);
|
|
1144
1138
|
const controlBlockFor = (leaf) => {
|
|
1145
1139
|
for (const [block, script] of payment.tapLeafScript ?? []) {
|
|
1146
|
-
if (script.length - 1 === leaf.length &&
|
|
1140
|
+
if (script.length - 1 === leaf.length && import_base5.hex.encode(script.subarray(0, leaf.length)) === import_base5.hex.encode(leaf)) {
|
|
1147
1141
|
return btc.TaprootControlBlock.encode(block);
|
|
1148
1142
|
}
|
|
1149
1143
|
}
|
|
@@ -1236,13 +1230,13 @@ var buildHtlcRefund = (input) => buildLeafSpend({
|
|
|
1236
1230
|
function extractPreimage(txHex, paymentHash) {
|
|
1237
1231
|
let raw;
|
|
1238
1232
|
try {
|
|
1239
|
-
raw = btc.RawTx.decode(
|
|
1233
|
+
raw = btc.RawTx.decode(import_base5.hex.decode(txHex));
|
|
1240
1234
|
} catch {
|
|
1241
1235
|
return null;
|
|
1242
1236
|
}
|
|
1243
1237
|
for (const stack of raw.witnesses ?? []) {
|
|
1244
1238
|
for (const item of stack) {
|
|
1245
|
-
if (item.length === 32 &&
|
|
1239
|
+
if (item.length === 32 && import_base5.hex.encode((0, import_sha2.sha256)(item)) === paymentHash) return item;
|
|
1246
1240
|
}
|
|
1247
1241
|
}
|
|
1248
1242
|
return null;
|
|
@@ -1283,7 +1277,7 @@ async function classifyOnchainHtlc(chain, input) {
|
|
|
1283
1277
|
const spend = await chain.getSpendingTx(input.funding.txid, input.funding.vout);
|
|
1284
1278
|
if (!spend) return { phase: "unfunded" };
|
|
1285
1279
|
const preimage = extractPreimage(spend.txHex, input.htlc.paymentHash);
|
|
1286
|
-
const txid = btc.Transaction.fromRaw(
|
|
1280
|
+
const txid = btc.Transaction.fromRaw(import_base5.hex.decode(spend.txHex), {
|
|
1287
1281
|
allowUnknownInputs: true,
|
|
1288
1282
|
allowUnknownOutputs: true
|
|
1289
1283
|
}).id;
|
|
@@ -1296,177 +1290,19 @@ async function classifyOnchainHtlc(chain, input) {
|
|
|
1296
1290
|
return { phase: "claimable", utxo: best };
|
|
1297
1291
|
}
|
|
1298
1292
|
|
|
1299
|
-
// src/
|
|
1300
|
-
var
|
|
1301
|
-
var import_sha22 = require("@noble/hashes/sha2.js");
|
|
1302
|
-
var import_utils2 = require("@noble/hashes/utils.js");
|
|
1303
|
-
var import_secp256k1 = require("@noble/curves/secp256k1.js");
|
|
1304
|
-
var import_sdk6 = require("@arkade-os/sdk");
|
|
1305
|
-
var RFQ_PREIMAGE_TAG = "Arkade-RFQ-Preimage-v1";
|
|
1306
|
-
function buildPreimageMessage(xonly, index) {
|
|
1307
|
-
if (xonly.length !== 32) {
|
|
1308
|
-
throw new Error(`x-only pubkey must be 32 bytes, got ${xonly.length}`);
|
|
1309
|
-
}
|
|
1310
|
-
if (!Number.isInteger(index) || index < 0 || index > 4294967295) {
|
|
1311
|
-
throw new Error(`index must be a u32, got ${index}`);
|
|
1312
|
-
}
|
|
1313
|
-
const tag = new TextEncoder().encode(RFQ_PREIMAGE_TAG);
|
|
1314
|
-
const message = new Uint8Array(tag.length + 32 + 4);
|
|
1315
|
-
message.set(tag, 0);
|
|
1316
|
-
message.set(xonly, tag.length);
|
|
1317
|
-
new DataView(message.buffer).setUint32(tag.length + 32, index, true);
|
|
1318
|
-
return message;
|
|
1319
|
-
}
|
|
1320
|
-
var PREIMAGE_INDEX = 0;
|
|
1321
|
-
async function deriveSwapSecrets(wallet) {
|
|
1322
|
-
if (!(0, import_sdk6.isHDAllocationCapable)(wallet)) return void 0;
|
|
1323
|
-
const signingDescriptor = await wallet.getNextSigningDescriptor();
|
|
1324
|
-
if (!signingDescriptor) return void 0;
|
|
1325
|
-
return { derivable: true, signingDescriptor };
|
|
1326
|
-
}
|
|
1327
|
-
function randomSwapSecrets(opts = {}) {
|
|
1328
|
-
if (opts.preimage instanceof Uint8Array && opts.preimage.length !== 32) {
|
|
1329
|
-
throw new Error(`preimage must be 32 bytes, got ${opts.preimage.length}`);
|
|
1330
|
-
}
|
|
1331
|
-
const preimage = opts.preimage instanceof Uint8Array ? opts.preimage : opts.preimage ? (0, import_utils2.randomBytes)(32) : void 0;
|
|
1332
|
-
return {
|
|
1333
|
-
derivable: false,
|
|
1334
|
-
senderPrivateKey: import_secp256k1.schnorr.utils.randomSecretKey(),
|
|
1335
|
-
...preimage ? { preimage } : {}
|
|
1336
|
-
};
|
|
1337
|
-
}
|
|
1338
|
-
function rfqSecretsToRecord(secrets) {
|
|
1339
|
-
if (secrets.derivable) {
|
|
1340
|
-
return {
|
|
1341
|
-
signingDescriptor: secrets.signingDescriptor,
|
|
1342
|
-
...secrets.preimage ? { preimageHex: import_base5.hex.encode(secrets.preimage) } : {}
|
|
1343
|
-
};
|
|
1344
|
-
}
|
|
1345
|
-
return {
|
|
1346
|
-
fallbackSecrets: {
|
|
1347
|
-
version: 1,
|
|
1348
|
-
type: "stored",
|
|
1349
|
-
senderPrivateKeyHex: import_base5.hex.encode(secrets.senderPrivateKey),
|
|
1350
|
-
...secrets.preimage ? { preimageHex: import_base5.hex.encode(secrets.preimage) } : {}
|
|
1351
|
-
}
|
|
1352
|
-
};
|
|
1353
|
-
}
|
|
1354
|
-
function rfqSecretsOfRecord(record) {
|
|
1355
|
-
if (record.signingDescriptor) {
|
|
1356
|
-
return {
|
|
1357
|
-
derivable: true,
|
|
1358
|
-
signingDescriptor: record.signingDescriptor,
|
|
1359
|
-
...record.preimageHex ? { preimage: decodeHex32(record.preimageHex, "preimageHex") } : {}
|
|
1360
|
-
};
|
|
1361
|
-
}
|
|
1362
|
-
const fallback = record.fallbackSecrets;
|
|
1363
|
-
if (!fallback) return void 0;
|
|
1364
|
-
if (fallback.version !== 1 || fallback.type !== "stored") {
|
|
1365
|
-
throw new Error("unsupported RFQ fallback secrets record");
|
|
1366
|
-
}
|
|
1367
|
-
return {
|
|
1368
|
-
derivable: false,
|
|
1369
|
-
senderPrivateKey: decodeHex32(fallback.senderPrivateKeyHex, "senderPrivateKeyHex"),
|
|
1370
|
-
...fallback.preimageHex ? { preimage: decodeHex32(fallback.preimageHex, "preimageHex") } : {}
|
|
1371
|
-
};
|
|
1372
|
-
}
|
|
1373
|
-
function decodeHex32(value, label) {
|
|
1374
|
-
const bytes = import_base5.hex.decode(value);
|
|
1375
|
-
if (bytes.length !== 32) {
|
|
1376
|
-
throw new Error(label + " must be 32 bytes, got " + bytes.length);
|
|
1377
|
-
}
|
|
1378
|
-
return bytes;
|
|
1379
|
-
}
|
|
1380
|
-
async function adoptSwapDescriptor(wallet, signingDescriptor) {
|
|
1381
|
-
if (!(0, import_sdk6.isHDAllocationCapable)(wallet)) return;
|
|
1382
|
-
await wallet.advanceSigningDescriptorWatermark(signingDescriptor);
|
|
1383
|
-
}
|
|
1384
|
-
var RefundNotLocallyPossibleError = class extends Error {
|
|
1385
|
-
constructor(reason, message, options) {
|
|
1386
|
-
super(message, options);
|
|
1387
|
-
this.reason = reason;
|
|
1388
|
-
}
|
|
1389
|
-
reason;
|
|
1390
|
-
name = "RefundNotLocallyPossibleError";
|
|
1391
|
-
};
|
|
1392
|
-
async function senderIdentityForRfqSecrets(wallet, secrets) {
|
|
1393
|
-
if (!secrets.derivable) return import_sdk6.SingleKey.fromPrivateKey(secrets.senderPrivateKey);
|
|
1394
|
-
const signer = (0, import_sdk6.isHDWalletCapable)(wallet) ? await wallet.signerForDescriptor(secrets.signingDescriptor) : void 0;
|
|
1395
|
-
if (!signer || !isDeterministicSigner(signer)) {
|
|
1396
|
-
throw new RefundNotLocallyPossibleError(
|
|
1397
|
-
"foreign-descriptor",
|
|
1398
|
-
`this wallet cannot derive ${secrets.signingDescriptor}; the swap was created on another wallet`
|
|
1399
|
-
);
|
|
1400
|
-
}
|
|
1401
|
-
return signer;
|
|
1402
|
-
}
|
|
1403
|
-
async function senderIdentityForSwapRecord(wallet, record) {
|
|
1404
|
-
let secrets;
|
|
1405
|
-
try {
|
|
1406
|
-
secrets = rfqSecretsOfRecord(record);
|
|
1407
|
-
} catch (error) {
|
|
1408
|
-
throw new RefundNotLocallyPossibleError(
|
|
1409
|
-
"unreadable-secrets",
|
|
1410
|
-
error instanceof Error ? error.message : String(error),
|
|
1411
|
-
// the record's own diagnosis, kept for a caller that wants more
|
|
1412
|
-
// than the message
|
|
1413
|
-
{ cause: error }
|
|
1414
|
-
);
|
|
1415
|
-
}
|
|
1416
|
-
if (!secrets) {
|
|
1417
|
-
throw new RefundNotLocallyPossibleError(
|
|
1418
|
-
"no-secrets",
|
|
1419
|
-
"this swap record carries no signing descriptor and no fallback secrets"
|
|
1420
|
-
);
|
|
1421
|
-
}
|
|
1422
|
-
return senderIdentityForRfqSecrets(wallet, secrets);
|
|
1423
|
-
}
|
|
1424
|
-
async function senderPubkeyForRfqSecrets(wallet, secrets) {
|
|
1425
|
-
if (!secrets.derivable) return import_secp256k1.schnorr.getPublicKey(secrets.senderPrivateKey);
|
|
1426
|
-
return (await senderIdentityForRfqSecrets(wallet, secrets)).xOnlyPublicKey();
|
|
1427
|
-
}
|
|
1428
|
-
function isDeterministicSigner(value) {
|
|
1429
|
-
if (typeof value !== "object" || value === null) return false;
|
|
1430
|
-
const v = value;
|
|
1431
|
-
return typeof v.signSchnorrDeterministic === "function" && typeof v.xOnlyPublicKey === "function";
|
|
1432
|
-
}
|
|
1433
|
-
async function derivePreimage(signer) {
|
|
1434
|
-
const xonly = await signer.xOnlyPublicKey();
|
|
1435
|
-
const message = buildPreimageMessage(xonly, PREIMAGE_INDEX);
|
|
1436
|
-
return (0, import_sha22.sha256)(await signer.signSchnorrDeterministic((0, import_sha22.sha256)(message)));
|
|
1437
|
-
}
|
|
1438
|
-
async function preimageForRfqSecrets(wallet, secrets) {
|
|
1439
|
-
if (!secrets.derivable) {
|
|
1440
|
-
if (!secrets.preimage) throw new Error("this swap carries no stored preimage");
|
|
1441
|
-
return secrets.preimage;
|
|
1442
|
-
}
|
|
1443
|
-
if (secrets.preimage) return secrets.preimage;
|
|
1444
|
-
const signer = await senderIdentityForRfqSecrets(wallet, secrets);
|
|
1445
|
-
if (!isDeterministicSigner(signer)) {
|
|
1446
|
-
throw new Error(
|
|
1447
|
-
`wallet cannot sign deterministically for ${secrets.signingDescriptor}; its preimage is not derivable`
|
|
1448
|
-
);
|
|
1449
|
-
}
|
|
1450
|
-
try {
|
|
1451
|
-
return await derivePreimage(signer);
|
|
1452
|
-
} catch (cause) {
|
|
1453
|
-
throw new Error(
|
|
1454
|
-
`wallet cannot sign deterministically for ${secrets.signingDescriptor}; its preimage is not derivable`,
|
|
1455
|
-
{ cause }
|
|
1456
|
-
);
|
|
1457
|
-
}
|
|
1458
|
-
}
|
|
1293
|
+
// src/rfq.ts
|
|
1294
|
+
var import_sdk8 = require("@arkade-os/sdk");
|
|
1459
1295
|
|
|
1460
1296
|
// src/claimPacket.ts
|
|
1461
1297
|
var import_base6 = require("@scure/base");
|
|
1462
|
-
var
|
|
1298
|
+
var import_secp256k1 = require("@noble/curves/secp256k1.js");
|
|
1463
1299
|
var import_hkdf = require("@noble/hashes/hkdf.js");
|
|
1464
|
-
var
|
|
1300
|
+
var import_sha22 = require("@noble/hashes/sha2.js");
|
|
1465
1301
|
var HKDF_INFO = new TextEncoder().encode("covclaimd/preimage/v1");
|
|
1466
1302
|
async function sealClaimPacket(input) {
|
|
1467
1303
|
return sealWithEntropy(
|
|
1468
1304
|
input,
|
|
1469
|
-
|
|
1305
|
+
import_secp256k1.secp256k1.utils.randomSecretKey(),
|
|
1470
1306
|
crypto.getRandomValues(new Uint8Array(12))
|
|
1471
1307
|
);
|
|
1472
1308
|
}
|
|
@@ -1475,9 +1311,9 @@ async function sealWithEntropy(input, ephemeralKey, nonce) {
|
|
|
1475
1311
|
if (input.covclaimdPubkey.length !== 33) {
|
|
1476
1312
|
throw new Error("covclaimd pubkey must be 33-byte compressed");
|
|
1477
1313
|
}
|
|
1478
|
-
const ephemeralPub =
|
|
1479
|
-
const sharedX =
|
|
1480
|
-
const key = (0, import_hkdf.hkdf)(
|
|
1314
|
+
const ephemeralPub = import_secp256k1.secp256k1.getPublicKey(ephemeralKey, true);
|
|
1315
|
+
const sharedX = import_secp256k1.secp256k1.getSharedSecret(ephemeralKey, input.covclaimdPubkey, true).subarray(1);
|
|
1316
|
+
const key = (0, import_hkdf.hkdf)(import_sha22.sha256, sharedX, ephemeralPub, HKDF_INFO, 32);
|
|
1481
1317
|
if (nonce.length !== 12) throw new Error("nonce must be 12 bytes");
|
|
1482
1318
|
const aesKey = await crypto.subtle.importKey("raw", key, "AES-GCM", false, [
|
|
1483
1319
|
"encrypt"
|
|
@@ -1502,7 +1338,7 @@ async function sealWithEntropy(input, ephemeralKey, nonce) {
|
|
|
1502
1338
|
|
|
1503
1339
|
// src/lockupContract.ts
|
|
1504
1340
|
var import_base7 = require("@scure/base");
|
|
1505
|
-
var
|
|
1341
|
+
var import_sdk6 = require("@arkade-os/sdk");
|
|
1506
1342
|
var SWAP_LOCKUP_CONTRACT_TYPE = "vhtlc-v2";
|
|
1507
1343
|
var SWAP_LOCKUP_CONTRACT_LABEL = "Arkade RFQ swap lockup";
|
|
1508
1344
|
var SWAP_LOCKUP_CONTRACT_KIND = "rfq-swap-lockup";
|
|
@@ -1524,7 +1360,7 @@ async function registerLockupContract(contracts, script, address) {
|
|
|
1524
1360
|
try {
|
|
1525
1361
|
await contracts.createContract({
|
|
1526
1362
|
type: SWAP_LOCKUP_CONTRACT_TYPE,
|
|
1527
|
-
params:
|
|
1363
|
+
params: import_sdk6.VHTLCV2ContractHandler.serializeParams(script.options),
|
|
1528
1364
|
script: import_base7.hex.encode(script.pkScript),
|
|
1529
1365
|
address,
|
|
1530
1366
|
label: SWAP_LOCKUP_CONTRACT_LABEL,
|
|
@@ -1806,7 +1642,7 @@ function lightningSendVtxoScript(params) {
|
|
|
1806
1642
|
type: "seconds",
|
|
1807
1643
|
value: BigInt(value)
|
|
1808
1644
|
});
|
|
1809
|
-
return new
|
|
1645
|
+
return new import_sdk7.VHTLC.ScriptV2({
|
|
1810
1646
|
sender: params.senderPubkey,
|
|
1811
1647
|
receiver: params.solverPubkey,
|
|
1812
1648
|
server: params.serverPubkey,
|
|
@@ -1829,15 +1665,10 @@ function lightningSendVtxoScript(params) {
|
|
|
1829
1665
|
}
|
|
1830
1666
|
async function requestLightningSend(wallet, arkServerUrl, transport, params) {
|
|
1831
1667
|
const rfqId = params.rfqId ?? newRfqId();
|
|
1832
|
-
const secrets = await
|
|
1833
|
-
|
|
1834
|
-
console.warn(
|
|
1835
|
-
"[swap] wallet cannot allocate an HD descriptor: the sender key is random and MUST be persisted before funding"
|
|
1836
|
-
);
|
|
1837
|
-
}
|
|
1838
|
-
const senderPubkey = await senderPubkeyForRfqSecrets(wallet, secrets);
|
|
1668
|
+
const secrets = await (0, import_sdk8.provisionRefundKey)(wallet);
|
|
1669
|
+
const senderPubkey = secrets.pubkey;
|
|
1839
1670
|
const [info, refundAddress] = await Promise.all([
|
|
1840
|
-
new
|
|
1671
|
+
new import_sdk7.RestArkProvider(arkServerUrl).getInfo(),
|
|
1841
1672
|
wallet.getAddress()
|
|
1842
1673
|
]);
|
|
1843
1674
|
const quote = await transport.requestQuote(
|
|
@@ -1861,7 +1692,7 @@ async function requestLightningSend(wallet, arkServerUrl, transport, params) {
|
|
|
1861
1692
|
);
|
|
1862
1693
|
}
|
|
1863
1694
|
const serverPubkey = xOnly(import_base8.hex.decode(info.signerPubkey), "ark signer key");
|
|
1864
|
-
const network = (0,
|
|
1695
|
+
const network = (0, import_sdk7.getNetwork)(info.network);
|
|
1865
1696
|
const script = lightningSendVtxoScript({
|
|
1866
1697
|
solverPubkey: xOnly(import_base8.hex.decode(quote.solver_pubkey), "solver key"),
|
|
1867
1698
|
refundLocktime: quote.refund_locktime,
|
|
@@ -1869,12 +1700,12 @@ async function requestLightningSend(wallet, arkServerUrl, transport, params) {
|
|
|
1869
1700
|
paymentHash: params.invoice.paymentHash,
|
|
1870
1701
|
claimDelay: unilateralClaimDelay(Number(info.unilateralExitDelay)),
|
|
1871
1702
|
emulatorPubkey: xOnly(
|
|
1872
|
-
import_base8.hex.decode((0,
|
|
1703
|
+
import_base8.hex.decode((0, import_sdk7.resolveEmulatorPubkey)(network, params.emulatorPubkey)),
|
|
1873
1704
|
"emulator signer key"
|
|
1874
1705
|
),
|
|
1875
1706
|
senderPubkey,
|
|
1876
1707
|
receiverPkScript: solverHex(receiverPkScriptHex, "profile.receiver_pk_script"),
|
|
1877
|
-
refundPkScript:
|
|
1708
|
+
refundPkScript: import_sdk7.ArkAddress.decode(refundAddress).pkScript
|
|
1878
1709
|
});
|
|
1879
1710
|
const address = script.address(network.hrp, serverPubkey).encode();
|
|
1880
1711
|
verifyLockupAddress(quote, address);
|
|
@@ -1969,7 +1800,7 @@ function deriveOnchainSend(input) {
|
|
|
1969
1800
|
emulatorPubkey: input.emulatorPubkey,
|
|
1970
1801
|
senderPubkey: input.senderPubkey,
|
|
1971
1802
|
receiverPkScript: solverHex(receiverPkScriptHex, "profile.receiver_pk_script"),
|
|
1972
|
-
refundPkScript:
|
|
1803
|
+
refundPkScript: import_sdk7.ArkAddress.decode(input.refundAddress).pkScript
|
|
1973
1804
|
});
|
|
1974
1805
|
const address = script.address(input.hrp, input.serverPubkey).encode();
|
|
1975
1806
|
verifyLockupAddress(quote, address);
|
|
@@ -1995,25 +1826,16 @@ function deriveOnchainSend(input) {
|
|
|
1995
1826
|
}
|
|
1996
1827
|
async function requestOnchainSend(wallet, arkServerUrl, transport, params) {
|
|
1997
1828
|
const rfqId = params.rfqId ?? newRfqId();
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
}
|
|
2001
|
-
const derivedSecrets = await deriveSwapSecrets(wallet);
|
|
2002
|
-
const secrets = derivedSecrets ? params.preimage ? { ...derivedSecrets, preimage: params.preimage } : derivedSecrets : randomSwapSecrets({ preimage: params.preimage ?? true });
|
|
2003
|
-
if (!secrets.derivable) {
|
|
2004
|
-
console.warn(
|
|
2005
|
-
params.preimage ? "[swap] this swap's sender key is random; the supplied preimage and sender key MUST be persisted before funding" : "[swap] this swap's preimage and sender key are random and MUST be persisted before funding"
|
|
2006
|
-
);
|
|
2007
|
-
} else if (params.preimage) {
|
|
1829
|
+
const secrets = await (0, import_sdk8.provisionClaimSecret)(wallet, { preimage: params.preimage });
|
|
1830
|
+
if (secrets.mustPersistPreimage) {
|
|
2008
1831
|
console.warn(
|
|
2009
|
-
"[swap] this swap's preimage
|
|
1832
|
+
"[swap] this swap's preimage cannot be re-derived from the seed and MUST be persisted with the record before funding"
|
|
2010
1833
|
);
|
|
2011
1834
|
}
|
|
2012
|
-
const
|
|
2013
|
-
const
|
|
2014
|
-
const senderPubkey = await senderPubkeyForRfqSecrets(wallet, secrets);
|
|
1835
|
+
const paymentHash = import_base8.hex.encode(secrets.paymentHash);
|
|
1836
|
+
const senderPubkey = secrets.pubkey;
|
|
2015
1837
|
const [info, refundAddress] = await Promise.all([
|
|
2016
|
-
new
|
|
1838
|
+
new import_sdk7.RestArkProvider(arkServerUrl).getInfo(),
|
|
2017
1839
|
wallet.getAddress()
|
|
2018
1840
|
]);
|
|
2019
1841
|
const quote = await transport.requestQuote(
|
|
@@ -2027,14 +1849,14 @@ async function requestOnchainSend(wallet, arkServerUrl, transport, params) {
|
|
|
2027
1849
|
amountSide: params.amountSide
|
|
2028
1850
|
})
|
|
2029
1851
|
);
|
|
2030
|
-
const network = (0,
|
|
1852
|
+
const network = (0, import_sdk7.getNetwork)(info.network);
|
|
2031
1853
|
const derived = deriveOnchainSend({
|
|
2032
1854
|
quote,
|
|
2033
1855
|
paymentHash,
|
|
2034
1856
|
payoutPubkey: params.payoutPubkey,
|
|
2035
1857
|
serverPubkey: xOnly(import_base8.hex.decode(info.signerPubkey), "ark signer key"),
|
|
2036
1858
|
emulatorPubkey: xOnly(
|
|
2037
|
-
import_base8.hex.decode((0,
|
|
1859
|
+
import_base8.hex.decode((0, import_sdk7.resolveEmulatorPubkey)(network, params.emulatorPubkey)),
|
|
2038
1860
|
"emulator signer key"
|
|
2039
1861
|
),
|
|
2040
1862
|
claimDelay: unilateralClaimDelay(Number(info.unilateralExitDelay)),
|
|
@@ -2142,7 +1964,7 @@ function receiveVtxoScript(params) {
|
|
|
2142
1964
|
type: "seconds",
|
|
2143
1965
|
value: BigInt(value)
|
|
2144
1966
|
});
|
|
2145
|
-
return new
|
|
1967
|
+
return new import_sdk7.VHTLC.ScriptV2({
|
|
2146
1968
|
sender: params.solverPubkey,
|
|
2147
1969
|
receiver: params.payoutPubkey,
|
|
2148
1970
|
server: params.serverPubkey,
|
|
@@ -2181,7 +2003,7 @@ function deriveLightningReceive(input) {
|
|
|
2181
2003
|
emulatorPubkey: input.emulatorPubkey,
|
|
2182
2004
|
solverRefundPkScript: solverHex(solverRefundPkScriptHex, "profile.solver_refund_pk_script"),
|
|
2183
2005
|
payoutPubkey: input.payoutPubkey,
|
|
2184
|
-
payoutPkScript:
|
|
2006
|
+
payoutPkScript: import_sdk7.ArkAddress.decode(input.payoutAddress).pkScript
|
|
2185
2007
|
});
|
|
2186
2008
|
const address = script.address(input.hrp, input.serverPubkey).encode();
|
|
2187
2009
|
verifyLockupAddress(quote, address);
|
|
@@ -2189,17 +2011,17 @@ function deriveLightningReceive(input) {
|
|
|
2189
2011
|
}
|
|
2190
2012
|
async function requestLightningReceive(wallet, arkServerUrl, transport, params) {
|
|
2191
2013
|
const rfqId = params.rfqId ?? newRfqId();
|
|
2192
|
-
const secrets = await
|
|
2193
|
-
if (
|
|
2014
|
+
const secrets = await (0, import_sdk8.provisionClaimSecret)(wallet);
|
|
2015
|
+
if (secrets.mustPersistPreimage) {
|
|
2194
2016
|
console.warn(
|
|
2195
|
-
"[swap] this swap's preimage
|
|
2017
|
+
"[swap] this swap's preimage cannot be re-derived from the seed and MUST be persisted with the record before paying"
|
|
2196
2018
|
);
|
|
2197
2019
|
}
|
|
2198
|
-
const preimage =
|
|
2199
|
-
const paymentHash =
|
|
2200
|
-
const payoutPubkey =
|
|
2020
|
+
const preimage = secrets.preimage;
|
|
2021
|
+
const paymentHash = import_base8.hex.encode(secrets.paymentHash);
|
|
2022
|
+
const payoutPubkey = secrets.pubkey;
|
|
2201
2023
|
const [info, payoutAddress] = await Promise.all([
|
|
2202
|
-
new
|
|
2024
|
+
new import_sdk7.RestArkProvider(arkServerUrl).getInfo(),
|
|
2203
2025
|
wallet.getAddress()
|
|
2204
2026
|
]);
|
|
2205
2027
|
const claimPacket = await sealClaimPacket({
|
|
@@ -2218,7 +2040,7 @@ async function requestLightningReceive(wallet, arkServerUrl, transport, params)
|
|
|
2218
2040
|
})
|
|
2219
2041
|
);
|
|
2220
2042
|
assertQuotedAmount(quote, params.amountSide, params.amount);
|
|
2221
|
-
const network = (0,
|
|
2043
|
+
const network = (0, import_sdk7.getNetwork)(info.network);
|
|
2222
2044
|
const derived = deriveLightningReceive({
|
|
2223
2045
|
quote,
|
|
2224
2046
|
paymentHash,
|
|
@@ -2226,7 +2048,7 @@ async function requestLightningReceive(wallet, arkServerUrl, transport, params)
|
|
|
2226
2048
|
payoutAddress,
|
|
2227
2049
|
serverPubkey: xOnly(import_base8.hex.decode(info.signerPubkey), "ark signer key"),
|
|
2228
2050
|
emulatorPubkey: xOnly(
|
|
2229
|
-
import_base8.hex.decode((0,
|
|
2051
|
+
import_base8.hex.decode((0, import_sdk7.resolveEmulatorPubkey)(network, params.emulatorPubkey)),
|
|
2230
2052
|
"emulator signer key"
|
|
2231
2053
|
),
|
|
2232
2054
|
claimDelay: unilateralClaimDelay(Number(info.unilateralExitDelay)),
|
|
@@ -2281,7 +2103,7 @@ function deriveOnchainReceive(input) {
|
|
|
2281
2103
|
emulatorPubkey: input.emulatorPubkey,
|
|
2282
2104
|
solverRefundPkScript: solverHex(solverRefundPkScriptHex, "profile.solver_refund_pk_script"),
|
|
2283
2105
|
payoutPubkey: input.payoutPubkey,
|
|
2284
|
-
payoutPkScript:
|
|
2106
|
+
payoutPkScript: import_sdk7.ArkAddress.decode(input.payoutAddress).pkScript
|
|
2285
2107
|
});
|
|
2286
2108
|
const address = script.address(input.hrp, input.serverPubkey).encode();
|
|
2287
2109
|
verifyLockupAddress(quote, address);
|
|
@@ -2307,17 +2129,17 @@ function deriveOnchainReceive(input) {
|
|
|
2307
2129
|
}
|
|
2308
2130
|
async function requestOnchainReceive(wallet, arkServerUrl, transport, params) {
|
|
2309
2131
|
const rfqId = params.rfqId ?? newRfqId();
|
|
2310
|
-
const secrets = await
|
|
2311
|
-
if (
|
|
2132
|
+
const secrets = await (0, import_sdk8.provisionClaimSecret)(wallet);
|
|
2133
|
+
if (secrets.mustPersistPreimage) {
|
|
2312
2134
|
console.warn(
|
|
2313
|
-
"[swap] this swap's preimage
|
|
2135
|
+
"[swap] this swap's preimage cannot be re-derived from the seed and MUST be persisted with the record before funding"
|
|
2314
2136
|
);
|
|
2315
2137
|
}
|
|
2316
|
-
const preimage =
|
|
2317
|
-
const paymentHash =
|
|
2318
|
-
const payoutPubkey =
|
|
2138
|
+
const preimage = secrets.preimage;
|
|
2139
|
+
const paymentHash = import_base8.hex.encode(secrets.paymentHash);
|
|
2140
|
+
const payoutPubkey = secrets.pubkey;
|
|
2319
2141
|
const [info, payoutAddress] = await Promise.all([
|
|
2320
|
-
new
|
|
2142
|
+
new import_sdk7.RestArkProvider(arkServerUrl).getInfo(),
|
|
2321
2143
|
wallet.getAddress()
|
|
2322
2144
|
]);
|
|
2323
2145
|
const claimPacket = await sealClaimPacket({
|
|
@@ -2337,7 +2159,7 @@ async function requestOnchainReceive(wallet, arkServerUrl, transport, params) {
|
|
|
2337
2159
|
})
|
|
2338
2160
|
);
|
|
2339
2161
|
assertQuotedAmount(quote, params.amountSide, params.amount);
|
|
2340
|
-
const network = (0,
|
|
2162
|
+
const network = (0, import_sdk7.getNetwork)(info.network);
|
|
2341
2163
|
const derived = deriveOnchainReceive({
|
|
2342
2164
|
quote,
|
|
2343
2165
|
paymentHash,
|
|
@@ -2346,7 +2168,7 @@ async function requestOnchainReceive(wallet, arkServerUrl, transport, params) {
|
|
|
2346
2168
|
refundPubkey: params.refundPubkey,
|
|
2347
2169
|
serverPubkey: xOnly(import_base8.hex.decode(info.signerPubkey), "ark signer key"),
|
|
2348
2170
|
emulatorPubkey: xOnly(
|
|
2349
|
-
import_base8.hex.decode((0,
|
|
2171
|
+
import_base8.hex.decode((0, import_sdk7.resolveEmulatorPubkey)(network, params.emulatorPubkey)),
|
|
2350
2172
|
"emulator signer key"
|
|
2351
2173
|
),
|
|
2352
2174
|
claimDelay: unilateralClaimDelay(Number(info.unilateralExitDelay)),
|
|
@@ -2385,12 +2207,12 @@ async function requestOnchainReceive(wallet, arkServerUrl, transport, params) {
|
|
|
2385
2207
|
// src/claim.ts
|
|
2386
2208
|
var import_base10 = require("@scure/base");
|
|
2387
2209
|
var import_legacy3 = require("@noble/hashes/legacy.js");
|
|
2388
|
-
var
|
|
2210
|
+
var import_sha24 = require("@noble/hashes/sha2.js");
|
|
2389
2211
|
var import_sdk10 = require("@arkade-os/sdk");
|
|
2390
2212
|
|
|
2391
2213
|
// src/refund.ts
|
|
2392
2214
|
var import_base9 = require("@scure/base");
|
|
2393
|
-
var
|
|
2215
|
+
var import_sha23 = require("@noble/hashes/sha2.js");
|
|
2394
2216
|
var import_sdk9 = require("@arkade-os/sdk");
|
|
2395
2217
|
var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
2396
2218
|
var isRfqTerminal = (state) => RFQ_TERMINAL_STATES.includes(state);
|
|
@@ -2463,7 +2285,7 @@ async function findLockupVtxos(indexer, swapPkScript) {
|
|
|
2463
2285
|
}
|
|
2464
2286
|
return out;
|
|
2465
2287
|
}
|
|
2466
|
-
var hashesTo = (candidate, paymentHash) => import_base9.hex.encode((0,
|
|
2288
|
+
var hashesTo = (candidate, paymentHash) => import_base9.hex.encode((0, import_sha23.sha256)(candidate)) === paymentHash;
|
|
2467
2289
|
var candidateWitnessItems = (tx, inputIndex) => [
|
|
2468
2290
|
...(0, import_sdk9.getArkPsbtFields)(tx, inputIndex, import_sdk9.ConditionWitness).flat(),
|
|
2469
2291
|
...tx.getInput(inputIndex).finalScriptWitness ?? []
|
|
@@ -2632,7 +2454,7 @@ async function pushClaim(ark, input) {
|
|
|
2632
2454
|
}
|
|
2633
2455
|
}
|
|
2634
2456
|
const committed = input.script.options.preimageHash;
|
|
2635
|
-
if (import_base10.hex.encode((0, import_legacy3.ripemd160)((0,
|
|
2457
|
+
if (import_base10.hex.encode((0, import_legacy3.ripemd160)((0, import_sha24.sha256)(input.preimage))) !== import_base10.hex.encode(committed)) {
|
|
2636
2458
|
throw new Error("preimage does not match the covenant's payment hash");
|
|
2637
2459
|
}
|
|
2638
2460
|
const info = await ark.getInfo();
|
|
@@ -2691,6 +2513,44 @@ async function claimReceiveLockup(indexer, ark, input) {
|
|
|
2691
2513
|
});
|
|
2692
2514
|
}
|
|
2693
2515
|
|
|
2516
|
+
// src/refundBlocked.ts
|
|
2517
|
+
var import_sdk11 = require("@arkade-os/sdk");
|
|
2518
|
+
var RefundNotLocallyPossibleError = class extends Error {
|
|
2519
|
+
constructor(reason, message, options) {
|
|
2520
|
+
super(message, options);
|
|
2521
|
+
this.reason = reason;
|
|
2522
|
+
}
|
|
2523
|
+
reason;
|
|
2524
|
+
name = "RefundNotLocallyPossibleError";
|
|
2525
|
+
};
|
|
2526
|
+
async function senderIdentityForSwapRecord(wallet, record) {
|
|
2527
|
+
if (!record.signingDescriptor) {
|
|
2528
|
+
throw new RefundNotLocallyPossibleError(
|
|
2529
|
+
"no-secrets",
|
|
2530
|
+
"this swap record carries no signing descriptor"
|
|
2531
|
+
);
|
|
2532
|
+
}
|
|
2533
|
+
try {
|
|
2534
|
+
return await (0, import_sdk11.contractSigner)(wallet, record.signingDescriptor);
|
|
2535
|
+
} catch (cause) {
|
|
2536
|
+
if (cause instanceof import_sdk11.WalletCannotSignError) {
|
|
2537
|
+
throw new RefundNotLocallyPossibleError(
|
|
2538
|
+
"unsignable-wallet",
|
|
2539
|
+
`this wallet holds ${record.signingDescriptor} but cannot sign with it; attach its signer`,
|
|
2540
|
+
{ cause }
|
|
2541
|
+
);
|
|
2542
|
+
}
|
|
2543
|
+
if (cause instanceof import_sdk11.ForeignDescriptorError) {
|
|
2544
|
+
throw new RefundNotLocallyPossibleError(
|
|
2545
|
+
"foreign-descriptor",
|
|
2546
|
+
`this wallet cannot derive ${record.signingDescriptor}; the swap was created on another wallet`,
|
|
2547
|
+
{ cause }
|
|
2548
|
+
);
|
|
2549
|
+
}
|
|
2550
|
+
throw cause;
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
|
|
2694
2554
|
// src/swapManager.ts
|
|
2695
2555
|
var import_base11 = require("@scure/base");
|
|
2696
2556
|
var RFQ_SWAP_TERMINAL_STATES = ["settled", "refunded", "failed"];
|
|
@@ -3484,7 +3344,6 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
|
|
|
3484
3344
|
ONCHAIN_SEND_PAIR,
|
|
3485
3345
|
QUOTE_OPTIONS,
|
|
3486
3346
|
REFUND_MTP_LAG_SECONDS,
|
|
3487
|
-
RFQ_PREIMAGE_TAG,
|
|
3488
3347
|
RFQ_RESOLVED_STATES,
|
|
3489
3348
|
RFQ_SWAP_TERMINAL_STATES,
|
|
3490
3349
|
RFQ_TERMINAL_STATES,
|
|
@@ -3495,7 +3354,6 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
|
|
|
3495
3354
|
SWAP_LOCKUP_CONTRACT_TYPE,
|
|
3496
3355
|
SwapRefusal,
|
|
3497
3356
|
addAssetSwap,
|
|
3498
|
-
adoptSwapDescriptor,
|
|
3499
3357
|
arkadeSwapRequest,
|
|
3500
3358
|
assertFundable,
|
|
3501
3359
|
assertReceivable,
|
|
@@ -3504,7 +3362,6 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
|
|
|
3504
3362
|
awaitRfqResolution,
|
|
3505
3363
|
buildHtlcClaim,
|
|
3506
3364
|
buildHtlcRefund,
|
|
3507
|
-
buildPreimageMessage,
|
|
3508
3365
|
cancelOffer,
|
|
3509
3366
|
claimOnchainFill,
|
|
3510
3367
|
claimReceiveLockup,
|
|
@@ -3516,8 +3373,6 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
|
|
|
3516
3373
|
deriveLightningReceive,
|
|
3517
3374
|
deriveOnchainReceive,
|
|
3518
3375
|
deriveOnchainSend,
|
|
3519
|
-
derivePreimage,
|
|
3520
|
-
deriveSwapSecrets,
|
|
3521
3376
|
discoverMarkets,
|
|
3522
3377
|
encodeOffer,
|
|
3523
3378
|
extractPreimage,
|
|
@@ -3526,7 +3381,6 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
|
|
|
3526
3381
|
getAssetSwaps,
|
|
3527
3382
|
getAssetSwapsOrThrow,
|
|
3528
3383
|
httpTransport,
|
|
3529
|
-
isDeterministicSigner,
|
|
3530
3384
|
isRfqSwapTerminal,
|
|
3531
3385
|
isRfqTerminal,
|
|
3532
3386
|
lightningReceiveRequest,
|
|
@@ -3542,10 +3396,8 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
|
|
|
3542
3396
|
onchainReceiveRequest,
|
|
3543
3397
|
onchainSendRequest,
|
|
3544
3398
|
paymentHashOf,
|
|
3545
|
-
preimageForRfqSecrets,
|
|
3546
3399
|
pushClaim,
|
|
3547
3400
|
pushRefundWithoutReceiver,
|
|
3548
|
-
randomSwapSecrets,
|
|
3549
3401
|
readLockupFate,
|
|
3550
3402
|
receiveVtxoScript,
|
|
3551
3403
|
refundIfUnresolved,
|
|
@@ -3558,15 +3410,12 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
|
|
|
3558
3410
|
restoreAssetSwaps,
|
|
3559
3411
|
retireSettledOfferContracts,
|
|
3560
3412
|
rfqPair,
|
|
3561
|
-
rfqSecretsOfRecord,
|
|
3562
|
-
rfqSecretsToRecord,
|
|
3563
3413
|
sealClaimPacket,
|
|
3564
|
-
senderIdentityForRfqSecrets,
|
|
3565
3414
|
senderIdentityForSwapRecord,
|
|
3566
|
-
senderPubkeyForRfqSecrets,
|
|
3567
3415
|
spendTxidsOf,
|
|
3568
3416
|
spendUpdate,
|
|
3569
3417
|
swapPrograms,
|
|
3418
|
+
swapSecretsToRecord,
|
|
3570
3419
|
unilateralClaimDelay,
|
|
3571
3420
|
unilateralRefundDelay,
|
|
3572
3421
|
unilateralRefundWithoutReceiverDelay,
|