@arkade-os/swap 0.0.12 → 0.0.14
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/{chunk-XXWOODUE.js → chunk-IFZOBTTG.js} +8 -8
- package/dist/index.cjs +311 -49
- package/dist/index.d.cts +131 -6
- package/dist/index.d.ts +131 -6
- package/dist/index.js +303 -31
- package/dist/nostr.d.cts +1 -1
- package/dist/nostr.d.ts +1 -1
- package/dist/nostr.js +1 -1
- package/dist/repositories/realm/index.d.cts +2 -2
- package/dist/repositories/realm/index.d.ts +2 -2
- package/dist/repositories/sqlite/index.d.cts +2 -2
- package/dist/repositories/sqlite/index.d.ts +2 -2
- package/dist/{repository-DlLvj_y6.d.ts → repository-D5JoeqwB.d.ts} +1 -1
- package/dist/{repository-DaK1RzRq.d.cts → repository-Vfx65uF1.d.cts} +1 -1
- package/dist/{rfq-DzsmhXX3.d.ts → rfq-CYfKvAPp.d.cts} +14 -8
- package/dist/{rfq-DzsmhXX3.d.cts → rfq-CYfKvAPp.d.ts} +14 -8
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -34,6 +34,8 @@ __export(index_exports, {
|
|
|
34
34
|
ARKADE_BTC: () => ARKADE_BTC,
|
|
35
35
|
AddressMismatch: () => AddressMismatch,
|
|
36
36
|
BTC_ASSET_ID: () => BTC_ASSET_ID,
|
|
37
|
+
CROSS_ASSET_RAIL: () => CROSS_ASSET_RAIL,
|
|
38
|
+
CovclaimdRevealError: () => CovclaimdRevealError,
|
|
37
39
|
InMemoryAssetSwapRepository: () => InMemoryAssetSwapRepository,
|
|
38
40
|
IndexedDbAssetSwapRepository: () => IndexedDbAssetSwapRepository,
|
|
39
41
|
LIGHTNING_BTC: () => LIGHTNING_BTC,
|
|
@@ -90,8 +92,10 @@ __export(index_exports, {
|
|
|
90
92
|
classifyDepositSpend: () => classifyDepositSpend,
|
|
91
93
|
classifyOnchainHtlc: () => classifyOnchainHtlc,
|
|
92
94
|
classifySpend: () => classifySpend,
|
|
95
|
+
covclaimdClient: () => covclaimdClient,
|
|
93
96
|
createOffer: () => createOffer,
|
|
94
97
|
createRfqSwapRecord: () => createRfqSwapRecord,
|
|
98
|
+
crossAssetRail: () => crossAssetRail,
|
|
95
99
|
decodeOffer: () => decodeOffer,
|
|
96
100
|
deriveLightningReceive: () => deriveLightningReceive,
|
|
97
101
|
deriveOnchainReceive: () => deriveOnchainReceive,
|
|
@@ -137,6 +141,8 @@ __export(index_exports, {
|
|
|
137
141
|
requestOnchainSend: () => requestOnchainSend,
|
|
138
142
|
restoreAssetSwaps: () => restoreAssetSwaps,
|
|
139
143
|
retireSettledOfferContracts: () => retireSettledOfferContracts,
|
|
144
|
+
revealClaimPacket: () => revealClaimPacket,
|
|
145
|
+
revealFieldsFromScript: () => revealFieldsFromScript,
|
|
140
146
|
rfqClaimSecretOf: () => rfqClaimSecretOf,
|
|
141
147
|
rfqPair: () => rfqPair,
|
|
142
148
|
rfqSecretsProfile: () => rfqSecretsProfile,
|
|
@@ -1829,7 +1835,7 @@ async function watchOfferSwaps({
|
|
|
1829
1835
|
}
|
|
1830
1836
|
};
|
|
1831
1837
|
const unsubscribe = manager.onContractEvent((event) => {
|
|
1832
|
-
if (event.type !== "vtxo_spent") return;
|
|
1838
|
+
if (!(0, import_sdk7.isContractVtxoEvent)(event) || event.type !== "vtxo_spent") return;
|
|
1833
1839
|
enqueue(() => handleSpend(event));
|
|
1834
1840
|
});
|
|
1835
1841
|
return {
|
|
@@ -2403,7 +2409,7 @@ var lightningReceiveRequest = (input) => ({
|
|
|
2403
2409
|
payment_hash: input.paymentHash,
|
|
2404
2410
|
payout_address: input.payoutAddress,
|
|
2405
2411
|
payout_pubkey: import_base10.hex.encode(input.payoutPubkey),
|
|
2406
|
-
claim_packet: input.claimPacket
|
|
2412
|
+
...input.claimPacket === void 0 ? {} : { claim_packet: input.claimPacket }
|
|
2407
2413
|
}
|
|
2408
2414
|
});
|
|
2409
2415
|
var onchainReceiveRequest = (input) => ({
|
|
@@ -2415,7 +2421,7 @@ var onchainReceiveRequest = (input) => ({
|
|
|
2415
2421
|
amount: input.amount,
|
|
2416
2422
|
profile: {
|
|
2417
2423
|
payment_hash: input.paymentHash,
|
|
2418
|
-
claim_packet: input.claimPacket,
|
|
2424
|
+
...input.claimPacket === void 0 ? {} : { claim_packet: input.claimPacket },
|
|
2419
2425
|
refund_pubkey: import_base10.hex.encode(input.refundPubkey),
|
|
2420
2426
|
payout_address: input.payoutAddress,
|
|
2421
2427
|
payout_pubkey: import_base10.hex.encode(input.payoutPubkey)
|
|
@@ -2686,17 +2692,17 @@ async function requestLightningReceive(wallet, arkServerUrl, transport, params)
|
|
|
2686
2692
|
new import_sdk9.RestArkProvider(arkServerUrl).getInfo(),
|
|
2687
2693
|
wallet.getAddress()
|
|
2688
2694
|
]);
|
|
2689
|
-
const claimPacket = await sealClaimPacket({
|
|
2695
|
+
const claimPacket = params.covclaimdPubkey ? await sealClaimPacket({
|
|
2690
2696
|
preimage,
|
|
2691
2697
|
covclaimdPubkey: params.covclaimdPubkey
|
|
2692
|
-
});
|
|
2698
|
+
}) : void 0;
|
|
2693
2699
|
const quote = await transport.requestQuote(
|
|
2694
2700
|
lightningReceiveRequest({
|
|
2695
2701
|
rfqId,
|
|
2696
2702
|
paymentHash,
|
|
2697
2703
|
payoutAddress,
|
|
2698
2704
|
payoutPubkey,
|
|
2699
|
-
claimPacket: claimPacket
|
|
2705
|
+
claimPacket: claimPacket?.ciphertext,
|
|
2700
2706
|
amount: params.amount,
|
|
2701
2707
|
amountSide: params.amountSide
|
|
2702
2708
|
})
|
|
@@ -2809,10 +2815,10 @@ async function requestOnchainReceive(wallet, arkServerUrl, transport, params) {
|
|
|
2809
2815
|
new import_sdk9.RestArkProvider(arkServerUrl).getInfo(),
|
|
2810
2816
|
wallet.getAddress()
|
|
2811
2817
|
]);
|
|
2812
|
-
const claimPacket = await sealClaimPacket({
|
|
2818
|
+
const claimPacket = params.covclaimdPubkey ? await sealClaimPacket({
|
|
2813
2819
|
preimage,
|
|
2814
2820
|
covclaimdPubkey: params.covclaimdPubkey
|
|
2815
|
-
});
|
|
2821
|
+
}) : void 0;
|
|
2816
2822
|
const quote = await transport.requestQuote(
|
|
2817
2823
|
onchainReceiveRequest({
|
|
2818
2824
|
rfqId,
|
|
@@ -2820,7 +2826,7 @@ async function requestOnchainReceive(wallet, arkServerUrl, transport, params) {
|
|
|
2820
2826
|
payoutAddress,
|
|
2821
2827
|
payoutPubkey,
|
|
2822
2828
|
refundPubkey: params.refundPubkey,
|
|
2823
|
-
claimPacket: claimPacket
|
|
2829
|
+
claimPacket: claimPacket?.ciphertext,
|
|
2824
2830
|
amount: params.amount,
|
|
2825
2831
|
amountSide: params.amountSide
|
|
2826
2832
|
})
|
|
@@ -2968,6 +2974,7 @@ function solverOnchainRail(deps) {
|
|
|
2968
2974
|
id: SOLVER_ONCHAIN_RAIL,
|
|
2969
2975
|
match: (req) => (0, import_sdk11.btcTarget)(req.raw) !== void 0,
|
|
2970
2976
|
available: async (req) => {
|
|
2977
|
+
if ((0, import_sdk11.assetsOf)(req).length > 0) return false;
|
|
2971
2978
|
const address = (0, import_sdk11.btcTarget)(req.raw);
|
|
2972
2979
|
if (!address) return false;
|
|
2973
2980
|
try {
|
|
@@ -2981,6 +2988,7 @@ function solverOnchainRail(deps) {
|
|
|
2981
2988
|
},
|
|
2982
2989
|
quote: async (req, ctx) => {
|
|
2983
2990
|
const address = (0, import_sdk11.btcTarget)(req.raw);
|
|
2991
|
+
(0, import_sdk11.assertNoAssets)(SOLVER_ONCHAIN_RAIL, req);
|
|
2984
2992
|
const amount = (0, import_sdk11.resolveSendAmount)(SOLVER_ONCHAIN_RAIL, req.raw, req.amount);
|
|
2985
2993
|
const payoutPkScript = l1ScriptForAddress(address, deps.l1Network);
|
|
2986
2994
|
const rendezvous = await rendezvousFor(amount);
|
|
@@ -3079,12 +3087,14 @@ function solverLightningRail(deps) {
|
|
|
3079
3087
|
id: SOLVER_LIGHTNING_RAIL,
|
|
3080
3088
|
match: (req) => (0, import_sdk12.invoiceTarget)(req.raw) !== void 0,
|
|
3081
3089
|
available: async (req) => {
|
|
3090
|
+
if ((0, import_sdk12.assetsOf)(req).length > 0) return false;
|
|
3082
3091
|
const facts = factsOf(req.raw, deps.decodeInvoice, Math.floor(Date.now() / 1e3));
|
|
3083
3092
|
if (!facts) return false;
|
|
3084
3093
|
if (req.amount !== void 0 && req.amount !== facts.amountSats) return false;
|
|
3085
3094
|
return await rendezvousFor(facts.amountSats) !== void 0;
|
|
3086
3095
|
},
|
|
3087
3096
|
quote: async (req, ctx) => {
|
|
3097
|
+
(0, import_sdk12.assertNoAssets)(SOLVER_LIGHTNING_RAIL, req);
|
|
3088
3098
|
const facts = factsOf(req.raw, deps.decodeInvoice, Math.floor(Date.now() / 1e3));
|
|
3089
3099
|
if (!facts) {
|
|
3090
3100
|
throw new Error(
|
|
@@ -3157,16 +3167,260 @@ function solverLightningRail(deps) {
|
|
|
3157
3167
|
};
|
|
3158
3168
|
}
|
|
3159
3169
|
|
|
3160
|
-
// src/
|
|
3161
|
-
var
|
|
3170
|
+
// src/payment/crossAsset.ts
|
|
3171
|
+
var import_sdk13 = require("@arkade-os/sdk");
|
|
3172
|
+
var CROSS_ASSET_RAIL = "cross-asset";
|
|
3173
|
+
var DEFAULT_CARRIER_SATS = 330;
|
|
3174
|
+
var parseAssetId = (assetId) => {
|
|
3175
|
+
try {
|
|
3176
|
+
return import_sdk13.asset.AssetId.fromString(assetId);
|
|
3177
|
+
} catch {
|
|
3178
|
+
return void 0;
|
|
3179
|
+
}
|
|
3180
|
+
};
|
|
3181
|
+
function crossAssetRail(deps) {
|
|
3182
|
+
const planFor = async (asset3) => {
|
|
3183
|
+
const markets = await deps.discover();
|
|
3184
|
+
const found = findMarket(markets, BTC_ASSET_ID, asset3.assetId);
|
|
3185
|
+
const market = found?.market;
|
|
3186
|
+
if (!market) return void 0;
|
|
3187
|
+
const plan = await deps.quote(market, found.give, asset3.amount);
|
|
3188
|
+
const [balance, dust] = await Promise.all([deps.btcBalance(), deps.dust()]);
|
|
3189
|
+
return { plan, error: validatePlan(plan, balance, dust) };
|
|
3190
|
+
};
|
|
3191
|
+
return {
|
|
3192
|
+
id: CROSS_ASSET_RAIL,
|
|
3193
|
+
match: (req) => (0, import_sdk13.arkTarget)(req.raw) !== void 0,
|
|
3194
|
+
available: async (req) => {
|
|
3195
|
+
const assets = (0, import_sdk13.assetsOf)(req);
|
|
3196
|
+
if (assets.length !== 1) return false;
|
|
3197
|
+
const [asset3] = assets;
|
|
3198
|
+
if (asset3.assetId === BTC_ASSET_ID) return false;
|
|
3199
|
+
if (typeof asset3.amount !== "bigint" || asset3.amount <= 0n) return false;
|
|
3200
|
+
if (!parseAssetId(asset3.assetId)) return false;
|
|
3201
|
+
const planned = await planFor(asset3);
|
|
3202
|
+
return planned !== void 0 && planned.error === void 0;
|
|
3203
|
+
},
|
|
3204
|
+
quote: async (req, ctx) => {
|
|
3205
|
+
const payTo = (0, import_sdk13.arkTarget)(req.raw);
|
|
3206
|
+
const asset3 = (0, import_sdk13.resolveAssetAmount)(CROSS_ASSET_RAIL, req);
|
|
3207
|
+
const wantAsset = parseAssetId(asset3.assetId);
|
|
3208
|
+
if (!wantAsset) {
|
|
3209
|
+
throw new Error(
|
|
3210
|
+
`${CROSS_ASSET_RAIL}: ${asset3.assetId} is not an asset id (expected 34 bytes of hex)`
|
|
3211
|
+
);
|
|
3212
|
+
}
|
|
3213
|
+
const planned = await planFor(asset3);
|
|
3214
|
+
if (!planned) {
|
|
3215
|
+
throw new Error(`${CROSS_ASSET_RAIL}: no market swaps BTC into ${asset3.assetId}`);
|
|
3216
|
+
}
|
|
3217
|
+
if (planned.error) {
|
|
3218
|
+
throw new Error(
|
|
3219
|
+
`${CROSS_ASSET_RAIL}: cannot swap into ${asset3.assetId} \u2014 ${planned.error}`
|
|
3220
|
+
);
|
|
3221
|
+
}
|
|
3222
|
+
const { plan } = planned;
|
|
3223
|
+
if (!Number.isSafeInteger(Number(plan.deposit.atomic))) {
|
|
3224
|
+
throw new Error(
|
|
3225
|
+
`${CROSS_ASSET_RAIL}: deposit of ${plan.deposit.atomic} does not fit a JS number`
|
|
3226
|
+
);
|
|
3227
|
+
}
|
|
3228
|
+
const depositSats = Number(plan.deposit.atomic);
|
|
3229
|
+
const carrier = deps.carrierSats ?? DEFAULT_CARRIER_SATS;
|
|
3230
|
+
return {
|
|
3231
|
+
railId: CROSS_ASSET_RAIL,
|
|
3232
|
+
// OPEN QUESTION for review: `total = amount + fee` forces the
|
|
3233
|
+
// purchase price into `fee`, which reads as a service charge.
|
|
3234
|
+
// A third field instead? `assets.spent` labels it correctly.
|
|
3235
|
+
amount: carrier,
|
|
3236
|
+
fee: depositSats,
|
|
3237
|
+
total: depositSats + carrier,
|
|
3238
|
+
assets: {
|
|
3239
|
+
delivered: asset3,
|
|
3240
|
+
spent: { assetId: BTC_ASSET_ID, amount: plan.deposit.atomic }
|
|
3241
|
+
},
|
|
3242
|
+
meta: {
|
|
3243
|
+
market: plan.market.pair,
|
|
3244
|
+
priceDisplay: plan.priceDisplay,
|
|
3245
|
+
give: plan.give
|
|
3246
|
+
},
|
|
3247
|
+
send: async () => (0, import_sdk13.makeHandle)(CROSS_ASSET_RAIL, async (emit) => {
|
|
3248
|
+
const offer = await createOffer(ctx.wallet, deps.arkServerUrl, {
|
|
3249
|
+
wantAmount: asset3.amount,
|
|
3250
|
+
wantAsset,
|
|
3251
|
+
...deps.emulatorPubkey ? { emulatorPubkey: deps.emulatorPubkey } : {}
|
|
3252
|
+
});
|
|
3253
|
+
const swap = {
|
|
3254
|
+
phase: "quoted",
|
|
3255
|
+
offerHex: offer.offerHex,
|
|
3256
|
+
address: offer.address,
|
|
3257
|
+
swapPkScript: offer.swapPkScript,
|
|
3258
|
+
depositSats,
|
|
3259
|
+
asset: asset3,
|
|
3260
|
+
payTo,
|
|
3261
|
+
plan
|
|
3262
|
+
};
|
|
3263
|
+
await deps.persist(swap);
|
|
3264
|
+
await ctx.wallet.send({
|
|
3265
|
+
address: offer.address,
|
|
3266
|
+
amount: depositSats,
|
|
3267
|
+
extensions: [offer.extension]
|
|
3268
|
+
});
|
|
3269
|
+
emit({ status: "sent" });
|
|
3270
|
+
await deps.awaitFill(swap);
|
|
3271
|
+
await deps.persist({ ...swap, phase: "filled" });
|
|
3272
|
+
await deps.persist({ ...swap, phase: "paying" });
|
|
3273
|
+
const txid = await ctx.wallet.send({
|
|
3274
|
+
address: payTo,
|
|
3275
|
+
amount: carrier,
|
|
3276
|
+
assets: [asset3]
|
|
3277
|
+
});
|
|
3278
|
+
await deps.persist({ ...swap, phase: "settled", txid });
|
|
3279
|
+
const result = {
|
|
3280
|
+
railId: CROSS_ASSET_RAIL,
|
|
3281
|
+
txid,
|
|
3282
|
+
swapId: offer.offerHex
|
|
3283
|
+
};
|
|
3284
|
+
emit({ status: "settled", result });
|
|
3285
|
+
return result;
|
|
3286
|
+
})
|
|
3287
|
+
};
|
|
3288
|
+
}
|
|
3289
|
+
};
|
|
3290
|
+
}
|
|
3291
|
+
|
|
3292
|
+
// src/reveal.ts
|
|
3293
|
+
var import_base13 = require("@scure/base");
|
|
3162
3294
|
var import_legacy3 = require("@noble/hashes/legacy.js");
|
|
3163
|
-
var
|
|
3295
|
+
var import_sha24 = require("@noble/hashes/sha2.js");
|
|
3164
3296
|
var import_sdk14 = require("@arkade-os/sdk");
|
|
3297
|
+
var CovclaimdRevealError = class extends Error {
|
|
3298
|
+
name = "CovclaimdRevealError";
|
|
3299
|
+
status;
|
|
3300
|
+
detail;
|
|
3301
|
+
retryable;
|
|
3302
|
+
constructor(what, status, detail) {
|
|
3303
|
+
super(`covclaimd ${what} failed: ${status || "no response"} ${detail}`.trimEnd());
|
|
3304
|
+
this.status = status;
|
|
3305
|
+
this.detail = detail;
|
|
3306
|
+
this.retryable = status === 0 || status === 429 || status >= 500;
|
|
3307
|
+
}
|
|
3308
|
+
};
|
|
3309
|
+
var decodeKey = (value, field) => {
|
|
3310
|
+
if (typeof value !== "string") throw new Error(`covclaimd info: ${field} is not a string`);
|
|
3311
|
+
let bytes;
|
|
3312
|
+
try {
|
|
3313
|
+
bytes = import_base13.hex.decode(value);
|
|
3314
|
+
} catch {
|
|
3315
|
+
throw new Error(`covclaimd info: ${field} is not hex`);
|
|
3316
|
+
}
|
|
3317
|
+
if (bytes.length !== 33) {
|
|
3318
|
+
throw new Error(`covclaimd info: ${field} must be 33-byte compressed, got ${bytes.length}`);
|
|
3319
|
+
}
|
|
3320
|
+
return bytes;
|
|
3321
|
+
};
|
|
3322
|
+
var LOOPBACK = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
3323
|
+
var assertTransportSecure = (baseUrl, allowInsecureHttp) => {
|
|
3324
|
+
const { protocol, hostname } = new URL(baseUrl);
|
|
3325
|
+
if (protocol === "https:" || allowInsecureHttp) return;
|
|
3326
|
+
if (protocol === "http:" && LOOPBACK.has(hostname)) return;
|
|
3327
|
+
throw new Error(
|
|
3328
|
+
`covclaimd URL must be https (got ${protocol}//${hostname}): the key it serves is the one the preimage gets sealed to. Pass allowInsecureHttp to override.`
|
|
3329
|
+
);
|
|
3330
|
+
};
|
|
3331
|
+
var covclaimdClient = (baseUrl, options = {}) => {
|
|
3332
|
+
assertTransportSecure(baseUrl, options.allowInsecureHttp === true);
|
|
3333
|
+
const url = baseUrl.replace(/\/+$/, "");
|
|
3334
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
3335
|
+
const timeoutMs = options.timeoutMs ?? 3e4;
|
|
3336
|
+
const send = async (what, path, init) => {
|
|
3337
|
+
let response;
|
|
3338
|
+
try {
|
|
3339
|
+
response = await fetchImpl(`${url}${path}`, {
|
|
3340
|
+
...init,
|
|
3341
|
+
// a redirect would move the key fetch off the vetted origin
|
|
3342
|
+
redirect: "error",
|
|
3343
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
3344
|
+
});
|
|
3345
|
+
} catch (error) {
|
|
3346
|
+
throw new CovclaimdRevealError(what, 0, String(error));
|
|
3347
|
+
}
|
|
3348
|
+
if (!response.ok) {
|
|
3349
|
+
throw new CovclaimdRevealError(what, response.status, await response.text());
|
|
3350
|
+
}
|
|
3351
|
+
return response;
|
|
3352
|
+
};
|
|
3353
|
+
const readJson = async (what, response) => {
|
|
3354
|
+
const body = await response.text();
|
|
3355
|
+
try {
|
|
3356
|
+
return JSON.parse(body);
|
|
3357
|
+
} catch {
|
|
3358
|
+
throw new CovclaimdRevealError(
|
|
3359
|
+
what,
|
|
3360
|
+
response.status,
|
|
3361
|
+
`non-JSON body: ${body.slice(0, 200)}`
|
|
3362
|
+
);
|
|
3363
|
+
}
|
|
3364
|
+
};
|
|
3365
|
+
return {
|
|
3366
|
+
async info() {
|
|
3367
|
+
const response = await send("info", "/v1/preimage/covclaimd-pubkey", {
|
|
3368
|
+
method: "GET"
|
|
3369
|
+
});
|
|
3370
|
+
const body = await readJson("info", response);
|
|
3371
|
+
return {
|
|
3372
|
+
covclaimdPubkey: decodeKey(body?.covclaimd_pub_key, "covclaimd_pub_key"),
|
|
3373
|
+
emulatorPubkey: import_base13.hex.encode(decodeKey(body?.emulator_pub_key, "emulator_pub_key"))
|
|
3374
|
+
};
|
|
3375
|
+
},
|
|
3376
|
+
async reveal(params) {
|
|
3377
|
+
await send("reveal", "/v1/reveal", {
|
|
3378
|
+
method: "POST",
|
|
3379
|
+
headers: { "content-type": "application/json" },
|
|
3380
|
+
body: JSON.stringify({
|
|
3381
|
+
swap_address: params.swapAddress,
|
|
3382
|
+
packet: { ciphertext: params.ciphertext, arkade_script: params.arkadeScript },
|
|
3383
|
+
taptree: params.taptree
|
|
3384
|
+
})
|
|
3385
|
+
});
|
|
3386
|
+
}
|
|
3387
|
+
};
|
|
3388
|
+
};
|
|
3389
|
+
function revealFieldsFromScript(script) {
|
|
3390
|
+
if (!script.nonInteractiveClaimArkadeScript) {
|
|
3391
|
+
throw new Error("this covenant has no non-interactive claim leaf to reveal against");
|
|
3392
|
+
}
|
|
3393
|
+
return {
|
|
3394
|
+
arkadeScript: import_base13.base64.encode(script.nonInteractiveClaimArkadeScript),
|
|
3395
|
+
taptree: import_base13.hex.encode(script.encode())
|
|
3396
|
+
};
|
|
3397
|
+
}
|
|
3398
|
+
async function revealClaimPacket(client, input) {
|
|
3399
|
+
const fields = revealFieldsFromScript(input.script);
|
|
3400
|
+
if (import_base13.hex.encode(import_sdk14.ArkAddress.decode(input.address).pkScript) !== import_base13.hex.encode(input.script.pkScript)) {
|
|
3401
|
+
throw new Error("address does not belong to this covenant");
|
|
3402
|
+
}
|
|
3403
|
+
if (import_base13.hex.encode((0, import_legacy3.ripemd160)((0, import_sha24.sha256)(input.preimage))) !== import_base13.hex.encode(input.script.options.preimageHash)) {
|
|
3404
|
+
throw new Error("preimage does not match the covenant's payment hash");
|
|
3405
|
+
}
|
|
3406
|
+
const { ciphertext } = await sealClaimPacket({
|
|
3407
|
+
preimage: input.preimage,
|
|
3408
|
+
covclaimdPubkey: (await client.info()).covclaimdPubkey
|
|
3409
|
+
});
|
|
3410
|
+
await client.reveal({ swapAddress: input.address, ciphertext, ...fields });
|
|
3411
|
+
return { ciphertext };
|
|
3412
|
+
}
|
|
3413
|
+
|
|
3414
|
+
// src/claim.ts
|
|
3415
|
+
var import_base15 = require("@scure/base");
|
|
3416
|
+
var import_legacy4 = require("@noble/hashes/legacy.js");
|
|
3417
|
+
var import_sha26 = require("@noble/hashes/sha2.js");
|
|
3418
|
+
var import_sdk16 = require("@arkade-os/sdk");
|
|
3165
3419
|
|
|
3166
3420
|
// src/refund.ts
|
|
3167
|
-
var
|
|
3168
|
-
var
|
|
3169
|
-
var
|
|
3421
|
+
var import_base14 = require("@scure/base");
|
|
3422
|
+
var import_sha25 = require("@noble/hashes/sha2.js");
|
|
3423
|
+
var import_sdk15 = require("@arkade-os/sdk");
|
|
3170
3424
|
var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
3171
3425
|
var isRfqTerminal = (state) => RFQ_TERMINAL_STATES.includes(state);
|
|
3172
3426
|
var RFQ_RESOLVED_STATES = ["settled", "refunded"];
|
|
@@ -3213,7 +3467,7 @@ var LockupNeedsRecoveryError = class extends Error {
|
|
|
3213
3467
|
}
|
|
3214
3468
|
};
|
|
3215
3469
|
async function findLockupVtxos(indexer, swapPkScript) {
|
|
3216
|
-
const scripts = [
|
|
3470
|
+
const scripts = [import_base14.hex.encode(swapPkScript)];
|
|
3217
3471
|
const [spendable, recoverable] = await Promise.all([
|
|
3218
3472
|
indexer.getVtxos({ scripts, spendableOnly: true }),
|
|
3219
3473
|
indexer.getVtxos({ scripts, recoverableOnly: true })
|
|
@@ -3239,16 +3493,16 @@ async function findLockupVtxos(indexer, swapPkScript) {
|
|
|
3239
3493
|
}
|
|
3240
3494
|
return out;
|
|
3241
3495
|
}
|
|
3242
|
-
var hashesTo = (candidate, paymentHash) =>
|
|
3496
|
+
var hashesTo = (candidate, paymentHash) => import_base14.hex.encode((0, import_sha25.sha256)(candidate)) === paymentHash;
|
|
3243
3497
|
var candidateWitnessItems = (tx, inputIndex) => [
|
|
3244
|
-
...(0,
|
|
3498
|
+
...(0, import_sdk15.getArkPsbtFields)(tx, inputIndex, import_sdk15.ConditionWitness).flat(),
|
|
3245
3499
|
...tx.getInput(inputIndex).finalScriptWitness ?? []
|
|
3246
3500
|
];
|
|
3247
3501
|
async function readLockupFate(indexer, input) {
|
|
3248
|
-
const { vtxos } = await indexer.getVtxos({ scripts: [
|
|
3502
|
+
const { vtxos } = await indexer.getVtxos({ scripts: [import_base14.hex.encode(input.swapPkScript)] });
|
|
3249
3503
|
const all = vtxos ?? [];
|
|
3250
3504
|
if (all.length === 0) return { fate: "unknown" };
|
|
3251
|
-
const exited = all.filter((vtxo) => vtxo.isUnrolled && !(0,
|
|
3505
|
+
const exited = all.filter((vtxo) => vtxo.isUnrolled && !(0, import_sdk15.hasTerminalSpend)(vtxo));
|
|
3252
3506
|
if (exited.length > 0) {
|
|
3253
3507
|
return {
|
|
3254
3508
|
fate: "exited",
|
|
@@ -3258,7 +3512,7 @@ async function readLockupFate(indexer, input) {
|
|
|
3258
3512
|
const spentBy = /* @__PURE__ */ new Map();
|
|
3259
3513
|
let everySpendNamed = true;
|
|
3260
3514
|
for (const vtxo of all) {
|
|
3261
|
-
if (!(0,
|
|
3515
|
+
if (!(0, import_sdk15.hasTerminalSpend)(vtxo)) return { fate: "open" };
|
|
3262
3516
|
if (vtxo.spentBy)
|
|
3263
3517
|
spentBy.set(vtxo.spentBy, {
|
|
3264
3518
|
checkpointTxid: vtxo.spentBy,
|
|
@@ -3272,7 +3526,7 @@ async function readLockupFate(indexer, input) {
|
|
|
3272
3526
|
for (const raw of txs) {
|
|
3273
3527
|
let tx;
|
|
3274
3528
|
try {
|
|
3275
|
-
tx =
|
|
3529
|
+
tx = import_sdk15.Transaction.fromPSBT(import_base14.base64.decode(raw));
|
|
3276
3530
|
} catch {
|
|
3277
3531
|
continue;
|
|
3278
3532
|
}
|
|
@@ -3280,7 +3534,7 @@ async function readLockupFate(indexer, input) {
|
|
|
3280
3534
|
for (let i = 0; i < tx.inputsLength; i++) {
|
|
3281
3535
|
const spent = tx.getInput(i);
|
|
3282
3536
|
if (!spent.txid) continue;
|
|
3283
|
-
const txid =
|
|
3537
|
+
const txid = import_base14.hex.encode(spent.txid);
|
|
3284
3538
|
if (!all.some((vtxo) => vtxo.txid === txid && vtxo.vout === spent.index)) continue;
|
|
3285
3539
|
for (const candidate of candidateWitnessItems(tx, i)) {
|
|
3286
3540
|
if (hashesTo(candidate, input.paymentHash)) {
|
|
@@ -3309,14 +3563,14 @@ async function pushRefundWithoutReceiver(ark, input) {
|
|
|
3309
3563
|
const info = await ark.getInfo();
|
|
3310
3564
|
let serverUnrollScript;
|
|
3311
3565
|
try {
|
|
3312
|
-
serverUnrollScript =
|
|
3566
|
+
serverUnrollScript = import_sdk15.CSVMultisigTapscript.decode(import_base14.hex.decode(info.checkpointTapscript));
|
|
3313
3567
|
} catch {
|
|
3314
3568
|
throw new Error("invalid checkpointTapscript from the Arkade server");
|
|
3315
3569
|
}
|
|
3316
3570
|
const leaf = input.script.refundWithoutReceiver();
|
|
3317
3571
|
const tapTree = input.script.encode();
|
|
3318
3572
|
const amount = input.vtxos.reduce((sum, vtxo) => sum + vtxo.value, 0);
|
|
3319
|
-
const { arkTx, checkpoints } = (0,
|
|
3573
|
+
const { arkTx, checkpoints } = (0, import_sdk15.buildOffchainTx)(
|
|
3320
3574
|
input.vtxos.map((vtxo) => ({
|
|
3321
3575
|
txid: vtxo.txid,
|
|
3322
3576
|
vout: vtxo.vout,
|
|
@@ -3329,18 +3583,18 @@ async function pushRefundWithoutReceiver(ark, input) {
|
|
|
3329
3583
|
);
|
|
3330
3584
|
const signedArkTx = await input.sender.sign(arkTx);
|
|
3331
3585
|
const submitted = await ark.submitTx(
|
|
3332
|
-
|
|
3333
|
-
checkpoints.map((c) =>
|
|
3586
|
+
import_base14.base64.encode(signedArkTx.toPSBT()),
|
|
3587
|
+
checkpoints.map((c) => import_base14.base64.encode(c.toPSBT()))
|
|
3334
3588
|
);
|
|
3335
|
-
(0,
|
|
3336
|
-
const matched = (0,
|
|
3589
|
+
(0, import_sdk15.assertSubmittedArkTxid)(submitted, signedArkTx, "refundWithoutReceiver");
|
|
3590
|
+
const matched = (0, import_sdk15.matchServerCheckpoints)(
|
|
3337
3591
|
submitted.signedCheckpointTxs,
|
|
3338
3592
|
checkpoints,
|
|
3339
3593
|
"refundWithoutReceiver"
|
|
3340
3594
|
);
|
|
3341
3595
|
const finalCheckpoints = await Promise.all(
|
|
3342
3596
|
matched.map(
|
|
3343
|
-
async ({ server }) =>
|
|
3597
|
+
async ({ server }) => import_base14.base64.encode((await input.sender.sign(server, [0])).toPSBT())
|
|
3344
3598
|
)
|
|
3345
3599
|
);
|
|
3346
3600
|
await ark.finalizeTx(submitted.arkTxid, finalCheckpoints);
|
|
@@ -3435,20 +3689,20 @@ async function pushClaim(ark, input) {
|
|
|
3435
3689
|
}
|
|
3436
3690
|
}
|
|
3437
3691
|
const committed = input.script.options.preimageHash;
|
|
3438
|
-
if (
|
|
3692
|
+
if (import_base15.hex.encode((0, import_legacy4.ripemd160)((0, import_sha26.sha256)(input.preimage))) !== import_base15.hex.encode(committed)) {
|
|
3439
3693
|
throw new Error("preimage does not match the covenant's payment hash");
|
|
3440
3694
|
}
|
|
3441
3695
|
const info = await ark.getInfo();
|
|
3442
3696
|
let serverUnrollScript;
|
|
3443
3697
|
try {
|
|
3444
|
-
serverUnrollScript =
|
|
3698
|
+
serverUnrollScript = import_sdk16.CSVMultisigTapscript.decode(import_base15.hex.decode(info.checkpointTapscript));
|
|
3445
3699
|
} catch {
|
|
3446
3700
|
throw new Error("invalid checkpointTapscript from the Arkade server");
|
|
3447
3701
|
}
|
|
3448
3702
|
const leaf = input.script.claim();
|
|
3449
3703
|
const tapTree = input.script.encode();
|
|
3450
|
-
const arkTxid = await (0,
|
|
3451
|
-
identity: (0,
|
|
3704
|
+
const arkTxid = await (0, import_sdk16.signAndSubmitOffchainTx)({
|
|
3705
|
+
identity: (0, import_sdk16.claimWithPreimageIdentity)(input.receiver, input.preimage),
|
|
3452
3706
|
provider: ark,
|
|
3453
3707
|
inputs: input.vtxos.map((vtxo) => ({
|
|
3454
3708
|
txid: vtxo.txid,
|
|
@@ -3495,7 +3749,7 @@ async function claimReceiveLockup(indexer, ark, input) {
|
|
|
3495
3749
|
}
|
|
3496
3750
|
|
|
3497
3751
|
// src/refundBlocked.ts
|
|
3498
|
-
var
|
|
3752
|
+
var import_sdk17 = require("@arkade-os/sdk");
|
|
3499
3753
|
var RefundNotLocallyPossibleError = class extends Error {
|
|
3500
3754
|
constructor(reason, message, options) {
|
|
3501
3755
|
super(message, options);
|
|
@@ -3512,16 +3766,16 @@ async function senderIdentityForSwapRecord(wallet, record) {
|
|
|
3512
3766
|
);
|
|
3513
3767
|
}
|
|
3514
3768
|
try {
|
|
3515
|
-
return await (0,
|
|
3769
|
+
return await (0, import_sdk17.contractSigner)(wallet, record.signingDescriptor);
|
|
3516
3770
|
} catch (cause) {
|
|
3517
|
-
if (cause instanceof
|
|
3771
|
+
if (cause instanceof import_sdk17.WalletCannotSignError) {
|
|
3518
3772
|
throw new RefundNotLocallyPossibleError(
|
|
3519
3773
|
"unsignable-wallet",
|
|
3520
3774
|
`this wallet holds ${record.signingDescriptor} but cannot sign with it; attach its signer`,
|
|
3521
3775
|
{ cause }
|
|
3522
3776
|
);
|
|
3523
3777
|
}
|
|
3524
|
-
if (cause instanceof
|
|
3778
|
+
if (cause instanceof import_sdk17.ForeignDescriptorError) {
|
|
3525
3779
|
throw new RefundNotLocallyPossibleError(
|
|
3526
3780
|
"foreign-descriptor",
|
|
3527
3781
|
`this wallet cannot derive ${record.signingDescriptor}; the swap was created on another wallet`,
|
|
@@ -3556,7 +3810,8 @@ function arkadeRefunder(deps) {
|
|
|
3556
3810
|
}
|
|
3557
3811
|
|
|
3558
3812
|
// src/swapManager.ts
|
|
3559
|
-
var
|
|
3813
|
+
var import_base16 = require("@scure/base");
|
|
3814
|
+
var import_sdk18 = require("@arkade-os/sdk");
|
|
3560
3815
|
function nextOnchainAction(input) {
|
|
3561
3816
|
switch (input.phase.phase) {
|
|
3562
3817
|
case "unfunded":
|
|
@@ -4004,7 +4259,7 @@ var RfqSwapManager = class {
|
|
|
4004
4259
|
// ── internals ────────────────────────────────────────────────────────────
|
|
4005
4260
|
track(swap) {
|
|
4006
4261
|
this.monitored.set(swap.rfqId, swap);
|
|
4007
|
-
this.byLockupScript.set(
|
|
4262
|
+
this.byLockupScript.set(import_base16.hex.encode(swap.lockupPkScript), swap);
|
|
4008
4263
|
}
|
|
4009
4264
|
/** Drops the swap from BOTH indexes. The event index is the one that stops
|
|
4010
4265
|
* a late event finding a swap that is gone; `pollSwap`'s own
|
|
@@ -4013,7 +4268,7 @@ var RfqSwapManager = class {
|
|
|
4013
4268
|
* them from silently re-driving a cancelled swap. */
|
|
4014
4269
|
untrack(rfqId) {
|
|
4015
4270
|
const swap = this.monitored.get(rfqId);
|
|
4016
|
-
if (swap) this.byLockupScript.delete(
|
|
4271
|
+
if (swap) this.byLockupScript.delete(import_base16.hex.encode(swap.lockupPkScript));
|
|
4017
4272
|
this.monitored.delete(rfqId);
|
|
4018
4273
|
this.refundRefused.delete(rfqId);
|
|
4019
4274
|
this.lastClaimError.delete(rfqId);
|
|
@@ -4046,6 +4301,7 @@ var RfqSwapManager = class {
|
|
|
4046
4301
|
});
|
|
4047
4302
|
return;
|
|
4048
4303
|
}
|
|
4304
|
+
if (!(0, import_sdk18.isContractVtxoEvent)(event)) return;
|
|
4049
4305
|
const swap = this.byLockupScript.get(event.contractScript);
|
|
4050
4306
|
if (!swap) return;
|
|
4051
4307
|
void this.pollSwap(swap).catch(() => {
|
|
@@ -4075,7 +4331,7 @@ var RfqSwapManager = class {
|
|
|
4075
4331
|
if (!lockup) {
|
|
4076
4332
|
try {
|
|
4077
4333
|
const [existing] = await contracts.getContracts({
|
|
4078
|
-
script:
|
|
4334
|
+
script: import_base16.hex.encode(swap.lockupPkScript)
|
|
4079
4335
|
});
|
|
4080
4336
|
if (existing) {
|
|
4081
4337
|
this.registered.set(swap.rfqId, true);
|
|
@@ -4094,13 +4350,13 @@ var RfqSwapManager = class {
|
|
|
4094
4350
|
);
|
|
4095
4351
|
return;
|
|
4096
4352
|
}
|
|
4097
|
-
const script =
|
|
4098
|
-
if (script !==
|
|
4353
|
+
const script = import_base16.hex.encode(lockup.script.pkScript);
|
|
4354
|
+
if (script !== import_base16.hex.encode(swap.lockupPkScript)) {
|
|
4099
4355
|
this.registered.set(swap.rfqId, false);
|
|
4100
4356
|
this.emitFailed(
|
|
4101
4357
|
swap,
|
|
4102
4358
|
new Error(
|
|
4103
|
-
`swap ${swap.rfqId} lockup script ${script} does not match its lockupPkScript ${
|
|
4359
|
+
`swap ${swap.rfqId} lockup script ${script} does not match its lockupPkScript ${import_base16.hex.encode(swap.lockupPkScript)}`
|
|
4104
4360
|
)
|
|
4105
4361
|
);
|
|
4106
4362
|
return;
|
|
@@ -4119,7 +4375,7 @@ var RfqSwapManager = class {
|
|
|
4119
4375
|
* script for its whole life. Best-effort — the swap is over either way. */
|
|
4120
4376
|
retireContract(swap) {
|
|
4121
4377
|
if (!this.deps.contracts || !this.registered.get(swap.rfqId)) return;
|
|
4122
|
-
void this.deps.contracts.setContractWatchState(
|
|
4378
|
+
void this.deps.contracts.setContractWatchState(import_base16.hex.encode(swap.lockupPkScript), "retained").catch((error) => this.emitFailed(swap, error));
|
|
4123
4379
|
}
|
|
4124
4380
|
arm() {
|
|
4125
4381
|
if (!this.running) return;
|
|
@@ -4592,8 +4848,8 @@ var errorMessage = (error) => error instanceof Error ? error.message : String(er
|
|
|
4592
4848
|
var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
|
|
4593
4849
|
|
|
4594
4850
|
// src/activity.ts
|
|
4595
|
-
var
|
|
4596
|
-
var
|
|
4851
|
+
var import_sdk19 = require("@arkade-os/sdk");
|
|
4852
|
+
var import_base17 = require("@scure/base");
|
|
4597
4853
|
var LABELS = {
|
|
4598
4854
|
lightning_send: "Lightning send",
|
|
4599
4855
|
lightning_receive: "Lightning receive",
|
|
@@ -4668,7 +4924,7 @@ async function activityInputOf(record, indexer) {
|
|
|
4668
4924
|
async function lockupTxids(indexer, record, wantFunding) {
|
|
4669
4925
|
let script;
|
|
4670
4926
|
try {
|
|
4671
|
-
script =
|
|
4927
|
+
script = import_base17.hex.encode(import_sdk19.ArkAddress.decode(record.lockupAddress).pkScript);
|
|
4672
4928
|
} catch {
|
|
4673
4929
|
return [];
|
|
4674
4930
|
}
|
|
@@ -4690,6 +4946,8 @@ async function lockupTxids(indexer, record, wantFunding) {
|
|
|
4690
4946
|
ARKADE_BTC,
|
|
4691
4947
|
AddressMismatch,
|
|
4692
4948
|
BTC_ASSET_ID,
|
|
4949
|
+
CROSS_ASSET_RAIL,
|
|
4950
|
+
CovclaimdRevealError,
|
|
4693
4951
|
InMemoryAssetSwapRepository,
|
|
4694
4952
|
IndexedDbAssetSwapRepository,
|
|
4695
4953
|
LIGHTNING_BTC,
|
|
@@ -4746,8 +5004,10 @@ async function lockupTxids(indexer, record, wantFunding) {
|
|
|
4746
5004
|
classifyDepositSpend,
|
|
4747
5005
|
classifyOnchainHtlc,
|
|
4748
5006
|
classifySpend,
|
|
5007
|
+
covclaimdClient,
|
|
4749
5008
|
createOffer,
|
|
4750
5009
|
createRfqSwapRecord,
|
|
5010
|
+
crossAssetRail,
|
|
4751
5011
|
decodeOffer,
|
|
4752
5012
|
deriveLightningReceive,
|
|
4753
5013
|
deriveOnchainReceive,
|
|
@@ -4793,6 +5053,8 @@ async function lockupTxids(indexer, record, wantFunding) {
|
|
|
4793
5053
|
requestOnchainSend,
|
|
4794
5054
|
restoreAssetSwaps,
|
|
4795
5055
|
retireSettledOfferContracts,
|
|
5056
|
+
revealClaimPacket,
|
|
5057
|
+
revealFieldsFromScript,
|
|
4796
5058
|
rfqClaimSecretOf,
|
|
4797
5059
|
rfqPair,
|
|
4798
5060
|
rfqSecretsProfile,
|