@arkade-os/swap 0.0.11 → 0.1.0-rc.0
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 +42 -15
- package/dist/{chunk-RIC5ZTZK.js → chunk-AM3NNUMR.js} +59 -53
- package/dist/index.cjs +585 -202
- package/dist/index.d.cts +127 -36
- package/dist/index.d.ts +127 -36
- package/dist/index.js +528 -157
- package/dist/nostr.cjs +4 -1
- 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 +4 -4
- package/dist/repositories/realm/index.d.ts +4 -4
- package/dist/repositories/sqlite/index.d.cts +2 -2
- package/dist/repositories/sqlite/index.d.ts +2 -2
- package/dist/{repository-CfE18Fif.d.ts → repository-BWP1UstE.d.cts} +84 -56
- package/dist/{repository-B02vsgcV.d.cts → repository-DLpH41ZO.d.ts} +84 -56
- package/dist/{rfq-DkckzRKK.d.ts → rfq-CzCGjICq.d.cts} +42 -32
- package/dist/{rfq-DkckzRKK.d.cts → rfq-CzCGjICq.d.ts} +42 -32
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -12,6 +12,33 @@ React Native does not, so install `react-native-get-random-values` (or `expo-cry
|
|
|
12
12
|
it before this package. `crypto.subtle` is not used. `EventSource` and `WebSocket` are needed only
|
|
13
13
|
by the watch and relay transports, both of which take an injected implementation.
|
|
14
14
|
|
|
15
|
+
The v2 swap client API is tracked in [V2_API.md](./V2_API.md). That document is
|
|
16
|
+
the package-level developer UX note for the new client surface as it lands; the
|
|
17
|
+
current README still documents the existing package exports and protocol
|
|
18
|
+
building blocks.
|
|
19
|
+
|
|
20
|
+
**The covenant-deriving entry points need a wallet and nothing else.** `createOffer`,
|
|
21
|
+
`requestLightningSend`, `requestLightningReceive`, `requestOnchainSend` and
|
|
22
|
+
`requestOnchainReceive` take their server facts from `wallet.getArkadeInfo()`: the network and
|
|
23
|
+
signer key, plus the unilateral-exit delay for the four `request*` calls. The wallet is the single
|
|
24
|
+
place that knows which server it speaks to, so there is no URL to thread through and no second
|
|
25
|
+
`/v1/info` round-trip *per call*. Each entrypoint still performs its own live read (deliberately —
|
|
26
|
+
covenant derivation requires live info and fails closed offline); a session creating many offers
|
|
27
|
+
pays one read per offer until the SDK grows a `CachingClientTransport`-style memo (the NArk
|
|
28
|
+
reference's answer), noted as follow-up on `ArkadeInfo`.
|
|
29
|
+
|
|
30
|
+
No offer entrypoint here takes a server URL. `cancelOffer` and `watchOfferSwaps` need more than
|
|
31
|
+
server info — cancel broadcasts the refund and falls back to the indexer for a deposit made
|
|
32
|
+
before contract registration existed, and the watcher reads spending transactions — so they
|
|
33
|
+
ask the wallet for those too: `wallet.getArkadeReader()` for chain reads and
|
|
34
|
+
`wallet.getArkadeBroadcaster()` for `submitTx`/`finalizeTx`. On a service-worker wallet both
|
|
35
|
+
are proxied to the worker, so these reads stay on the wallet's own connection.
|
|
36
|
+
The RFQ restore/refund/claim helpers still take provider instances. An `ArkadeReader`
|
|
37
|
+
satisfies their *indexer* parameter structurally — `restoreAssetSwaps` can be fed
|
|
38
|
+
`await wallet.getArkadeReader()` today — while `arkadeRefunder` and `claim`/`refund` also
|
|
39
|
+
want an ark provider (`getInfo` plus the broadcast pair), buildable from
|
|
40
|
+
`wallet.getArkadeInfo()` and `wallet.getArkadeBroadcaster()`.
|
|
41
|
+
|
|
15
42
|
## Roles
|
|
16
43
|
|
|
17
44
|
Arkade Intents names two participants:
|
|
@@ -76,7 +103,7 @@ funds an offer should keep cancelling within reach.
|
|
|
76
103
|
|
|
77
104
|
1. **`offer`** — the swap covenant itself. Two program JSONs (want-BTC / want-asset), the
|
|
78
105
|
`Offer` type, the TLV wire codec (`encodeOffer`/`decodeOffer`, `OFFER_PACKET_TYPE`), address
|
|
79
|
-
derivation (`
|
|
106
|
+
derivation (`offerContract`), and the user-side operations `createOffer`/`cancelOffer`. Identical
|
|
80
107
|
offers always derive identical swap addresses — the program JSONs are hashed into the address,
|
|
81
108
|
so their bytes are frozen (guarded by a golden test).
|
|
82
109
|
2. **`markets`** — solver discovery and pricing guardrails: `discoverMarkets` (1-hour cached
|
|
@@ -128,8 +155,8 @@ Realm — since the two record types have different keys and no consumer wants t
|
|
|
128
155
|
|
|
129
156
|
**Records are stored whole.** The SQLite and Realm backends serialize each record to **JSON** in a
|
|
130
157
|
`data` column, with only `status` / `createdAt` (and an RFQ record's `state` / `updatedAt`) mapped
|
|
131
|
-
out for querying — so a field they do not know about survives, which is what
|
|
132
|
-
|
|
158
|
+
out for querying — so a field they do not know about survives, which is what a consumer's
|
|
159
|
+
cast-extended record relies on. It is also what keeps an RFQ record's corridor `profile`
|
|
133
160
|
intact: `profile.hashlock` is a nested object holding the payment hash and any preimage material, and
|
|
134
161
|
a field-mapped backend is exactly what would lose it. JSON is
|
|
135
162
|
the boundary, though, and it is narrower than IndexedDB's structured clone: a `Date` in a
|
|
@@ -200,11 +227,11 @@ the rest:
|
|
|
200
227
|
|
|
201
228
|
```ts
|
|
202
229
|
// BTC -> asset
|
|
203
|
-
const o = await createOffer(wallet,
|
|
230
|
+
const o = await createOffer(wallet, { wantAmount: 1000n, wantAsset });
|
|
204
231
|
await wallet.send({ address: o.address, amount: 1000, extensions: [o.extension] });
|
|
205
232
|
|
|
206
233
|
// asset -> BTC (the sats are the VTXO carrier for the asset)
|
|
207
|
-
const o = await createOffer(wallet,
|
|
234
|
+
const o = await createOffer(wallet, { wantAmount: 1000n, offerAsset });
|
|
208
235
|
await wallet.send({
|
|
209
236
|
address: o.address,
|
|
210
237
|
amount: 500,
|
|
@@ -238,7 +265,7 @@ offer bytes themselves are recoverable from the funding tx if the record is lost
|
|
|
238
265
|
## Live status
|
|
239
266
|
|
|
240
267
|
```ts
|
|
241
|
-
const watcher = await watchOfferSwaps({ wallet,
|
|
268
|
+
const watcher = await watchOfferSwaps({ wallet, repository, onUpdate: render });
|
|
242
269
|
// later
|
|
243
270
|
watcher.stop();
|
|
244
271
|
```
|
|
@@ -260,7 +287,7 @@ repository.
|
|
|
260
287
|
## Cancelling: the refund path
|
|
261
288
|
|
|
262
289
|
```ts
|
|
263
|
-
const txid = await cancelOffer(wallet,
|
|
290
|
+
const txid = await cancelOffer(wallet, swap.offerHex, {
|
|
264
291
|
repository,
|
|
265
292
|
fundingTxid: swap.fundingTxid,
|
|
266
293
|
swapAddress: swap.swapAddress,
|
|
@@ -322,7 +349,7 @@ message anywhere: **acceptance is funding**.
|
|
|
322
349
|
import { httpTransport, requestLightningSend } from "@arkade-os/swap";
|
|
323
350
|
|
|
324
351
|
// invoice facts from YOUR OWN decoder — the module takes facts, not a decoder
|
|
325
|
-
const swap = await requestLightningSend(wallet,
|
|
352
|
+
const swap = await requestLightningSend(wallet, httpTransport(solverUrl), {
|
|
326
353
|
invoice: { raw: bolt11, paymentHash, amountSats, expiresAt },
|
|
327
354
|
});
|
|
328
355
|
// quote verified against the LOCAL derivation and gated; now fund and go offline:
|
|
@@ -395,7 +422,7 @@ import {
|
|
|
395
422
|
swapSecretsToRecord,
|
|
396
423
|
} from "@arkade-os/swap";
|
|
397
424
|
|
|
398
|
-
const swap = await requestOnchainSend(wallet,
|
|
425
|
+
const swap = await requestOnchainSend(wallet, httpTransport(solverUrl), {
|
|
399
426
|
amount: 100_000,
|
|
400
427
|
amountSide: "to",
|
|
401
428
|
payoutPubkey,
|
|
@@ -829,7 +856,7 @@ Notes from before 0.0.1, kept for consumers who tracked the branch.
|
|
|
829
856
|
silently overwritten.
|
|
830
857
|
- **`readLockupFate` names the spends it observed.** `claimed` and `returned` now carry
|
|
831
858
|
`spends: readonly LockupSpend[]`, one per spent lockup output, with the `checkpointTxid` that
|
|
832
|
-
`spentBy` names and the `
|
|
859
|
+
`spentBy` names and the `txid` that rode it. History correlation wants `txid`; the
|
|
833
860
|
checkpoint txid is the wrong value to correlate on alone. `unknown` and `open` claim no spend.
|
|
834
861
|
|
|
835
862
|
- **Every derived address changed again, in both corridors — the unilateral ladder was re-spaced.**
|
|
@@ -901,8 +928,8 @@ stored?)`. The returned `ProvisionedKey` / `ProvisionedClaimSecret` replace `Swa
|
|
|
901
928
|
quote at `verifyLockupAddress`. Upgrade both sides before expecting fills.
|
|
902
929
|
- **`cancelOffer` and `restoreAssetSwaps` take an options object.** `cancelOffer(wallet, url,
|
|
903
930
|
offerHex, { repository, fundingTxid?, swapAddress? })` — the repository is required because the
|
|
904
|
-
call now records its own outcome. `restoreAssetSwaps(indexer, txs, existingIds, {
|
|
905
|
-
scanned? })` — the
|
|
931
|
+
call now records its own outcome. `restoreAssetSwaps(indexer, txs, existingIds, { operatorPubkey,
|
|
932
|
+
scanned? })` — the operator key is required because a spend is classified by rebuilding the
|
|
906
933
|
covenant and matching the leaf it took.
|
|
907
934
|
- **`isCancelSpend` is gone**, replaced by `classifySpend`, and `Tx.assets` with it. The old test
|
|
908
935
|
read what a transaction moved, which a wallet reports as a _net_ delta: once the deposit is a
|
|
@@ -944,7 +971,7 @@ scanned? })` — the server key is required because a spend is classified by reb
|
|
|
944
971
|
kind: "lightning_receive",
|
|
945
972
|
lockupAddress: result.address,
|
|
946
973
|
profile: {
|
|
947
|
-
...rfqSecretsProfile(result.secrets, result.
|
|
974
|
+
...rfqSecretsProfile(result.secrets, result.contractParams.paymentHash),
|
|
948
975
|
expectedAmount: result.expectedAmount,
|
|
949
976
|
payoutAddress: result.payoutAddress,
|
|
950
977
|
},
|
|
@@ -1014,7 +1041,7 @@ scanned? })` — the server key is required because a spend is classified by reb
|
|
|
1014
1041
|
when `persisted` is true — the callback is documented as following a persisted change, and a
|
|
1015
1042
|
consumer caching from it must not run ahead of the store.
|
|
1016
1043
|
- **`lightningSendProgram` and `htlcSendProgram` are gone** along with the program-artifact layer
|
|
1017
|
-
they compiled. Derive scripts through `
|
|
1044
|
+
they compiled. Derive scripts through `lightningSendContract` / `onchainHtlcScript`.
|
|
1018
1045
|
- **The receive corridors are wired, and the wire shape settled.** `lightningReceiveRequest` is
|
|
1019
1046
|
new; `onchainReceiveRequest`'s profile now matches the shipped solver schema (`payment_hash`,
|
|
1020
1047
|
`claim_packet`, `refund_pubkey`, `payout_address`, `payout_pubkey` — the earlier
|
|
@@ -1025,7 +1052,7 @@ scanned? })` — the server key is required because a spend is classified by reb
|
|
|
1025
1052
|
corridor's fee — and refuses quotes whose `to_amount` reprices the invoice; solvers charge
|
|
1026
1053
|
per-corridor fees on all four pairs, and funding the bare invoice amount underfunds by exactly
|
|
1027
1054
|
the fee.
|
|
1028
|
-
- **`
|
|
1055
|
+
- **`lightningSendContract` takes two new required fields**: `senderPubkey` (the trader's VHTLC
|
|
1029
1056
|
sender key — generate, persist, see `requestLightningSend`) and `receiverPkScript` (the solver's
|
|
1030
1057
|
claim destination, from `profile.receiver_pk_script`). Callers that built the lockup directly
|
|
1031
1058
|
must supply both; callers going through `requestLightningSend` are unaffected.
|
|
@@ -309,9 +309,8 @@ import { hex as hex3 } from "@scure/base";
|
|
|
309
309
|
import { ripemd160 as ripemd1602 } from "@noble/hashes/legacy.js";
|
|
310
310
|
import {
|
|
311
311
|
ArkAddress as ArkAddress2,
|
|
312
|
-
RestArkProvider,
|
|
313
312
|
VHTLC,
|
|
314
|
-
|
|
313
|
+
networkFromArkadeInfo,
|
|
315
314
|
resolveEmulatorPubkey,
|
|
316
315
|
toXOnly
|
|
317
316
|
} from "@arkade-os/sdk";
|
|
@@ -338,11 +337,14 @@ var ONCHAIN_SEND_PAIR = rfqPair(ARKADE_BTC, ONCHAIN_BTC);
|
|
|
338
337
|
var ONCHAIN_RECEIVE_PAIR = rfqPair(ONCHAIN_BTC, ARKADE_BTC);
|
|
339
338
|
var RFQ_TERMINAL_STATES = ["settled", "refused", "expired", "refunded", "stuck"];
|
|
340
339
|
var SwapRefusal = class extends Error {
|
|
340
|
+
/** Literal-typed so the v2 error taxonomy's union discriminates on `name`
|
|
341
|
+
* — a `string` here collapses the discriminant for every member. Same value
|
|
342
|
+
* the constructor has always set, moved to a field initializer. */
|
|
343
|
+
name = "SwapRefusal";
|
|
341
344
|
reason;
|
|
342
345
|
rfqId;
|
|
343
346
|
constructor(reason, rfqId) {
|
|
344
347
|
super(`solver refused: ${reason}`);
|
|
345
|
-
this.name = "SwapRefusal";
|
|
346
348
|
this.reason = reason;
|
|
347
349
|
this.rfqId = rfqId;
|
|
348
350
|
}
|
|
@@ -608,22 +610,22 @@ var relayTransport = (relayUrl, options) => {
|
|
|
608
610
|
};
|
|
609
611
|
var SEQUENCE_GRANULARITY_SECONDS = 512;
|
|
610
612
|
var SOLO_REFUND_HEADROOM_SECONDS = 8 * SEQUENCE_GRANULARITY_SECONDS;
|
|
611
|
-
var unilateralClaimDelay = (
|
|
612
|
-
if (!Number.isFinite(
|
|
613
|
+
var unilateralClaimDelay = (operatorExitDelaySeconds) => {
|
|
614
|
+
if (!Number.isFinite(operatorExitDelaySeconds) || operatorExitDelaySeconds < SEQUENCE_GRANULARITY_SECONDS) {
|
|
613
615
|
throw new Error(
|
|
614
|
-
`
|
|
616
|
+
`operator exit delay must be at least ${SEQUENCE_GRANULARITY_SECONDS}s of seconds, got ${operatorExitDelaySeconds}`
|
|
615
617
|
);
|
|
616
618
|
}
|
|
617
|
-
if (
|
|
619
|
+
if (operatorExitDelaySeconds > 65535 * SEQUENCE_GRANULARITY_SECONDS - SOLO_REFUND_HEADROOM_SECONDS) {
|
|
618
620
|
throw new Error(
|
|
619
|
-
`
|
|
621
|
+
`operator exit delay ${operatorExitDelaySeconds}s exceeds what BIP68 can encode once the solo refund's headroom is stacked above it`
|
|
620
622
|
);
|
|
621
623
|
}
|
|
622
|
-
return Math.ceil(
|
|
624
|
+
return Math.ceil(operatorExitDelaySeconds / SEQUENCE_GRANULARITY_SECONDS) * SEQUENCE_GRANULARITY_SECONDS;
|
|
623
625
|
};
|
|
624
626
|
var unilateralRefundDelay = (claimDelay) => claimDelay;
|
|
625
627
|
var unilateralRefundWithoutReceiverDelay = (claimDelay) => claimDelay + SOLO_REFUND_HEADROOM_SECONDS;
|
|
626
|
-
function
|
|
628
|
+
function lightningSendContract(params) {
|
|
627
629
|
const seconds = (value) => ({
|
|
628
630
|
type: "seconds",
|
|
629
631
|
value: BigInt(value)
|
|
@@ -631,7 +633,7 @@ function lightningSendVtxoScript(params) {
|
|
|
631
633
|
return new VHTLC.ScriptV2({
|
|
632
634
|
sender: params.senderPubkey,
|
|
633
635
|
receiver: params.solverPubkey,
|
|
634
|
-
server: params.
|
|
636
|
+
server: params.operatorPubkey,
|
|
635
637
|
preimageHash: ripemd1602(hex3.decode(params.paymentHash)),
|
|
636
638
|
refundLocktime: BigInt(params.refundLocktime),
|
|
637
639
|
unilateralClaimDelay: seconds(params.claimDelay),
|
|
@@ -647,12 +649,12 @@ function lightningSendVtxoScript(params) {
|
|
|
647
649
|
}
|
|
648
650
|
});
|
|
649
651
|
}
|
|
650
|
-
async function requestLightningSend(wallet,
|
|
652
|
+
async function requestLightningSend(wallet, transport, params) {
|
|
651
653
|
const rfqId = params.rfqId ?? newRfqId();
|
|
652
654
|
const secrets = await provisionRefundKey(wallet);
|
|
653
655
|
const senderPubkey = secrets.pubkey;
|
|
654
656
|
const refundAddress = secrets.address;
|
|
655
|
-
const info = await
|
|
657
|
+
const info = await wallet.getArkadeInfo({ requireLive: true });
|
|
656
658
|
const quote = await transport.requestQuote(
|
|
657
659
|
lightningSendRequest({ rfqId, invoice: params.invoice.raw, refundAddress, senderPubkey })
|
|
658
660
|
);
|
|
@@ -673,12 +675,12 @@ async function requestLightningSend(wallet, arkServerUrl, transport, params) {
|
|
|
673
675
|
`quote from_amount ${quote.from_amount} is below the invoice amount \u2014 a negative spread is not a quote`
|
|
674
676
|
);
|
|
675
677
|
}
|
|
676
|
-
const
|
|
677
|
-
const network =
|
|
678
|
-
const
|
|
678
|
+
const operatorPubkey = toXOnly(hex3.decode(info.signerPubkey), "ark signer key");
|
|
679
|
+
const network = networkFromArkadeInfo(info);
|
|
680
|
+
const contractParams = {
|
|
679
681
|
solverPubkey: toXOnly(hex3.decode(quote.solver_pubkey), "solver key"),
|
|
680
682
|
refundLocktime: quote.refund_locktime,
|
|
681
|
-
|
|
683
|
+
operatorPubkey,
|
|
682
684
|
paymentHash: params.invoice.paymentHash,
|
|
683
685
|
claimDelay: unilateralClaimDelay(Number(info.unilateralExitDelay)),
|
|
684
686
|
emulatorPubkey: toXOnly(
|
|
@@ -692,13 +694,13 @@ async function requestLightningSend(wallet, arkServerUrl, transport, params) {
|
|
|
692
694
|
const matched = matchQuotedLockup(
|
|
693
695
|
quote,
|
|
694
696
|
network.hrp,
|
|
695
|
-
|
|
696
|
-
(legacy) =>
|
|
697
|
+
operatorPubkey,
|
|
698
|
+
(legacy) => lightningSendContract({ ...contractParams, ...legacy !== void 0 && { legacy } })
|
|
697
699
|
);
|
|
698
700
|
const script = matched.script;
|
|
699
701
|
const address = matched.address;
|
|
700
|
-
const
|
|
701
|
-
...
|
|
702
|
+
const matchedContractParams = {
|
|
703
|
+
...contractParams,
|
|
702
704
|
...matched.legacy !== void 0 && { legacy: matched.legacy }
|
|
703
705
|
};
|
|
704
706
|
assertFundable({
|
|
@@ -719,7 +721,7 @@ async function requestLightningSend(wallet, arkServerUrl, transport, params) {
|
|
|
719
721
|
refundAddress,
|
|
720
722
|
senderPubkey,
|
|
721
723
|
secrets,
|
|
722
|
-
|
|
724
|
+
contractParams: matchedContractParams
|
|
723
725
|
};
|
|
724
726
|
}
|
|
725
727
|
var offerTermsFromQuote = (quote, assets) => {
|
|
@@ -784,10 +786,10 @@ function deriveOnchainSend(input) {
|
|
|
784
786
|
if (refundLocktime === void 0 || htlcPubkey === void 0 || htlcLocktime === void 0 || minConfirmations === void 0 || receiverPkScriptHex === void 0) {
|
|
785
787
|
throw new Error("onchain-send quote is missing a binding field");
|
|
786
788
|
}
|
|
787
|
-
const
|
|
789
|
+
const contractParams = {
|
|
788
790
|
solverPubkey: toXOnly(hex3.decode(quote.solver_pubkey), "solver key"),
|
|
789
791
|
refundLocktime,
|
|
790
|
-
|
|
792
|
+
operatorPubkey: input.operatorPubkey,
|
|
791
793
|
paymentHash: input.paymentHash,
|
|
792
794
|
claimDelay: input.claimDelay,
|
|
793
795
|
emulatorPubkey: input.emulatorPubkey,
|
|
@@ -798,8 +800,8 @@ function deriveOnchainSend(input) {
|
|
|
798
800
|
const { script, address } = matchQuotedLockup(
|
|
799
801
|
quote,
|
|
800
802
|
input.hrp,
|
|
801
|
-
input.
|
|
802
|
-
(legacy) =>
|
|
803
|
+
input.operatorPubkey,
|
|
804
|
+
(legacy) => lightningSendContract({ ...contractParams, ...legacy !== void 0 && { legacy } })
|
|
803
805
|
);
|
|
804
806
|
const htlcParams = {
|
|
805
807
|
paymentHash: input.paymentHash,
|
|
@@ -821,7 +823,7 @@ function deriveOnchainSend(input) {
|
|
|
821
823
|
minConfirmations
|
|
822
824
|
};
|
|
823
825
|
}
|
|
824
|
-
async function requestOnchainSend(wallet,
|
|
826
|
+
async function requestOnchainSend(wallet, transport, params) {
|
|
825
827
|
const rfqId = params.rfqId ?? newRfqId();
|
|
826
828
|
const secrets = await provisionClaimSecret(wallet, { preimage: params.preimage });
|
|
827
829
|
if (secrets.mustPersistPreimage) {
|
|
@@ -832,7 +834,7 @@ async function requestOnchainSend(wallet, arkServerUrl, transport, params) {
|
|
|
832
834
|
const paymentHash = hex3.encode(secrets.paymentHash);
|
|
833
835
|
const senderPubkey = secrets.pubkey;
|
|
834
836
|
const [info, refundAddress] = await Promise.all([
|
|
835
|
-
|
|
837
|
+
wallet.getArkadeInfo({ requireLive: true }),
|
|
836
838
|
wallet.getAddress()
|
|
837
839
|
]);
|
|
838
840
|
const quote = await transport.requestQuote(
|
|
@@ -846,12 +848,12 @@ async function requestOnchainSend(wallet, arkServerUrl, transport, params) {
|
|
|
846
848
|
amountSide: params.amountSide
|
|
847
849
|
})
|
|
848
850
|
);
|
|
849
|
-
const network =
|
|
851
|
+
const network = networkFromArkadeInfo(info);
|
|
850
852
|
const derived = deriveOnchainSend({
|
|
851
853
|
quote,
|
|
852
854
|
paymentHash,
|
|
853
855
|
payoutPubkey: params.payoutPubkey,
|
|
854
|
-
|
|
856
|
+
operatorPubkey: toXOnly(hex3.decode(info.signerPubkey), "ark signer key"),
|
|
855
857
|
emulatorPubkey: toXOnly(
|
|
856
858
|
hex3.decode(resolveEmulatorPubkey(network, params.emulatorPubkey)),
|
|
857
859
|
"emulator signer key"
|
|
@@ -888,6 +890,7 @@ async function requestOnchainSend(wallet, arkServerUrl, transport, params) {
|
|
|
888
890
|
htlcParams: derived.htlcParams,
|
|
889
891
|
l1Network: derived.l1Network,
|
|
890
892
|
minConfirmations: derived.minConfirmations,
|
|
893
|
+
refundLocktime: derived.refundLocktime,
|
|
891
894
|
senderPubkey,
|
|
892
895
|
secrets
|
|
893
896
|
};
|
|
@@ -959,7 +962,7 @@ var assertReceivable = (input) => {
|
|
|
959
962
|
);
|
|
960
963
|
}
|
|
961
964
|
};
|
|
962
|
-
function
|
|
965
|
+
function lightningReceiveContract(params) {
|
|
963
966
|
const seconds = (value) => ({
|
|
964
967
|
type: "seconds",
|
|
965
968
|
value: BigInt(value)
|
|
@@ -967,7 +970,7 @@ function receiveVtxoScript(params) {
|
|
|
967
970
|
return new VHTLC.ScriptV2({
|
|
968
971
|
sender: params.solverPubkey,
|
|
969
972
|
receiver: params.payoutPubkey,
|
|
970
|
-
server: params.
|
|
973
|
+
server: params.operatorPubkey,
|
|
971
974
|
preimageHash: ripemd1602(hex3.decode(params.paymentHash)),
|
|
972
975
|
refundLocktime: BigInt(params.refundLocktime),
|
|
973
976
|
unilateralClaimDelay: seconds(params.claimDelay),
|
|
@@ -992,10 +995,10 @@ function deriveLightningReceive(input) {
|
|
|
992
995
|
if (refundLocktime === void 0 || invoice === void 0 || solverRefundPkScriptHex === void 0) {
|
|
993
996
|
throw new Error("lightning-receive quote is missing a binding field");
|
|
994
997
|
}
|
|
995
|
-
const
|
|
998
|
+
const contractParams = {
|
|
996
999
|
solverPubkey: toXOnly(hex3.decode(quote.solver_pubkey), "solver key"),
|
|
997
1000
|
refundLocktime,
|
|
998
|
-
|
|
1001
|
+
operatorPubkey: input.operatorPubkey,
|
|
999
1002
|
paymentHash: input.paymentHash,
|
|
1000
1003
|
claimDelay: input.claimDelay,
|
|
1001
1004
|
emulatorPubkey: input.emulatorPubkey,
|
|
@@ -1006,8 +1009,8 @@ function deriveLightningReceive(input) {
|
|
|
1006
1009
|
const matched = matchQuotedLockup(
|
|
1007
1010
|
quote,
|
|
1008
1011
|
input.hrp,
|
|
1009
|
-
input.
|
|
1010
|
-
(legacy) =>
|
|
1012
|
+
input.operatorPubkey,
|
|
1013
|
+
(legacy) => lightningReceiveContract({ ...contractParams, ...legacy !== void 0 && { legacy } })
|
|
1011
1014
|
);
|
|
1012
1015
|
return {
|
|
1013
1016
|
address: matched.address,
|
|
@@ -1015,13 +1018,13 @@ function deriveLightningReceive(input) {
|
|
|
1015
1018
|
script: matched.script,
|
|
1016
1019
|
invoice,
|
|
1017
1020
|
refundLocktime,
|
|
1018
|
-
|
|
1019
|
-
...
|
|
1021
|
+
contractParams: {
|
|
1022
|
+
...contractParams,
|
|
1020
1023
|
...matched.legacy !== void 0 && { legacy: matched.legacy }
|
|
1021
1024
|
}
|
|
1022
1025
|
};
|
|
1023
1026
|
}
|
|
1024
|
-
async function requestLightningReceive(wallet,
|
|
1027
|
+
async function requestLightningReceive(wallet, transport, params) {
|
|
1025
1028
|
const rfqId = params.rfqId ?? newRfqId();
|
|
1026
1029
|
const secrets = await provisionClaimSecret(wallet);
|
|
1027
1030
|
if (secrets.mustPersistPreimage) {
|
|
@@ -1033,7 +1036,7 @@ async function requestLightningReceive(wallet, arkServerUrl, transport, params)
|
|
|
1033
1036
|
const paymentHash = hex3.encode(secrets.paymentHash);
|
|
1034
1037
|
const payoutPubkey = secrets.pubkey;
|
|
1035
1038
|
const [info, payoutAddress] = await Promise.all([
|
|
1036
|
-
|
|
1039
|
+
wallet.getArkadeInfo({ requireLive: true }),
|
|
1037
1040
|
wallet.getAddress()
|
|
1038
1041
|
]);
|
|
1039
1042
|
const claimPacket = await sealClaimPacket({
|
|
@@ -1052,13 +1055,13 @@ async function requestLightningReceive(wallet, arkServerUrl, transport, params)
|
|
|
1052
1055
|
})
|
|
1053
1056
|
);
|
|
1054
1057
|
assertQuotedAmount(quote, params.amountSide, params.amount);
|
|
1055
|
-
const network =
|
|
1058
|
+
const network = networkFromArkadeInfo(info);
|
|
1056
1059
|
const derived = deriveLightningReceive({
|
|
1057
1060
|
quote,
|
|
1058
1061
|
paymentHash,
|
|
1059
1062
|
payoutPubkey,
|
|
1060
1063
|
payoutAddress,
|
|
1061
|
-
|
|
1064
|
+
operatorPubkey: toXOnly(hex3.decode(info.signerPubkey), "ark signer key"),
|
|
1062
1065
|
emulatorPubkey: toXOnly(
|
|
1063
1066
|
hex3.decode(resolveEmulatorPubkey(network, params.emulatorPubkey)),
|
|
1064
1067
|
"emulator signer key"
|
|
@@ -1092,7 +1095,7 @@ async function requestLightningReceive(wallet, arkServerUrl, transport, params)
|
|
|
1092
1095
|
payoutAddress,
|
|
1093
1096
|
payoutPubkey,
|
|
1094
1097
|
secrets,
|
|
1095
|
-
|
|
1098
|
+
contractParams: derived.contractParams
|
|
1096
1099
|
};
|
|
1097
1100
|
}
|
|
1098
1101
|
function deriveOnchainReceive(input) {
|
|
@@ -1107,10 +1110,10 @@ function deriveOnchainReceive(input) {
|
|
|
1107
1110
|
if (refundLocktime === void 0 || claimPubkey === void 0 || htlcLocktime === void 0 || minConfirmations === void 0 || solverRefundPkScriptHex === void 0) {
|
|
1108
1111
|
throw new Error("onchain-receive quote is missing a binding field");
|
|
1109
1112
|
}
|
|
1110
|
-
const
|
|
1113
|
+
const contractParams = {
|
|
1111
1114
|
solverPubkey: toXOnly(hex3.decode(quote.solver_pubkey), "solver key"),
|
|
1112
1115
|
refundLocktime,
|
|
1113
|
-
|
|
1116
|
+
operatorPubkey: input.operatorPubkey,
|
|
1114
1117
|
paymentHash: input.paymentHash,
|
|
1115
1118
|
claimDelay: input.claimDelay,
|
|
1116
1119
|
emulatorPubkey: input.emulatorPubkey,
|
|
@@ -1121,8 +1124,11 @@ function deriveOnchainReceive(input) {
|
|
|
1121
1124
|
const { script, address } = matchQuotedLockup(
|
|
1122
1125
|
quote,
|
|
1123
1126
|
input.hrp,
|
|
1124
|
-
input.
|
|
1125
|
-
(legacy) =>
|
|
1127
|
+
input.operatorPubkey,
|
|
1128
|
+
(legacy) => lightningReceiveContract({
|
|
1129
|
+
...contractParams,
|
|
1130
|
+
...legacy !== void 0 && { legacy }
|
|
1131
|
+
})
|
|
1126
1132
|
);
|
|
1127
1133
|
const htlc = onchainHtlcScript(
|
|
1128
1134
|
{
|
|
@@ -1144,7 +1150,7 @@ function deriveOnchainReceive(input) {
|
|
|
1144
1150
|
minConfirmations
|
|
1145
1151
|
};
|
|
1146
1152
|
}
|
|
1147
|
-
async function requestOnchainReceive(wallet,
|
|
1153
|
+
async function requestOnchainReceive(wallet, transport, params) {
|
|
1148
1154
|
const rfqId = params.rfqId ?? newRfqId();
|
|
1149
1155
|
const secrets = await provisionClaimSecret(wallet);
|
|
1150
1156
|
if (secrets.mustPersistPreimage) {
|
|
@@ -1156,7 +1162,7 @@ async function requestOnchainReceive(wallet, arkServerUrl, transport, params) {
|
|
|
1156
1162
|
const paymentHash = hex3.encode(secrets.paymentHash);
|
|
1157
1163
|
const payoutPubkey = secrets.pubkey;
|
|
1158
1164
|
const [info, payoutAddress] = await Promise.all([
|
|
1159
|
-
|
|
1165
|
+
wallet.getArkadeInfo({ requireLive: true }),
|
|
1160
1166
|
wallet.getAddress()
|
|
1161
1167
|
]);
|
|
1162
1168
|
const claimPacket = await sealClaimPacket({
|
|
@@ -1176,14 +1182,14 @@ async function requestOnchainReceive(wallet, arkServerUrl, transport, params) {
|
|
|
1176
1182
|
})
|
|
1177
1183
|
);
|
|
1178
1184
|
assertQuotedAmount(quote, params.amountSide, params.amount);
|
|
1179
|
-
const network =
|
|
1185
|
+
const network = networkFromArkadeInfo(info);
|
|
1180
1186
|
const derived = deriveOnchainReceive({
|
|
1181
1187
|
quote,
|
|
1182
1188
|
paymentHash,
|
|
1183
1189
|
payoutPubkey,
|
|
1184
1190
|
payoutAddress,
|
|
1185
1191
|
refundPubkey: params.refundPubkey,
|
|
1186
|
-
|
|
1192
|
+
operatorPubkey: toXOnly(hex3.decode(info.signerPubkey), "ark signer key"),
|
|
1187
1193
|
emulatorPubkey: toXOnly(
|
|
1188
1194
|
hex3.decode(resolveEmulatorPubkey(network, params.emulatorPubkey)),
|
|
1189
1195
|
"emulator signer key"
|
|
@@ -1272,7 +1278,7 @@ export {
|
|
|
1272
1278
|
unilateralClaimDelay,
|
|
1273
1279
|
unilateralRefundDelay,
|
|
1274
1280
|
unilateralRefundWithoutReceiverDelay,
|
|
1275
|
-
|
|
1281
|
+
lightningSendContract,
|
|
1276
1282
|
requestLightningSend,
|
|
1277
1283
|
offerTermsFromQuote,
|
|
1278
1284
|
onchainSendRequest,
|
|
@@ -1283,7 +1289,7 @@ export {
|
|
|
1283
1289
|
MIN_CLAIM_WINDOW_SECONDS,
|
|
1284
1290
|
verifyReceiveInvoice,
|
|
1285
1291
|
assertReceivable,
|
|
1286
|
-
|
|
1292
|
+
lightningReceiveContract,
|
|
1287
1293
|
deriveLightningReceive,
|
|
1288
1294
|
requestLightningReceive,
|
|
1289
1295
|
deriveOnchainReceive,
|