@arkade-os/swap 0.0.12 → 0.0.13
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 +308 -48
- package/dist/index.d.cts +131 -6
- package/dist/index.d.ts +131 -6
- package/dist/index.js +297 -30
- 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,
|
|
@@ -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,7 @@ function arkadeRefunder(deps) {
|
|
|
3556
3810
|
}
|
|
3557
3811
|
|
|
3558
3812
|
// src/swapManager.ts
|
|
3559
|
-
var
|
|
3813
|
+
var import_base16 = require("@scure/base");
|
|
3560
3814
|
function nextOnchainAction(input) {
|
|
3561
3815
|
switch (input.phase.phase) {
|
|
3562
3816
|
case "unfunded":
|
|
@@ -4004,7 +4258,7 @@ var RfqSwapManager = class {
|
|
|
4004
4258
|
// ── internals ────────────────────────────────────────────────────────────
|
|
4005
4259
|
track(swap) {
|
|
4006
4260
|
this.monitored.set(swap.rfqId, swap);
|
|
4007
|
-
this.byLockupScript.set(
|
|
4261
|
+
this.byLockupScript.set(import_base16.hex.encode(swap.lockupPkScript), swap);
|
|
4008
4262
|
}
|
|
4009
4263
|
/** Drops the swap from BOTH indexes. The event index is the one that stops
|
|
4010
4264
|
* a late event finding a swap that is gone; `pollSwap`'s own
|
|
@@ -4013,7 +4267,7 @@ var RfqSwapManager = class {
|
|
|
4013
4267
|
* them from silently re-driving a cancelled swap. */
|
|
4014
4268
|
untrack(rfqId) {
|
|
4015
4269
|
const swap = this.monitored.get(rfqId);
|
|
4016
|
-
if (swap) this.byLockupScript.delete(
|
|
4270
|
+
if (swap) this.byLockupScript.delete(import_base16.hex.encode(swap.lockupPkScript));
|
|
4017
4271
|
this.monitored.delete(rfqId);
|
|
4018
4272
|
this.refundRefused.delete(rfqId);
|
|
4019
4273
|
this.lastClaimError.delete(rfqId);
|
|
@@ -4075,7 +4329,7 @@ var RfqSwapManager = class {
|
|
|
4075
4329
|
if (!lockup) {
|
|
4076
4330
|
try {
|
|
4077
4331
|
const [existing] = await contracts.getContracts({
|
|
4078
|
-
script:
|
|
4332
|
+
script: import_base16.hex.encode(swap.lockupPkScript)
|
|
4079
4333
|
});
|
|
4080
4334
|
if (existing) {
|
|
4081
4335
|
this.registered.set(swap.rfqId, true);
|
|
@@ -4094,13 +4348,13 @@ var RfqSwapManager = class {
|
|
|
4094
4348
|
);
|
|
4095
4349
|
return;
|
|
4096
4350
|
}
|
|
4097
|
-
const script =
|
|
4098
|
-
if (script !==
|
|
4351
|
+
const script = import_base16.hex.encode(lockup.script.pkScript);
|
|
4352
|
+
if (script !== import_base16.hex.encode(swap.lockupPkScript)) {
|
|
4099
4353
|
this.registered.set(swap.rfqId, false);
|
|
4100
4354
|
this.emitFailed(
|
|
4101
4355
|
swap,
|
|
4102
4356
|
new Error(
|
|
4103
|
-
`swap ${swap.rfqId} lockup script ${script} does not match its lockupPkScript ${
|
|
4357
|
+
`swap ${swap.rfqId} lockup script ${script} does not match its lockupPkScript ${import_base16.hex.encode(swap.lockupPkScript)}`
|
|
4104
4358
|
)
|
|
4105
4359
|
);
|
|
4106
4360
|
return;
|
|
@@ -4119,7 +4373,7 @@ var RfqSwapManager = class {
|
|
|
4119
4373
|
* script for its whole life. Best-effort — the swap is over either way. */
|
|
4120
4374
|
retireContract(swap) {
|
|
4121
4375
|
if (!this.deps.contracts || !this.registered.get(swap.rfqId)) return;
|
|
4122
|
-
void this.deps.contracts.setContractWatchState(
|
|
4376
|
+
void this.deps.contracts.setContractWatchState(import_base16.hex.encode(swap.lockupPkScript), "retained").catch((error) => this.emitFailed(swap, error));
|
|
4123
4377
|
}
|
|
4124
4378
|
arm() {
|
|
4125
4379
|
if (!this.running) return;
|
|
@@ -4592,8 +4846,8 @@ var errorMessage = (error) => error instanceof Error ? error.message : String(er
|
|
|
4592
4846
|
var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
|
|
4593
4847
|
|
|
4594
4848
|
// src/activity.ts
|
|
4595
|
-
var
|
|
4596
|
-
var
|
|
4849
|
+
var import_sdk18 = require("@arkade-os/sdk");
|
|
4850
|
+
var import_base17 = require("@scure/base");
|
|
4597
4851
|
var LABELS = {
|
|
4598
4852
|
lightning_send: "Lightning send",
|
|
4599
4853
|
lightning_receive: "Lightning receive",
|
|
@@ -4668,7 +4922,7 @@ async function activityInputOf(record, indexer) {
|
|
|
4668
4922
|
async function lockupTxids(indexer, record, wantFunding) {
|
|
4669
4923
|
let script;
|
|
4670
4924
|
try {
|
|
4671
|
-
script =
|
|
4925
|
+
script = import_base17.hex.encode(import_sdk18.ArkAddress.decode(record.lockupAddress).pkScript);
|
|
4672
4926
|
} catch {
|
|
4673
4927
|
return [];
|
|
4674
4928
|
}
|
|
@@ -4690,6 +4944,8 @@ async function lockupTxids(indexer, record, wantFunding) {
|
|
|
4690
4944
|
ARKADE_BTC,
|
|
4691
4945
|
AddressMismatch,
|
|
4692
4946
|
BTC_ASSET_ID,
|
|
4947
|
+
CROSS_ASSET_RAIL,
|
|
4948
|
+
CovclaimdRevealError,
|
|
4693
4949
|
InMemoryAssetSwapRepository,
|
|
4694
4950
|
IndexedDbAssetSwapRepository,
|
|
4695
4951
|
LIGHTNING_BTC,
|
|
@@ -4746,8 +5002,10 @@ async function lockupTxids(indexer, record, wantFunding) {
|
|
|
4746
5002
|
classifyDepositSpend,
|
|
4747
5003
|
classifyOnchainHtlc,
|
|
4748
5004
|
classifySpend,
|
|
5005
|
+
covclaimdClient,
|
|
4749
5006
|
createOffer,
|
|
4750
5007
|
createRfqSwapRecord,
|
|
5008
|
+
crossAssetRail,
|
|
4751
5009
|
decodeOffer,
|
|
4752
5010
|
deriveLightningReceive,
|
|
4753
5011
|
deriveOnchainReceive,
|
|
@@ -4793,6 +5051,8 @@ async function lockupTxids(indexer, record, wantFunding) {
|
|
|
4793
5051
|
requestOnchainSend,
|
|
4794
5052
|
restoreAssetSwaps,
|
|
4795
5053
|
retireSettledOfferContracts,
|
|
5054
|
+
revealClaimPacket,
|
|
5055
|
+
revealFieldsFromScript,
|
|
4796
5056
|
rfqClaimSecretOf,
|
|
4797
5057
|
rfqPair,
|
|
4798
5058
|
rfqSecretsProfile,
|