@arkade-os/swap 0.0.8 → 0.0.10
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 +5 -0
- package/dist/{chunk-TU4NGZDP.js → chunk-5NPYNQ5V.js} +28 -41
- package/dist/index.cjs +63 -44
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +40 -5
- package/dist/nostr.cjs +1 -0
- 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-Dso34L4D.d.cts → repository-C8FXlmHY.d.cts} +68 -11
- package/dist/{repository-BcZ9LXRP.d.ts → repository-Cw2EvvZG.d.ts} +68 -11
- package/dist/{rfq-C-aq5LDJ.d.ts → rfq-DglvHMNC.d.cts} +19 -10
- package/dist/{rfq-C-aq5LDJ.d.cts → rfq-DglvHMNC.d.ts} +19 -10
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -7,6 +7,11 @@ Node-specific APIs, so it runs in Node, the browser, and React Native alike. Fou
|
|
|
7
7
|
ship — in-memory (anywhere, nothing outlives the process), IndexedDB (browser), SQLite and Realm
|
|
8
8
|
(React Native, on subpath entry points) — see "Storage backends" below.
|
|
9
9
|
|
|
10
|
+
The one global the core API requires is `crypto.getRandomValues`. Node and browsers have it;
|
|
11
|
+
React Native does not, so install `react-native-get-random-values` (or `expo-crypto`) and import
|
|
12
|
+
it before this package. `crypto.subtle` is not used. `EventSource` and `WebSocket` are needed only
|
|
13
|
+
by the watch and relay transports, both of which take an injected implementation.
|
|
14
|
+
|
|
10
15
|
## Roles
|
|
11
16
|
|
|
12
17
|
Arkade Intents names two participants:
|
|
@@ -6,6 +6,7 @@ import * as btc from "@scure/btc-signer";
|
|
|
6
6
|
var ONCHAIN_ORDER_MARGIN_SECONDS = 2 * 60 * 60;
|
|
7
7
|
var ONCHAIN_CLAIM_MARGIN_SECONDS = 90 * 60;
|
|
8
8
|
var MAX_MIN_CONFIRMATIONS = 6;
|
|
9
|
+
var LOCKTIME_THRESHOLD = 5e8;
|
|
9
10
|
var ONCHAIN_SECONDS_PER_BLOCK = 600;
|
|
10
11
|
var ONCHAIN_DUST_SATS = BigInt(330);
|
|
11
12
|
var newPreimage = () => crypto.getRandomValues(new Uint8Array(32));
|
|
@@ -25,6 +26,11 @@ function onchainHtlcScript(params, network) {
|
|
|
25
26
|
`refundLocktime must be a positive unix timestamp, got ${params.refundLocktime}`
|
|
26
27
|
);
|
|
27
28
|
}
|
|
29
|
+
if (params.refundLocktime < LOCKTIME_THRESHOLD) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
`refundLocktime ${params.refundLocktime} is below LOCKTIME_THRESHOLD (${LOCKTIME_THRESHOLD}) and would be interpreted as a block height`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
28
34
|
if (!Object.hasOwn(L1_NETWORKS, network)) {
|
|
29
35
|
throw new Error(
|
|
30
36
|
`unknown L1 network '${String(network)}' \u2014 expected one of ${Object.keys(L1_NETWORKS).join(", ")}`
|
|
@@ -211,6 +217,7 @@ async function classifyOnchainHtlc(chain, input) {
|
|
|
211
217
|
|
|
212
218
|
// src/claimPacket.ts
|
|
213
219
|
import { base64 } from "@scure/base";
|
|
220
|
+
import { gcm } from "@noble/ciphers/aes.js";
|
|
214
221
|
import { secp256k1 } from "@noble/curves/secp256k1.js";
|
|
215
222
|
import { hkdf } from "@noble/hashes/hkdf.js";
|
|
216
223
|
import { sha256 as sha2562 } from "@noble/hashes/sha2.js";
|
|
@@ -231,20 +238,7 @@ async function sealWithEntropy(input, ephemeralKey, nonce) {
|
|
|
231
238
|
const sharedX = secp256k1.getSharedSecret(ephemeralKey, input.covclaimdPubkey, true).subarray(1);
|
|
232
239
|
const key = hkdf(sha2562, sharedX, ephemeralPub, HKDF_INFO, 32);
|
|
233
240
|
if (nonce.length !== 12) throw new Error("nonce must be 12 bytes");
|
|
234
|
-
const
|
|
235
|
-
"encrypt"
|
|
236
|
-
]);
|
|
237
|
-
const sealed = new Uint8Array(
|
|
238
|
-
await crypto.subtle.encrypt(
|
|
239
|
-
{
|
|
240
|
-
name: "AES-GCM",
|
|
241
|
-
iv: nonce,
|
|
242
|
-
additionalData: ephemeralPub
|
|
243
|
-
},
|
|
244
|
-
aesKey,
|
|
245
|
-
input.preimage
|
|
246
|
-
)
|
|
247
|
-
);
|
|
241
|
+
const sealed = gcm(key, nonce, ephemeralPub).encrypt(input.preimage);
|
|
248
242
|
const packet = new Uint8Array(33 + 12 + sealed.length);
|
|
249
243
|
packet.set(ephemeralPub, 0);
|
|
250
244
|
packet.set(nonce, 33);
|
|
@@ -318,19 +312,13 @@ import {
|
|
|
318
312
|
RestArkProvider,
|
|
319
313
|
VHTLC,
|
|
320
314
|
getNetwork,
|
|
321
|
-
resolveEmulatorPubkey
|
|
315
|
+
resolveEmulatorPubkey,
|
|
316
|
+
toXOnly
|
|
322
317
|
} from "@arkade-os/sdk";
|
|
323
318
|
import {
|
|
324
319
|
provisionClaimSecret,
|
|
325
320
|
provisionRefundKey
|
|
326
321
|
} from "@arkade-os/sdk";
|
|
327
|
-
var xOnly = (key, label) => {
|
|
328
|
-
if (key.length === 32) return key;
|
|
329
|
-
if (key.length !== 33 || key[0] !== 2 && key[0] !== 3) {
|
|
330
|
-
throw new Error(`${label} is not a compressed or x-only public key`);
|
|
331
|
-
}
|
|
332
|
-
return key.slice(1);
|
|
333
|
-
};
|
|
334
322
|
var solverHex = (value, field) => {
|
|
335
323
|
try {
|
|
336
324
|
return hex3.decode(value);
|
|
@@ -651,10 +639,8 @@ async function requestLightningSend(wallet, arkServerUrl, transport, params) {
|
|
|
651
639
|
const rfqId = params.rfqId ?? newRfqId();
|
|
652
640
|
const secrets = await provisionRefundKey(wallet);
|
|
653
641
|
const senderPubkey = secrets.pubkey;
|
|
654
|
-
const
|
|
655
|
-
|
|
656
|
-
wallet.getAddress()
|
|
657
|
-
]);
|
|
642
|
+
const refundAddress = secrets.address;
|
|
643
|
+
const info = await new RestArkProvider(arkServerUrl).getInfo();
|
|
658
644
|
const quote = await transport.requestQuote(
|
|
659
645
|
lightningSendRequest({ rfqId, invoice: params.invoice.raw, refundAddress, senderPubkey })
|
|
660
646
|
);
|
|
@@ -675,21 +661,21 @@ async function requestLightningSend(wallet, arkServerUrl, transport, params) {
|
|
|
675
661
|
`quote from_amount ${quote.from_amount} is below the invoice amount \u2014 a negative spread is not a quote`
|
|
676
662
|
);
|
|
677
663
|
}
|
|
678
|
-
const serverPubkey =
|
|
664
|
+
const serverPubkey = toXOnly(hex3.decode(info.signerPubkey), "ark signer key");
|
|
679
665
|
const network = getNetwork(info.network);
|
|
680
666
|
const treeParams = {
|
|
681
|
-
solverPubkey:
|
|
667
|
+
solverPubkey: toXOnly(hex3.decode(quote.solver_pubkey), "solver key"),
|
|
682
668
|
refundLocktime: quote.refund_locktime,
|
|
683
669
|
serverPubkey,
|
|
684
670
|
paymentHash: params.invoice.paymentHash,
|
|
685
671
|
claimDelay: unilateralClaimDelay(Number(info.unilateralExitDelay)),
|
|
686
|
-
emulatorPubkey:
|
|
672
|
+
emulatorPubkey: toXOnly(
|
|
687
673
|
hex3.decode(resolveEmulatorPubkey(network, params.emulatorPubkey)),
|
|
688
674
|
"emulator signer key"
|
|
689
675
|
),
|
|
690
676
|
senderPubkey,
|
|
691
677
|
receiverPkScript: solverHex(receiverPkScriptHex, "profile.receiver_pk_script"),
|
|
692
|
-
refundPkScript:
|
|
678
|
+
refundPkScript: secrets.pkScript
|
|
693
679
|
};
|
|
694
680
|
const script = lightningSendVtxoScript(treeParams);
|
|
695
681
|
const address = script.address(network.hrp, serverPubkey).encode();
|
|
@@ -778,7 +764,7 @@ function deriveOnchainSend(input) {
|
|
|
778
764
|
throw new Error("onchain-send quote is missing a binding field");
|
|
779
765
|
}
|
|
780
766
|
const script = lightningSendVtxoScript({
|
|
781
|
-
solverPubkey:
|
|
767
|
+
solverPubkey: toXOnly(hex3.decode(quote.solver_pubkey), "solver key"),
|
|
782
768
|
refundLocktime,
|
|
783
769
|
serverPubkey: input.serverPubkey,
|
|
784
770
|
paymentHash: input.paymentHash,
|
|
@@ -793,7 +779,7 @@ function deriveOnchainSend(input) {
|
|
|
793
779
|
const htlcParams = {
|
|
794
780
|
paymentHash: input.paymentHash,
|
|
795
781
|
claimKey: input.payoutPubkey,
|
|
796
|
-
refundKey:
|
|
782
|
+
refundKey: toXOnly(hex3.decode(htlcPubkey), "solver L1 htlc key"),
|
|
797
783
|
refundLocktime: htlcLocktime
|
|
798
784
|
};
|
|
799
785
|
const htlc = onchainHtlcScript(htlcParams, input.l1Network);
|
|
@@ -840,8 +826,8 @@ async function requestOnchainSend(wallet, arkServerUrl, transport, params) {
|
|
|
840
826
|
quote,
|
|
841
827
|
paymentHash,
|
|
842
828
|
payoutPubkey: params.payoutPubkey,
|
|
843
|
-
serverPubkey:
|
|
844
|
-
emulatorPubkey:
|
|
829
|
+
serverPubkey: toXOnly(hex3.decode(info.signerPubkey), "ark signer key"),
|
|
830
|
+
emulatorPubkey: toXOnly(
|
|
845
831
|
hex3.decode(resolveEmulatorPubkey(network, params.emulatorPubkey)),
|
|
846
832
|
"emulator signer key"
|
|
847
833
|
),
|
|
@@ -984,7 +970,7 @@ function deriveLightningReceive(input) {
|
|
|
984
970
|
throw new Error("lightning-receive quote is missing a binding field");
|
|
985
971
|
}
|
|
986
972
|
const treeParams = {
|
|
987
|
-
solverPubkey:
|
|
973
|
+
solverPubkey: toXOnly(hex3.decode(quote.solver_pubkey), "solver key"),
|
|
988
974
|
refundLocktime,
|
|
989
975
|
serverPubkey: input.serverPubkey,
|
|
990
976
|
paymentHash: input.paymentHash,
|
|
@@ -1036,8 +1022,8 @@ async function requestLightningReceive(wallet, arkServerUrl, transport, params)
|
|
|
1036
1022
|
paymentHash,
|
|
1037
1023
|
payoutPubkey,
|
|
1038
1024
|
payoutAddress,
|
|
1039
|
-
serverPubkey:
|
|
1040
|
-
emulatorPubkey:
|
|
1025
|
+
serverPubkey: toXOnly(hex3.decode(info.signerPubkey), "ark signer key"),
|
|
1026
|
+
emulatorPubkey: toXOnly(
|
|
1041
1027
|
hex3.decode(resolveEmulatorPubkey(network, params.emulatorPubkey)),
|
|
1042
1028
|
"emulator signer key"
|
|
1043
1029
|
),
|
|
@@ -1086,7 +1072,7 @@ function deriveOnchainReceive(input) {
|
|
|
1086
1072
|
throw new Error("onchain-receive quote is missing a binding field");
|
|
1087
1073
|
}
|
|
1088
1074
|
const script = receiveVtxoScript({
|
|
1089
|
-
solverPubkey:
|
|
1075
|
+
solverPubkey: toXOnly(hex3.decode(quote.solver_pubkey), "solver key"),
|
|
1090
1076
|
refundLocktime,
|
|
1091
1077
|
serverPubkey: input.serverPubkey,
|
|
1092
1078
|
paymentHash: input.paymentHash,
|
|
@@ -1101,7 +1087,7 @@ function deriveOnchainReceive(input) {
|
|
|
1101
1087
|
const htlc = onchainHtlcScript(
|
|
1102
1088
|
{
|
|
1103
1089
|
paymentHash: input.paymentHash,
|
|
1104
|
-
claimKey:
|
|
1090
|
+
claimKey: toXOnly(hex3.decode(claimPubkey), "solver L1 claim key"),
|
|
1105
1091
|
refundKey: input.refundPubkey,
|
|
1106
1092
|
refundLocktime: htlcLocktime
|
|
1107
1093
|
},
|
|
@@ -1157,8 +1143,8 @@ async function requestOnchainReceive(wallet, arkServerUrl, transport, params) {
|
|
|
1157
1143
|
payoutPubkey,
|
|
1158
1144
|
payoutAddress,
|
|
1159
1145
|
refundPubkey: params.refundPubkey,
|
|
1160
|
-
serverPubkey:
|
|
1161
|
-
emulatorPubkey:
|
|
1146
|
+
serverPubkey: toXOnly(hex3.decode(info.signerPubkey), "ark signer key"),
|
|
1147
|
+
emulatorPubkey: toXOnly(
|
|
1162
1148
|
hex3.decode(resolveEmulatorPubkey(network, params.emulatorPubkey)),
|
|
1163
1149
|
"emulator signer key"
|
|
1164
1150
|
),
|
|
@@ -1199,6 +1185,7 @@ export {
|
|
|
1199
1185
|
ONCHAIN_ORDER_MARGIN_SECONDS,
|
|
1200
1186
|
ONCHAIN_CLAIM_MARGIN_SECONDS,
|
|
1201
1187
|
MAX_MIN_CONFIRMATIONS,
|
|
1188
|
+
LOCKTIME_THRESHOLD,
|
|
1202
1189
|
ONCHAIN_SECONDS_PER_BLOCK,
|
|
1203
1190
|
ONCHAIN_DUST_SATS,
|
|
1204
1191
|
newPreimage,
|
package/dist/index.cjs
CHANGED
|
@@ -39,6 +39,7 @@ __export(index_exports, {
|
|
|
39
39
|
LIGHTNING_BTC: () => LIGHTNING_BTC,
|
|
40
40
|
LIGHTNING_RECEIVE_PAIR: () => LIGHTNING_RECEIVE_PAIR,
|
|
41
41
|
LIGHTNING_SEND_PAIR: () => LIGHTNING_SEND_PAIR,
|
|
42
|
+
LOCKTIME_THRESHOLD: () => LOCKTIME_THRESHOLD,
|
|
42
43
|
LockupAmountMismatchError: () => LockupAmountMismatchError,
|
|
43
44
|
LockupContractMissing: () => LockupContractMissing,
|
|
44
45
|
LockupNeedsRecoveryError: () => LockupNeedsRecoveryError,
|
|
@@ -608,8 +609,8 @@ async function cancelOffer(wallet, arkServerUrl, offerHex, opts) {
|
|
|
608
609
|
// script and the payout script comes from wallet.getAddress(), so the
|
|
609
610
|
// client's network (which only shapes address derivation) is unused here
|
|
610
611
|
});
|
|
611
|
-
const
|
|
612
|
-
const { program, args, keys } = swapProgramBinding(offer,
|
|
612
|
+
const operatorPubkey = swapAddress ? import_sdk2.ArkAddress.decode(swapAddress).serverPubKey : client.serverKey;
|
|
613
|
+
const { program, args, keys } = swapProgramBinding(offer, operatorPubkey);
|
|
613
614
|
const rebuilt = new import_sdk2.arkade.ArkadeProgramScript(program, args, keys);
|
|
614
615
|
if (import_base2.hex.encode(rebuilt.pkScript) !== import_base2.hex.encode(offer.swapPkScript)) {
|
|
615
616
|
throw new Error(
|
|
@@ -1050,6 +1051,7 @@ var btc = __toESM(require("@scure/btc-signer"), 1);
|
|
|
1050
1051
|
var ONCHAIN_ORDER_MARGIN_SECONDS = 2 * 60 * 60;
|
|
1051
1052
|
var ONCHAIN_CLAIM_MARGIN_SECONDS = 90 * 60;
|
|
1052
1053
|
var MAX_MIN_CONFIRMATIONS = 6;
|
|
1054
|
+
var LOCKTIME_THRESHOLD = 5e8;
|
|
1053
1055
|
var ONCHAIN_SECONDS_PER_BLOCK = 600;
|
|
1054
1056
|
var ONCHAIN_DUST_SATS = BigInt(330);
|
|
1055
1057
|
var newPreimage = () => crypto.getRandomValues(new Uint8Array(32));
|
|
@@ -1069,6 +1071,11 @@ function onchainHtlcScript(params, network) {
|
|
|
1069
1071
|
`refundLocktime must be a positive unix timestamp, got ${params.refundLocktime}`
|
|
1070
1072
|
);
|
|
1071
1073
|
}
|
|
1074
|
+
if (params.refundLocktime < LOCKTIME_THRESHOLD) {
|
|
1075
|
+
throw new Error(
|
|
1076
|
+
`refundLocktime ${params.refundLocktime} is below LOCKTIME_THRESHOLD (${LOCKTIME_THRESHOLD}) and would be interpreted as a block height`
|
|
1077
|
+
);
|
|
1078
|
+
}
|
|
1072
1079
|
if (!Object.hasOwn(L1_NETWORKS, network)) {
|
|
1073
1080
|
throw new Error(
|
|
1074
1081
|
`unknown L1 network '${String(network)}' \u2014 expected one of ${Object.keys(L1_NETWORKS).join(", ")}`
|
|
@@ -1723,6 +1730,7 @@ var import_sdk10 = require("@arkade-os/sdk");
|
|
|
1723
1730
|
|
|
1724
1731
|
// src/claimPacket.ts
|
|
1725
1732
|
var import_base8 = require("@scure/base");
|
|
1733
|
+
var import_aes = require("@noble/ciphers/aes.js");
|
|
1726
1734
|
var import_secp256k1 = require("@noble/curves/secp256k1.js");
|
|
1727
1735
|
var import_hkdf = require("@noble/hashes/hkdf.js");
|
|
1728
1736
|
var import_sha23 = require("@noble/hashes/sha2.js");
|
|
@@ -1743,20 +1751,7 @@ async function sealWithEntropy(input, ephemeralKey, nonce) {
|
|
|
1743
1751
|
const sharedX = import_secp256k1.secp256k1.getSharedSecret(ephemeralKey, input.covclaimdPubkey, true).subarray(1);
|
|
1744
1752
|
const key = (0, import_hkdf.hkdf)(import_sha23.sha256, sharedX, ephemeralPub, HKDF_INFO, 32);
|
|
1745
1753
|
if (nonce.length !== 12) throw new Error("nonce must be 12 bytes");
|
|
1746
|
-
const
|
|
1747
|
-
"encrypt"
|
|
1748
|
-
]);
|
|
1749
|
-
const sealed = new Uint8Array(
|
|
1750
|
-
await crypto.subtle.encrypt(
|
|
1751
|
-
{
|
|
1752
|
-
name: "AES-GCM",
|
|
1753
|
-
iv: nonce,
|
|
1754
|
-
additionalData: ephemeralPub
|
|
1755
|
-
},
|
|
1756
|
-
aesKey,
|
|
1757
|
-
input.preimage
|
|
1758
|
-
)
|
|
1759
|
-
);
|
|
1754
|
+
const sealed = (0, import_aes.gcm)(key, nonce, ephemeralPub).encrypt(input.preimage);
|
|
1760
1755
|
const packet = new Uint8Array(33 + 12 + sealed.length);
|
|
1761
1756
|
packet.set(ephemeralPub, 0);
|
|
1762
1757
|
packet.set(nonce, 33);
|
|
@@ -1820,13 +1815,6 @@ async function lockupContractParams(contracts, lockupAddress) {
|
|
|
1820
1815
|
}
|
|
1821
1816
|
|
|
1822
1817
|
// src/rfq.ts
|
|
1823
|
-
var xOnly = (key, label) => {
|
|
1824
|
-
if (key.length === 32) return key;
|
|
1825
|
-
if (key.length !== 33 || key[0] !== 2 && key[0] !== 3) {
|
|
1826
|
-
throw new Error(`${label} is not a compressed or x-only public key`);
|
|
1827
|
-
}
|
|
1828
|
-
return key.slice(1);
|
|
1829
|
-
};
|
|
1830
1818
|
var solverHex = (value, field) => {
|
|
1831
1819
|
try {
|
|
1832
1820
|
return import_base10.hex.decode(value);
|
|
@@ -2147,10 +2135,8 @@ async function requestLightningSend(wallet, arkServerUrl, transport, params) {
|
|
|
2147
2135
|
const rfqId = params.rfqId ?? newRfqId();
|
|
2148
2136
|
const secrets = await (0, import_sdk10.provisionRefundKey)(wallet);
|
|
2149
2137
|
const senderPubkey = secrets.pubkey;
|
|
2150
|
-
const
|
|
2151
|
-
|
|
2152
|
-
wallet.getAddress()
|
|
2153
|
-
]);
|
|
2138
|
+
const refundAddress = secrets.address;
|
|
2139
|
+
const info = await new import_sdk9.RestArkProvider(arkServerUrl).getInfo();
|
|
2154
2140
|
const quote = await transport.requestQuote(
|
|
2155
2141
|
lightningSendRequest({ rfqId, invoice: params.invoice.raw, refundAddress, senderPubkey })
|
|
2156
2142
|
);
|
|
@@ -2171,21 +2157,21 @@ async function requestLightningSend(wallet, arkServerUrl, transport, params) {
|
|
|
2171
2157
|
`quote from_amount ${quote.from_amount} is below the invoice amount \u2014 a negative spread is not a quote`
|
|
2172
2158
|
);
|
|
2173
2159
|
}
|
|
2174
|
-
const serverPubkey =
|
|
2160
|
+
const serverPubkey = (0, import_sdk9.toXOnly)(import_base10.hex.decode(info.signerPubkey), "ark signer key");
|
|
2175
2161
|
const network = (0, import_sdk9.getNetwork)(info.network);
|
|
2176
2162
|
const treeParams = {
|
|
2177
|
-
solverPubkey:
|
|
2163
|
+
solverPubkey: (0, import_sdk9.toXOnly)(import_base10.hex.decode(quote.solver_pubkey), "solver key"),
|
|
2178
2164
|
refundLocktime: quote.refund_locktime,
|
|
2179
2165
|
serverPubkey,
|
|
2180
2166
|
paymentHash: params.invoice.paymentHash,
|
|
2181
2167
|
claimDelay: unilateralClaimDelay(Number(info.unilateralExitDelay)),
|
|
2182
|
-
emulatorPubkey:
|
|
2168
|
+
emulatorPubkey: (0, import_sdk9.toXOnly)(
|
|
2183
2169
|
import_base10.hex.decode((0, import_sdk9.resolveEmulatorPubkey)(network, params.emulatorPubkey)),
|
|
2184
2170
|
"emulator signer key"
|
|
2185
2171
|
),
|
|
2186
2172
|
senderPubkey,
|
|
2187
2173
|
receiverPkScript: solverHex(receiverPkScriptHex, "profile.receiver_pk_script"),
|
|
2188
|
-
refundPkScript:
|
|
2174
|
+
refundPkScript: secrets.pkScript
|
|
2189
2175
|
};
|
|
2190
2176
|
const script = lightningSendVtxoScript(treeParams);
|
|
2191
2177
|
const address = script.address(network.hrp, serverPubkey).encode();
|
|
@@ -2274,7 +2260,7 @@ function deriveOnchainSend(input) {
|
|
|
2274
2260
|
throw new Error("onchain-send quote is missing a binding field");
|
|
2275
2261
|
}
|
|
2276
2262
|
const script = lightningSendVtxoScript({
|
|
2277
|
-
solverPubkey:
|
|
2263
|
+
solverPubkey: (0, import_sdk9.toXOnly)(import_base10.hex.decode(quote.solver_pubkey), "solver key"),
|
|
2278
2264
|
refundLocktime,
|
|
2279
2265
|
serverPubkey: input.serverPubkey,
|
|
2280
2266
|
paymentHash: input.paymentHash,
|
|
@@ -2289,7 +2275,7 @@ function deriveOnchainSend(input) {
|
|
|
2289
2275
|
const htlcParams = {
|
|
2290
2276
|
paymentHash: input.paymentHash,
|
|
2291
2277
|
claimKey: input.payoutPubkey,
|
|
2292
|
-
refundKey:
|
|
2278
|
+
refundKey: (0, import_sdk9.toXOnly)(import_base10.hex.decode(htlcPubkey), "solver L1 htlc key"),
|
|
2293
2279
|
refundLocktime: htlcLocktime
|
|
2294
2280
|
};
|
|
2295
2281
|
const htlc = onchainHtlcScript(htlcParams, input.l1Network);
|
|
@@ -2336,8 +2322,8 @@ async function requestOnchainSend(wallet, arkServerUrl, transport, params) {
|
|
|
2336
2322
|
quote,
|
|
2337
2323
|
paymentHash,
|
|
2338
2324
|
payoutPubkey: params.payoutPubkey,
|
|
2339
|
-
serverPubkey:
|
|
2340
|
-
emulatorPubkey:
|
|
2325
|
+
serverPubkey: (0, import_sdk9.toXOnly)(import_base10.hex.decode(info.signerPubkey), "ark signer key"),
|
|
2326
|
+
emulatorPubkey: (0, import_sdk9.toXOnly)(
|
|
2341
2327
|
import_base10.hex.decode((0, import_sdk9.resolveEmulatorPubkey)(network, params.emulatorPubkey)),
|
|
2342
2328
|
"emulator signer key"
|
|
2343
2329
|
),
|
|
@@ -2480,7 +2466,7 @@ function deriveLightningReceive(input) {
|
|
|
2480
2466
|
throw new Error("lightning-receive quote is missing a binding field");
|
|
2481
2467
|
}
|
|
2482
2468
|
const treeParams = {
|
|
2483
|
-
solverPubkey:
|
|
2469
|
+
solverPubkey: (0, import_sdk9.toXOnly)(import_base10.hex.decode(quote.solver_pubkey), "solver key"),
|
|
2484
2470
|
refundLocktime,
|
|
2485
2471
|
serverPubkey: input.serverPubkey,
|
|
2486
2472
|
paymentHash: input.paymentHash,
|
|
@@ -2532,8 +2518,8 @@ async function requestLightningReceive(wallet, arkServerUrl, transport, params)
|
|
|
2532
2518
|
paymentHash,
|
|
2533
2519
|
payoutPubkey,
|
|
2534
2520
|
payoutAddress,
|
|
2535
|
-
serverPubkey:
|
|
2536
|
-
emulatorPubkey:
|
|
2521
|
+
serverPubkey: (0, import_sdk9.toXOnly)(import_base10.hex.decode(info.signerPubkey), "ark signer key"),
|
|
2522
|
+
emulatorPubkey: (0, import_sdk9.toXOnly)(
|
|
2537
2523
|
import_base10.hex.decode((0, import_sdk9.resolveEmulatorPubkey)(network, params.emulatorPubkey)),
|
|
2538
2524
|
"emulator signer key"
|
|
2539
2525
|
),
|
|
@@ -2582,7 +2568,7 @@ function deriveOnchainReceive(input) {
|
|
|
2582
2568
|
throw new Error("onchain-receive quote is missing a binding field");
|
|
2583
2569
|
}
|
|
2584
2570
|
const script = receiveVtxoScript({
|
|
2585
|
-
solverPubkey:
|
|
2571
|
+
solverPubkey: (0, import_sdk9.toXOnly)(import_base10.hex.decode(quote.solver_pubkey), "solver key"),
|
|
2586
2572
|
refundLocktime,
|
|
2587
2573
|
serverPubkey: input.serverPubkey,
|
|
2588
2574
|
paymentHash: input.paymentHash,
|
|
@@ -2597,7 +2583,7 @@ function deriveOnchainReceive(input) {
|
|
|
2597
2583
|
const htlc = onchainHtlcScript(
|
|
2598
2584
|
{
|
|
2599
2585
|
paymentHash: input.paymentHash,
|
|
2600
|
-
claimKey:
|
|
2586
|
+
claimKey: (0, import_sdk9.toXOnly)(import_base10.hex.decode(claimPubkey), "solver L1 claim key"),
|
|
2601
2587
|
refundKey: input.refundPubkey,
|
|
2602
2588
|
refundLocktime: htlcLocktime
|
|
2603
2589
|
},
|
|
@@ -2653,8 +2639,8 @@ async function requestOnchainReceive(wallet, arkServerUrl, transport, params) {
|
|
|
2653
2639
|
payoutPubkey,
|
|
2654
2640
|
payoutAddress,
|
|
2655
2641
|
refundPubkey: params.refundPubkey,
|
|
2656
|
-
serverPubkey:
|
|
2657
|
-
emulatorPubkey:
|
|
2642
|
+
serverPubkey: (0, import_sdk9.toXOnly)(import_base10.hex.decode(info.signerPubkey), "ark signer key"),
|
|
2643
|
+
emulatorPubkey: (0, import_sdk9.toXOnly)(
|
|
2658
2644
|
import_base10.hex.decode((0, import_sdk9.resolveEmulatorPubkey)(network, params.emulatorPubkey)),
|
|
2659
2645
|
"emulator signer key"
|
|
2660
2646
|
),
|
|
@@ -2759,6 +2745,7 @@ async function findLockupVtxos(indexer, swapPkScript) {
|
|
|
2759
2745
|
[recoverable.vtxos ?? [], true]
|
|
2760
2746
|
]) {
|
|
2761
2747
|
for (const vtxo of vtxos) {
|
|
2748
|
+
if (vtxo.isUnrolled) continue;
|
|
2762
2749
|
const key = `${vtxo.txid}:${vtxo.vout}`;
|
|
2763
2750
|
if (seen.has(key)) continue;
|
|
2764
2751
|
seen.add(key);
|
|
@@ -2781,10 +2768,17 @@ async function readLockupFate(indexer, input) {
|
|
|
2781
2768
|
const { vtxos } = await indexer.getVtxos({ scripts: [import_base11.hex.encode(input.swapPkScript)] });
|
|
2782
2769
|
const all = vtxos ?? [];
|
|
2783
2770
|
if (all.length === 0) return { fate: "unknown" };
|
|
2771
|
+
const exited = all.filter((vtxo) => vtxo.isUnrolled && !(0, import_sdk11.hasTerminalSpend)(vtxo));
|
|
2772
|
+
if (exited.length > 0) {
|
|
2773
|
+
return {
|
|
2774
|
+
fate: "exited",
|
|
2775
|
+
outpoints: exited.map((vtxo) => ({ txid: vtxo.txid, vout: vtxo.vout }))
|
|
2776
|
+
};
|
|
2777
|
+
}
|
|
2784
2778
|
const spentBy = /* @__PURE__ */ new Map();
|
|
2785
2779
|
let everySpendNamed = true;
|
|
2786
2780
|
for (const vtxo of all) {
|
|
2787
|
-
if (!
|
|
2781
|
+
if (!(0, import_sdk11.hasTerminalSpend)(vtxo)) return { fate: "open" };
|
|
2788
2782
|
if (vtxo.spentBy)
|
|
2789
2783
|
spentBy.set(vtxo.spentBy, {
|
|
2790
2784
|
checkpointTxid: vtxo.spentBy,
|
|
@@ -3672,12 +3666,36 @@ var RfqSwapManager = class {
|
|
|
3672
3666
|
this.setState(swap, fate.fate === "claimed" ? "settled" : "refunded");
|
|
3673
3667
|
return;
|
|
3674
3668
|
}
|
|
3675
|
-
if (swap.kind === "lightning_receive")
|
|
3669
|
+
if (swap.kind === "lightning_receive") {
|
|
3670
|
+
return fate.fate === "exited" ? this.blockExitedLockup(swap, fate) : this.driveReceiveClaim(swap);
|
|
3671
|
+
}
|
|
3676
3672
|
if (swap.kind === "onchain_send" && swap.state !== "claimed") {
|
|
3677
3673
|
if (await this.driveOnchain(swap) === "handled") return;
|
|
3678
3674
|
}
|
|
3675
|
+
if (fate.fate === "exited") {
|
|
3676
|
+
const claiming = swap.state === "claimable" || swap.state === "claimed";
|
|
3677
|
+
if (this.config.now() < swap.refundLocktime && claiming) return;
|
|
3678
|
+
return this.blockExitedLockup(swap, fate);
|
|
3679
|
+
}
|
|
3679
3680
|
await this.driveArkadeRefund(swap);
|
|
3680
3681
|
}
|
|
3682
|
+
/**
|
|
3683
|
+
* The lockup was unilaterally exited: its outputs sit onchain under the
|
|
3684
|
+
* VHTLC script, where no offchain claim or refund can reach them.
|
|
3685
|
+
*
|
|
3686
|
+
* `needs_counterparty` rather than a terminal state, because the money still
|
|
3687
|
+
* needs action and the swap can still end either way — an onchain claim can
|
|
3688
|
+
* reveal the preimage, an onchain refund can return it — and that state is
|
|
3689
|
+
* documented as re-checked every pass. It must be set from HERE and not from
|
|
3690
|
+
* inside `driveArkadeRefund`, whose two `unblock` calls would lift it again
|
|
3691
|
+
* on the very next pass.
|
|
3692
|
+
*/
|
|
3693
|
+
blockExitedLockup(swap, fate) {
|
|
3694
|
+
this.block(
|
|
3695
|
+
swap,
|
|
3696
|
+
`the lockup was unilaterally exited (${fate.outpoints.length} output(s) onchain), so no offchain spend can move it \u2014 complete the unroll and spend it onchain`
|
|
3697
|
+
);
|
|
3698
|
+
}
|
|
3681
3699
|
/**
|
|
3682
3700
|
* The receive leg's whole state machine: claim the solver-funded lockup
|
|
3683
3701
|
* while the window is open, and recognise the shapes in which it can be
|
|
@@ -4182,6 +4200,7 @@ async function lockupTxids(indexer, record, wantFunding) {
|
|
|
4182
4200
|
LIGHTNING_BTC,
|
|
4183
4201
|
LIGHTNING_RECEIVE_PAIR,
|
|
4184
4202
|
LIGHTNING_SEND_PAIR,
|
|
4203
|
+
LOCKTIME_THRESHOLD,
|
|
4185
4204
|
LockupAmountMismatchError,
|
|
4186
4205
|
LockupContractMissing,
|
|
4187
4206
|
LockupNeedsRecoveryError,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ProvisionedKey, ProvisionedClaimSecret, asset, IWallet, arkade, RestIndexerProvider, Transaction, IContractManager, VHTLC, Identity, ActivityResolver } from '@arkade-os/sdk';
|
|
2
|
-
import { S as SwapSecretsProjection, R as RfqSwapRecord, A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry, b as RefundArkProvider, c as RefundIndexer, L as LockupVtxo, d as RfqSwap, e as ArkadeRefundResult, f as LockupSpendIndexer, g as RfqSwapState } from './repository-
|
|
3
|
-
export { h as AssetSwapStatus, i as AvailableRfqSwapManagerCallbacks, B as BTC_ASSET_ID, I as InMemoryAssetSwapRepository, j as LightningReceiveSwap, k as LightningSendSwap, l as LockupFate, m as LockupNeedsRecoveryError, n as LockupParams, o as LockupSpend, O as OnchainSendAction, p as OnchainSendSwap, P as PersistableRfqSwap, q as PreimageBlockedReason, r as PreimageNotRecoverableError, s as REFUND_MTP_LAG_SECONDS, t as RFQ_RESOLVED_STATES, u as RFQ_SWAP_RETENTION_SECONDS, v as RFQ_SWAP_TERMINAL_STATES, w as RefundOutcome, x as RfqRestoreFailure, y as RfqRestoreOptions, z as RfqRestoreResult, C as RfqSwapActionName, D as RfqSwapLockup, E as RfqSwapManager, F as RfqSwapManagerCallbacks, G as RfqSwapManagerConfig, H as RfqSwapManagerDeps, J as RfqSwapManagerEvents, K as RfqSwapOrigin, N as RfqSwapOriginRequired, Q as RfqSwapOutcome, T as RfqSwapRecordStore, U as SwapContractRegistry, V as addAssetSwap, W as awaitRfqResolution, X as createRfqSwapRecord, Y as findLockupVtxos, Z as getAssetSwaps, _ as getAssetSwapsOrThrow, $ as isRfqSwapTerminal, a0 as isRfqTerminal, a1 as nextOnchainAction, a2 as preimageForSwapRecord, a3 as pushRefundWithoutReceiver, a4 as readLockupFate, a5 as rebuildRfqSwap, a6 as refundIfUnresolved, a7 as rfqSwapOriginOf, a8 as shouldRetainRfqSwap, a9 as swapSecretsToRecord, aa as updateAssetSwap, ab as updateAssetSwapBestEffort, ac as updateRfqSwapRecord } from './repository-
|
|
2
|
+
import { S as SwapSecretsProjection, R as RfqSwapRecord, A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry, b as RefundArkProvider, c as RefundIndexer, L as LockupVtxo, d as RfqSwap, e as ArkadeRefundResult, f as LockupSpendIndexer, g as RfqSwapState } from './repository-C8FXlmHY.cjs';
|
|
3
|
+
export { h as AssetSwapStatus, i as AvailableRfqSwapManagerCallbacks, B as BTC_ASSET_ID, I as InMemoryAssetSwapRepository, j as LightningReceiveSwap, k as LightningSendSwap, l as LockupFate, m as LockupNeedsRecoveryError, n as LockupParams, o as LockupSpend, O as OnchainSendAction, p as OnchainSendSwap, P as PersistableRfqSwap, q as PreimageBlockedReason, r as PreimageNotRecoverableError, s as REFUND_MTP_LAG_SECONDS, t as RFQ_RESOLVED_STATES, u as RFQ_SWAP_RETENTION_SECONDS, v as RFQ_SWAP_TERMINAL_STATES, w as RefundOutcome, x as RfqRestoreFailure, y as RfqRestoreOptions, z as RfqRestoreResult, C as RfqSwapActionName, D as RfqSwapLockup, E as RfqSwapManager, F as RfqSwapManagerCallbacks, G as RfqSwapManagerConfig, H as RfqSwapManagerDeps, J as RfqSwapManagerEvents, K as RfqSwapOrigin, N as RfqSwapOriginRequired, Q as RfqSwapOutcome, T as RfqSwapRecordStore, U as SwapContractRegistry, V as addAssetSwap, W as awaitRfqResolution, X as createRfqSwapRecord, Y as findLockupVtxos, Z as getAssetSwaps, _ as getAssetSwapsOrThrow, $ as isRfqSwapTerminal, a0 as isRfqTerminal, a1 as nextOnchainAction, a2 as preimageForSwapRecord, a3 as pushRefundWithoutReceiver, a4 as readLockupFate, a5 as rebuildRfqSwap, a6 as refundIfUnresolved, a7 as rfqSwapOriginOf, a8 as shouldRetainRfqSwap, a9 as swapSecretsToRecord, aa as updateAssetSwap, ab as updateAssetSwapBestEffort, ac as updateRfqSwapRecord } from './repository-C8FXlmHY.cjs';
|
|
4
4
|
import { Network, LocalCardInput, DiscoveredMarket, Side, OfferPlan } from '@arkade-os/solver-discovery';
|
|
5
|
-
import { O as OnchainNetwork, a as OnchainHtlc, b as OnchainHtlcParams } from './rfq-
|
|
6
|
-
export { A as ARKADE_ASSET, c as ARKADE_BTC, d as AddressMismatch, C as ChainSource, e as ChainUtxo, H as HtlcUtxo, I as InvoiceFacts, L as LIGHTNING_BTC, f as LIGHTNING_RECEIVE_PAIR, g as LIGHTNING_SEND_PAIR, h as
|
|
5
|
+
import { O as OnchainNetwork, a as OnchainHtlc, b as OnchainHtlcParams } from './rfq-DglvHMNC.cjs';
|
|
6
|
+
export { A as ARKADE_ASSET, c as ARKADE_BTC, d as AddressMismatch, C as ChainSource, e as ChainUtxo, H as HtlcUtxo, I as InvoiceFacts, L as LIGHTNING_BTC, f as LIGHTNING_RECEIVE_PAIR, g as LIGHTNING_SEND_PAIR, h as LOCKTIME_THRESHOLD, i as LightningReceiveTreeParams, j as LightningSendTreeParams, M as MAX_MIN_CONFIRMATIONS, k as MIN_CLAIM_WINDOW_SECONDS, l as MIN_HEADROOM_SECONDS, m as ONCHAIN_BTC, n as ONCHAIN_CLAIM_MARGIN_SECONDS, o as ONCHAIN_DUST_SATS, p as ONCHAIN_ORDER_MARGIN_SECONDS, q as ONCHAIN_RECEIVE_PAIR, r as ONCHAIN_SECONDS_PER_BLOCK, s as ONCHAIN_SEND_PAIR, t as OnchainHtlcPhase, R as RFQ_TERMINAL_STATES, u as RelaySocket, v as RfqQuote, w as RfqRefusalReason, x as RfqStatus, y as RfqTransport, S as SOLO_REFUND_HEADROOM_SECONDS, z as SwapRefusal, B as arkadeAssetLeg, D as arkadeSwapRequest, E as assertFundable, F as assertReceivable, G as awaitOnchainFill, J as buildHtlcClaim, K as buildHtlcRefund, N as claimOnchainFill, P as classifyOnchainHtlc, Q as deriveLightningReceive, T as deriveOnchainReceive, U as deriveOnchainSend, V as extractPreimage, W as httpTransport, X as lightningReceiveRequest, Y as lightningSendRequest, Z as lightningSendVtxoScript, _ as newPreimage, $ as newRfqId, a0 as offerTermsFromQuote, a1 as onchainHtlcScript, a2 as onchainReceiveRequest, a3 as onchainSendRequest, a4 as paymentHashOf, a5 as receiveVtxoScript, a6 as relayTransport, a7 as requestLightningReceive, a8 as requestLightningSend, a9 as requestOnchainReceive, aa as requestOnchainSend, ab as rfqPair, ac as unilateralClaimDelay, ad as unilateralRefundDelay, ae as unilateralRefundWithoutReceiverDelay, af as verifyLockupAddress, ag as verifyReceiveInvoice } from './rfq-DglvHMNC.cjs';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Which wallet key signs this leg. Stored at `profile.signer`.
|
|
@@ -633,7 +633,7 @@ interface ClaimPacketInput {
|
|
|
633
633
|
covclaimdPubkey: Uint8Array;
|
|
634
634
|
}
|
|
635
635
|
/**
|
|
636
|
-
* Seal a preimage to covclaimd.
|
|
636
|
+
* Seal a preimage to covclaimd.
|
|
637
637
|
*
|
|
638
638
|
* The ephemeral key and nonce are generated here and CANNOT be supplied by a
|
|
639
639
|
* caller. That is the point of this signature: AES-GCM under a repeated
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ProvisionedKey, ProvisionedClaimSecret, asset, IWallet, arkade, RestIndexerProvider, Transaction, IContractManager, VHTLC, Identity, ActivityResolver } from '@arkade-os/sdk';
|
|
2
|
-
import { S as SwapSecretsProjection, R as RfqSwapRecord, A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry, b as RefundArkProvider, c as RefundIndexer, L as LockupVtxo, d as RfqSwap, e as ArkadeRefundResult, f as LockupSpendIndexer, g as RfqSwapState } from './repository-
|
|
3
|
-
export { h as AssetSwapStatus, i as AvailableRfqSwapManagerCallbacks, B as BTC_ASSET_ID, I as InMemoryAssetSwapRepository, j as LightningReceiveSwap, k as LightningSendSwap, l as LockupFate, m as LockupNeedsRecoveryError, n as LockupParams, o as LockupSpend, O as OnchainSendAction, p as OnchainSendSwap, P as PersistableRfqSwap, q as PreimageBlockedReason, r as PreimageNotRecoverableError, s as REFUND_MTP_LAG_SECONDS, t as RFQ_RESOLVED_STATES, u as RFQ_SWAP_RETENTION_SECONDS, v as RFQ_SWAP_TERMINAL_STATES, w as RefundOutcome, x as RfqRestoreFailure, y as RfqRestoreOptions, z as RfqRestoreResult, C as RfqSwapActionName, D as RfqSwapLockup, E as RfqSwapManager, F as RfqSwapManagerCallbacks, G as RfqSwapManagerConfig, H as RfqSwapManagerDeps, J as RfqSwapManagerEvents, K as RfqSwapOrigin, N as RfqSwapOriginRequired, Q as RfqSwapOutcome, T as RfqSwapRecordStore, U as SwapContractRegistry, V as addAssetSwap, W as awaitRfqResolution, X as createRfqSwapRecord, Y as findLockupVtxos, Z as getAssetSwaps, _ as getAssetSwapsOrThrow, $ as isRfqSwapTerminal, a0 as isRfqTerminal, a1 as nextOnchainAction, a2 as preimageForSwapRecord, a3 as pushRefundWithoutReceiver, a4 as readLockupFate, a5 as rebuildRfqSwap, a6 as refundIfUnresolved, a7 as rfqSwapOriginOf, a8 as shouldRetainRfqSwap, a9 as swapSecretsToRecord, aa as updateAssetSwap, ab as updateAssetSwapBestEffort, ac as updateRfqSwapRecord } from './repository-
|
|
2
|
+
import { S as SwapSecretsProjection, R as RfqSwapRecord, A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry, b as RefundArkProvider, c as RefundIndexer, L as LockupVtxo, d as RfqSwap, e as ArkadeRefundResult, f as LockupSpendIndexer, g as RfqSwapState } from './repository-Cw2EvvZG.js';
|
|
3
|
+
export { h as AssetSwapStatus, i as AvailableRfqSwapManagerCallbacks, B as BTC_ASSET_ID, I as InMemoryAssetSwapRepository, j as LightningReceiveSwap, k as LightningSendSwap, l as LockupFate, m as LockupNeedsRecoveryError, n as LockupParams, o as LockupSpend, O as OnchainSendAction, p as OnchainSendSwap, P as PersistableRfqSwap, q as PreimageBlockedReason, r as PreimageNotRecoverableError, s as REFUND_MTP_LAG_SECONDS, t as RFQ_RESOLVED_STATES, u as RFQ_SWAP_RETENTION_SECONDS, v as RFQ_SWAP_TERMINAL_STATES, w as RefundOutcome, x as RfqRestoreFailure, y as RfqRestoreOptions, z as RfqRestoreResult, C as RfqSwapActionName, D as RfqSwapLockup, E as RfqSwapManager, F as RfqSwapManagerCallbacks, G as RfqSwapManagerConfig, H as RfqSwapManagerDeps, J as RfqSwapManagerEvents, K as RfqSwapOrigin, N as RfqSwapOriginRequired, Q as RfqSwapOutcome, T as RfqSwapRecordStore, U as SwapContractRegistry, V as addAssetSwap, W as awaitRfqResolution, X as createRfqSwapRecord, Y as findLockupVtxos, Z as getAssetSwaps, _ as getAssetSwapsOrThrow, $ as isRfqSwapTerminal, a0 as isRfqTerminal, a1 as nextOnchainAction, a2 as preimageForSwapRecord, a3 as pushRefundWithoutReceiver, a4 as readLockupFate, a5 as rebuildRfqSwap, a6 as refundIfUnresolved, a7 as rfqSwapOriginOf, a8 as shouldRetainRfqSwap, a9 as swapSecretsToRecord, aa as updateAssetSwap, ab as updateAssetSwapBestEffort, ac as updateRfqSwapRecord } from './repository-Cw2EvvZG.js';
|
|
4
4
|
import { Network, LocalCardInput, DiscoveredMarket, Side, OfferPlan } from '@arkade-os/solver-discovery';
|
|
5
|
-
import { O as OnchainNetwork, a as OnchainHtlc, b as OnchainHtlcParams } from './rfq-
|
|
6
|
-
export { A as ARKADE_ASSET, c as ARKADE_BTC, d as AddressMismatch, C as ChainSource, e as ChainUtxo, H as HtlcUtxo, I as InvoiceFacts, L as LIGHTNING_BTC, f as LIGHTNING_RECEIVE_PAIR, g as LIGHTNING_SEND_PAIR, h as
|
|
5
|
+
import { O as OnchainNetwork, a as OnchainHtlc, b as OnchainHtlcParams } from './rfq-DglvHMNC.js';
|
|
6
|
+
export { A as ARKADE_ASSET, c as ARKADE_BTC, d as AddressMismatch, C as ChainSource, e as ChainUtxo, H as HtlcUtxo, I as InvoiceFacts, L as LIGHTNING_BTC, f as LIGHTNING_RECEIVE_PAIR, g as LIGHTNING_SEND_PAIR, h as LOCKTIME_THRESHOLD, i as LightningReceiveTreeParams, j as LightningSendTreeParams, M as MAX_MIN_CONFIRMATIONS, k as MIN_CLAIM_WINDOW_SECONDS, l as MIN_HEADROOM_SECONDS, m as ONCHAIN_BTC, n as ONCHAIN_CLAIM_MARGIN_SECONDS, o as ONCHAIN_DUST_SATS, p as ONCHAIN_ORDER_MARGIN_SECONDS, q as ONCHAIN_RECEIVE_PAIR, r as ONCHAIN_SECONDS_PER_BLOCK, s as ONCHAIN_SEND_PAIR, t as OnchainHtlcPhase, R as RFQ_TERMINAL_STATES, u as RelaySocket, v as RfqQuote, w as RfqRefusalReason, x as RfqStatus, y as RfqTransport, S as SOLO_REFUND_HEADROOM_SECONDS, z as SwapRefusal, B as arkadeAssetLeg, D as arkadeSwapRequest, E as assertFundable, F as assertReceivable, G as awaitOnchainFill, J as buildHtlcClaim, K as buildHtlcRefund, N as claimOnchainFill, P as classifyOnchainHtlc, Q as deriveLightningReceive, T as deriveOnchainReceive, U as deriveOnchainSend, V as extractPreimage, W as httpTransport, X as lightningReceiveRequest, Y as lightningSendRequest, Z as lightningSendVtxoScript, _ as newPreimage, $ as newRfqId, a0 as offerTermsFromQuote, a1 as onchainHtlcScript, a2 as onchainReceiveRequest, a3 as onchainSendRequest, a4 as paymentHashOf, a5 as receiveVtxoScript, a6 as relayTransport, a7 as requestLightningReceive, a8 as requestLightningSend, a9 as requestOnchainReceive, aa as requestOnchainSend, ab as rfqPair, ac as unilateralClaimDelay, ad as unilateralRefundDelay, ae as unilateralRefundWithoutReceiverDelay, af as verifyLockupAddress, ag as verifyReceiveInvoice } from './rfq-DglvHMNC.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Which wallet key signs this leg. Stored at `profile.signer`.
|
|
@@ -633,7 +633,7 @@ interface ClaimPacketInput {
|
|
|
633
633
|
covclaimdPubkey: Uint8Array;
|
|
634
634
|
}
|
|
635
635
|
/**
|
|
636
|
-
* Seal a preimage to covclaimd.
|
|
636
|
+
* Seal a preimage to covclaimd.
|
|
637
637
|
*
|
|
638
638
|
* The ephemeral key and nonce are generated here and CANNOT be supplied by a
|
|
639
639
|
* caller. That is the point of this signature: AES-GCM under a repeated
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
LIGHTNING_BTC,
|
|
6
6
|
LIGHTNING_RECEIVE_PAIR,
|
|
7
7
|
LIGHTNING_SEND_PAIR,
|
|
8
|
+
LOCKTIME_THRESHOLD,
|
|
8
9
|
LockupContractMissing,
|
|
9
10
|
LockupRegistrationFailed,
|
|
10
11
|
MAX_MIN_CONFIRMATIONS,
|
|
@@ -62,7 +63,7 @@ import {
|
|
|
62
63
|
unilateralRefundWithoutReceiverDelay,
|
|
63
64
|
verifyLockupAddress,
|
|
64
65
|
verifyReceiveInvoice
|
|
65
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-5NPYNQ5V.js";
|
|
66
67
|
import {
|
|
67
68
|
InMemoryAssetSwapRepository,
|
|
68
69
|
marketsCacheKey
|
|
@@ -526,8 +527,8 @@ async function cancelOffer(wallet, arkServerUrl, offerHex, opts) {
|
|
|
526
527
|
// script and the payout script comes from wallet.getAddress(), so the
|
|
527
528
|
// client's network (which only shapes address derivation) is unused here
|
|
528
529
|
});
|
|
529
|
-
const
|
|
530
|
-
const { program, args, keys } = swapProgramBinding(offer,
|
|
530
|
+
const operatorPubkey = swapAddress ? ArkAddress.decode(swapAddress).serverPubKey : client.serverKey;
|
|
531
|
+
const { program, args, keys } = swapProgramBinding(offer, operatorPubkey);
|
|
531
532
|
const rebuilt = new arkade.ArkadeProgramScript(program, args, keys);
|
|
532
533
|
if (hex2.encode(rebuilt.pkScript) !== hex2.encode(offer.swapPkScript)) {
|
|
533
534
|
throw new Error(
|
|
@@ -1411,6 +1412,7 @@ import {
|
|
|
1411
1412
|
assertSubmittedArkTxid,
|
|
1412
1413
|
buildOffchainTx,
|
|
1413
1414
|
getArkPsbtFields,
|
|
1415
|
+
hasTerminalSpend,
|
|
1414
1416
|
matchServerCheckpoints
|
|
1415
1417
|
} from "@arkade-os/sdk";
|
|
1416
1418
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -1471,6 +1473,7 @@ async function findLockupVtxos(indexer, swapPkScript) {
|
|
|
1471
1473
|
[recoverable.vtxos ?? [], true]
|
|
1472
1474
|
]) {
|
|
1473
1475
|
for (const vtxo of vtxos) {
|
|
1476
|
+
if (vtxo.isUnrolled) continue;
|
|
1474
1477
|
const key = `${vtxo.txid}:${vtxo.vout}`;
|
|
1475
1478
|
if (seen.has(key)) continue;
|
|
1476
1479
|
seen.add(key);
|
|
@@ -1493,10 +1496,17 @@ async function readLockupFate(indexer, input) {
|
|
|
1493
1496
|
const { vtxos } = await indexer.getVtxos({ scripts: [hex7.encode(input.swapPkScript)] });
|
|
1494
1497
|
const all = vtxos ?? [];
|
|
1495
1498
|
if (all.length === 0) return { fate: "unknown" };
|
|
1499
|
+
const exited = all.filter((vtxo) => vtxo.isUnrolled && !hasTerminalSpend(vtxo));
|
|
1500
|
+
if (exited.length > 0) {
|
|
1501
|
+
return {
|
|
1502
|
+
fate: "exited",
|
|
1503
|
+
outpoints: exited.map((vtxo) => ({ txid: vtxo.txid, vout: vtxo.vout }))
|
|
1504
|
+
};
|
|
1505
|
+
}
|
|
1496
1506
|
const spentBy = /* @__PURE__ */ new Map();
|
|
1497
1507
|
let everySpendNamed = true;
|
|
1498
1508
|
for (const vtxo of all) {
|
|
1499
|
-
if (!vtxo
|
|
1509
|
+
if (!hasTerminalSpend(vtxo)) return { fate: "open" };
|
|
1500
1510
|
if (vtxo.spentBy)
|
|
1501
1511
|
spentBy.set(vtxo.spentBy, {
|
|
1502
1512
|
checkpointTxid: vtxo.spentBy,
|
|
@@ -2388,12 +2398,36 @@ var RfqSwapManager = class {
|
|
|
2388
2398
|
this.setState(swap, fate.fate === "claimed" ? "settled" : "refunded");
|
|
2389
2399
|
return;
|
|
2390
2400
|
}
|
|
2391
|
-
if (swap.kind === "lightning_receive")
|
|
2401
|
+
if (swap.kind === "lightning_receive") {
|
|
2402
|
+
return fate.fate === "exited" ? this.blockExitedLockup(swap, fate) : this.driveReceiveClaim(swap);
|
|
2403
|
+
}
|
|
2392
2404
|
if (swap.kind === "onchain_send" && swap.state !== "claimed") {
|
|
2393
2405
|
if (await this.driveOnchain(swap) === "handled") return;
|
|
2394
2406
|
}
|
|
2407
|
+
if (fate.fate === "exited") {
|
|
2408
|
+
const claiming = swap.state === "claimable" || swap.state === "claimed";
|
|
2409
|
+
if (this.config.now() < swap.refundLocktime && claiming) return;
|
|
2410
|
+
return this.blockExitedLockup(swap, fate);
|
|
2411
|
+
}
|
|
2395
2412
|
await this.driveArkadeRefund(swap);
|
|
2396
2413
|
}
|
|
2414
|
+
/**
|
|
2415
|
+
* The lockup was unilaterally exited: its outputs sit onchain under the
|
|
2416
|
+
* VHTLC script, where no offchain claim or refund can reach them.
|
|
2417
|
+
*
|
|
2418
|
+
* `needs_counterparty` rather than a terminal state, because the money still
|
|
2419
|
+
* needs action and the swap can still end either way — an onchain claim can
|
|
2420
|
+
* reveal the preimage, an onchain refund can return it — and that state is
|
|
2421
|
+
* documented as re-checked every pass. It must be set from HERE and not from
|
|
2422
|
+
* inside `driveArkadeRefund`, whose two `unblock` calls would lift it again
|
|
2423
|
+
* on the very next pass.
|
|
2424
|
+
*/
|
|
2425
|
+
blockExitedLockup(swap, fate) {
|
|
2426
|
+
this.block(
|
|
2427
|
+
swap,
|
|
2428
|
+
`the lockup was unilaterally exited (${fate.outpoints.length} output(s) onchain), so no offchain spend can move it \u2014 complete the unroll and spend it onchain`
|
|
2429
|
+
);
|
|
2430
|
+
}
|
|
2397
2431
|
/**
|
|
2398
2432
|
* The receive leg's whole state machine: claim the solver-funded lockup
|
|
2399
2433
|
* while the window is open, and recognise the shapes in which it can be
|
|
@@ -2899,6 +2933,7 @@ export {
|
|
|
2899
2933
|
LIGHTNING_BTC,
|
|
2900
2934
|
LIGHTNING_RECEIVE_PAIR,
|
|
2901
2935
|
LIGHTNING_SEND_PAIR,
|
|
2936
|
+
LOCKTIME_THRESHOLD,
|
|
2902
2937
|
LockupAmountMismatchError,
|
|
2903
2938
|
LockupContractMissing,
|
|
2904
2939
|
LockupNeedsRecoveryError,
|
package/dist/nostr.cjs
CHANGED
|
@@ -62,6 +62,7 @@ var import_sdk3 = require("@arkade-os/sdk");
|
|
|
62
62
|
|
|
63
63
|
// src/claimPacket.ts
|
|
64
64
|
var import_base2 = require("@scure/base");
|
|
65
|
+
var import_aes = require("@noble/ciphers/aes.js");
|
|
65
66
|
var import_secp256k1 = require("@noble/curves/secp256k1.js");
|
|
66
67
|
var import_hkdf = require("@noble/hashes/hkdf.js");
|
|
67
68
|
var import_sha22 = require("@noble/hashes/sha2.js");
|
package/dist/nostr.d.cts
CHANGED
package/dist/nostr.d.ts
CHANGED
package/dist/nostr.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { RealmLike } from '@arkade-os/sdk/repositories/realm';
|
|
2
|
-
import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-
|
|
2
|
+
import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-C8FXlmHY.cjs';
|
|
3
3
|
import '@arkade-os/solver-discovery';
|
|
4
4
|
import '@arkade-os/sdk';
|
|
5
|
-
import '../../rfq-
|
|
5
|
+
import '../../rfq-DglvHMNC.cjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Realm backend for React Native.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { RealmLike } from '@arkade-os/sdk/repositories/realm';
|
|
2
|
-
import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-
|
|
2
|
+
import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-Cw2EvvZG.js';
|
|
3
3
|
import '@arkade-os/solver-discovery';
|
|
4
4
|
import '@arkade-os/sdk';
|
|
5
|
-
import '../../rfq-
|
|
5
|
+
import '../../rfq-DglvHMNC.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Realm backend for React Native.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { SQLExecutor } from '@arkade-os/sdk/repositories/sqlite';
|
|
2
|
-
import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-
|
|
2
|
+
import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-C8FXlmHY.cjs';
|
|
3
3
|
import '@arkade-os/solver-discovery';
|
|
4
4
|
import '@arkade-os/sdk';
|
|
5
|
-
import '../../rfq-
|
|
5
|
+
import '../../rfq-DglvHMNC.cjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* SQLite backend over the SDK's `SQLExecutor`, so any driver plugs in
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { SQLExecutor } from '@arkade-os/sdk/repositories/sqlite';
|
|
2
|
-
import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-
|
|
2
|
+
import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-Cw2EvvZG.js';
|
|
3
3
|
import '@arkade-os/solver-discovery';
|
|
4
4
|
import '@arkade-os/sdk';
|
|
5
|
-
import '../../rfq-
|
|
5
|
+
import '../../rfq-DglvHMNC.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* SQLite backend over the SDK's `SQLExecutor`, so any driver plugs in
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DiscoveredMarket } from '@arkade-os/solver-discovery';
|
|
2
2
|
import { IWallet, ProvisionedKey, ProvisionedClaimSecret, RestArkProvider, RestIndexerProvider, VHTLC, Identity, IContractManager } from '@arkade-os/sdk';
|
|
3
|
-
import {
|
|
3
|
+
import { x as RfqStatus, y as RfqTransport, a as OnchainHtlc, e as ChainUtxo, C as ChainSource, t as OnchainHtlcPhase } from './rfq-DglvHMNC.cjs';
|
|
4
4
|
|
|
5
5
|
type AssetSwapStatus = "pending" | "cancelling" | "fulfilled" | "cancelled" | "recoverable" | "awaiting_fill" | "claimable" | "claimed" | "refunded_l1";
|
|
6
6
|
/** The sentinel asset id for BTC itself, as opposed to a 68-hex asset id.
|
|
@@ -227,12 +227,15 @@ interface LockupVtxo {
|
|
|
227
227
|
* It is still the trader's money and it is still visible, which is why
|
|
228
228
|
* {@link findLockupVtxos} returns it. What it is not is refundable by
|
|
229
229
|
* {@link pushRefundWithoutReceiver}: that builds an offchain Ark
|
|
230
|
-
* transaction, and the SDK's own predicates
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
230
|
+
* transaction, and the SDK's own predicates put the two states on opposite
|
|
231
|
+
* sides — `canSpendOffchain` is false whenever `canRecoverOnchain` is true
|
|
232
|
+
* (`wallet/vtxo.ts`), and the latter is documented as "must be recovered
|
|
233
|
+
* into a fresh batch rather than spent offchain". Holding the trader's
|
|
234
|
+
* `sender` key does not change that; a sweep removes the leaf from the live
|
|
235
|
+
* tree, not the signature from the trader.
|
|
236
|
+
*
|
|
237
|
+
* Opposite, but not exhaustive: an unrolled output satisfies neither, and
|
|
238
|
+
* {@link findLockupVtxos} drops those before they reach this type at all.
|
|
236
239
|
*
|
|
237
240
|
* `packages/boltz-swap` splits on exactly this fact rather than working
|
|
238
241
|
* around it: `settleRefundWithoutReceiver` sends a live VTXO through an
|
|
@@ -321,6 +324,18 @@ declare class LockupNeedsRecoveryError extends Error {
|
|
|
321
324
|
* That function refuses the recoverable ones by name rather than submitting a
|
|
322
325
|
* spend the server must reject.
|
|
323
326
|
*
|
|
327
|
+
* **Unrolled outputs are the one exception, and are dropped.** A unilaterally
|
|
328
|
+
* exited output lives onchain behind its CSV; no offchain spend of any leaf can
|
|
329
|
+
* reach it, and `LockupVtxo` carries no field to say so, so a caller could not
|
|
330
|
+
* tell it apart from a live one. Whether arkd returns such an output under
|
|
331
|
+
* `spendableOnly` is not determinable from here, so the exclusion is made
|
|
332
|
+
* defensively rather than assumed. It costs the two waiting callers nothing
|
|
333
|
+
* they wanted: `awaitLockupFunding` keeps waiting for a claimable lockup
|
|
334
|
+
* instead of publishing `P` into a spend that cannot land, and
|
|
335
|
+
* `refundIfUnresolved` reports `nothing_to_refund` instead of grinding a doomed
|
|
336
|
+
* push to its deadline. The manager reads the exit through
|
|
337
|
+
* {@link readLockupFate}, which queries unfiltered and reports it as `exited`.
|
|
338
|
+
*
|
|
324
339
|
* This read — not the RFQ's reported state — is the authority on whether
|
|
325
340
|
* there is anything left at the lockup.
|
|
326
341
|
*
|
|
@@ -374,6 +389,29 @@ type LockupFate =
|
|
|
374
389
|
fate: "returned";
|
|
375
390
|
spends: readonly LockupSpend[];
|
|
376
391
|
}
|
|
392
|
+
/**
|
|
393
|
+
* At least one output was unilaterally exited: it sits onchain under the
|
|
394
|
+
* VHTLC script, where no offchain claim or refund can reach it.
|
|
395
|
+
*
|
|
396
|
+
* Not terminal, and not a loss. The money is still under the same script
|
|
397
|
+
* with the same leaves, so `completeUnroll` plus an onchain spend can still
|
|
398
|
+
* end the swap either way — which is why this outranks `open`: an output
|
|
399
|
+
* that is "still unspent" but unreachable is not a swap that is merely
|
|
400
|
+
* running.
|
|
401
|
+
*
|
|
402
|
+
* It outranks a verdict too, on a lockup where a sibling output was claimed
|
|
403
|
+
* or returned. That is the rule `open` already sets, not a new one: the
|
|
404
|
+
* unspent test short-circuits before any witness is read, so a partially
|
|
405
|
+
* resolved lockup has never reported `claimed`/`returned`. What changes is
|
|
406
|
+
* only that such a lockup now says why it is unresolved.
|
|
407
|
+
*/
|
|
408
|
+
| {
|
|
409
|
+
fate: "exited";
|
|
410
|
+
outpoints: readonly {
|
|
411
|
+
txid: string;
|
|
412
|
+
vout: number;
|
|
413
|
+
}[];
|
|
414
|
+
}
|
|
377
415
|
/** Nothing was learned: no outputs visible, an output spent by nothing the
|
|
378
416
|
* indexer names, a spend it could not produce, or a blob that would not
|
|
379
417
|
* decode. Never an answer. */
|
|
@@ -409,6 +447,11 @@ type LockupFate =
|
|
|
409
447
|
* response to `unknown` is the same as to `open`: keep watching, and let the
|
|
410
448
|
* refund timelock — which no outage can move — be what ends the wait.
|
|
411
449
|
*
|
|
450
|
+
* **An exit is read before anything else, and over the whole set.** It is the
|
|
451
|
+
* one fact that makes an unspent output unreachable, so it outranks `open`; and
|
|
452
|
+
* it is scanned across every output rather than in outpoint order, so which
|
|
453
|
+
* output happens to come first cannot change the answer.
|
|
454
|
+
*
|
|
412
455
|
* Ask-the-indexer, don't-trust-local-state: read fresh on every poll, never
|
|
413
456
|
* cached, the same posture {@link findLockupVtxos} already establishes.
|
|
414
457
|
*/
|
|
@@ -447,9 +490,9 @@ declare function readLockupFate(indexer: LockupSpendIndexer, input: {
|
|
|
447
490
|
* {@link refundIfUnresolved}, which retries.
|
|
448
491
|
*
|
|
449
492
|
* **Swept outputs are refused, not attempted.** This is an OFFCHAIN spend, and
|
|
450
|
-
* a swept output is no longer a live leaf: `canSpendOffchain`
|
|
451
|
-
* `canRecoverOnchain`
|
|
452
|
-
*
|
|
493
|
+
* a swept output is no longer a live leaf: `canSpendOffchain` is false wherever
|
|
494
|
+
* `canRecoverOnchain` is true, so a recoverable input cannot be spent this way
|
|
495
|
+
* whatever key signs it (see
|
|
453
496
|
* {@link LockupVtxo.recoverable}). Because every input lands in ONE aggregate
|
|
454
497
|
* transaction, a single swept output would take the live ones down with it —
|
|
455
498
|
* so the whole push is refused with {@link LockupNeedsRecoveryError} naming the
|
|
@@ -1162,7 +1205,9 @@ interface RfqSwapManagerDeps {
|
|
|
1162
1205
|
* `settled`; a lockup fully spent by anything else ends it `refunded`.
|
|
1163
1206
|
* Anything the indexer could not answer is `unknown`, which is NOT an
|
|
1164
1207
|
* answer: the pass carries on to the steps below, whose deadlines an indexer
|
|
1165
|
-
* outage has no bearing on.
|
|
1208
|
+
* outage has no bearing on. `exited` — an output unilaterally taken onchain
|
|
1209
|
+
* — ends neither the swap nor the pass: it blocks the Arkade half below,
|
|
1210
|
+
* with the L1 half left running.
|
|
1166
1211
|
* 2. **Drive the trader's claim.** On an onchain send that is the L1 fill — see
|
|
1167
1212
|
* {@link nextOnchainAction}. On a receive it is the lockup itself, and it
|
|
1168
1213
|
* ends the pass: that leg has no step 3.
|
|
@@ -1493,6 +1538,18 @@ declare class RfqSwapManager {
|
|
|
1493
1538
|
private arm;
|
|
1494
1539
|
private pollSwap;
|
|
1495
1540
|
private runPass;
|
|
1541
|
+
/**
|
|
1542
|
+
* The lockup was unilaterally exited: its outputs sit onchain under the
|
|
1543
|
+
* VHTLC script, where no offchain claim or refund can reach them.
|
|
1544
|
+
*
|
|
1545
|
+
* `needs_counterparty` rather than a terminal state, because the money still
|
|
1546
|
+
* needs action and the swap can still end either way — an onchain claim can
|
|
1547
|
+
* reveal the preimage, an onchain refund can return it — and that state is
|
|
1548
|
+
* documented as re-checked every pass. It must be set from HERE and not from
|
|
1549
|
+
* inside `driveArkadeRefund`, whose two `unblock` calls would lift it again
|
|
1550
|
+
* on the very next pass.
|
|
1551
|
+
*/
|
|
1552
|
+
private blockExitedLockup;
|
|
1496
1553
|
/**
|
|
1497
1554
|
* The receive leg's whole state machine: claim the solver-funded lockup
|
|
1498
1555
|
* while the window is open, and recognise the shapes in which it can be
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DiscoveredMarket } from '@arkade-os/solver-discovery';
|
|
2
2
|
import { IWallet, ProvisionedKey, ProvisionedClaimSecret, RestArkProvider, RestIndexerProvider, VHTLC, Identity, IContractManager } from '@arkade-os/sdk';
|
|
3
|
-
import {
|
|
3
|
+
import { x as RfqStatus, y as RfqTransport, a as OnchainHtlc, e as ChainUtxo, C as ChainSource, t as OnchainHtlcPhase } from './rfq-DglvHMNC.js';
|
|
4
4
|
|
|
5
5
|
type AssetSwapStatus = "pending" | "cancelling" | "fulfilled" | "cancelled" | "recoverable" | "awaiting_fill" | "claimable" | "claimed" | "refunded_l1";
|
|
6
6
|
/** The sentinel asset id for BTC itself, as opposed to a 68-hex asset id.
|
|
@@ -227,12 +227,15 @@ interface LockupVtxo {
|
|
|
227
227
|
* It is still the trader's money and it is still visible, which is why
|
|
228
228
|
* {@link findLockupVtxos} returns it. What it is not is refundable by
|
|
229
229
|
* {@link pushRefundWithoutReceiver}: that builds an offchain Ark
|
|
230
|
-
* transaction, and the SDK's own predicates
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
230
|
+
* transaction, and the SDK's own predicates put the two states on opposite
|
|
231
|
+
* sides — `canSpendOffchain` is false whenever `canRecoverOnchain` is true
|
|
232
|
+
* (`wallet/vtxo.ts`), and the latter is documented as "must be recovered
|
|
233
|
+
* into a fresh batch rather than spent offchain". Holding the trader's
|
|
234
|
+
* `sender` key does not change that; a sweep removes the leaf from the live
|
|
235
|
+
* tree, not the signature from the trader.
|
|
236
|
+
*
|
|
237
|
+
* Opposite, but not exhaustive: an unrolled output satisfies neither, and
|
|
238
|
+
* {@link findLockupVtxos} drops those before they reach this type at all.
|
|
236
239
|
*
|
|
237
240
|
* `packages/boltz-swap` splits on exactly this fact rather than working
|
|
238
241
|
* around it: `settleRefundWithoutReceiver` sends a live VTXO through an
|
|
@@ -321,6 +324,18 @@ declare class LockupNeedsRecoveryError extends Error {
|
|
|
321
324
|
* That function refuses the recoverable ones by name rather than submitting a
|
|
322
325
|
* spend the server must reject.
|
|
323
326
|
*
|
|
327
|
+
* **Unrolled outputs are the one exception, and are dropped.** A unilaterally
|
|
328
|
+
* exited output lives onchain behind its CSV; no offchain spend of any leaf can
|
|
329
|
+
* reach it, and `LockupVtxo` carries no field to say so, so a caller could not
|
|
330
|
+
* tell it apart from a live one. Whether arkd returns such an output under
|
|
331
|
+
* `spendableOnly` is not determinable from here, so the exclusion is made
|
|
332
|
+
* defensively rather than assumed. It costs the two waiting callers nothing
|
|
333
|
+
* they wanted: `awaitLockupFunding` keeps waiting for a claimable lockup
|
|
334
|
+
* instead of publishing `P` into a spend that cannot land, and
|
|
335
|
+
* `refundIfUnresolved` reports `nothing_to_refund` instead of grinding a doomed
|
|
336
|
+
* push to its deadline. The manager reads the exit through
|
|
337
|
+
* {@link readLockupFate}, which queries unfiltered and reports it as `exited`.
|
|
338
|
+
*
|
|
324
339
|
* This read — not the RFQ's reported state — is the authority on whether
|
|
325
340
|
* there is anything left at the lockup.
|
|
326
341
|
*
|
|
@@ -374,6 +389,29 @@ type LockupFate =
|
|
|
374
389
|
fate: "returned";
|
|
375
390
|
spends: readonly LockupSpend[];
|
|
376
391
|
}
|
|
392
|
+
/**
|
|
393
|
+
* At least one output was unilaterally exited: it sits onchain under the
|
|
394
|
+
* VHTLC script, where no offchain claim or refund can reach it.
|
|
395
|
+
*
|
|
396
|
+
* Not terminal, and not a loss. The money is still under the same script
|
|
397
|
+
* with the same leaves, so `completeUnroll` plus an onchain spend can still
|
|
398
|
+
* end the swap either way — which is why this outranks `open`: an output
|
|
399
|
+
* that is "still unspent" but unreachable is not a swap that is merely
|
|
400
|
+
* running.
|
|
401
|
+
*
|
|
402
|
+
* It outranks a verdict too, on a lockup where a sibling output was claimed
|
|
403
|
+
* or returned. That is the rule `open` already sets, not a new one: the
|
|
404
|
+
* unspent test short-circuits before any witness is read, so a partially
|
|
405
|
+
* resolved lockup has never reported `claimed`/`returned`. What changes is
|
|
406
|
+
* only that such a lockup now says why it is unresolved.
|
|
407
|
+
*/
|
|
408
|
+
| {
|
|
409
|
+
fate: "exited";
|
|
410
|
+
outpoints: readonly {
|
|
411
|
+
txid: string;
|
|
412
|
+
vout: number;
|
|
413
|
+
}[];
|
|
414
|
+
}
|
|
377
415
|
/** Nothing was learned: no outputs visible, an output spent by nothing the
|
|
378
416
|
* indexer names, a spend it could not produce, or a blob that would not
|
|
379
417
|
* decode. Never an answer. */
|
|
@@ -409,6 +447,11 @@ type LockupFate =
|
|
|
409
447
|
* response to `unknown` is the same as to `open`: keep watching, and let the
|
|
410
448
|
* refund timelock — which no outage can move — be what ends the wait.
|
|
411
449
|
*
|
|
450
|
+
* **An exit is read before anything else, and over the whole set.** It is the
|
|
451
|
+
* one fact that makes an unspent output unreachable, so it outranks `open`; and
|
|
452
|
+
* it is scanned across every output rather than in outpoint order, so which
|
|
453
|
+
* output happens to come first cannot change the answer.
|
|
454
|
+
*
|
|
412
455
|
* Ask-the-indexer, don't-trust-local-state: read fresh on every poll, never
|
|
413
456
|
* cached, the same posture {@link findLockupVtxos} already establishes.
|
|
414
457
|
*/
|
|
@@ -447,9 +490,9 @@ declare function readLockupFate(indexer: LockupSpendIndexer, input: {
|
|
|
447
490
|
* {@link refundIfUnresolved}, which retries.
|
|
448
491
|
*
|
|
449
492
|
* **Swept outputs are refused, not attempted.** This is an OFFCHAIN spend, and
|
|
450
|
-
* a swept output is no longer a live leaf: `canSpendOffchain`
|
|
451
|
-
* `canRecoverOnchain`
|
|
452
|
-
*
|
|
493
|
+
* a swept output is no longer a live leaf: `canSpendOffchain` is false wherever
|
|
494
|
+
* `canRecoverOnchain` is true, so a recoverable input cannot be spent this way
|
|
495
|
+
* whatever key signs it (see
|
|
453
496
|
* {@link LockupVtxo.recoverable}). Because every input lands in ONE aggregate
|
|
454
497
|
* transaction, a single swept output would take the live ones down with it —
|
|
455
498
|
* so the whole push is refused with {@link LockupNeedsRecoveryError} naming the
|
|
@@ -1162,7 +1205,9 @@ interface RfqSwapManagerDeps {
|
|
|
1162
1205
|
* `settled`; a lockup fully spent by anything else ends it `refunded`.
|
|
1163
1206
|
* Anything the indexer could not answer is `unknown`, which is NOT an
|
|
1164
1207
|
* answer: the pass carries on to the steps below, whose deadlines an indexer
|
|
1165
|
-
* outage has no bearing on.
|
|
1208
|
+
* outage has no bearing on. `exited` — an output unilaterally taken onchain
|
|
1209
|
+
* — ends neither the swap nor the pass: it blocks the Arkade half below,
|
|
1210
|
+
* with the L1 half left running.
|
|
1166
1211
|
* 2. **Drive the trader's claim.** On an onchain send that is the L1 fill — see
|
|
1167
1212
|
* {@link nextOnchainAction}. On a receive it is the lockup itself, and it
|
|
1168
1213
|
* ends the pass: that leg has no step 3.
|
|
@@ -1493,6 +1538,18 @@ declare class RfqSwapManager {
|
|
|
1493
1538
|
private arm;
|
|
1494
1539
|
private pollSwap;
|
|
1495
1540
|
private runPass;
|
|
1541
|
+
/**
|
|
1542
|
+
* The lockup was unilaterally exited: its outputs sit onchain under the
|
|
1543
|
+
* VHTLC script, where no offchain claim or refund can reach them.
|
|
1544
|
+
*
|
|
1545
|
+
* `needs_counterparty` rather than a terminal state, because the money still
|
|
1546
|
+
* needs action and the swap can still end either way — an onchain claim can
|
|
1547
|
+
* reveal the preimage, an onchain refund can return it — and that state is
|
|
1548
|
+
* documented as re-checked every pass. It must be set from HERE and not from
|
|
1549
|
+
* inside `driveArkadeRefund`, whose two `unblock` calls would lift it again
|
|
1550
|
+
* on the very next pass.
|
|
1551
|
+
*/
|
|
1552
|
+
private blockExitedLockup;
|
|
1496
1553
|
/**
|
|
1497
1554
|
* The receive leg's whole state machine: claim the solver-funded lockup
|
|
1498
1555
|
* while the window is open, and recognise the shapes in which it can be
|
|
@@ -9,6 +9,13 @@ declare const ONCHAIN_ORDER_MARGIN_SECONDS: number;
|
|
|
9
9
|
declare const ONCHAIN_CLAIM_MARGIN_SECONDS: number;
|
|
10
10
|
/** Bounds on the confirmation depth a quote may demand. */
|
|
11
11
|
declare const MAX_MIN_CONFIRMATIONS = 6;
|
|
12
|
+
/**
|
|
13
|
+
* BIP65's boundary between the two things an absolute locktime can mean.
|
|
14
|
+
* Below it consensus reads the value as a block height; at or above it, as a
|
|
15
|
+
* unix timestamp. 500,000,000 itself is 1985-07-05 and is a timestamp, so the
|
|
16
|
+
* comparison against it is strict.
|
|
17
|
+
*/
|
|
18
|
+
declare const LOCKTIME_THRESHOLD = 500000000;
|
|
12
19
|
/** Conservative block interval for converting depths into wall-clock time. */
|
|
13
20
|
declare const ONCHAIN_SECONDS_PER_BLOCK = 600;
|
|
14
21
|
/**
|
|
@@ -239,7 +246,7 @@ declare const ONCHAIN_SEND_PAIR: string;
|
|
|
239
246
|
/** On-board: a Bitcoin-L1 HTLC in, Arkade sats out. */
|
|
240
247
|
declare const ONCHAIN_RECEIVE_PAIR: string;
|
|
241
248
|
/** The closed refusal set. Treat any unknown reason as a generic decline. */
|
|
242
|
-
type RfqRefusalReason = "unsupported_pair" | "unsupported_payload" | "amount_out_of_range" | "exposure_cap" | "invoice_expired" | "quote_conflict" | "pricing_unavailable";
|
|
249
|
+
type RfqRefusalReason = "unsupported_pair" | "unsupported_payload" | "amount_out_of_range" | "exposure_cap" | "invoice_expired" | "quote_conflict" | "pricing_unavailable" | "rate_limited";
|
|
243
250
|
/** Lifecycle vocabulary; states after which nothing more will happen. */
|
|
244
251
|
declare const RFQ_TERMINAL_STATES: readonly ["settled", "refused", "expired", "refunded", "stuck"];
|
|
245
252
|
/** A refusal from the solver, carrying its closed-set reason. */
|
|
@@ -480,12 +487,11 @@ interface InvoiceFacts {
|
|
|
480
487
|
* throws while nothing is funded. `RfqSwapManager` re-registers as a backstop
|
|
481
488
|
* for older records; a repeat write is a no-op.
|
|
482
489
|
*
|
|
483
|
-
* The `sender` key
|
|
484
|
-
*
|
|
485
|
-
*
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
* recovers the funds even without it — but it needs the SOLVER's active
|
|
490
|
+
* The `sender` key is the wallet's identity key, reused by {@link
|
|
491
|
+
* provisionRefundKey} — returned as `senderPubkey` plus `secrets`. `secrets`
|
|
492
|
+
* holds only a public descriptor; the signer re-derives from the wallet, so
|
|
493
|
+
* nothing secret is at rest. Persist `secrets` with the record anyway: it is
|
|
494
|
+
* how the refund signer is found again. `nonInteractiveRefund` recovers the funds even without it — but it needs the SOLVER's active
|
|
489
495
|
* cooperation, not just infrastructure uptime.
|
|
490
496
|
*/
|
|
491
497
|
declare function requestLightningSend(wallet: IWallet, arkServerUrl: string, transport: RfqTransport, params: {
|
|
@@ -508,7 +514,8 @@ declare function requestLightningSend(wallet: IWallet, arkServerUrl: string, tra
|
|
|
508
514
|
* `lockup` (with `address`): without it the manager can only poll, and
|
|
509
515
|
* cannot retire the row this call just wrote. */
|
|
510
516
|
script: InstanceType<typeof VHTLC.ScriptV2>;
|
|
511
|
-
/** Where a failed swap refunds.
|
|
517
|
+
/** Where a failed swap refunds — the same address `secrets.pkScript` was
|
|
518
|
+
* decoded from, so the quote and the covenant always name one script. */
|
|
512
519
|
refundAddress: string;
|
|
513
520
|
/** The VHTLC `sender` x-only key, bound into the covenant. Public. */
|
|
514
521
|
senderPubkey: Uint8Array;
|
|
@@ -521,7 +528,9 @@ declare function requestLightningSend(wallet: IWallet, arkServerUrl: string, tra
|
|
|
521
528
|
* Returned so a consumer can persist the swap without re-deriving any of
|
|
522
529
|
* it. Half of these are not on the quote: `serverPubkey` and `claimDelay`
|
|
523
530
|
* come from this wallet's own `getInfo()`, `emulatorPubkey` from a
|
|
524
|
-
* per-network pin, `refundPkScript` from
|
|
531
|
+
* per-network pin, `refundPkScript` from `secrets` — decoded from the
|
|
532
|
+
* refund address at provisioning time, the same address this call returns
|
|
533
|
+
* as `refundAddress`.
|
|
525
534
|
*
|
|
526
535
|
* All public. Persisting them is optional: this call also registers the
|
|
527
536
|
* lockup as a contract, and that row is where `rebuildRfqSwap` takes its
|
|
@@ -993,4 +1002,4 @@ declare function requestOnchainReceive(wallet: IWallet, arkServerUrl: string, tr
|
|
|
993
1002
|
secrets: ProvisionedClaimSecret;
|
|
994
1003
|
}>;
|
|
995
1004
|
|
|
996
|
-
export {
|
|
1005
|
+
export { newRfqId as $, ARKADE_ASSET as A, arkadeAssetLeg as B, type ChainSource as C, arkadeSwapRequest as D, assertFundable as E, assertReceivable as F, awaitOnchainFill as G, type HtlcUtxo as H, type InvoiceFacts as I, buildHtlcClaim as J, buildHtlcRefund as K, LIGHTNING_BTC as L, MAX_MIN_CONFIRMATIONS as M, claimOnchainFill as N, type OnchainNetwork as O, classifyOnchainHtlc as P, deriveLightningReceive as Q, RFQ_TERMINAL_STATES as R, SOLO_REFUND_HEADROOM_SECONDS as S, deriveOnchainReceive as T, deriveOnchainSend as U, extractPreimage as V, httpTransport as W, lightningReceiveRequest as X, lightningSendRequest as Y, lightningSendVtxoScript as Z, newPreimage as _, type OnchainHtlc as a, offerTermsFromQuote as a0, onchainHtlcScript as a1, onchainReceiveRequest as a2, onchainSendRequest as a3, paymentHashOf as a4, receiveVtxoScript as a5, relayTransport as a6, requestLightningReceive as a7, requestLightningSend as a8, requestOnchainReceive as a9, requestOnchainSend as aa, rfqPair as ab, unilateralClaimDelay as ac, unilateralRefundDelay as ad, unilateralRefundWithoutReceiverDelay as ae, verifyLockupAddress as af, verifyReceiveInvoice as ag, type OnchainHtlcParams as b, ARKADE_BTC as c, AddressMismatch as d, type ChainUtxo as e, LIGHTNING_RECEIVE_PAIR as f, LIGHTNING_SEND_PAIR as g, LOCKTIME_THRESHOLD as h, type LightningReceiveTreeParams as i, type LightningSendTreeParams as j, MIN_CLAIM_WINDOW_SECONDS as k, MIN_HEADROOM_SECONDS as l, ONCHAIN_BTC as m, ONCHAIN_CLAIM_MARGIN_SECONDS as n, ONCHAIN_DUST_SATS as o, ONCHAIN_ORDER_MARGIN_SECONDS as p, ONCHAIN_RECEIVE_PAIR as q, ONCHAIN_SECONDS_PER_BLOCK as r, ONCHAIN_SEND_PAIR as s, type OnchainHtlcPhase as t, type RelaySocket as u, type RfqQuote as v, type RfqRefusalReason as w, type RfqStatus as x, type RfqTransport as y, SwapRefusal as z };
|
|
@@ -9,6 +9,13 @@ declare const ONCHAIN_ORDER_MARGIN_SECONDS: number;
|
|
|
9
9
|
declare const ONCHAIN_CLAIM_MARGIN_SECONDS: number;
|
|
10
10
|
/** Bounds on the confirmation depth a quote may demand. */
|
|
11
11
|
declare const MAX_MIN_CONFIRMATIONS = 6;
|
|
12
|
+
/**
|
|
13
|
+
* BIP65's boundary between the two things an absolute locktime can mean.
|
|
14
|
+
* Below it consensus reads the value as a block height; at or above it, as a
|
|
15
|
+
* unix timestamp. 500,000,000 itself is 1985-07-05 and is a timestamp, so the
|
|
16
|
+
* comparison against it is strict.
|
|
17
|
+
*/
|
|
18
|
+
declare const LOCKTIME_THRESHOLD = 500000000;
|
|
12
19
|
/** Conservative block interval for converting depths into wall-clock time. */
|
|
13
20
|
declare const ONCHAIN_SECONDS_PER_BLOCK = 600;
|
|
14
21
|
/**
|
|
@@ -239,7 +246,7 @@ declare const ONCHAIN_SEND_PAIR: string;
|
|
|
239
246
|
/** On-board: a Bitcoin-L1 HTLC in, Arkade sats out. */
|
|
240
247
|
declare const ONCHAIN_RECEIVE_PAIR: string;
|
|
241
248
|
/** The closed refusal set. Treat any unknown reason as a generic decline. */
|
|
242
|
-
type RfqRefusalReason = "unsupported_pair" | "unsupported_payload" | "amount_out_of_range" | "exposure_cap" | "invoice_expired" | "quote_conflict" | "pricing_unavailable";
|
|
249
|
+
type RfqRefusalReason = "unsupported_pair" | "unsupported_payload" | "amount_out_of_range" | "exposure_cap" | "invoice_expired" | "quote_conflict" | "pricing_unavailable" | "rate_limited";
|
|
243
250
|
/** Lifecycle vocabulary; states after which nothing more will happen. */
|
|
244
251
|
declare const RFQ_TERMINAL_STATES: readonly ["settled", "refused", "expired", "refunded", "stuck"];
|
|
245
252
|
/** A refusal from the solver, carrying its closed-set reason. */
|
|
@@ -480,12 +487,11 @@ interface InvoiceFacts {
|
|
|
480
487
|
* throws while nothing is funded. `RfqSwapManager` re-registers as a backstop
|
|
481
488
|
* for older records; a repeat write is a no-op.
|
|
482
489
|
*
|
|
483
|
-
* The `sender` key
|
|
484
|
-
*
|
|
485
|
-
*
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
* recovers the funds even without it — but it needs the SOLVER's active
|
|
490
|
+
* The `sender` key is the wallet's identity key, reused by {@link
|
|
491
|
+
* provisionRefundKey} — returned as `senderPubkey` plus `secrets`. `secrets`
|
|
492
|
+
* holds only a public descriptor; the signer re-derives from the wallet, so
|
|
493
|
+
* nothing secret is at rest. Persist `secrets` with the record anyway: it is
|
|
494
|
+
* how the refund signer is found again. `nonInteractiveRefund` recovers the funds even without it — but it needs the SOLVER's active
|
|
489
495
|
* cooperation, not just infrastructure uptime.
|
|
490
496
|
*/
|
|
491
497
|
declare function requestLightningSend(wallet: IWallet, arkServerUrl: string, transport: RfqTransport, params: {
|
|
@@ -508,7 +514,8 @@ declare function requestLightningSend(wallet: IWallet, arkServerUrl: string, tra
|
|
|
508
514
|
* `lockup` (with `address`): without it the manager can only poll, and
|
|
509
515
|
* cannot retire the row this call just wrote. */
|
|
510
516
|
script: InstanceType<typeof VHTLC.ScriptV2>;
|
|
511
|
-
/** Where a failed swap refunds.
|
|
517
|
+
/** Where a failed swap refunds — the same address `secrets.pkScript` was
|
|
518
|
+
* decoded from, so the quote and the covenant always name one script. */
|
|
512
519
|
refundAddress: string;
|
|
513
520
|
/** The VHTLC `sender` x-only key, bound into the covenant. Public. */
|
|
514
521
|
senderPubkey: Uint8Array;
|
|
@@ -521,7 +528,9 @@ declare function requestLightningSend(wallet: IWallet, arkServerUrl: string, tra
|
|
|
521
528
|
* Returned so a consumer can persist the swap without re-deriving any of
|
|
522
529
|
* it. Half of these are not on the quote: `serverPubkey` and `claimDelay`
|
|
523
530
|
* come from this wallet's own `getInfo()`, `emulatorPubkey` from a
|
|
524
|
-
* per-network pin, `refundPkScript` from
|
|
531
|
+
* per-network pin, `refundPkScript` from `secrets` — decoded from the
|
|
532
|
+
* refund address at provisioning time, the same address this call returns
|
|
533
|
+
* as `refundAddress`.
|
|
525
534
|
*
|
|
526
535
|
* All public. Persisting them is optional: this call also registers the
|
|
527
536
|
* lockup as a contract, and that row is where `rebuildRfqSwap` takes its
|
|
@@ -993,4 +1002,4 @@ declare function requestOnchainReceive(wallet: IWallet, arkServerUrl: string, tr
|
|
|
993
1002
|
secrets: ProvisionedClaimSecret;
|
|
994
1003
|
}>;
|
|
995
1004
|
|
|
996
|
-
export {
|
|
1005
|
+
export { newRfqId as $, ARKADE_ASSET as A, arkadeAssetLeg as B, type ChainSource as C, arkadeSwapRequest as D, assertFundable as E, assertReceivable as F, awaitOnchainFill as G, type HtlcUtxo as H, type InvoiceFacts as I, buildHtlcClaim as J, buildHtlcRefund as K, LIGHTNING_BTC as L, MAX_MIN_CONFIRMATIONS as M, claimOnchainFill as N, type OnchainNetwork as O, classifyOnchainHtlc as P, deriveLightningReceive as Q, RFQ_TERMINAL_STATES as R, SOLO_REFUND_HEADROOM_SECONDS as S, deriveOnchainReceive as T, deriveOnchainSend as U, extractPreimage as V, httpTransport as W, lightningReceiveRequest as X, lightningSendRequest as Y, lightningSendVtxoScript as Z, newPreimage as _, type OnchainHtlc as a, offerTermsFromQuote as a0, onchainHtlcScript as a1, onchainReceiveRequest as a2, onchainSendRequest as a3, paymentHashOf as a4, receiveVtxoScript as a5, relayTransport as a6, requestLightningReceive as a7, requestLightningSend as a8, requestOnchainReceive as a9, requestOnchainSend as aa, rfqPair as ab, unilateralClaimDelay as ac, unilateralRefundDelay as ad, unilateralRefundWithoutReceiverDelay as ae, verifyLockupAddress as af, verifyReceiveInvoice as ag, type OnchainHtlcParams as b, ARKADE_BTC as c, AddressMismatch as d, type ChainUtxo as e, LIGHTNING_RECEIVE_PAIR as f, LIGHTNING_SEND_PAIR as g, LOCKTIME_THRESHOLD as h, type LightningReceiveTreeParams as i, type LightningSendTreeParams as j, MIN_CLAIM_WINDOW_SECONDS as k, MIN_HEADROOM_SECONDS as l, ONCHAIN_BTC as m, ONCHAIN_CLAIM_MARGIN_SECONDS as n, ONCHAIN_DUST_SATS as o, ONCHAIN_ORDER_MARGIN_SECONDS as p, ONCHAIN_RECEIVE_PAIR as q, ONCHAIN_SECONDS_PER_BLOCK as r, ONCHAIN_SEND_PAIR as s, type OnchainHtlcPhase as t, type RelaySocket as u, type RfqQuote as v, type RfqRefusalReason as w, type RfqStatus as x, type RfqTransport as y, SwapRefusal as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arkade-os/swap",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Client-side Arkade Intents asset swaps: discover markets, quote, create/track/cancel offers, restore from chain.",
|
|
6
6
|
"repository": {
|
|
@@ -65,11 +65,12 @@
|
|
|
65
65
|
"license": "MIT",
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"@arkade-os/solver-discovery": "0.2.3",
|
|
68
|
+
"@noble/ciphers": "2.1.1",
|
|
68
69
|
"@noble/curves": "2.0.1",
|
|
69
70
|
"@noble/hashes": "2.0.1",
|
|
70
71
|
"@scure/base": "2.0.0",
|
|
71
72
|
"@scure/btc-signer": "2.0.1",
|
|
72
|
-
"@arkade-os/sdk": "0.4.
|
|
73
|
+
"@arkade-os/sdk": "0.4.67"
|
|
73
74
|
},
|
|
74
75
|
"peerDependencies": {
|
|
75
76
|
"nostr-tools": "^2.12.0"
|
|
@@ -90,8 +91,8 @@
|
|
|
90
91
|
"scripts": {
|
|
91
92
|
"build": "tsup src/index.ts src/nostr.ts src/repositories/sqlite/index.ts src/repositories/realm/index.ts --format esm,cjs --dts --clean",
|
|
92
93
|
"typecheck": "tsc --noEmit",
|
|
93
|
-
"format": "
|
|
94
|
-
"lint": "
|
|
94
|
+
"format": "biome format --write src test",
|
|
95
|
+
"lint": "biome format src test",
|
|
95
96
|
"test": "vitest run --exclude test/e2e",
|
|
96
97
|
"test:unit": "vitest run --exclude test/e2e",
|
|
97
98
|
"test:integration": "vitest run test/e2e/** --exclude test/e2e/rfq*.test.ts",
|