@buildonspark/spark-sdk 0.1.43 → 0.1.44
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/CHANGELOG.md +7 -0
- package/dist/{RequestLightningSendInput-Na1mHdWg.d.cts → RequestLightningSendInput-BxbCtwpV.d.cts} +43 -4
- package/dist/{RequestLightningSendInput-D7fZdT4A.d.ts → RequestLightningSendInput-RGel43ks.d.ts} +43 -4
- package/dist/address/index.d.cts +2 -2
- package/dist/address/index.d.ts +2 -2
- package/dist/address/index.js +2 -2
- package/dist/{chunk-M6A4KFIG.js → chunk-4Q2ZDYYU.js} +332 -221
- package/dist/{chunk-WWOTVNPP.js → chunk-A2ZLMH6I.js} +323 -142
- package/dist/{chunk-VA7MV4MZ.js → chunk-B3AMIGJG.js} +1 -1
- package/dist/{chunk-DQYKQJRZ.js → chunk-CIZNCBKE.js} +29 -9
- package/dist/{chunk-BUTZWYBW.js → chunk-DAXGVPVM.js} +2 -2
- package/dist/{chunk-DOA6QXYQ.js → chunk-EKFD62HN.js} +2 -1
- package/dist/{chunk-TIUBYNN5.js → chunk-HTMXTJRK.js} +1 -1
- package/dist/{chunk-TOSP3INR.js → chunk-I54FARY2.js} +4 -2
- package/dist/{chunk-MIVX3GHD.js → chunk-K4BJARWM.js} +1 -1
- package/dist/{chunk-O4RYNJNB.js → chunk-KEKGSH7B.js} +1 -1
- package/dist/{chunk-GYQR4B4P.js → chunk-NBCNYDWJ.js} +2 -2
- package/dist/{chunk-ABZA6R5S.js → chunk-SQKXGAIR.js} +1 -1
- package/dist/{chunk-VFJQNBFX.js → chunk-UBT6EDVJ.js} +5 -2
- package/dist/{chunk-HRQRRDSS.js → chunk-WPTRVD2V.js} +3 -3
- package/dist/{chunk-IRW5TWMH.js → chunk-XX4RRWOX.js} +5 -5
- package/dist/graphql/objects/index.d.cts +5 -43
- package/dist/graphql/objects/index.d.ts +5 -43
- package/dist/graphql/objects/index.js +1 -1
- package/dist/{index-BJOc8Ur-.d.cts → index-CZmDdSts.d.cts} +24 -10
- package/dist/{index-7RYRH5wc.d.ts → index-ClIRO_3y.d.ts} +24 -10
- package/dist/index.cjs +827 -414
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +15 -15
- package/dist/index.node.cjs +830 -417
- package/dist/index.node.d.cts +7 -7
- package/dist/index.node.d.ts +7 -7
- package/dist/index.node.js +18 -18
- package/dist/native/index.cjs +827 -414
- package/dist/native/index.d.cts +88 -23
- package/dist/native/index.d.ts +88 -23
- package/dist/native/index.js +819 -407
- package/dist/{network-D5lKssVl.d.cts → network-CfxLnaot.d.cts} +1 -1
- package/dist/{network-xkBSpaTn.d.ts → network-CroCOQ0B.d.ts} +1 -1
- package/dist/proto/lrc20.d.cts +1 -1
- package/dist/proto/lrc20.d.ts +1 -1
- package/dist/proto/lrc20.js +2 -2
- package/dist/proto/spark.cjs +332 -221
- package/dist/proto/spark.d.cts +1 -1
- package/dist/proto/spark.d.ts +1 -1
- package/dist/proto/spark.js +3 -5
- package/dist/proto/spark_token.cjs +149 -9
- package/dist/proto/spark_token.d.cts +1 -1
- package/dist/proto/spark_token.d.ts +1 -1
- package/dist/proto/spark_token.js +2 -2
- package/dist/{sdk-types-B-q9py_P.d.cts → sdk-types-BeCBoozO.d.cts} +1 -1
- package/dist/{sdk-types-BPoPgzda.d.ts → sdk-types-CTbTdDbE.d.ts} +1 -1
- package/dist/services/config.cjs +7 -3
- package/dist/services/config.d.cts +4 -4
- package/dist/services/config.d.ts +4 -4
- package/dist/services/config.js +5 -5
- package/dist/services/connection.cjs +334 -218
- package/dist/services/connection.d.cts +4 -4
- package/dist/services/connection.d.ts +4 -4
- package/dist/services/connection.js +4 -4
- package/dist/services/index.cjs +364 -227
- package/dist/services/index.d.cts +4 -4
- package/dist/services/index.d.ts +4 -4
- package/dist/services/index.js +9 -9
- package/dist/services/lrc-connection.cjs +5 -2
- package/dist/services/lrc-connection.d.cts +4 -4
- package/dist/services/lrc-connection.d.ts +4 -4
- package/dist/services/lrc-connection.js +4 -4
- package/dist/services/token-transactions.cjs +28 -8
- package/dist/services/token-transactions.d.cts +4 -4
- package/dist/services/token-transactions.d.ts +4 -4
- package/dist/services/token-transactions.js +3 -3
- package/dist/services/wallet-config.cjs +2 -1
- package/dist/services/wallet-config.d.cts +4 -4
- package/dist/services/wallet-config.d.ts +4 -4
- package/dist/services/wallet-config.js +1 -1
- package/dist/signer/signer.cjs +5 -2
- package/dist/signer/signer.d.cts +2 -2
- package/dist/signer/signer.d.ts +2 -2
- package/dist/signer/signer.js +2 -2
- package/dist/{signer-wqesWifN.d.ts → signer-D7vfYik9.d.ts} +1 -1
- package/dist/{signer-IO3oMRNj.d.cts → signer-DaY8c60s.d.cts} +1 -1
- package/dist/{spark-CDm4gqS6.d.ts → spark-C4ZrsgjC.d.cts} +47 -29
- package/dist/{spark-CDm4gqS6.d.cts → spark-C4ZrsgjC.d.ts} +47 -29
- package/dist/types/index.cjs +331 -219
- package/dist/types/index.d.cts +5 -5
- package/dist/types/index.d.ts +5 -5
- package/dist/types/index.js +3 -3
- package/dist/utils/index.cjs +298 -28
- package/dist/utils/index.d.cts +5 -5
- package/dist/utils/index.d.ts +5 -5
- package/dist/utils/index.js +6 -6
- package/package.json +1 -1
- package/src/constants.ts +5 -1
- package/src/graphql/client.ts +28 -0
- package/src/graphql/mutations/RequestCoopExit.ts +6 -0
- package/src/graphql/mutations/RequestSwapLeaves.ts +2 -0
- package/src/graphql/queries/GetCoopExitFeeQuote.ts +20 -0
- package/src/proto/spark.ts +454 -322
- package/src/services/token-transactions.ts +12 -0
- package/src/services/transfer.ts +0 -3
- package/src/services/wallet-config.ts +1 -0
- package/src/spark-wallet/spark-wallet.node.ts +3 -3
- package/src/spark-wallet/spark-wallet.ts +301 -125
- package/src/tests/integration/deposit.test.ts +16 -0
- package/src/tests/integration/ssp/coop-exit.test.ts +85 -21
- package/src/tests/integration/ssp/swap.test.ts +47 -0
- package/src/tests/tokens.test.ts +3 -2
- package/src/utils/token-hashing.ts +28 -10
- package/src/utils/transaction.ts +2 -2
- package/src/logger.ts +0 -3
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ConnectionManager
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-WPTRVD2V.js";
|
|
4
4
|
import {
|
|
5
5
|
Lrc20ConnectionManager
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-NBCNYDWJ.js";
|
|
7
7
|
import {
|
|
8
8
|
TokenTransactionService
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-CIZNCBKE.js";
|
|
10
10
|
import {
|
|
11
11
|
DEFAULT_FEE_SATS,
|
|
12
12
|
computeTaprootKeyNoScript,
|
|
@@ -23,16 +23,17 @@ import {
|
|
|
23
23
|
getTxFromRawTxHex,
|
|
24
24
|
getTxId,
|
|
25
25
|
proofOfPossessionMessageHashForDepositAddress
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-XX4RRWOX.js";
|
|
27
27
|
import {
|
|
28
28
|
calculateAvailableTokenAmount
|
|
29
29
|
} from "./chunk-6AFUC5M2.js";
|
|
30
30
|
import {
|
|
31
31
|
mapTransferToWalletTransfer,
|
|
32
32
|
mapTreeNodeToWalletLeaf
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-K4BJARWM.js";
|
|
34
34
|
import {
|
|
35
35
|
ClaimStaticDepositRequestType_default,
|
|
36
|
+
CoopExitFeeQuoteFromJson,
|
|
36
37
|
CurrencyAmountFromJson,
|
|
37
38
|
ExitSpeed_default,
|
|
38
39
|
FRAGMENT,
|
|
@@ -40,20 +41,21 @@ import {
|
|
|
40
41
|
FRAGMENT3,
|
|
41
42
|
FRAGMENT4,
|
|
42
43
|
FRAGMENT5,
|
|
44
|
+
FRAGMENT6,
|
|
43
45
|
LeavesSwapRequestFromJson,
|
|
44
46
|
LightningReceiveRequestFromJson,
|
|
45
47
|
LightningSendRequestFromJson,
|
|
46
48
|
SparkCoopExitRequestStatus_default,
|
|
47
49
|
TransferFromJson
|
|
48
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-I54FARY2.js";
|
|
49
51
|
import {
|
|
50
52
|
decodeSparkAddress,
|
|
51
53
|
encodeSparkAddress,
|
|
52
54
|
isValidPublicKey
|
|
53
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-KEKGSH7B.js";
|
|
54
56
|
import {
|
|
55
57
|
WalletConfigService
|
|
56
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-DAXGVPVM.js";
|
|
57
59
|
import {
|
|
58
60
|
LRC_WALLET_NETWORK,
|
|
59
61
|
LRC_WALLET_NETWORK_TYPE,
|
|
@@ -63,17 +65,17 @@ import {
|
|
|
63
65
|
} from "./chunk-Z5HIAYFT.js";
|
|
64
66
|
import {
|
|
65
67
|
ELECTRS_CREDENTIALS
|
|
66
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-EKFD62HN.js";
|
|
67
69
|
import {
|
|
68
70
|
BitcoinNetwork_default
|
|
69
71
|
} from "./chunk-HMLOC6TE.js";
|
|
70
72
|
import {
|
|
71
73
|
SendLeafKeyTweaks,
|
|
72
74
|
networkToJSON
|
|
73
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-4Q2ZDYYU.js";
|
|
74
76
|
import {
|
|
75
77
|
isReactNative
|
|
76
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-UBT6EDVJ.js";
|
|
77
79
|
import {
|
|
78
80
|
addPublicKeys,
|
|
79
81
|
applyAdaptorToSignature,
|
|
@@ -126,7 +128,7 @@ var ClaimStaticDepositOutputFromJson = (obj) => {
|
|
|
126
128
|
transferId: obj["claim_static_deposit_output_transfer_id"]
|
|
127
129
|
};
|
|
128
130
|
};
|
|
129
|
-
var
|
|
131
|
+
var FRAGMENT7 = `
|
|
130
132
|
fragment ClaimStaticDepositOutputFragment on ClaimStaticDepositOutput {
|
|
131
133
|
__typename
|
|
132
134
|
claim_static_deposit_output_transfer_id: transfer_id
|
|
@@ -159,7 +161,7 @@ var ClaimStaticDeposit = `
|
|
|
159
161
|
}
|
|
160
162
|
}
|
|
161
163
|
|
|
162
|
-
${
|
|
164
|
+
${FRAGMENT7}
|
|
163
165
|
`;
|
|
164
166
|
|
|
165
167
|
// src/graphql/objects/CoopExitRequest.ts
|
|
@@ -185,7 +187,7 @@ var CoopExitRequestFromJson = (obj) => {
|
|
|
185
187
|
transfer: !!obj["coop_exit_request_transfer"] ? TransferFromJson(obj["coop_exit_request_transfer"]) : void 0
|
|
186
188
|
};
|
|
187
189
|
};
|
|
188
|
-
var
|
|
190
|
+
var FRAGMENT8 = `
|
|
189
191
|
fragment CoopExitRequestFragment on CoopExitRequest {
|
|
190
192
|
__typename
|
|
191
193
|
coop_exit_request_id: id
|
|
@@ -250,7 +252,7 @@ var CompleteCoopExit = `
|
|
|
250
252
|
}
|
|
251
253
|
}
|
|
252
254
|
|
|
253
|
-
${
|
|
255
|
+
${FRAGMENT8}
|
|
254
256
|
`;
|
|
255
257
|
|
|
256
258
|
// src/graphql/mutations/CompleteLeavesSwap.ts
|
|
@@ -276,7 +278,7 @@ var GetChallengeOutputFromJson = (obj) => {
|
|
|
276
278
|
protectedChallenge: obj["get_challenge_output_protected_challenge"]
|
|
277
279
|
};
|
|
278
280
|
};
|
|
279
|
-
var
|
|
281
|
+
var FRAGMENT9 = `
|
|
280
282
|
fragment GetChallengeOutputFragment on GetChallengeOutput {
|
|
281
283
|
__typename
|
|
282
284
|
get_challenge_output_protected_challenge: protected_challenge
|
|
@@ -294,7 +296,7 @@ var GetChallenge = `
|
|
|
294
296
|
}
|
|
295
297
|
}
|
|
296
298
|
|
|
297
|
-
${
|
|
299
|
+
${FRAGMENT9}
|
|
298
300
|
`;
|
|
299
301
|
|
|
300
302
|
// src/graphql/mutations/RequestCoopExit.ts
|
|
@@ -304,6 +306,9 @@ var RequestCoopExit = `
|
|
|
304
306
|
$withdrawal_address: String!
|
|
305
307
|
$idempotency_key: String!
|
|
306
308
|
$exit_speed: ExitSpeed!
|
|
309
|
+
$withdraw_all: Boolean
|
|
310
|
+
$fee_leaf_external_ids: [UUID!]
|
|
311
|
+
$fee_quote_id: ID
|
|
307
312
|
) {
|
|
308
313
|
request_coop_exit(
|
|
309
314
|
input: {
|
|
@@ -311,6 +316,9 @@ var RequestCoopExit = `
|
|
|
311
316
|
withdrawal_address: $withdrawal_address
|
|
312
317
|
idempotency_key: $idempotency_key
|
|
313
318
|
exit_speed: $exit_speed
|
|
319
|
+
withdraw_all: $withdraw_all
|
|
320
|
+
fee_leaf_external_ids: $fee_leaf_external_ids
|
|
321
|
+
fee_quote_id: $fee_quote_id
|
|
314
322
|
}
|
|
315
323
|
) {
|
|
316
324
|
request {
|
|
@@ -318,7 +326,7 @@ var RequestCoopExit = `
|
|
|
318
326
|
}
|
|
319
327
|
}
|
|
320
328
|
}
|
|
321
|
-
${
|
|
329
|
+
${FRAGMENT8}
|
|
322
330
|
`;
|
|
323
331
|
|
|
324
332
|
// src/graphql/mutations/RequestLightningReceive.ts
|
|
@@ -382,6 +390,7 @@ var RequestSwapLeaves = `
|
|
|
382
390
|
$fee_sats: Long!
|
|
383
391
|
$user_leaves: [UserLeafInput!]!
|
|
384
392
|
$idempotency_key: String!
|
|
393
|
+
$target_amount_sats_list: [Long!]
|
|
385
394
|
) {
|
|
386
395
|
request_leaves_swap(input: {
|
|
387
396
|
adaptor_pubkey: $adaptor_pubkey
|
|
@@ -390,6 +399,7 @@ var RequestSwapLeaves = `
|
|
|
390
399
|
fee_sats: $fee_sats
|
|
391
400
|
user_leaves: $user_leaves
|
|
392
401
|
idempotency_key: $idempotency_key
|
|
402
|
+
target_amount_sats_list: $target_amount_sats_list
|
|
393
403
|
}) {
|
|
394
404
|
request {
|
|
395
405
|
...LeavesSwapRequestFragment
|
|
@@ -406,7 +416,7 @@ var VerifyChallengeOutputFromJson = (obj) => {
|
|
|
406
416
|
sessionToken: obj["verify_challenge_output_session_token"]
|
|
407
417
|
};
|
|
408
418
|
};
|
|
409
|
-
var
|
|
419
|
+
var FRAGMENT10 = `
|
|
410
420
|
fragment VerifyChallengeOutputFragment on VerifyChallengeOutput {
|
|
411
421
|
__typename
|
|
412
422
|
verify_challenge_output_valid_until: valid_until
|
|
@@ -431,7 +441,7 @@ var VerifyChallenge = `
|
|
|
431
441
|
}
|
|
432
442
|
}
|
|
433
443
|
|
|
434
|
-
${
|
|
444
|
+
${FRAGMENT10}
|
|
435
445
|
`;
|
|
436
446
|
|
|
437
447
|
// src/graphql/objects/CoopExitFeeEstimate.ts
|
|
@@ -450,7 +460,7 @@ var CoopExitFeeEstimatesOutputFromJson = (obj) => {
|
|
|
450
460
|
speedSlow: !!obj["coop_exit_fee_estimates_output_speed_slow"] ? CoopExitFeeEstimateFromJson(obj["coop_exit_fee_estimates_output_speed_slow"]) : void 0
|
|
451
461
|
};
|
|
452
462
|
};
|
|
453
|
-
var
|
|
463
|
+
var FRAGMENT11 = `
|
|
454
464
|
fragment CoopExitFeeEstimatesOutputFragment on CoopExitFeeEstimatesOutput {
|
|
455
465
|
__typename
|
|
456
466
|
coop_exit_fee_estimates_output_speed_fast: speed_fast {
|
|
@@ -518,7 +528,7 @@ var LeavesSwapFeeEstimateOutputFromJson = (obj) => {
|
|
|
518
528
|
feeEstimate: CurrencyAmountFromJson(obj["leaves_swap_fee_estimate_output_fee_estimate"])
|
|
519
529
|
};
|
|
520
530
|
};
|
|
521
|
-
var
|
|
531
|
+
var FRAGMENT12 = `
|
|
522
532
|
fragment LeavesSwapFeeEstimateOutputFragment on LeavesSwapFeeEstimateOutput {
|
|
523
533
|
__typename
|
|
524
534
|
leaves_swap_fee_estimate_output_fee_estimate: fee_estimate {
|
|
@@ -537,7 +547,7 @@ var LightningSendFeeEstimateOutputFromJson = (obj) => {
|
|
|
537
547
|
feeEstimate: CurrencyAmountFromJson(obj["lightning_send_fee_estimate_output_fee_estimate"])
|
|
538
548
|
};
|
|
539
549
|
};
|
|
540
|
-
var
|
|
550
|
+
var FRAGMENT13 = `
|
|
541
551
|
fragment LightningSendFeeEstimateOutputFragment on LightningSendFeeEstimateOutput {
|
|
542
552
|
__typename
|
|
543
553
|
lightning_send_fee_estimate_output_fee_estimate: fee_estimate {
|
|
@@ -560,7 +570,7 @@ var StaticDepositQuoteOutputFromJson = (obj) => {
|
|
|
560
570
|
signature: obj["static_deposit_quote_output_signature"]
|
|
561
571
|
};
|
|
562
572
|
};
|
|
563
|
-
var
|
|
573
|
+
var FRAGMENT14 = `
|
|
564
574
|
fragment StaticDepositQuoteOutputFragment on StaticDepositQuoteOutput {
|
|
565
575
|
__typename
|
|
566
576
|
static_deposit_quote_output_transaction_id: transaction_id
|
|
@@ -585,7 +595,7 @@ var CoopExitFeeEstimate2 = `
|
|
|
585
595
|
...CoopExitFeeEstimatesOutputFragment
|
|
586
596
|
}
|
|
587
597
|
}
|
|
588
|
-
${
|
|
598
|
+
${FRAGMENT11}
|
|
589
599
|
`;
|
|
590
600
|
|
|
591
601
|
// src/graphql/queries/GetClaimDepositQuote.ts
|
|
@@ -605,7 +615,27 @@ var GetClaimDepositQuote = `
|
|
|
605
615
|
...StaticDepositQuoteOutputFragment
|
|
606
616
|
}
|
|
607
617
|
}
|
|
608
|
-
${
|
|
618
|
+
${FRAGMENT14}
|
|
619
|
+
`;
|
|
620
|
+
|
|
621
|
+
// src/graphql/queries/GetCoopExitFeeQuote.ts
|
|
622
|
+
var GetCoopExitFeeQuote = `
|
|
623
|
+
query CoopExitFeeQuote(
|
|
624
|
+
$leaf_external_ids: [UUID!]!
|
|
625
|
+
$withdrawal_address: String!
|
|
626
|
+
) {
|
|
627
|
+
coop_exit_fee_quote(
|
|
628
|
+
input: {
|
|
629
|
+
leaf_external_ids: $leaf_external_ids,
|
|
630
|
+
withdrawal_address: $withdrawal_address
|
|
631
|
+
}
|
|
632
|
+
) {
|
|
633
|
+
quote {
|
|
634
|
+
...CoopExitFeeQuoteFragment
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
${FRAGMENT5}
|
|
609
639
|
`;
|
|
610
640
|
|
|
611
641
|
// src/graphql/queries/LeavesSwapFeeEstimate.ts
|
|
@@ -621,7 +651,7 @@ var LeavesSwapFeeEstimate = `
|
|
|
621
651
|
...LeavesSwapFeeEstimateOutputFragment
|
|
622
652
|
}
|
|
623
653
|
}
|
|
624
|
-
${
|
|
654
|
+
${FRAGMENT12}
|
|
625
655
|
`;
|
|
626
656
|
|
|
627
657
|
// src/graphql/queries/LightningSendFeeEstimate.ts
|
|
@@ -639,7 +669,7 @@ var LightningSendFeeEstimate = `
|
|
|
639
669
|
...LightningSendFeeEstimateOutputFragment
|
|
640
670
|
}
|
|
641
671
|
}
|
|
642
|
-
${
|
|
672
|
+
${FRAGMENT13}
|
|
643
673
|
`;
|
|
644
674
|
|
|
645
675
|
// src/graphql/queries/Transfer.ts
|
|
@@ -659,7 +689,7 @@ var UserRequest = `
|
|
|
659
689
|
...UserRequestFragment
|
|
660
690
|
}
|
|
661
691
|
}
|
|
662
|
-
${
|
|
692
|
+
${FRAGMENT6}
|
|
663
693
|
`;
|
|
664
694
|
|
|
665
695
|
// src/graphql/client.ts
|
|
@@ -781,7 +811,10 @@ var SspClient = class {
|
|
|
781
811
|
leafExternalIds,
|
|
782
812
|
withdrawalAddress,
|
|
783
813
|
idempotencyKey,
|
|
784
|
-
exitSpeed
|
|
814
|
+
exitSpeed,
|
|
815
|
+
feeLeafExternalIds,
|
|
816
|
+
feeQuoteId,
|
|
817
|
+
withdrawAll
|
|
785
818
|
}) {
|
|
786
819
|
return await this.executeRawQuery({
|
|
787
820
|
queryPayload: RequestCoopExit,
|
|
@@ -789,7 +822,10 @@ var SspClient = class {
|
|
|
789
822
|
leaf_external_ids: leafExternalIds,
|
|
790
823
|
withdrawal_address: withdrawalAddress,
|
|
791
824
|
idempotency_key: idempotencyKey,
|
|
792
|
-
exit_speed: exitSpeed
|
|
825
|
+
exit_speed: exitSpeed,
|
|
826
|
+
fee_leaf_external_ids: feeLeafExternalIds,
|
|
827
|
+
fee_quote_id: feeQuoteId,
|
|
828
|
+
withdraw_all: withdrawAll
|
|
793
829
|
},
|
|
794
830
|
constructObject: (response) => {
|
|
795
831
|
return CoopExitRequestFromJson(response.request_coop_exit.request);
|
|
@@ -851,7 +887,8 @@ var SspClient = class {
|
|
|
851
887
|
targetAmountSats,
|
|
852
888
|
feeSats,
|
|
853
889
|
userLeaves,
|
|
854
|
-
idempotencyKey
|
|
890
|
+
idempotencyKey,
|
|
891
|
+
targetAmountSatsList
|
|
855
892
|
}) {
|
|
856
893
|
const query = {
|
|
857
894
|
queryPayload: RequestSwapLeaves,
|
|
@@ -861,7 +898,8 @@ var SspClient = class {
|
|
|
861
898
|
target_amount_sats: targetAmountSats,
|
|
862
899
|
fee_sats: feeSats,
|
|
863
900
|
user_leaves: userLeaves,
|
|
864
|
-
idempotency_key: idempotencyKey
|
|
901
|
+
idempotency_key: idempotencyKey,
|
|
902
|
+
target_amount_sats_list: targetAmountSatsList
|
|
865
903
|
},
|
|
866
904
|
constructObject: (response) => {
|
|
867
905
|
if (!response.request_leaves_swap) {
|
|
@@ -1053,6 +1091,21 @@ var SspClient = class {
|
|
|
1053
1091
|
new Date(verifyChallenge.validUntil)
|
|
1054
1092
|
);
|
|
1055
1093
|
}
|
|
1094
|
+
async getCoopExitFeeQuote({
|
|
1095
|
+
leafExternalIds,
|
|
1096
|
+
withdrawalAddress
|
|
1097
|
+
}) {
|
|
1098
|
+
return await this.executeRawQuery({
|
|
1099
|
+
queryPayload: GetCoopExitFeeQuote,
|
|
1100
|
+
variables: {
|
|
1101
|
+
leaf_external_ids: leafExternalIds,
|
|
1102
|
+
withdrawal_address: withdrawalAddress
|
|
1103
|
+
},
|
|
1104
|
+
constructObject: (response) => {
|
|
1105
|
+
return CoopExitFeeQuoteFromJson(response.coop_exit_fee_quote.quote);
|
|
1106
|
+
}
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1056
1109
|
};
|
|
1057
1110
|
var SparkAuthProvider = class {
|
|
1058
1111
|
sessionToken;
|
|
@@ -3250,7 +3303,7 @@ import { hexToBytes as hexToBytes4 } from "@noble/curves/abstract/utils";
|
|
|
3250
3303
|
import { sha256 as sha2566 } from "@noble/hashes/sha2";
|
|
3251
3304
|
import { Address as Address2, OutScript as OutScript2, Transaction as Transaction4 } from "@scure/btc-signer";
|
|
3252
3305
|
var INITIAL_TIME_LOCK3 = 2e3;
|
|
3253
|
-
function
|
|
3306
|
+
function maybeApplyFee(amount) {
|
|
3254
3307
|
if (amount > BigInt(DEFAULT_FEE_SATS)) {
|
|
3255
3308
|
return amount - BigInt(DEFAULT_FEE_SATS);
|
|
3256
3309
|
}
|
|
@@ -3519,7 +3572,7 @@ var TreeCreationService = class {
|
|
|
3519
3572
|
const refundPkScript = OutScript2.encode(refundAddress);
|
|
3520
3573
|
refundTx.addOutput({
|
|
3521
3574
|
script: refundPkScript,
|
|
3522
|
-
amount:
|
|
3575
|
+
amount: maybeApplyFee(parentTxOut.amount)
|
|
3523
3576
|
});
|
|
3524
3577
|
refundTx.addOutput(getEphemeralAnchorOutput());
|
|
3525
3578
|
const refundSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
@@ -4387,13 +4440,34 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
4387
4440
|
([_, node]) => node.status === "AVAILABLE" && !leavesToIgnore.has(node.id)
|
|
4388
4441
|
).map(([_, node]) => node);
|
|
4389
4442
|
}
|
|
4390
|
-
async selectLeaves(
|
|
4391
|
-
if (
|
|
4443
|
+
async selectLeaves(targetAmounts) {
|
|
4444
|
+
if (targetAmounts.length === 0) {
|
|
4445
|
+
throw new ValidationError("Target amounts must be non-empty", {
|
|
4446
|
+
field: "targetAmounts",
|
|
4447
|
+
value: targetAmounts
|
|
4448
|
+
});
|
|
4449
|
+
}
|
|
4450
|
+
if (targetAmounts.some((amount) => amount <= 0)) {
|
|
4392
4451
|
throw new ValidationError("Target amount must be positive", {
|
|
4393
|
-
field: "
|
|
4394
|
-
value:
|
|
4452
|
+
field: "targetAmounts",
|
|
4453
|
+
value: targetAmounts
|
|
4395
4454
|
});
|
|
4396
4455
|
}
|
|
4456
|
+
const totalTargetAmount = targetAmounts.reduce(
|
|
4457
|
+
(acc, amount) => acc + amount,
|
|
4458
|
+
0
|
|
4459
|
+
);
|
|
4460
|
+
const totalBalance = this.getInternalBalance();
|
|
4461
|
+
if (totalTargetAmount > totalBalance) {
|
|
4462
|
+
throw new ValidationError(
|
|
4463
|
+
"Total target amount exceeds available balance",
|
|
4464
|
+
{
|
|
4465
|
+
field: "targetAmounts",
|
|
4466
|
+
value: totalTargetAmount,
|
|
4467
|
+
expected: `less than or equal to ${totalBalance}`
|
|
4468
|
+
}
|
|
4469
|
+
);
|
|
4470
|
+
}
|
|
4397
4471
|
const leaves = await this.getLeaves();
|
|
4398
4472
|
if (leaves.length === 0) {
|
|
4399
4473
|
throw new ValidationError("No owned leaves found", {
|
|
@@ -4401,33 +4475,49 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
4401
4475
|
});
|
|
4402
4476
|
}
|
|
4403
4477
|
leaves.sort((a, b) => b.value - a.value);
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
nodes
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
amount += leaf.value;
|
|
4421
|
-
nodes.push(leaf);
|
|
4478
|
+
const selectLeavesForTargets = (targetAmounts2, leaves2) => {
|
|
4479
|
+
const usedLeaves = /* @__PURE__ */ new Set();
|
|
4480
|
+
const results2 = /* @__PURE__ */ new Map();
|
|
4481
|
+
let totalAmount = 0;
|
|
4482
|
+
for (const targetAmount of targetAmounts2) {
|
|
4483
|
+
const nodes = [];
|
|
4484
|
+
let amount = 0;
|
|
4485
|
+
for (const leaf of leaves2) {
|
|
4486
|
+
if (usedLeaves.has(leaf.id)) {
|
|
4487
|
+
continue;
|
|
4488
|
+
}
|
|
4489
|
+
if (targetAmount - amount >= leaf.value) {
|
|
4490
|
+
amount += leaf.value;
|
|
4491
|
+
nodes.push(leaf);
|
|
4492
|
+
usedLeaves.add(leaf.id);
|
|
4493
|
+
}
|
|
4422
4494
|
}
|
|
4495
|
+
totalAmount += amount;
|
|
4496
|
+
results2.set(targetAmount, nodes);
|
|
4423
4497
|
}
|
|
4498
|
+
return {
|
|
4499
|
+
results: results2,
|
|
4500
|
+
foundSelections: totalAmount === totalTargetAmount
|
|
4501
|
+
};
|
|
4502
|
+
};
|
|
4503
|
+
let { results, foundSelections } = selectLeavesForTargets(
|
|
4504
|
+
targetAmounts,
|
|
4505
|
+
leaves
|
|
4506
|
+
);
|
|
4507
|
+
if (!foundSelections) {
|
|
4508
|
+
const newLeaves = await this.requestLeavesSwap({ targetAmounts });
|
|
4509
|
+
newLeaves.sort((a, b) => b.value - a.value);
|
|
4510
|
+
({ results, foundSelections } = selectLeavesForTargets(
|
|
4511
|
+
targetAmounts,
|
|
4512
|
+
newLeaves
|
|
4513
|
+
));
|
|
4424
4514
|
}
|
|
4425
|
-
if (
|
|
4515
|
+
if (!foundSelections) {
|
|
4426
4516
|
throw new Error(
|
|
4427
|
-
`Failed to select leaves for target amount ${
|
|
4517
|
+
`Failed to select leaves for target amount ${totalTargetAmount}`
|
|
4428
4518
|
);
|
|
4429
4519
|
}
|
|
4430
|
-
return
|
|
4520
|
+
return results;
|
|
4431
4521
|
}
|
|
4432
4522
|
async selectLeavesForSwap(targetAmount) {
|
|
4433
4523
|
if (targetAmount == 0) {
|
|
@@ -4660,27 +4750,44 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
4660
4750
|
* @private
|
|
4661
4751
|
*/
|
|
4662
4752
|
async requestLeavesSwap({
|
|
4663
|
-
|
|
4753
|
+
targetAmounts,
|
|
4664
4754
|
leaves
|
|
4665
4755
|
}) {
|
|
4666
|
-
if (
|
|
4667
|
-
throw new Error("targetAmount must be positive");
|
|
4756
|
+
if (targetAmounts && targetAmounts.some((amount) => amount <= 0)) {
|
|
4757
|
+
throw new Error("specified targetAmount must be positive");
|
|
4668
4758
|
}
|
|
4669
|
-
if (
|
|
4759
|
+
if (targetAmounts && targetAmounts.some((amount) => !Number.isSafeInteger(amount))) {
|
|
4670
4760
|
throw new ValidationError("targetAmount must be less than 2^53", {
|
|
4671
|
-
field: "
|
|
4672
|
-
value:
|
|
4761
|
+
field: "targetAmounts",
|
|
4762
|
+
value: targetAmounts,
|
|
4673
4763
|
expected: "smaller or equal to " + Number.MAX_SAFE_INTEGER
|
|
4674
4764
|
});
|
|
4675
4765
|
}
|
|
4676
4766
|
let leavesToSwap;
|
|
4677
|
-
|
|
4678
|
-
|
|
4767
|
+
const totalTargetAmount = targetAmounts?.reduce(
|
|
4768
|
+
(acc, amount) => acc + amount,
|
|
4769
|
+
0
|
|
4770
|
+
);
|
|
4771
|
+
if (totalTargetAmount) {
|
|
4772
|
+
const totalBalance = this.getInternalBalance();
|
|
4773
|
+
if (totalTargetAmount > totalBalance) {
|
|
4774
|
+
throw new ValidationError(
|
|
4775
|
+
"Total target amount exceeds available balance",
|
|
4776
|
+
{
|
|
4777
|
+
field: "targetAmounts",
|
|
4778
|
+
value: totalTargetAmount,
|
|
4779
|
+
expected: `less than or equal to ${totalBalance}`
|
|
4780
|
+
}
|
|
4781
|
+
);
|
|
4782
|
+
}
|
|
4783
|
+
}
|
|
4784
|
+
if (totalTargetAmount && leaves && leaves.length > 0) {
|
|
4785
|
+
if (totalTargetAmount < leaves.reduce((acc, leaf) => acc + leaf.value, 0)) {
|
|
4679
4786
|
throw new Error("targetAmount is less than the sum of leaves");
|
|
4680
4787
|
}
|
|
4681
4788
|
leavesToSwap = leaves;
|
|
4682
|
-
} else if (
|
|
4683
|
-
leavesToSwap = await this.selectLeavesForSwap(
|
|
4789
|
+
} else if (totalTargetAmount) {
|
|
4790
|
+
leavesToSwap = await this.selectLeavesForSwap(totalTargetAmount);
|
|
4684
4791
|
} else if (leaves && leaves.length > 0) {
|
|
4685
4792
|
leavesToSwap = leaves;
|
|
4686
4793
|
} else {
|
|
@@ -4690,15 +4797,15 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
4690
4797
|
const batches = chunkArray(leavesToSwap, 100);
|
|
4691
4798
|
const results = [];
|
|
4692
4799
|
for (const batch of batches) {
|
|
4693
|
-
const result = await this.processSwapBatch(batch,
|
|
4694
|
-
results.push(...result
|
|
4800
|
+
const result = await this.processSwapBatch(batch, targetAmounts);
|
|
4801
|
+
results.push(...result);
|
|
4695
4802
|
}
|
|
4696
4803
|
return results;
|
|
4697
4804
|
}
|
|
4698
4805
|
/**
|
|
4699
4806
|
* Processes a single batch of leaves for swapping.
|
|
4700
4807
|
*/
|
|
4701
|
-
async processSwapBatch(leavesBatch,
|
|
4808
|
+
async processSwapBatch(leavesBatch, targetAmounts) {
|
|
4702
4809
|
const leafKeyTweaks = await Promise.all(
|
|
4703
4810
|
leavesBatch.map(async (leaf) => ({
|
|
4704
4811
|
leaf,
|
|
@@ -4762,8 +4869,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
4762
4869
|
request = await sspClient.requestLeaveSwap({
|
|
4763
4870
|
userLeaves,
|
|
4764
4871
|
adaptorPubkey,
|
|
4765
|
-
targetAmountSats:
|
|
4872
|
+
targetAmountSats: targetAmounts?.reduce((acc, amount) => acc + amount, 0) || leavesBatch.reduce((acc, leaf) => acc + leaf.value, 0),
|
|
4766
4873
|
totalAmountSats: leavesBatch.reduce((acc, leaf) => acc + leaf.value, 0),
|
|
4874
|
+
targetAmountSatsList: targetAmounts,
|
|
4767
4875
|
// TODO: Request fee from SSP
|
|
4768
4876
|
feeSats: 0,
|
|
4769
4877
|
idempotencyKey: uuidv74()
|
|
@@ -4819,11 +4927,21 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
4819
4927
|
userOutboundTransferExternalId: transfer.id,
|
|
4820
4928
|
leavesSwapRequestId: request.id
|
|
4821
4929
|
});
|
|
4822
|
-
if (!completeResponse) {
|
|
4930
|
+
if (!completeResponse || !completeResponse.inboundTransfer?.sparkId) {
|
|
4823
4931
|
throw new Error("Failed to complete leaves swap");
|
|
4824
4932
|
}
|
|
4825
|
-
await this.
|
|
4826
|
-
|
|
4933
|
+
const incomingTransfer = await this.transferService.queryTransfer(
|
|
4934
|
+
completeResponse.inboundTransfer.sparkId
|
|
4935
|
+
);
|
|
4936
|
+
if (!incomingTransfer) {
|
|
4937
|
+
throw new Error("Failed to get incoming transfer");
|
|
4938
|
+
}
|
|
4939
|
+
return await this.claimTransfer({
|
|
4940
|
+
transfer: incomingTransfer,
|
|
4941
|
+
emit: false,
|
|
4942
|
+
retryCount: 0,
|
|
4943
|
+
optimize: false
|
|
4944
|
+
});
|
|
4827
4945
|
} catch (e) {
|
|
4828
4946
|
await this.cancelAllSenderInitiatedTransfers();
|
|
4829
4947
|
throw new Error(`Failed to request leaves swap: ${e}`);
|
|
@@ -5360,13 +5478,45 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
5360
5478
|
* @returns {Promise<string[]>} The unused deposit addresses
|
|
5361
5479
|
*/
|
|
5362
5480
|
async getUnusedDepositAddresses() {
|
|
5481
|
+
return (await this.queryAllUnusedDepositAddresses({})).map(
|
|
5482
|
+
(addr) => addr.depositAddress
|
|
5483
|
+
);
|
|
5484
|
+
}
|
|
5485
|
+
/**
|
|
5486
|
+
* Gets all unused deposit addresses for the wallet.
|
|
5487
|
+
*
|
|
5488
|
+
* @param {Object} params - Parameters for querying unused deposit addresses
|
|
5489
|
+
* @param {Uint8Array<ArrayBufferLike>} [params.identityPublicKey] - The identity public key
|
|
5490
|
+
* @param {NetworkProto} [params.network] - The network
|
|
5491
|
+
* @returns {Promise<DepositAddressQueryResult[]>} The unused deposit addresses
|
|
5492
|
+
*/
|
|
5493
|
+
async queryAllUnusedDepositAddresses({
|
|
5494
|
+
identityPublicKey,
|
|
5495
|
+
network
|
|
5496
|
+
}) {
|
|
5363
5497
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
5364
5498
|
this.config.getCoordinatorAddress()
|
|
5365
5499
|
);
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5500
|
+
let limit = 100;
|
|
5501
|
+
let offset = 0;
|
|
5502
|
+
const pastOffsets = /* @__PURE__ */ new Set();
|
|
5503
|
+
const depositAddresses = [];
|
|
5504
|
+
while (offset >= 0) {
|
|
5505
|
+
if (pastOffsets.has(offset)) {
|
|
5506
|
+
console.warn("Offset has already been seen, stopping");
|
|
5507
|
+
break;
|
|
5508
|
+
}
|
|
5509
|
+
const response = await sparkClient.query_unused_deposit_addresses({
|
|
5510
|
+
identityPublicKey: identityPublicKey ?? await this.config.signer.getIdentityPublicKey(),
|
|
5511
|
+
network: network ?? NetworkToProto[this.config.getNetwork()],
|
|
5512
|
+
limit,
|
|
5513
|
+
offset
|
|
5514
|
+
});
|
|
5515
|
+
depositAddresses.push(...response.depositAddresses);
|
|
5516
|
+
pastOffsets.add(offset);
|
|
5517
|
+
offset = response.offset;
|
|
5518
|
+
}
|
|
5519
|
+
return depositAddresses;
|
|
5370
5520
|
}
|
|
5371
5521
|
/**
|
|
5372
5522
|
* Claims a deposit to the wallet.
|
|
@@ -5415,14 +5565,11 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
5415
5565
|
});
|
|
5416
5566
|
}
|
|
5417
5567
|
const depositTx = getTxFromRawTxHex(txHex);
|
|
5418
|
-
const sparkClient = await this.connectionManager.createSparkClient(
|
|
5419
|
-
this.config.getCoordinatorAddress()
|
|
5420
|
-
);
|
|
5421
5568
|
const unusedDepositAddresses = new Map(
|
|
5422
|
-
(await
|
|
5569
|
+
(await this.queryAllUnusedDepositAddresses({
|
|
5423
5570
|
identityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
5424
5571
|
network: NetworkToProto[this.config.getNetwork()]
|
|
5425
|
-
})).
|
|
5572
|
+
})).map((addr) => [addr.depositAddress, addr])
|
|
5426
5573
|
);
|
|
5427
5574
|
let depositAddress;
|
|
5428
5575
|
let vout = 0;
|
|
@@ -5476,14 +5623,11 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
5476
5623
|
*/
|
|
5477
5624
|
async advancedDeposit(txHex) {
|
|
5478
5625
|
const depositTx = getTxFromRawTxHex(txHex);
|
|
5479
|
-
const sparkClient = await this.connectionManager.createSparkClient(
|
|
5480
|
-
this.config.getCoordinatorAddress()
|
|
5481
|
-
);
|
|
5482
5626
|
const unusedDepositAddresses = new Map(
|
|
5483
|
-
(await
|
|
5627
|
+
(await this.queryAllUnusedDepositAddresses({
|
|
5484
5628
|
identityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
5485
5629
|
network: NetworkToProto[this.config.getNetwork()]
|
|
5486
|
-
})).
|
|
5630
|
+
})).map((addr) => [addr.depositAddress, addr])
|
|
5487
5631
|
);
|
|
5488
5632
|
let vout = 0;
|
|
5489
5633
|
const responses = [];
|
|
@@ -5587,7 +5731,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
5587
5731
|
hexToBytes7(receiverAddress.identityPublicKey)
|
|
5588
5732
|
);
|
|
5589
5733
|
return await this.withLeaves(async () => {
|
|
5590
|
-
let leavesToSend = await this.selectLeaves(amountSats)
|
|
5734
|
+
let leavesToSend = (await this.selectLeaves([amountSats])).get(
|
|
5735
|
+
amountSats
|
|
5736
|
+
);
|
|
5591
5737
|
leavesToSend = await this.checkRefreshTimelockNodes(leavesToSend);
|
|
5592
5738
|
leavesToSend = await this.checkExtendTimeLockNodes(leavesToSend);
|
|
5593
5739
|
const leafKeyTweaks = await Promise.all(
|
|
@@ -5830,7 +5976,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
5830
5976
|
if (type && transfer.type !== type) {
|
|
5831
5977
|
continue;
|
|
5832
5978
|
}
|
|
5833
|
-
if (transfer.status !== 2 /* TRANSFER_STATUS_SENDER_KEY_TWEAKED */ && transfer.status !== 3 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAKED */ && transfer.status !== 4 /*
|
|
5979
|
+
if (transfer.status !== 2 /* TRANSFER_STATUS_SENDER_KEY_TWEAKED */ && transfer.status !== 3 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAKED */ && transfer.status !== 4 /* TRANSFER_STATUS_RECEIVER_REFUND_SIGNED */ && transfer.status !== 10 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAK_APPLIED */) {
|
|
5834
5980
|
continue;
|
|
5835
5981
|
}
|
|
5836
5982
|
promises.push(
|
|
@@ -6089,7 +6235,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
6089
6235
|
expected: `${totalAmount} sats`
|
|
6090
6236
|
});
|
|
6091
6237
|
}
|
|
6092
|
-
let leaves = await this.selectLeaves(totalAmount);
|
|
6238
|
+
let leaves = (await this.selectLeaves([totalAmount])).get(totalAmount);
|
|
6093
6239
|
leaves = await this.checkRefreshTimelockNodes(leaves);
|
|
6094
6240
|
leaves = await this.checkExtendTimeLockNodes(leaves);
|
|
6095
6241
|
const leavesToSend = await Promise.all(
|
|
@@ -6199,13 +6345,18 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
6199
6345
|
*
|
|
6200
6346
|
* @param {Object} params - Parameters for the withdrawal
|
|
6201
6347
|
* @param {string} params.onchainAddress - The Bitcoin address where the funds should be sent
|
|
6202
|
-
* @param {
|
|
6348
|
+
* @param {CoopExitFeeQuote} params.feeQuote - The fee quote for the withdrawal
|
|
6349
|
+
* @param {ExitSpeed} params.exitSpeed - The exit speed chosen for the withdrawal
|
|
6350
|
+
* @param {number} [params.amountSats] - The amount in satoshis to withdraw. If not specified, attempts to withdraw all available funds and deductFeeFromWithdrawalAmount is set to true.
|
|
6351
|
+
* @param {boolean} [params.deductFeeFromWithdrawalAmount] - Controls how the withdrawal fee is handled. If true, the fee is deducted from the withdrawal amount (amountSats), meaning the recipient will receive amountSats minus the fee. If false, the fee is paid separately from the wallet balance, meaning the recipient will receive the full amountSats.
|
|
6203
6352
|
* @returns {Promise<CoopExitRequest | null | undefined>} The withdrawal request details, or null/undefined if the request cannot be completed
|
|
6204
6353
|
*/
|
|
6205
6354
|
async withdraw({
|
|
6206
6355
|
onchainAddress,
|
|
6207
6356
|
exitSpeed,
|
|
6208
|
-
|
|
6357
|
+
feeQuote,
|
|
6358
|
+
amountSats,
|
|
6359
|
+
deductFeeFromWithdrawalAmount = true
|
|
6209
6360
|
}) {
|
|
6210
6361
|
if (!Number.isSafeInteger(amountSats)) {
|
|
6211
6362
|
throw new ValidationError("Sats amount must be less than 2^53", {
|
|
@@ -6215,7 +6366,13 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
6215
6366
|
});
|
|
6216
6367
|
}
|
|
6217
6368
|
return await this.withLeaves(async () => {
|
|
6218
|
-
return await this.coopExit(
|
|
6369
|
+
return await this.coopExit(
|
|
6370
|
+
onchainAddress,
|
|
6371
|
+
feeQuote,
|
|
6372
|
+
exitSpeed,
|
|
6373
|
+
deductFeeFromWithdrawalAmount,
|
|
6374
|
+
amountSats
|
|
6375
|
+
);
|
|
6219
6376
|
});
|
|
6220
6377
|
}
|
|
6221
6378
|
/**
|
|
@@ -6226,7 +6383,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
6226
6383
|
* @returns {Promise<Object | null | undefined>} The exit request details
|
|
6227
6384
|
* @private
|
|
6228
6385
|
*/
|
|
6229
|
-
async coopExit(onchainAddress, exitSpeed, targetAmountSats) {
|
|
6386
|
+
async coopExit(onchainAddress, feeEstimate, exitSpeed, deductFeeFromWithdrawalAmount, targetAmountSats) {
|
|
6230
6387
|
if (!Number.isSafeInteger(targetAmountSats)) {
|
|
6231
6388
|
throw new ValidationError("Sats amount must be less than 2^53", {
|
|
6232
6389
|
field: "targetAmountSats",
|
|
@@ -6234,41 +6391,34 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
6234
6391
|
expected: "smaller or equal to " + Number.MAX_SAFE_INTEGER
|
|
6235
6392
|
});
|
|
6236
6393
|
}
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
leavesToSend = await this.selectLeaves(targetAmountSats);
|
|
6240
|
-
} else {
|
|
6241
|
-
leavesToSend = this.leaves.map((leaf) => ({
|
|
6242
|
-
...leaf
|
|
6243
|
-
}));
|
|
6394
|
+
if (!targetAmountSats) {
|
|
6395
|
+
deductFeeFromWithdrawalAmount = true;
|
|
6244
6396
|
}
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
}
|
|
6269
|
-
if (fee !== void 0 && fee > leavesToSend.reduce((acc, leaf) => acc + leaf.value, 0)) {
|
|
6397
|
+
let fee;
|
|
6398
|
+
switch (exitSpeed) {
|
|
6399
|
+
case ExitSpeed_default.FAST:
|
|
6400
|
+
fee = (feeEstimate.l1BroadcastFeeFast?.originalValue || 0) + (feeEstimate.userFeeFast?.originalValue || 0);
|
|
6401
|
+
break;
|
|
6402
|
+
case ExitSpeed_default.MEDIUM:
|
|
6403
|
+
fee = (feeEstimate.l1BroadcastFeeMedium?.originalValue || 0) + (feeEstimate.userFeeMedium?.originalValue || 0);
|
|
6404
|
+
break;
|
|
6405
|
+
case ExitSpeed_default.SLOW:
|
|
6406
|
+
fee = (feeEstimate.l1BroadcastFeeSlow?.originalValue || 0) + (feeEstimate.userFeeSlow?.originalValue || 0);
|
|
6407
|
+
break;
|
|
6408
|
+
default:
|
|
6409
|
+
throw new ValidationError("Invalid exit speed", {
|
|
6410
|
+
field: "exitSpeed",
|
|
6411
|
+
value: exitSpeed,
|
|
6412
|
+
expected: "FAST, MEDIUM, or SLOW"
|
|
6413
|
+
});
|
|
6414
|
+
}
|
|
6415
|
+
let leavesToSendToSsp = [];
|
|
6416
|
+
let leavesToSendToSE = [];
|
|
6417
|
+
if (deductFeeFromWithdrawalAmount) {
|
|
6418
|
+
leavesToSendToSsp = targetAmountSats ? (await this.selectLeaves([targetAmountSats])).get(targetAmountSats) : this.leaves;
|
|
6419
|
+
if (fee > leavesToSendToSsp.reduce((acc, leaf) => acc + leaf.value, 0)) {
|
|
6270
6420
|
throw new ValidationError(
|
|
6271
|
-
"The fee for the withdrawal is greater than the target amount",
|
|
6421
|
+
"The fee for the withdrawal is greater than the target withdrawal amount",
|
|
6272
6422
|
{
|
|
6273
6423
|
field: "fee",
|
|
6274
6424
|
value: fee,
|
|
@@ -6276,11 +6426,32 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
6276
6426
|
}
|
|
6277
6427
|
);
|
|
6278
6428
|
}
|
|
6429
|
+
} else {
|
|
6430
|
+
if (!targetAmountSats) {
|
|
6431
|
+
throw new ValidationError(
|
|
6432
|
+
"targetAmountSats is required when deductFeeFromWithdrawalAmount is false",
|
|
6433
|
+
{
|
|
6434
|
+
field: "targetAmountSats",
|
|
6435
|
+
value: targetAmountSats,
|
|
6436
|
+
expected: "defined when deductFeeFromWithdrawalAmount is false"
|
|
6437
|
+
}
|
|
6438
|
+
);
|
|
6439
|
+
}
|
|
6440
|
+
const leaves = await this.selectLeaves([targetAmountSats, fee]);
|
|
6441
|
+
const leavesForTargetAmount = leaves.get(targetAmountSats);
|
|
6442
|
+
const leavesForFee = leaves.get(fee);
|
|
6443
|
+
if (!leavesForTargetAmount || !leavesForFee) {
|
|
6444
|
+
throw new Error("Failed to select leaves for target amount and fee");
|
|
6445
|
+
}
|
|
6446
|
+
leavesToSendToSsp = leavesForTargetAmount;
|
|
6447
|
+
leavesToSendToSE = leavesForFee;
|
|
6279
6448
|
}
|
|
6280
|
-
|
|
6281
|
-
|
|
6449
|
+
leavesToSendToSsp = await this.checkRefreshTimelockNodes(leavesToSendToSsp);
|
|
6450
|
+
leavesToSendToSsp = await this.checkExtendTimeLockNodes(leavesToSendToSsp);
|
|
6451
|
+
leavesToSendToSE = await this.checkRefreshTimelockNodes(leavesToSendToSE);
|
|
6452
|
+
leavesToSendToSE = await this.checkExtendTimeLockNodes(leavesToSendToSE);
|
|
6282
6453
|
const leafKeyTweaks = await Promise.all(
|
|
6283
|
-
|
|
6454
|
+
[...leavesToSendToSE, ...leavesToSendToSsp].map(async (leaf) => ({
|
|
6284
6455
|
leaf,
|
|
6285
6456
|
signingPubKey: await this.config.signer.generatePublicKey(
|
|
6286
6457
|
sha2567(leaf.id)
|
|
@@ -6288,13 +6459,23 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
6288
6459
|
newSigningPubKey: await this.config.signer.generatePublicKey()
|
|
6289
6460
|
}))
|
|
6290
6461
|
);
|
|
6291
|
-
const
|
|
6292
|
-
leafExternalIds:
|
|
6462
|
+
const requestCoopExitParams = {
|
|
6463
|
+
leafExternalIds: leavesToSendToSsp.map((leaf) => leaf.id),
|
|
6293
6464
|
withdrawalAddress: onchainAddress,
|
|
6294
6465
|
idempotencyKey: uuidv74(),
|
|
6295
6466
|
exitSpeed,
|
|
6296
|
-
withdrawAll:
|
|
6297
|
-
}
|
|
6467
|
+
withdrawAll: deductFeeFromWithdrawalAmount
|
|
6468
|
+
};
|
|
6469
|
+
if (!deductFeeFromWithdrawalAmount) {
|
|
6470
|
+
requestCoopExitParams.feeQuoteId = feeEstimate.id;
|
|
6471
|
+
requestCoopExitParams.feeLeafExternalIds = leavesToSendToSE.map(
|
|
6472
|
+
(leaf) => leaf.id
|
|
6473
|
+
);
|
|
6474
|
+
}
|
|
6475
|
+
const sspClient = this.getSspClient();
|
|
6476
|
+
const coopExitRequest = await sspClient.requestCoopExit(
|
|
6477
|
+
requestCoopExitParams
|
|
6478
|
+
);
|
|
6298
6479
|
if (!coopExitRequest?.rawConnectorTransaction) {
|
|
6299
6480
|
throw new Error("Failed to request coop exit");
|
|
6300
6481
|
}
|
|
@@ -6332,9 +6513,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
6332
6513
|
* @param {Object} params - Input parameters for fee estimation
|
|
6333
6514
|
* @param {number} params.amountSats - The amount in satoshis to withdraw
|
|
6334
6515
|
* @param {string} params.withdrawalAddress - The Bitcoin address where the funds should be sent
|
|
6335
|
-
* @returns {Promise<
|
|
6516
|
+
* @returns {Promise<CoopExitFeeQuote | null>} Fee estimate for the withdrawal
|
|
6336
6517
|
*/
|
|
6337
|
-
async
|
|
6518
|
+
async getWithdrawalFeeQuote({
|
|
6338
6519
|
amountSats,
|
|
6339
6520
|
withdrawalAddress
|
|
6340
6521
|
}) {
|
|
@@ -6346,10 +6527,10 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
6346
6527
|
expected: "smaller or equal to " + Number.MAX_SAFE_INTEGER
|
|
6347
6528
|
});
|
|
6348
6529
|
}
|
|
6349
|
-
let leaves = await this.selectLeaves(amountSats);
|
|
6530
|
+
let leaves = (await this.selectLeaves([amountSats])).get(amountSats);
|
|
6350
6531
|
leaves = await this.checkRefreshTimelockNodes(leaves);
|
|
6351
6532
|
leaves = await this.checkExtendTimeLockNodes(leaves);
|
|
6352
|
-
const feeEstimate = await sspClient.
|
|
6533
|
+
const feeEstimate = await sspClient.getCoopExitFeeQuote({
|
|
6353
6534
|
leafExternalIds: leaves.map((leaf) => leaf.id),
|
|
6354
6535
|
withdrawalAddress
|
|
6355
6536
|
});
|