@buildonspark/spark-sdk 0.2.3 → 0.2.5
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 +17 -0
- package/dist/{chunk-3SEOTO43.js → chunk-3SPMJMUX.js} +3 -2
- package/dist/{chunk-CDLETEDT.js → chunk-CQY5ML2A.js} +16 -3
- package/dist/{chunk-PTRXJS7Q.js → chunk-LQZL2D3Y.js} +1 -1
- package/dist/{chunk-PLLJIZC3.js → chunk-U7LRIWTF.js} +2471 -822
- package/dist/{client-CcYzmpmj.d.cts → client-C88GCTPB.d.cts} +211 -104
- package/dist/{client-CGTRS23n.d.ts → client-Dg6vS_2I.d.ts} +211 -104
- package/dist/debug.cjs +2511 -831
- package/dist/debug.d.cts +19 -6
- package/dist/debug.d.ts +19 -6
- package/dist/debug.js +3 -3
- package/dist/graphql/objects/index.cjs +13 -1
- package/dist/graphql/objects/index.d.cts +6 -51
- package/dist/graphql/objects/index.d.ts +6 -51
- package/dist/graphql/objects/index.js +1 -1
- package/dist/index.cjs +2491 -797
- package/dist/index.d.cts +189 -9
- package/dist/index.d.ts +189 -9
- package/dist/index.js +32 -4
- package/dist/index.node.cjs +2596 -799
- package/dist/index.node.d.cts +9 -190
- package/dist/index.node.d.ts +9 -190
- package/dist/index.node.js +134 -4
- package/dist/native/index.cjs +2491 -797
- package/dist/native/index.d.cts +309 -174
- package/dist/native/index.d.ts +309 -174
- package/dist/native/index.js +2495 -814
- package/dist/proto/lrc20.d.cts +1 -1
- package/dist/proto/lrc20.d.ts +1 -1
- package/dist/proto/spark.d.cts +1 -1
- package/dist/proto/spark.d.ts +1 -1
- package/dist/proto/spark_token.d.cts +1 -1
- package/dist/proto/spark_token.d.ts +1 -1
- package/dist/{spark-B_7nZx6T.d.cts → spark-ESAfZARg.d.cts} +1 -1
- package/dist/{spark-B_7nZx6T.d.ts → spark-ESAfZARg.d.ts} +1 -1
- package/dist/{spark-wallet-CxcGPXRB.d.ts → spark-wallet-B2WwKN8W.d.ts} +57 -35
- package/dist/{spark-wallet-DJJm19BP.d.cts → spark-wallet-Di65w0Us.d.cts} +57 -35
- package/dist/spark-wallet.node-7R0Rxyj9.d.cts +13 -0
- package/dist/spark-wallet.node-CSPWOWRu.d.ts +13 -0
- package/dist/tests/test-utils.cjs +578 -77
- package/dist/tests/test-utils.d.cts +12 -13
- package/dist/tests/test-utils.d.ts +12 -13
- package/dist/tests/test-utils.js +54 -17
- package/dist/types/index.cjs +16 -3
- package/dist/types/index.d.cts +3 -4
- package/dist/types/index.d.ts +3 -4
- package/dist/types/index.js +2 -2
- package/dist/{xchain-address-Bh9w1SeC.d.ts → xchain-address-BsveIy5l.d.ts} +56 -8
- package/dist/{xchain-address-SZ7dkVUE.d.cts → xchain-address-CqRu3F21.d.cts} +56 -8
- package/package.json +1 -1
- package/src/graphql/client.ts +57 -8
- package/src/graphql/mutations/CompleteLeavesSwap.ts +9 -1
- package/src/graphql/mutations/RequestSwapLeaves.ts +4 -0
- package/src/graphql/objects/CompleteLeavesSwapInput.ts +34 -34
- package/src/graphql/objects/LeavesSwapRequest.ts +4 -0
- package/src/graphql/objects/RequestLeavesSwapInput.ts +48 -47
- package/src/graphql/objects/SparkWalletUser.ts +1 -1
- package/src/graphql/objects/SwapLeaf.ts +40 -32
- package/src/graphql/objects/UserLeafInput.ts +24 -0
- package/src/graphql/objects/UserRequest.ts +4 -0
- package/src/graphql/queries/Transfers.ts +15 -0
- package/src/index.node.ts +1 -1
- package/src/native/index.ts +4 -5
- package/src/services/coop-exit.ts +171 -36
- package/src/services/deposit.ts +471 -74
- package/src/services/lightning.ts +18 -5
- package/src/services/signing.ts +162 -50
- package/src/services/transfer.ts +950 -384
- package/src/services/tree-creation.ts +342 -121
- package/src/spark-wallet/spark-wallet.node.ts +71 -66
- package/src/spark-wallet/spark-wallet.ts +561 -192
- package/src/tests/integration/coop-exit.test.ts +3 -8
- package/src/tests/integration/deposit.test.ts +3 -3
- package/src/tests/integration/lightning.test.ts +521 -466
- package/src/tests/integration/ssp/static_deposit.test.ts +83 -1
- package/src/tests/integration/ssp/transfers.test.ts +97 -0
- package/src/tests/integration/swap.test.ts +559 -307
- package/src/tests/integration/transfer.test.ts +625 -623
- package/src/tests/integration/wallet.test.ts +2 -2
- package/src/tests/integration/watchtower.test.ts +211 -0
- package/src/tests/test-utils.ts +63 -14
- package/src/tests/utils/test-faucet.ts +4 -2
- package/src/types/sdk-types.ts +15 -0
- package/src/utils/adaptor-signature.ts +15 -5
- package/src/utils/bitcoin.ts +13 -0
- package/src/utils/fetch.ts +75 -0
- package/src/utils/mempool.ts +9 -4
- package/src/utils/transaction.ts +388 -26
- package/dist/sdk-types-CB9HrW5O.d.cts +0 -44
- package/dist/sdk-types-CkRNraXT.d.ts +0 -44
- package/src/graphql/queries/Transfer.ts +0 -10
|
@@ -4,9 +4,10 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
mapTransferToWalletTransfer,
|
|
6
6
|
mapTreeNodeToWalletLeaf
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-3SPMJMUX.js";
|
|
8
8
|
import {
|
|
9
9
|
BitcoinNetwork_default,
|
|
10
|
+
ClaimStaticDepositFromJson,
|
|
10
11
|
ClaimStaticDepositRequestType_default,
|
|
11
12
|
CoopExitFeeQuoteFromJson,
|
|
12
13
|
CurrencyAmountFromJson,
|
|
@@ -22,7 +23,7 @@ import {
|
|
|
22
23
|
LightningSendRequestFromJson,
|
|
23
24
|
SparkCoopExitRequestStatus_default,
|
|
24
25
|
TransferFromJson
|
|
25
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-CQY5ML2A.js";
|
|
26
27
|
import {
|
|
27
28
|
Empty,
|
|
28
29
|
SendLeafKeyTweaks,
|
|
@@ -577,7 +578,7 @@ import * as ecies from "eciesjs";
|
|
|
577
578
|
import { isNode } from "@lightsparkdev/core";
|
|
578
579
|
var isReactNative = typeof navigator !== "undefined" && navigator.product === "ReactNative";
|
|
579
580
|
var isBun = globalThis.Bun !== void 0;
|
|
580
|
-
var packageVersion = true ? "0.2.
|
|
581
|
+
var packageVersion = true ? "0.2.5" : "unknown";
|
|
581
582
|
var baseEnvStr = "unknown";
|
|
582
583
|
if (isBun) {
|
|
583
584
|
const bunVersion = "version" in globalThis.Bun ? globalThis.Bun.version : "unknown-version";
|
|
@@ -2911,10 +2912,23 @@ function getTxId(tx) {
|
|
|
2911
2912
|
function getTxIdNoReverse(tx) {
|
|
2912
2913
|
return bytesToHex4(sha2563(sha2563(tx.toBytes(true))));
|
|
2913
2914
|
}
|
|
2915
|
+
function getTxEstimatedVbytesSizeByNumberOfInputsOutputs(numInputs, numOutputs) {
|
|
2916
|
+
const TX_OVERHEAD = 10;
|
|
2917
|
+
const IN_VBYTES = 150;
|
|
2918
|
+
const OUT_VBYTES = 34;
|
|
2919
|
+
return TX_OVERHEAD + numInputs * IN_VBYTES + numOutputs * OUT_VBYTES;
|
|
2920
|
+
}
|
|
2914
2921
|
|
|
2915
2922
|
// src/utils/transaction.ts
|
|
2916
2923
|
import { Transaction as Transaction2 } from "@scure/btc-signer";
|
|
2924
|
+
var INITIAL_TIMELOCK = 2e3;
|
|
2925
|
+
var TEST_UNILATERAL_TIMELOCK = 100;
|
|
2917
2926
|
var TIME_LOCK_INTERVAL = 100;
|
|
2927
|
+
var DIRECT_TIMELOCK_OFFSET = 50;
|
|
2928
|
+
var INITIAL_SEQUENCE = 1 << 30 | INITIAL_TIMELOCK;
|
|
2929
|
+
var INITIAL_DIRECT_SEQUENCE = 1 << 30 | INITIAL_TIMELOCK + DIRECT_TIMELOCK_OFFSET;
|
|
2930
|
+
var TEST_UNILATERAL_SEQUENCE = 1 << 30 | TEST_UNILATERAL_TIMELOCK;
|
|
2931
|
+
var TEST_UNILATERAL_DIRECT_SEQUENCE = 1 << 30 | TEST_UNILATERAL_TIMELOCK + DIRECT_TIMELOCK_OFFSET;
|
|
2918
2932
|
var ESTIMATED_TX_SIZE = 191;
|
|
2919
2933
|
var DEFAULT_SATS_PER_VBYTE = 5;
|
|
2920
2934
|
var DEFAULT_FEE_SATS = ESTIMATED_TX_SIZE * DEFAULT_SATS_PER_VBYTE;
|
|
@@ -2924,29 +2938,270 @@ function maybeApplyFee(amount) {
|
|
|
2924
2938
|
}
|
|
2925
2939
|
return amount;
|
|
2926
2940
|
}
|
|
2927
|
-
function
|
|
2928
|
-
const
|
|
2941
|
+
function createRootTx(depositOutPoint, depositTxOut) {
|
|
2942
|
+
const cpfpRootTx = new Transaction2({
|
|
2943
|
+
version: 3,
|
|
2944
|
+
allowUnknownOutputs: true
|
|
2945
|
+
});
|
|
2946
|
+
cpfpRootTx.addInput(depositOutPoint);
|
|
2947
|
+
cpfpRootTx.addOutput(depositTxOut);
|
|
2948
|
+
cpfpRootTx.addOutput(getEphemeralAnchorOutput());
|
|
2949
|
+
const directRootTx = new Transaction2({
|
|
2950
|
+
version: 3,
|
|
2951
|
+
allowUnknownOutputs: true
|
|
2952
|
+
});
|
|
2953
|
+
directRootTx.addInput(depositOutPoint);
|
|
2954
|
+
directRootTx.addOutput({
|
|
2955
|
+
script: depositTxOut.script,
|
|
2956
|
+
amount: maybeApplyFee(depositTxOut.amount ?? 0n)
|
|
2957
|
+
});
|
|
2958
|
+
return [cpfpRootTx, directRootTx];
|
|
2959
|
+
}
|
|
2960
|
+
function createSplitTx(parentOutPoint, childTxOuts) {
|
|
2961
|
+
const cpfpSplitTx = new Transaction2({
|
|
2962
|
+
version: 3,
|
|
2963
|
+
allowUnknownOutputs: true
|
|
2964
|
+
});
|
|
2965
|
+
cpfpSplitTx.addInput(parentOutPoint);
|
|
2966
|
+
for (const txOut of childTxOuts) {
|
|
2967
|
+
cpfpSplitTx.addOutput(txOut);
|
|
2968
|
+
}
|
|
2969
|
+
cpfpSplitTx.addOutput(getEphemeralAnchorOutput());
|
|
2970
|
+
const directSplitTx = new Transaction2({
|
|
2971
|
+
version: 3,
|
|
2972
|
+
allowUnknownOutputs: true
|
|
2973
|
+
});
|
|
2974
|
+
directSplitTx.addInput(parentOutPoint);
|
|
2975
|
+
let totalOutputAmount = 0n;
|
|
2976
|
+
for (const txOut of childTxOuts) {
|
|
2977
|
+
totalOutputAmount += txOut.amount ?? 0n;
|
|
2978
|
+
}
|
|
2979
|
+
if (totalOutputAmount > BigInt(DEFAULT_FEE_SATS)) {
|
|
2980
|
+
const feeRatio = Number(DEFAULT_FEE_SATS) / Number(totalOutputAmount);
|
|
2981
|
+
for (const txOut of childTxOuts) {
|
|
2982
|
+
const adjustedAmount = BigInt(
|
|
2983
|
+
Math.floor(Number(txOut.amount ?? 0n) * (1 - feeRatio))
|
|
2984
|
+
);
|
|
2985
|
+
directSplitTx.addOutput({
|
|
2986
|
+
script: txOut.script,
|
|
2987
|
+
amount: adjustedAmount
|
|
2988
|
+
});
|
|
2989
|
+
}
|
|
2990
|
+
} else {
|
|
2991
|
+
for (const txOut of childTxOuts) {
|
|
2992
|
+
directSplitTx.addOutput(txOut);
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
return [cpfpSplitTx, directSplitTx];
|
|
2996
|
+
}
|
|
2997
|
+
function createNodeTx({
|
|
2998
|
+
txOut,
|
|
2999
|
+
parentOutPoint,
|
|
3000
|
+
applyFee,
|
|
3001
|
+
includeAnchor
|
|
3002
|
+
}) {
|
|
3003
|
+
const nodeTx = new Transaction2({
|
|
3004
|
+
version: 3,
|
|
3005
|
+
allowUnknownOutputs: true
|
|
3006
|
+
});
|
|
3007
|
+
nodeTx.addInput(parentOutPoint);
|
|
3008
|
+
if (applyFee) {
|
|
3009
|
+
nodeTx.addOutput({
|
|
3010
|
+
script: txOut.script,
|
|
3011
|
+
amount: maybeApplyFee(txOut.amount ?? 0n)
|
|
3012
|
+
});
|
|
3013
|
+
} else {
|
|
3014
|
+
nodeTx.addOutput(txOut);
|
|
3015
|
+
}
|
|
3016
|
+
if (includeAnchor) {
|
|
3017
|
+
nodeTx.addOutput(getEphemeralAnchorOutput());
|
|
3018
|
+
}
|
|
3019
|
+
return nodeTx;
|
|
3020
|
+
}
|
|
3021
|
+
function createNodeTxs(txOut, txIn, directTxIn) {
|
|
3022
|
+
const cpfpNodeTx = createNodeTx({
|
|
3023
|
+
txOut,
|
|
3024
|
+
parentOutPoint: txIn,
|
|
3025
|
+
includeAnchor: true
|
|
3026
|
+
});
|
|
3027
|
+
let directNodeTx;
|
|
3028
|
+
if (directTxIn) {
|
|
3029
|
+
directNodeTx = createNodeTx({
|
|
3030
|
+
txOut,
|
|
3031
|
+
parentOutPoint: directTxIn,
|
|
3032
|
+
includeAnchor: false,
|
|
3033
|
+
applyFee: true
|
|
3034
|
+
});
|
|
3035
|
+
}
|
|
3036
|
+
return { cpfpNodeTx, directNodeTx };
|
|
3037
|
+
}
|
|
3038
|
+
function createLeafNodeTx(sequence, directSequence, parentOutPoint, txOut, shouldCalculateFee) {
|
|
3039
|
+
const cpfpLeafTx = new Transaction2({
|
|
3040
|
+
version: 3,
|
|
3041
|
+
allowUnknownOutputs: true
|
|
3042
|
+
});
|
|
3043
|
+
cpfpLeafTx.addInput({
|
|
3044
|
+
...parentOutPoint,
|
|
3045
|
+
sequence
|
|
3046
|
+
});
|
|
3047
|
+
cpfpLeafTx.addOutput(txOut);
|
|
3048
|
+
cpfpLeafTx.addOutput(getEphemeralAnchorOutput());
|
|
3049
|
+
const directLeafTx = new Transaction2({
|
|
3050
|
+
version: 3,
|
|
3051
|
+
allowUnknownOutputs: true
|
|
3052
|
+
});
|
|
3053
|
+
directLeafTx.addInput({
|
|
3054
|
+
...parentOutPoint,
|
|
3055
|
+
sequence: directSequence
|
|
3056
|
+
});
|
|
3057
|
+
const amountSats = txOut.amount ?? 0n;
|
|
3058
|
+
let outputAmount = amountSats;
|
|
3059
|
+
if (shouldCalculateFee) {
|
|
3060
|
+
outputAmount = maybeApplyFee(amountSats);
|
|
3061
|
+
}
|
|
3062
|
+
directLeafTx.addOutput({
|
|
3063
|
+
script: txOut.script,
|
|
3064
|
+
amount: outputAmount
|
|
3065
|
+
});
|
|
3066
|
+
return [cpfpLeafTx, directLeafTx];
|
|
3067
|
+
}
|
|
3068
|
+
function createRefundTx({
|
|
3069
|
+
sequence,
|
|
3070
|
+
input,
|
|
3071
|
+
amountSats,
|
|
3072
|
+
receivingPubkey,
|
|
3073
|
+
network,
|
|
3074
|
+
shouldCalculateFee,
|
|
3075
|
+
includeAnchor
|
|
3076
|
+
}) {
|
|
3077
|
+
const refundTx = new Transaction2({
|
|
2929
3078
|
version: 3,
|
|
2930
3079
|
allowUnknownOutputs: true
|
|
2931
3080
|
});
|
|
2932
|
-
|
|
2933
|
-
...
|
|
3081
|
+
refundTx.addInput({
|
|
3082
|
+
...input,
|
|
2934
3083
|
sequence
|
|
2935
3084
|
});
|
|
2936
3085
|
const refundPkScript = getP2TRScriptFromPublicKey(receivingPubkey, network);
|
|
2937
|
-
|
|
3086
|
+
let outputAmount = amountSats;
|
|
3087
|
+
if (shouldCalculateFee) {
|
|
3088
|
+
outputAmount = maybeApplyFee(amountSats);
|
|
3089
|
+
}
|
|
3090
|
+
refundTx.addOutput({
|
|
2938
3091
|
script: refundPkScript,
|
|
3092
|
+
amount: outputAmount
|
|
3093
|
+
});
|
|
3094
|
+
if (includeAnchor) {
|
|
3095
|
+
refundTx.addOutput(getEphemeralAnchorOutput());
|
|
3096
|
+
}
|
|
3097
|
+
return refundTx;
|
|
3098
|
+
}
|
|
3099
|
+
function createRefundTxs({
|
|
3100
|
+
sequence,
|
|
3101
|
+
directSequence,
|
|
3102
|
+
input,
|
|
3103
|
+
directInput,
|
|
3104
|
+
amountSats,
|
|
3105
|
+
receivingPubkey,
|
|
3106
|
+
network
|
|
3107
|
+
}) {
|
|
3108
|
+
const cpfpRefundTx = createRefundTx({
|
|
3109
|
+
sequence,
|
|
3110
|
+
input,
|
|
3111
|
+
amountSats,
|
|
3112
|
+
receivingPubkey,
|
|
3113
|
+
network,
|
|
3114
|
+
shouldCalculateFee: false,
|
|
3115
|
+
includeAnchor: true
|
|
3116
|
+
});
|
|
3117
|
+
let directRefundTx;
|
|
3118
|
+
let directFromCpfpRefundTx;
|
|
3119
|
+
if (directSequence && directInput) {
|
|
3120
|
+
directRefundTx = createRefundTx({
|
|
3121
|
+
sequence: directSequence,
|
|
3122
|
+
input: directInput,
|
|
3123
|
+
amountSats,
|
|
3124
|
+
receivingPubkey,
|
|
3125
|
+
network,
|
|
3126
|
+
shouldCalculateFee: true,
|
|
3127
|
+
includeAnchor: false
|
|
3128
|
+
});
|
|
3129
|
+
directFromCpfpRefundTx = createRefundTx({
|
|
3130
|
+
sequence: directSequence,
|
|
3131
|
+
input,
|
|
3132
|
+
amountSats,
|
|
3133
|
+
receivingPubkey,
|
|
3134
|
+
network,
|
|
3135
|
+
shouldCalculateFee: true,
|
|
3136
|
+
includeAnchor: false
|
|
3137
|
+
});
|
|
3138
|
+
} else if (directInput && !directSequence) {
|
|
3139
|
+
throw new ValidationError(
|
|
3140
|
+
"directSequence must be provided if directInput is",
|
|
3141
|
+
{
|
|
3142
|
+
field: "directSequence",
|
|
3143
|
+
value: directSequence
|
|
3144
|
+
}
|
|
3145
|
+
);
|
|
3146
|
+
}
|
|
3147
|
+
return { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx };
|
|
3148
|
+
}
|
|
3149
|
+
function createConnectorRefundTransactions(sequence, cpfpNodeOutPoint, directNodeOutPoint, connectorOutput, amountSats, receiverPubKey, network, shouldCalculateFee) {
|
|
3150
|
+
const cpfpRefundTx = new Transaction2({
|
|
3151
|
+
version: 3,
|
|
3152
|
+
allowUnknownOutputs: true
|
|
3153
|
+
});
|
|
3154
|
+
cpfpRefundTx.addInput({
|
|
3155
|
+
...cpfpNodeOutPoint,
|
|
3156
|
+
sequence
|
|
3157
|
+
});
|
|
3158
|
+
cpfpRefundTx.addInput(connectorOutput);
|
|
3159
|
+
const receiverScript = getP2TRScriptFromPublicKey(receiverPubKey, network);
|
|
3160
|
+
cpfpRefundTx.addOutput({
|
|
3161
|
+
script: receiverScript,
|
|
2939
3162
|
amount: amountSats
|
|
2940
3163
|
});
|
|
2941
|
-
|
|
2942
|
-
|
|
3164
|
+
const directRefundTx = new Transaction2({
|
|
3165
|
+
version: 3,
|
|
3166
|
+
allowUnknownOutputs: true
|
|
3167
|
+
});
|
|
3168
|
+
directRefundTx.addInput({
|
|
3169
|
+
...directNodeOutPoint,
|
|
3170
|
+
sequence
|
|
3171
|
+
});
|
|
3172
|
+
directRefundTx.addInput(connectorOutput);
|
|
3173
|
+
let outputAmount = amountSats;
|
|
3174
|
+
if (shouldCalculateFee) {
|
|
3175
|
+
outputAmount = maybeApplyFee(amountSats);
|
|
3176
|
+
}
|
|
3177
|
+
directRefundTx.addOutput({
|
|
3178
|
+
script: receiverScript,
|
|
3179
|
+
amount: outputAmount
|
|
3180
|
+
});
|
|
3181
|
+
const directFromCpfpTx = new Transaction2({
|
|
3182
|
+
version: 3,
|
|
3183
|
+
allowUnknownOutputs: true
|
|
3184
|
+
});
|
|
3185
|
+
directFromCpfpTx.addInput({
|
|
3186
|
+
...cpfpNodeOutPoint,
|
|
3187
|
+
sequence
|
|
3188
|
+
});
|
|
3189
|
+
directFromCpfpTx.addInput(connectorOutput);
|
|
3190
|
+
directFromCpfpTx.addOutput({
|
|
3191
|
+
script: receiverScript,
|
|
3192
|
+
amount: outputAmount
|
|
3193
|
+
});
|
|
3194
|
+
return [cpfpRefundTx, directRefundTx, directFromCpfpTx];
|
|
2943
3195
|
}
|
|
2944
3196
|
function getCurrentTimelock(currSequence) {
|
|
2945
3197
|
return (currSequence || 0) & 65535;
|
|
2946
3198
|
}
|
|
2947
3199
|
function getTransactionSequence(currSequence) {
|
|
2948
3200
|
const timelock = getCurrentTimelock(currSequence);
|
|
2949
|
-
return
|
|
3201
|
+
return {
|
|
3202
|
+
nextSequence: 1 << 30 | timelock,
|
|
3203
|
+
nextDirectSequence: 1 << 30 | timelock + DIRECT_TIMELOCK_OFFSET
|
|
3204
|
+
};
|
|
2950
3205
|
}
|
|
2951
3206
|
function checkIfValidSequence(currSequence) {
|
|
2952
3207
|
const TIME_LOCK_ACTIVE = (currSequence || 0) & 2147483648;
|
|
@@ -2964,24 +3219,32 @@ function checkIfValidSequence(currSequence) {
|
|
|
2964
3219
|
});
|
|
2965
3220
|
}
|
|
2966
3221
|
}
|
|
2967
|
-
function
|
|
3222
|
+
function doesLeafNeedRefresh(currSequence, isNodeTx) {
|
|
2968
3223
|
const currentTimelock = getCurrentTimelock(currSequence);
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
return {
|
|
2972
|
-
nextSequence: 1 << 30 | nextTimelock,
|
|
2973
|
-
needRefresh: true
|
|
2974
|
-
};
|
|
3224
|
+
if (isNodeTx) {
|
|
3225
|
+
return currentTimelock === 0;
|
|
2975
3226
|
}
|
|
2976
|
-
|
|
3227
|
+
return currentTimelock <= 100;
|
|
3228
|
+
}
|
|
3229
|
+
function getNextTransactionSequence(currSequence, isNodeTx) {
|
|
3230
|
+
const currentTimelock = getCurrentTimelock(currSequence);
|
|
3231
|
+
const nextTimelock = currentTimelock - TIME_LOCK_INTERVAL;
|
|
3232
|
+
if (isNodeTx && nextTimelock < 0) {
|
|
2977
3233
|
throw new ValidationError("timelock interval is less than 0", {
|
|
2978
3234
|
field: "nextTimelock",
|
|
2979
|
-
value: nextTimelock
|
|
3235
|
+
value: nextTimelock,
|
|
3236
|
+
expected: "Non-negative timelock interval"
|
|
3237
|
+
});
|
|
3238
|
+
} else if (!isNodeTx && nextTimelock <= 0) {
|
|
3239
|
+
throw new ValidationError("timelock interval is less than or equal to 0", {
|
|
3240
|
+
field: "nextTimelock",
|
|
3241
|
+
value: nextTimelock,
|
|
3242
|
+
expected: "Timelock greater than 0"
|
|
2980
3243
|
});
|
|
2981
3244
|
}
|
|
2982
3245
|
return {
|
|
2983
3246
|
nextSequence: 1 << 30 | nextTimelock,
|
|
2984
|
-
|
|
3247
|
+
nextDirectSequence: 1 << 30 | nextTimelock + DIRECT_TIMELOCK_OFFSET
|
|
2985
3248
|
};
|
|
2986
3249
|
}
|
|
2987
3250
|
function getEphemeralAnchorOutput() {
|
|
@@ -3033,10 +3296,8 @@ function proofOfPossessionMessageHashForDepositAddress(userPubkey, operatorPubke
|
|
|
3033
3296
|
import { schnorr as schnorr3, secp256k1 as secp256k16 } from "@noble/curves/secp256k1";
|
|
3034
3297
|
import { sha256 as sha2566 } from "@noble/hashes/sha2";
|
|
3035
3298
|
import { hexToBytes as hexToBytes4 } from "@noble/hashes/utils";
|
|
3036
|
-
import
|
|
3037
|
-
import { p2tr as p2tr2, Transaction as Transaction3 } from "@scure/btc-signer";
|
|
3299
|
+
import { p2tr as p2tr2 } from "@scure/btc-signer";
|
|
3038
3300
|
import { equalBytes as equalBytes3 } from "@scure/btc-signer/utils";
|
|
3039
|
-
var INITIAL_TIME_LOCK = 2e3;
|
|
3040
3301
|
var DepositService = class {
|
|
3041
3302
|
config;
|
|
3042
3303
|
connectionManager;
|
|
@@ -3154,7 +3415,6 @@ var DepositService = class {
|
|
|
3154
3415
|
depositTx,
|
|
3155
3416
|
vout
|
|
3156
3417
|
}) {
|
|
3157
|
-
const rootTx = new Transaction3({ version: 3 });
|
|
3158
3418
|
const output = depositTx.getOutput(vout);
|
|
3159
3419
|
if (!output) {
|
|
3160
3420
|
throw new ValidationError("Invalid deposit transaction output", {
|
|
@@ -3172,39 +3432,59 @@ var DepositService = class {
|
|
|
3172
3432
|
expected: "Output with script and amount"
|
|
3173
3433
|
});
|
|
3174
3434
|
}
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
txid: getTxId(depositTx),
|
|
3435
|
+
const depositOutPoint = {
|
|
3436
|
+
txid: hexToBytes4(getTxId(depositTx)),
|
|
3178
3437
|
index: vout
|
|
3179
|
-
}
|
|
3180
|
-
|
|
3438
|
+
};
|
|
3439
|
+
const depositTxOut = {
|
|
3181
3440
|
script,
|
|
3182
|
-
amount
|
|
3183
|
-
}
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
const
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
sequence
|
|
3193
|
-
});
|
|
3441
|
+
amount
|
|
3442
|
+
};
|
|
3443
|
+
const [cpfpRootTx, directRootTx] = createRootTx(
|
|
3444
|
+
depositOutPoint,
|
|
3445
|
+
depositTxOut
|
|
3446
|
+
);
|
|
3447
|
+
const cpfpRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
3448
|
+
const directRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
3449
|
+
const cpfpRootTxSighash = getSigHashFromTx(cpfpRootTx, 0, output);
|
|
3450
|
+
const directRootTxSighash = getSigHashFromTx(directRootTx, 0, output);
|
|
3194
3451
|
const signingPubKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
3195
|
-
const
|
|
3196
|
-
|
|
3197
|
-
|
|
3452
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
3453
|
+
sequence: INITIAL_SEQUENCE,
|
|
3454
|
+
directSequence: INITIAL_DIRECT_SEQUENCE,
|
|
3455
|
+
input: { txid: hexToBytes4(getTxId(cpfpRootTx)), index: 0 },
|
|
3456
|
+
directInput: { txid: hexToBytes4(getTxId(directRootTx)), index: 0 },
|
|
3457
|
+
amountSats: amount,
|
|
3458
|
+
receivingPubkey: signingPubKey,
|
|
3459
|
+
network: this.config.getNetwork()
|
|
3460
|
+
});
|
|
3461
|
+
const cpfpRefundNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
3462
|
+
const directRefundNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
3463
|
+
const directFromCpfpRefundNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
3464
|
+
const cpfpRefundTxSighash = getSigHashFromTx(
|
|
3465
|
+
cpfpRefundTx,
|
|
3466
|
+
0,
|
|
3467
|
+
cpfpRootTx.getOutput(0)
|
|
3468
|
+
);
|
|
3469
|
+
if (!directRefundTx || !directFromCpfpRefundTx) {
|
|
3470
|
+
throw new ValidationError(
|
|
3471
|
+
"Expected direct refund transactions for tree creation",
|
|
3472
|
+
{
|
|
3473
|
+
field: "directRefundTx",
|
|
3474
|
+
value: directRefundTx
|
|
3475
|
+
}
|
|
3476
|
+
);
|
|
3477
|
+
}
|
|
3478
|
+
const directRefundTxSighash = getSigHashFromTx(
|
|
3479
|
+
directRefundTx,
|
|
3480
|
+
0,
|
|
3481
|
+
directRootTx.getOutput(0)
|
|
3482
|
+
);
|
|
3483
|
+
const directFromCpfpRefundTxSighash = getSigHashFromTx(
|
|
3484
|
+
directFromCpfpRefundTx,
|
|
3485
|
+
0,
|
|
3486
|
+
cpfpRootTx.getOutput(0)
|
|
3198
3487
|
);
|
|
3199
|
-
const refundAddress = btc3.Address(getNetwork(this.config.getNetwork())).decode(refundP2trAddress);
|
|
3200
|
-
const refundPkScript = btc3.OutScript.encode(refundAddress);
|
|
3201
|
-
refundTx.addOutput({
|
|
3202
|
-
script: refundPkScript,
|
|
3203
|
-
amount: outputAmount
|
|
3204
|
-
});
|
|
3205
|
-
refundTx.addOutput(getEphemeralAnchorOutput());
|
|
3206
|
-
const refundNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
3207
|
-
const refundTxSighash = getSigHashFromTx(refundTx, 0, rootTx.getOutput(0));
|
|
3208
3488
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
3209
3489
|
this.config.getCoordinatorAddress()
|
|
3210
3490
|
);
|
|
@@ -3218,14 +3498,29 @@ var DepositService = class {
|
|
|
3218
3498
|
network: this.config.getNetworkProto()
|
|
3219
3499
|
},
|
|
3220
3500
|
rootTxSigningJob: {
|
|
3221
|
-
rawTx:
|
|
3501
|
+
rawTx: cpfpRootTx.toBytes(),
|
|
3222
3502
|
signingPublicKey: signingPubKey,
|
|
3223
|
-
signingNonceCommitment:
|
|
3503
|
+
signingNonceCommitment: cpfpRootNonceCommitment.commitment
|
|
3224
3504
|
},
|
|
3225
3505
|
refundTxSigningJob: {
|
|
3226
|
-
rawTx:
|
|
3506
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
3507
|
+
signingPublicKey: signingPubKey,
|
|
3508
|
+
signingNonceCommitment: cpfpRefundNonceCommitment.commitment
|
|
3509
|
+
},
|
|
3510
|
+
directRootTxSigningJob: {
|
|
3511
|
+
rawTx: directRootTx.toBytes(),
|
|
3512
|
+
signingPublicKey: signingPubKey,
|
|
3513
|
+
signingNonceCommitment: directRootNonceCommitment.commitment
|
|
3514
|
+
},
|
|
3515
|
+
directRefundTxSigningJob: {
|
|
3516
|
+
rawTx: directRefundTx.toBytes(),
|
|
3227
3517
|
signingPublicKey: signingPubKey,
|
|
3228
|
-
signingNonceCommitment:
|
|
3518
|
+
signingNonceCommitment: directRefundNonceCommitment.commitment
|
|
3519
|
+
},
|
|
3520
|
+
directFromCpfpRefundTxSigningJob: {
|
|
3521
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
3522
|
+
signingPublicKey: signingPubKey,
|
|
3523
|
+
signingNonceCommitment: directFromCpfpRefundNonceCommitment.commitment
|
|
3229
3524
|
}
|
|
3230
3525
|
});
|
|
3231
3526
|
} catch (error) {
|
|
@@ -3264,6 +3559,30 @@ var DepositService = class {
|
|
|
3264
3559
|
}
|
|
3265
3560
|
);
|
|
3266
3561
|
}
|
|
3562
|
+
if (!treeResp.rootNodeSignatureShares.directNodeTxSigningResult?.signingNonceCommitments) {
|
|
3563
|
+
throw new ValidationError(
|
|
3564
|
+
"No direct node signing nonce commitments found in tree response",
|
|
3565
|
+
{
|
|
3566
|
+
field: "directNodeTxSigningResult.signingNonceCommitments"
|
|
3567
|
+
}
|
|
3568
|
+
);
|
|
3569
|
+
}
|
|
3570
|
+
if (!treeResp.rootNodeSignatureShares.directRefundTxSigningResult?.signingNonceCommitments) {
|
|
3571
|
+
throw new ValidationError(
|
|
3572
|
+
"No direct refund signing nonce commitments found in tree response",
|
|
3573
|
+
{
|
|
3574
|
+
field: "directRefundTxSigningResult.signingNonceCommitments"
|
|
3575
|
+
}
|
|
3576
|
+
);
|
|
3577
|
+
}
|
|
3578
|
+
if (!treeResp.rootNodeSignatureShares.directFromCpfpRefundTxSigningResult?.signingNonceCommitments) {
|
|
3579
|
+
throw new ValidationError(
|
|
3580
|
+
"No direct from CPFP refund signing nonce commitments found in tree response",
|
|
3581
|
+
{
|
|
3582
|
+
field: "directFromCpfpRefundTxSigningResult.signingNonceCommitments"
|
|
3583
|
+
}
|
|
3584
|
+
);
|
|
3585
|
+
}
|
|
3267
3586
|
if (!equalBytes3(treeResp.rootNodeSignatureShares.verifyingKey, verifyingKey)) {
|
|
3268
3587
|
throw new ValidationError("Verifying key mismatch", {
|
|
3269
3588
|
field: "verifyingKey",
|
|
@@ -3271,55 +3590,302 @@ var DepositService = class {
|
|
|
3271
3590
|
expected: verifyingKey
|
|
3272
3591
|
});
|
|
3273
3592
|
}
|
|
3274
|
-
const
|
|
3275
|
-
message:
|
|
3593
|
+
const cpfpRootSignature = await this.config.signer.signFrost({
|
|
3594
|
+
message: cpfpRootTxSighash,
|
|
3276
3595
|
publicKey: signingPubKey,
|
|
3277
3596
|
keyDerivation,
|
|
3278
3597
|
verifyingKey,
|
|
3279
|
-
selfCommitment:
|
|
3598
|
+
selfCommitment: cpfpRootNonceCommitment,
|
|
3280
3599
|
statechainCommitments: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signingNonceCommitments,
|
|
3281
3600
|
adaptorPubKey: new Uint8Array()
|
|
3282
3601
|
});
|
|
3283
|
-
const
|
|
3284
|
-
message:
|
|
3602
|
+
const directRootSignature = await this.config.signer.signFrost({
|
|
3603
|
+
message: directRootTxSighash,
|
|
3285
3604
|
publicKey: signingPubKey,
|
|
3286
3605
|
keyDerivation,
|
|
3287
3606
|
verifyingKey,
|
|
3288
|
-
selfCommitment:
|
|
3607
|
+
selfCommitment: directRootNonceCommitment,
|
|
3608
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directNodeTxSigningResult.signingNonceCommitments,
|
|
3609
|
+
adaptorPubKey: new Uint8Array()
|
|
3610
|
+
});
|
|
3611
|
+
const cpfpRefundSignature = await this.config.signer.signFrost({
|
|
3612
|
+
message: cpfpRefundTxSighash,
|
|
3613
|
+
publicKey: signingPubKey,
|
|
3614
|
+
keyDerivation,
|
|
3615
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
3616
|
+
selfCommitment: cpfpRefundNonceCommitment,
|
|
3289
3617
|
statechainCommitments: treeResp.rootNodeSignatureShares.refundTxSigningResult.signingNonceCommitments,
|
|
3290
3618
|
adaptorPubKey: new Uint8Array()
|
|
3291
3619
|
});
|
|
3292
|
-
const
|
|
3293
|
-
message:
|
|
3620
|
+
const directRefundSignature = await this.config.signer.signFrost({
|
|
3621
|
+
message: directRefundTxSighash,
|
|
3622
|
+
publicKey: signingPubKey,
|
|
3623
|
+
keyDerivation,
|
|
3624
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
3625
|
+
selfCommitment: directRefundNonceCommitment,
|
|
3626
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directRefundTxSigningResult.signingNonceCommitments,
|
|
3627
|
+
adaptorPubKey: new Uint8Array()
|
|
3628
|
+
});
|
|
3629
|
+
const directFromCpfpRefundSignature = await this.config.signer.signFrost({
|
|
3630
|
+
message: directFromCpfpRefundTxSighash,
|
|
3631
|
+
publicKey: signingPubKey,
|
|
3632
|
+
keyDerivation,
|
|
3633
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
3634
|
+
selfCommitment: directFromCpfpRefundNonceCommitment,
|
|
3635
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directFromCpfpRefundTxSigningResult.signingNonceCommitments,
|
|
3636
|
+
adaptorPubKey: new Uint8Array()
|
|
3637
|
+
});
|
|
3638
|
+
const cpfpRootAggregate = await this.config.signer.aggregateFrost({
|
|
3639
|
+
message: cpfpRootTxSighash,
|
|
3294
3640
|
statechainSignatures: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signatureShares,
|
|
3295
3641
|
statechainPublicKeys: treeResp.rootNodeSignatureShares.nodeTxSigningResult.publicKeys,
|
|
3296
3642
|
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
3297
3643
|
statechainCommitments: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signingNonceCommitments,
|
|
3298
|
-
selfCommitment:
|
|
3644
|
+
selfCommitment: cpfpRootNonceCommitment,
|
|
3299
3645
|
publicKey: signingPubKey,
|
|
3300
|
-
selfSignature:
|
|
3646
|
+
selfSignature: cpfpRootSignature,
|
|
3301
3647
|
adaptorPubKey: new Uint8Array()
|
|
3302
3648
|
});
|
|
3303
|
-
const
|
|
3304
|
-
message:
|
|
3649
|
+
const directRootAggregate = await this.config.signer.aggregateFrost({
|
|
3650
|
+
message: directRootTxSighash,
|
|
3651
|
+
statechainSignatures: treeResp.rootNodeSignatureShares.directNodeTxSigningResult.signatureShares,
|
|
3652
|
+
statechainPublicKeys: treeResp.rootNodeSignatureShares.directNodeTxSigningResult.publicKeys,
|
|
3653
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
3654
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directNodeTxSigningResult.signingNonceCommitments,
|
|
3655
|
+
selfCommitment: directRootNonceCommitment,
|
|
3656
|
+
publicKey: signingPubKey,
|
|
3657
|
+
selfSignature: directRootSignature,
|
|
3658
|
+
adaptorPubKey: new Uint8Array()
|
|
3659
|
+
});
|
|
3660
|
+
const cpfpRefundAggregate = await this.config.signer.aggregateFrost({
|
|
3661
|
+
message: cpfpRefundTxSighash,
|
|
3305
3662
|
statechainSignatures: treeResp.rootNodeSignatureShares.refundTxSigningResult.signatureShares,
|
|
3306
3663
|
statechainPublicKeys: treeResp.rootNodeSignatureShares.refundTxSigningResult.publicKeys,
|
|
3307
3664
|
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
3308
3665
|
statechainCommitments: treeResp.rootNodeSignatureShares.refundTxSigningResult.signingNonceCommitments,
|
|
3309
|
-
selfCommitment:
|
|
3666
|
+
selfCommitment: cpfpRefundNonceCommitment,
|
|
3310
3667
|
publicKey: signingPubKey,
|
|
3311
|
-
selfSignature:
|
|
3668
|
+
selfSignature: cpfpRefundSignature,
|
|
3669
|
+
adaptorPubKey: new Uint8Array()
|
|
3670
|
+
});
|
|
3671
|
+
const directRefundAggregate = await this.config.signer.aggregateFrost({
|
|
3672
|
+
message: directRefundTxSighash,
|
|
3673
|
+
statechainSignatures: treeResp.rootNodeSignatureShares.directRefundTxSigningResult.signatureShares,
|
|
3674
|
+
statechainPublicKeys: treeResp.rootNodeSignatureShares.directRefundTxSigningResult.publicKeys,
|
|
3675
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
3676
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directRefundTxSigningResult.signingNonceCommitments,
|
|
3677
|
+
selfCommitment: directRefundNonceCommitment,
|
|
3678
|
+
publicKey: signingPubKey,
|
|
3679
|
+
selfSignature: directRefundSignature,
|
|
3680
|
+
adaptorPubKey: new Uint8Array()
|
|
3681
|
+
});
|
|
3682
|
+
const directFromCpfpRefundAggregate = await this.config.signer.aggregateFrost({
|
|
3683
|
+
message: directFromCpfpRefundTxSighash,
|
|
3684
|
+
statechainSignatures: treeResp.rootNodeSignatureShares.directFromCpfpRefundTxSigningResult.signatureShares,
|
|
3685
|
+
statechainPublicKeys: treeResp.rootNodeSignatureShares.directFromCpfpRefundTxSigningResult.publicKeys,
|
|
3686
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
3687
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directFromCpfpRefundTxSigningResult.signingNonceCommitments,
|
|
3688
|
+
selfCommitment: directFromCpfpRefundNonceCommitment,
|
|
3689
|
+
publicKey: signingPubKey,
|
|
3690
|
+
selfSignature: directFromCpfpRefundSignature,
|
|
3312
3691
|
adaptorPubKey: new Uint8Array()
|
|
3313
3692
|
});
|
|
3314
3693
|
let finalizeResp;
|
|
3315
3694
|
try {
|
|
3316
|
-
finalizeResp = await sparkClient.
|
|
3695
|
+
finalizeResp = await sparkClient.finalize_node_signatures_v2({
|
|
3317
3696
|
intent: 0 /* CREATION */,
|
|
3318
3697
|
nodeSignatures: [
|
|
3319
3698
|
{
|
|
3320
3699
|
nodeId: treeResp.rootNodeSignatureShares.nodeId,
|
|
3321
|
-
nodeTxSignature:
|
|
3322
|
-
refundTxSignature:
|
|
3700
|
+
nodeTxSignature: cpfpRootAggregate,
|
|
3701
|
+
refundTxSignature: cpfpRefundAggregate,
|
|
3702
|
+
directNodeTxSignature: directRootAggregate,
|
|
3703
|
+
directRefundTxSignature: directRefundAggregate,
|
|
3704
|
+
directFromCpfpRefundTxSignature: directFromCpfpRefundAggregate
|
|
3705
|
+
}
|
|
3706
|
+
]
|
|
3707
|
+
});
|
|
3708
|
+
} catch (error) {
|
|
3709
|
+
throw new NetworkError(
|
|
3710
|
+
"Failed to finalize node signatures",
|
|
3711
|
+
{
|
|
3712
|
+
operation: "finalize_node_signatures",
|
|
3713
|
+
errorCount: 1,
|
|
3714
|
+
errors: error instanceof Error ? error.message : String(error)
|
|
3715
|
+
},
|
|
3716
|
+
error
|
|
3717
|
+
);
|
|
3718
|
+
}
|
|
3719
|
+
return finalizeResp;
|
|
3720
|
+
}
|
|
3721
|
+
/**
|
|
3722
|
+
* @deprecated
|
|
3723
|
+
* Use createTreeRoot instead.
|
|
3724
|
+
* This is currently only used to test backwards compatibility.
|
|
3725
|
+
*/
|
|
3726
|
+
async createTreeWithoutDirectTx({
|
|
3727
|
+
keyDerivation,
|
|
3728
|
+
verifyingKey,
|
|
3729
|
+
depositTx,
|
|
3730
|
+
vout
|
|
3731
|
+
}) {
|
|
3732
|
+
const output = depositTx.getOutput(vout);
|
|
3733
|
+
if (!output) {
|
|
3734
|
+
throw new ValidationError("Invalid deposit transaction output", {
|
|
3735
|
+
field: "vout",
|
|
3736
|
+
value: vout,
|
|
3737
|
+
expected: "Valid output index"
|
|
3738
|
+
});
|
|
3739
|
+
}
|
|
3740
|
+
const script = output.script;
|
|
3741
|
+
const amount = output.amount;
|
|
3742
|
+
if (!script || !amount) {
|
|
3743
|
+
throw new ValidationError("No script or amount found in deposit tx", {
|
|
3744
|
+
field: "output",
|
|
3745
|
+
value: output,
|
|
3746
|
+
expected: "Output with script and amount"
|
|
3747
|
+
});
|
|
3748
|
+
}
|
|
3749
|
+
const depositOutPoint = {
|
|
3750
|
+
txid: hexToBytes4(getTxId(depositTx)),
|
|
3751
|
+
index: vout
|
|
3752
|
+
};
|
|
3753
|
+
const depositTxOut = {
|
|
3754
|
+
script,
|
|
3755
|
+
amount
|
|
3756
|
+
};
|
|
3757
|
+
const [cpfpRootTx, _] = createRootTx(depositOutPoint, depositTxOut);
|
|
3758
|
+
const cpfpRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
3759
|
+
const cpfpRootTxSighash = getSigHashFromTx(cpfpRootTx, 0, output);
|
|
3760
|
+
const signingPubKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
3761
|
+
const { cpfpRefundTx } = createRefundTxs({
|
|
3762
|
+
sequence: INITIAL_SEQUENCE,
|
|
3763
|
+
input: { txid: hexToBytes4(getTxId(cpfpRootTx)), index: 0 },
|
|
3764
|
+
amountSats: amount,
|
|
3765
|
+
receivingPubkey: signingPubKey,
|
|
3766
|
+
network: this.config.getNetwork()
|
|
3767
|
+
});
|
|
3768
|
+
const cpfpRefundNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
3769
|
+
const cpfpRefundTxSighash = getSigHashFromTx(
|
|
3770
|
+
cpfpRefundTx,
|
|
3771
|
+
0,
|
|
3772
|
+
cpfpRootTx.getOutput(0)
|
|
3773
|
+
);
|
|
3774
|
+
const sparkClient = await this.connectionManager.createSparkClient(
|
|
3775
|
+
this.config.getCoordinatorAddress()
|
|
3776
|
+
);
|
|
3777
|
+
let treeResp;
|
|
3778
|
+
try {
|
|
3779
|
+
treeResp = await sparkClient.start_deposit_tree_creation({
|
|
3780
|
+
identityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
3781
|
+
onChainUtxo: {
|
|
3782
|
+
vout,
|
|
3783
|
+
rawTx: depositTx.toBytes(true),
|
|
3784
|
+
network: this.config.getNetworkProto()
|
|
3785
|
+
},
|
|
3786
|
+
rootTxSigningJob: {
|
|
3787
|
+
rawTx: cpfpRootTx.toBytes(),
|
|
3788
|
+
signingPublicKey: signingPubKey,
|
|
3789
|
+
signingNonceCommitment: cpfpRootNonceCommitment.commitment
|
|
3790
|
+
},
|
|
3791
|
+
refundTxSigningJob: {
|
|
3792
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
3793
|
+
signingPublicKey: signingPubKey,
|
|
3794
|
+
signingNonceCommitment: cpfpRefundNonceCommitment.commitment
|
|
3795
|
+
}
|
|
3796
|
+
});
|
|
3797
|
+
} catch (error) {
|
|
3798
|
+
throw new NetworkError(
|
|
3799
|
+
"Failed to start deposit tree creation",
|
|
3800
|
+
{
|
|
3801
|
+
operation: "start_deposit_tree_creation",
|
|
3802
|
+
errorCount: 1,
|
|
3803
|
+
errors: error instanceof Error ? error.message : String(error)
|
|
3804
|
+
},
|
|
3805
|
+
error
|
|
3806
|
+
);
|
|
3807
|
+
}
|
|
3808
|
+
if (!treeResp.rootNodeSignatureShares?.verifyingKey) {
|
|
3809
|
+
throw new ValidationError("No verifying key found in tree response", {
|
|
3810
|
+
field: "verifyingKey",
|
|
3811
|
+
value: treeResp.rootNodeSignatureShares,
|
|
3812
|
+
expected: "Non-null verifying key"
|
|
3813
|
+
});
|
|
3814
|
+
}
|
|
3815
|
+
if (!treeResp.rootNodeSignatureShares.nodeTxSigningResult?.signingNonceCommitments) {
|
|
3816
|
+
throw new ValidationError(
|
|
3817
|
+
"No signing nonce commitments found in tree response",
|
|
3818
|
+
{
|
|
3819
|
+
field: "nodeTxSigningResult.signingNonceCommitments",
|
|
3820
|
+
value: treeResp.rootNodeSignatureShares.nodeTxSigningResult,
|
|
3821
|
+
expected: "Non-null signing nonce commitments"
|
|
3822
|
+
}
|
|
3823
|
+
);
|
|
3824
|
+
}
|
|
3825
|
+
if (!treeResp.rootNodeSignatureShares.refundTxSigningResult?.signingNonceCommitments) {
|
|
3826
|
+
throw new ValidationError(
|
|
3827
|
+
"No signing nonce commitments found in tree response",
|
|
3828
|
+
{
|
|
3829
|
+
field: "refundTxSigningResult.signingNonceCommitments"
|
|
3830
|
+
}
|
|
3831
|
+
);
|
|
3832
|
+
}
|
|
3833
|
+
if (!equalBytes3(treeResp.rootNodeSignatureShares.verifyingKey, verifyingKey)) {
|
|
3834
|
+
throw new ValidationError("Verifying key mismatch", {
|
|
3835
|
+
field: "verifyingKey",
|
|
3836
|
+
value: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
3837
|
+
expected: verifyingKey
|
|
3838
|
+
});
|
|
3839
|
+
}
|
|
3840
|
+
const cpfpRootSignature = await this.config.signer.signFrost({
|
|
3841
|
+
message: cpfpRootTxSighash,
|
|
3842
|
+
publicKey: signingPubKey,
|
|
3843
|
+
keyDerivation,
|
|
3844
|
+
verifyingKey,
|
|
3845
|
+
selfCommitment: cpfpRootNonceCommitment,
|
|
3846
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signingNonceCommitments,
|
|
3847
|
+
adaptorPubKey: new Uint8Array()
|
|
3848
|
+
});
|
|
3849
|
+
const cpfpRefundSignature = await this.config.signer.signFrost({
|
|
3850
|
+
message: cpfpRefundTxSighash,
|
|
3851
|
+
publicKey: signingPubKey,
|
|
3852
|
+
keyDerivation,
|
|
3853
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
3854
|
+
selfCommitment: cpfpRefundNonceCommitment,
|
|
3855
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.refundTxSigningResult.signingNonceCommitments,
|
|
3856
|
+
adaptorPubKey: new Uint8Array()
|
|
3857
|
+
});
|
|
3858
|
+
const cpfpRootAggregate = await this.config.signer.aggregateFrost({
|
|
3859
|
+
message: cpfpRootTxSighash,
|
|
3860
|
+
statechainSignatures: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signatureShares,
|
|
3861
|
+
statechainPublicKeys: treeResp.rootNodeSignatureShares.nodeTxSigningResult.publicKeys,
|
|
3862
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
3863
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signingNonceCommitments,
|
|
3864
|
+
selfCommitment: cpfpRootNonceCommitment,
|
|
3865
|
+
publicKey: signingPubKey,
|
|
3866
|
+
selfSignature: cpfpRootSignature,
|
|
3867
|
+
adaptorPubKey: new Uint8Array()
|
|
3868
|
+
});
|
|
3869
|
+
const cpfpRefundAggregate = await this.config.signer.aggregateFrost({
|
|
3870
|
+
message: cpfpRefundTxSighash,
|
|
3871
|
+
statechainSignatures: treeResp.rootNodeSignatureShares.refundTxSigningResult.signatureShares,
|
|
3872
|
+
statechainPublicKeys: treeResp.rootNodeSignatureShares.refundTxSigningResult.publicKeys,
|
|
3873
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
3874
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.refundTxSigningResult.signingNonceCommitments,
|
|
3875
|
+
selfCommitment: cpfpRefundNonceCommitment,
|
|
3876
|
+
publicKey: signingPubKey,
|
|
3877
|
+
selfSignature: cpfpRefundSignature,
|
|
3878
|
+
adaptorPubKey: new Uint8Array()
|
|
3879
|
+
});
|
|
3880
|
+
let finalizeResp;
|
|
3881
|
+
try {
|
|
3882
|
+
finalizeResp = await sparkClient.finalize_node_signatures_v2({
|
|
3883
|
+
intent: 0 /* CREATION */,
|
|
3884
|
+
nodeSignatures: [
|
|
3885
|
+
{
|
|
3886
|
+
nodeId: treeResp.rootNodeSignatureShares.nodeId,
|
|
3887
|
+
nodeTxSignature: cpfpRootAggregate,
|
|
3888
|
+
refundTxSignature: cpfpRefundAggregate
|
|
3323
3889
|
}
|
|
3324
3890
|
]
|
|
3325
3891
|
});
|
|
@@ -6021,13 +6587,24 @@ function applyAdaptorToSignature(pubkey, hash, signature, adaptorPrivateKeyBytes
|
|
|
6021
6587
|
const adaptorPrivateKey = bytesToNumberBE6(adaptorPrivateKeyBytes);
|
|
6022
6588
|
const newS = mod(sBigInt + adaptorPrivateKey, secp256k110.CURVE.n);
|
|
6023
6589
|
const newSig = new Uint8Array([...r, ...numberToBytesBE3(newS, 32)]);
|
|
6024
|
-
|
|
6025
|
-
|
|
6590
|
+
try {
|
|
6591
|
+
if (schnorr4.verify(newSig, hash, pubkey)) {
|
|
6592
|
+
return newSig;
|
|
6593
|
+
}
|
|
6594
|
+
} catch (e) {
|
|
6595
|
+
console.error("[applyAdaptorToSignature] Addition verification failed:", e);
|
|
6026
6596
|
}
|
|
6027
6597
|
const altS = mod(sBigInt - adaptorPrivateKey, secp256k110.CURVE.n);
|
|
6028
6598
|
const altSig = new Uint8Array([...r, ...numberToBytesBE3(altS, 32)]);
|
|
6029
|
-
|
|
6030
|
-
|
|
6599
|
+
try {
|
|
6600
|
+
if (schnorr4.verify(altSig, hash, pubkey)) {
|
|
6601
|
+
return altSig;
|
|
6602
|
+
}
|
|
6603
|
+
} catch (e) {
|
|
6604
|
+
console.error(
|
|
6605
|
+
"[applyAdaptorToSignature] Subtraction verification failed:",
|
|
6606
|
+
e
|
|
6607
|
+
);
|
|
6031
6608
|
}
|
|
6032
6609
|
throw new Error("Cannot apply adaptor to signature");
|
|
6033
6610
|
}
|
|
@@ -6106,9 +6683,31 @@ function parseSignature(signature) {
|
|
|
6106
6683
|
// src/tests/utils/test-faucet.ts
|
|
6107
6684
|
import { bytesToHex as bytesToHex8, hexToBytes as hexToBytes7 } from "@noble/curves/abstract/utils";
|
|
6108
6685
|
import { schnorr as schnorr5, secp256k1 as secp256k111 } from "@noble/curves/secp256k1";
|
|
6109
|
-
import * as
|
|
6110
|
-
import { Address as
|
|
6686
|
+
import * as btc3 from "@scure/btc-signer";
|
|
6687
|
+
import { Address as Address2, OutScript as OutScript2, SigHash as SigHash2, Transaction as Transaction4 } from "@scure/btc-signer";
|
|
6111
6688
|
import { taprootTweakPrivKey as taprootTweakPrivKey2 } from "@scure/btc-signer/utils";
|
|
6689
|
+
|
|
6690
|
+
// src/utils/fetch.ts
|
|
6691
|
+
var fetchImpl = typeof window !== "undefined" && window.fetch ? window.fetch.bind(window) : globalThis.fetch ? globalThis.fetch : null;
|
|
6692
|
+
var Headers = globalThis.Headers ?? null;
|
|
6693
|
+
var getFetch = () => {
|
|
6694
|
+
if (!fetchImpl) {
|
|
6695
|
+
throw new Error(
|
|
6696
|
+
"Fetch implementation is not set. Please set it using setFetch()."
|
|
6697
|
+
);
|
|
6698
|
+
}
|
|
6699
|
+
if (!Headers) {
|
|
6700
|
+
throw new Error(
|
|
6701
|
+
"Headers implementation is not set. Please set it using setFetch()."
|
|
6702
|
+
);
|
|
6703
|
+
}
|
|
6704
|
+
return {
|
|
6705
|
+
fetch: fetchImpl,
|
|
6706
|
+
Headers
|
|
6707
|
+
};
|
|
6708
|
+
};
|
|
6709
|
+
|
|
6710
|
+
// src/tests/utils/test-faucet.ts
|
|
6112
6711
|
var STATIC_FAUCET_KEY = hexToBytes7(
|
|
6113
6712
|
"deadbeef1337cafe4242424242424242deadbeef1337cafe4242424242424242"
|
|
6114
6713
|
);
|
|
@@ -6252,7 +6851,7 @@ var BitcoinFaucet = class _BitcoinFaucet {
|
|
|
6252
6851
|
}
|
|
6253
6852
|
async sendFaucetCoinToP2WPKHAddress(pubKey) {
|
|
6254
6853
|
const sendToPubKeyTx = new Transaction4();
|
|
6255
|
-
const p2wpkhAddress =
|
|
6854
|
+
const p2wpkhAddress = btc3.p2wpkh(pubKey, getNetwork(4 /* LOCAL */)).address;
|
|
6256
6855
|
if (!p2wpkhAddress) {
|
|
6257
6856
|
throw new Error("Invalid P2WPKH address");
|
|
6258
6857
|
}
|
|
@@ -6308,12 +6907,13 @@ var BitcoinFaucet = class _BitcoinFaucet {
|
|
|
6308
6907
|
}
|
|
6309
6908
|
async call(method, params) {
|
|
6310
6909
|
try {
|
|
6311
|
-
const
|
|
6910
|
+
const { fetch: fetch2, Headers: Headers2 } = getFetch();
|
|
6911
|
+
const response = await fetch2(this.url, {
|
|
6312
6912
|
method: "POST",
|
|
6313
|
-
headers: {
|
|
6913
|
+
headers: new Headers2({
|
|
6314
6914
|
"Content-Type": "application/json",
|
|
6315
6915
|
Authorization: "Basic " + btoa(`${this.username}:${this.password}`)
|
|
6316
|
-
},
|
|
6916
|
+
}),
|
|
6317
6917
|
body: JSON.stringify({
|
|
6318
6918
|
jsonrpc: "1.0",
|
|
6319
6919
|
id: "spark-js",
|
|
@@ -6368,10 +6968,10 @@ var BitcoinFaucet = class _BitcoinFaucet {
|
|
|
6368
6968
|
const tx = new Transaction4();
|
|
6369
6969
|
tx.addInput(coin.outpoint);
|
|
6370
6970
|
const availableAmount = COIN_AMOUNT - FEE_AMOUNT;
|
|
6371
|
-
const destinationAddress =
|
|
6971
|
+
const destinationAddress = Address2(getNetwork(4 /* LOCAL */)).decode(
|
|
6372
6972
|
address2
|
|
6373
6973
|
);
|
|
6374
|
-
const destinationScript =
|
|
6974
|
+
const destinationScript = OutScript2.encode(destinationAddress);
|
|
6375
6975
|
tx.addOutput({
|
|
6376
6976
|
script: destinationScript,
|
|
6377
6977
|
amount
|
|
@@ -6418,7 +7018,7 @@ import {
|
|
|
6418
7018
|
import { secp256k1 as secp256k114 } from "@noble/curves/secp256k1";
|
|
6419
7019
|
import { validateMnemonic } from "@scure/bip39";
|
|
6420
7020
|
import { wordlist as wordlist2 } from "@scure/bip39/wordlists/english";
|
|
6421
|
-
import { Address as
|
|
7021
|
+
import { Address as Address4, OutScript as OutScript4, Transaction as Transaction8 } from "@scure/btc-signer";
|
|
6422
7022
|
import { Mutex } from "async-mutex";
|
|
6423
7023
|
import { uuidv7 as uuidv75, uuidv7obj } from "uuidv7";
|
|
6424
7024
|
|
|
@@ -6569,10 +7169,18 @@ var CompleteCoopExit = `
|
|
|
6569
7169
|
var CompleteLeavesSwap = `
|
|
6570
7170
|
mutation CompleteLeavesSwap(
|
|
6571
7171
|
$adaptor_secret_key: String!
|
|
7172
|
+
$direct_adaptor_secret_key: String!
|
|
7173
|
+
$direct_from_cpfp_adaptor_secret_key: String!
|
|
6572
7174
|
$user_outbound_transfer_external_id: UUID!
|
|
6573
7175
|
$leaves_swap_request_id: ID!
|
|
6574
7176
|
) {
|
|
6575
|
-
complete_leaves_swap(input: {
|
|
7177
|
+
complete_leaves_swap(input: {
|
|
7178
|
+
adaptor_secret_key: $adaptor_secret_key,
|
|
7179
|
+
direct_adaptor_secret_key: $direct_adaptor_secret_key,
|
|
7180
|
+
direct_from_cpfp_adaptor_secret_key: $direct_from_cpfp_adaptor_secret_key,
|
|
7181
|
+
user_outbound_transfer_external_id: $user_outbound_transfer_external_id,
|
|
7182
|
+
leaves_swap_request_id: $leaves_swap_request_id
|
|
7183
|
+
}) {
|
|
6576
7184
|
request {
|
|
6577
7185
|
...LeavesSwapRequestFragment
|
|
6578
7186
|
}
|
|
@@ -6695,6 +7303,8 @@ var RequestLightningSend = `
|
|
|
6695
7303
|
var RequestSwapLeaves = `
|
|
6696
7304
|
mutation RequestSwapLeaves(
|
|
6697
7305
|
$adaptor_pubkey: PublicKey!
|
|
7306
|
+
$direct_adaptor_pubkey: PublicKey
|
|
7307
|
+
$direct_from_cpfp_adaptor_pubkey: PublicKey
|
|
6698
7308
|
$total_amount_sats: Long!
|
|
6699
7309
|
$target_amount_sats: Long!
|
|
6700
7310
|
$fee_sats: Long!
|
|
@@ -6704,6 +7314,8 @@ var RequestSwapLeaves = `
|
|
|
6704
7314
|
) {
|
|
6705
7315
|
request_leaves_swap(input: {
|
|
6706
7316
|
adaptor_pubkey: $adaptor_pubkey
|
|
7317
|
+
direct_adaptor_pubkey: $direct_adaptor_pubkey
|
|
7318
|
+
direct_from_cpfp_adaptor_pubkey: $direct_from_cpfp_adaptor_pubkey
|
|
6707
7319
|
total_amount_sats: $total_amount_sats
|
|
6708
7320
|
target_amount_sats: $target_amount_sats
|
|
6709
7321
|
fee_sats: $fee_sats
|
|
@@ -6982,14 +7594,18 @@ var LightningSendFeeEstimate = `
|
|
|
6982
7594
|
${FRAGMENT13}
|
|
6983
7595
|
`;
|
|
6984
7596
|
|
|
6985
|
-
// src/graphql/queries/
|
|
6986
|
-
var
|
|
6987
|
-
query
|
|
6988
|
-
|
|
7597
|
+
// src/graphql/queries/Transfers.ts
|
|
7598
|
+
var GetTransfers = `
|
|
7599
|
+
query Transfers($transfer_spark_ids: [UUID!]!) {
|
|
7600
|
+
transfers(transfer_spark_ids: $transfer_spark_ids) {
|
|
6989
7601
|
...TransferFragment
|
|
7602
|
+
transfer_user_request: user_request {
|
|
7603
|
+
...UserRequestFragment
|
|
7604
|
+
}
|
|
6990
7605
|
}
|
|
6991
7606
|
}
|
|
6992
7607
|
${FRAGMENT}
|
|
7608
|
+
${FRAGMENT6}
|
|
6993
7609
|
`;
|
|
6994
7610
|
|
|
6995
7611
|
// src/graphql/queries/UserRequest.ts
|
|
@@ -7194,6 +7810,8 @@ var SspClient = class {
|
|
|
7194
7810
|
}
|
|
7195
7811
|
async requestLeaveSwap({
|
|
7196
7812
|
adaptorPubkey,
|
|
7813
|
+
directAdaptorPubkey,
|
|
7814
|
+
directFromCpfpAdaptorPubkey,
|
|
7197
7815
|
totalAmountSats,
|
|
7198
7816
|
targetAmountSats,
|
|
7199
7817
|
feeSats,
|
|
@@ -7205,6 +7823,8 @@ var SspClient = class {
|
|
|
7205
7823
|
queryPayload: RequestSwapLeaves,
|
|
7206
7824
|
variables: {
|
|
7207
7825
|
adaptor_pubkey: adaptorPubkey,
|
|
7826
|
+
direct_adaptor_pubkey: directAdaptorPubkey,
|
|
7827
|
+
direct_from_cpfp_adaptor_pubkey: directFromCpfpAdaptorPubkey,
|
|
7208
7828
|
total_amount_sats: totalAmountSats,
|
|
7209
7829
|
target_amount_sats: targetAmountSats,
|
|
7210
7830
|
fee_sats: feeSats,
|
|
@@ -7223,6 +7843,8 @@ var SspClient = class {
|
|
|
7223
7843
|
}
|
|
7224
7844
|
async completeLeaveSwap({
|
|
7225
7845
|
adaptorSecretKey,
|
|
7846
|
+
directAdaptorSecretKey,
|
|
7847
|
+
directFromCpfpAdaptorSecretKey,
|
|
7226
7848
|
userOutboundTransferExternalId,
|
|
7227
7849
|
leavesSwapRequestId
|
|
7228
7850
|
}) {
|
|
@@ -7230,6 +7852,8 @@ var SspClient = class {
|
|
|
7230
7852
|
queryPayload: CompleteLeavesSwap,
|
|
7231
7853
|
variables: {
|
|
7232
7854
|
adaptor_secret_key: adaptorSecretKey,
|
|
7855
|
+
direct_adaptor_secret_key: directAdaptorSecretKey,
|
|
7856
|
+
direct_from_cpfp_adaptor_secret_key: directFromCpfpAdaptorSecretKey,
|
|
7233
7857
|
user_outbound_transfer_external_id: userOutboundTransferExternalId,
|
|
7234
7858
|
leaves_swap_request_id: leavesSwapRequestId
|
|
7235
7859
|
},
|
|
@@ -7337,14 +7961,47 @@ var SspClient = class {
|
|
|
7337
7961
|
}
|
|
7338
7962
|
});
|
|
7339
7963
|
}
|
|
7340
|
-
async
|
|
7964
|
+
async getTransfers(ids) {
|
|
7341
7965
|
return await this.executeRawQuery({
|
|
7342
|
-
queryPayload:
|
|
7966
|
+
queryPayload: GetTransfers,
|
|
7343
7967
|
variables: {
|
|
7344
|
-
|
|
7968
|
+
transfer_spark_ids: ids
|
|
7345
7969
|
},
|
|
7346
7970
|
constructObject: (response) => {
|
|
7347
|
-
return
|
|
7971
|
+
return response.transfers.map((transfer) => {
|
|
7972
|
+
const transferObj = TransferFromJson(
|
|
7973
|
+
transfer
|
|
7974
|
+
);
|
|
7975
|
+
switch (transfer.transfer_user_request.__typename) {
|
|
7976
|
+
case "ClaimStaticDeposit":
|
|
7977
|
+
transferObj.userRequest = ClaimStaticDepositFromJson(
|
|
7978
|
+
transfer.transfer_user_request
|
|
7979
|
+
);
|
|
7980
|
+
break;
|
|
7981
|
+
case "CoopExitRequest":
|
|
7982
|
+
transferObj.userRequest = CoopExitRequestFromJson(
|
|
7983
|
+
transfer.transfer_user_request
|
|
7984
|
+
);
|
|
7985
|
+
break;
|
|
7986
|
+
case "LeavesSwapRequest":
|
|
7987
|
+
transferObj.userRequest = LeavesSwapRequestFromJson(
|
|
7988
|
+
transfer.transfer_user_request
|
|
7989
|
+
);
|
|
7990
|
+
break;
|
|
7991
|
+
case "LightningReceiveRequest":
|
|
7992
|
+
transferObj.userRequest = LightningReceiveRequestFromJson(
|
|
7993
|
+
transfer.transfer_user_request
|
|
7994
|
+
);
|
|
7995
|
+
break;
|
|
7996
|
+
case "LightningSendRequest":
|
|
7997
|
+
transferObj.userRequest = LightningSendRequestFromJson(
|
|
7998
|
+
transfer.transfer_user_request
|
|
7999
|
+
);
|
|
8000
|
+
break;
|
|
8001
|
+
}
|
|
8002
|
+
const { userRequestId, ...rest } = transferObj;
|
|
8003
|
+
return rest;
|
|
8004
|
+
});
|
|
7348
8005
|
}
|
|
7349
8006
|
});
|
|
7350
8007
|
}
|
|
@@ -7497,11 +8154,7 @@ import { sha256 as sha2569 } from "@noble/hashes/sha2";
|
|
|
7497
8154
|
import { Transaction as Transaction5 } from "@scure/btc-signer";
|
|
7498
8155
|
import * as ecies2 from "eciesjs";
|
|
7499
8156
|
import { uuidv7 as uuidv72 } from "uuidv7";
|
|
7500
|
-
var INITIAL_TIME_LOCK2 = 2e3;
|
|
7501
8157
|
var DEFAULT_EXPIRY_TIME = 10 * 60 * 1e3;
|
|
7502
|
-
function initialSequence() {
|
|
7503
|
-
return 1 << 30 | INITIAL_TIME_LOCK2;
|
|
7504
|
-
}
|
|
7505
8158
|
function getSigningJobProto(signingJob) {
|
|
7506
8159
|
return {
|
|
7507
8160
|
signingPublicKey: signingJob.signingPublicKey,
|
|
@@ -7518,12 +8171,14 @@ var BaseTransferService = class {
|
|
|
7518
8171
|
this.connectionManager = connectionManager;
|
|
7519
8172
|
this.signingService = signingService;
|
|
7520
8173
|
}
|
|
7521
|
-
async sendTransferTweakKey(transfer, leaves,
|
|
8174
|
+
async sendTransferTweakKey(transfer, leaves, cpfpRefundSignatureMap, directRefundSignatureMap, directFromCpfpRefundSignatureMap) {
|
|
7522
8175
|
const keyTweakInputMap = await this.prepareSendTransferKeyTweaks(
|
|
7523
8176
|
transfer.id,
|
|
7524
8177
|
transfer.receiverIdentityPublicKey,
|
|
7525
8178
|
leaves,
|
|
7526
|
-
|
|
8179
|
+
cpfpRefundSignatureMap,
|
|
8180
|
+
directRefundSignatureMap,
|
|
8181
|
+
directFromCpfpRefundSignatureMap
|
|
7527
8182
|
);
|
|
7528
8183
|
let updatedTransfer;
|
|
7529
8184
|
const coordinatorOperator = this.config.getSigningOperators()[this.config.getCoordinatorIdentifier()];
|
|
@@ -7561,13 +8216,26 @@ var BaseTransferService = class {
|
|
|
7561
8216
|
}
|
|
7562
8217
|
return updatedTransfer;
|
|
7563
8218
|
}
|
|
7564
|
-
async deliverTransferPackage(transfer, leaves,
|
|
8219
|
+
async deliverTransferPackage(transfer, leaves, cpfpRefundSignatureMap, directRefundSignatureMap, directFromCpfpRefundSignatureMap) {
|
|
7565
8220
|
const keyTweakInputMap = await this.prepareSendTransferKeyTweaks(
|
|
7566
8221
|
transfer.id,
|
|
7567
8222
|
transfer.receiverIdentityPublicKey,
|
|
7568
8223
|
leaves,
|
|
7569
|
-
|
|
8224
|
+
cpfpRefundSignatureMap,
|
|
8225
|
+
directRefundSignatureMap,
|
|
8226
|
+
directFromCpfpRefundSignatureMap
|
|
7570
8227
|
);
|
|
8228
|
+
for (const [key, operator] of Object.entries(
|
|
8229
|
+
this.config.getSigningOperators()
|
|
8230
|
+
)) {
|
|
8231
|
+
const tweaks = keyTweakInputMap.get(key);
|
|
8232
|
+
if (!tweaks) {
|
|
8233
|
+
throw new ValidationError("No tweaks for operator", {
|
|
8234
|
+
field: "operator",
|
|
8235
|
+
value: key
|
|
8236
|
+
});
|
|
8237
|
+
}
|
|
8238
|
+
}
|
|
7571
8239
|
const transferPackage = await this.prepareTransferPackage(
|
|
7572
8240
|
transfer.id,
|
|
7573
8241
|
keyTweakInputMap,
|
|
@@ -7593,6 +8261,8 @@ var BaseTransferService = class {
|
|
|
7593
8261
|
transferID,
|
|
7594
8262
|
receiverIdentityPubkey,
|
|
7595
8263
|
leaves,
|
|
8264
|
+
/* @__PURE__ */ new Map(),
|
|
8265
|
+
/* @__PURE__ */ new Map(),
|
|
7596
8266
|
/* @__PURE__ */ new Map()
|
|
7597
8267
|
);
|
|
7598
8268
|
const transferPackage = await this.prepareTransferPackage(
|
|
@@ -7606,7 +8276,7 @@ var BaseTransferService = class {
|
|
|
7606
8276
|
);
|
|
7607
8277
|
let response;
|
|
7608
8278
|
try {
|
|
7609
|
-
response = await sparkClient.
|
|
8279
|
+
response = await sparkClient.start_transfer_v2({
|
|
7610
8280
|
transferId: transferID,
|
|
7611
8281
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
7612
8282
|
receiverIdentityPublicKey: receiverIdentityPubkey,
|
|
@@ -7635,12 +8305,22 @@ var BaseTransferService = class {
|
|
|
7635
8305
|
nodes.push(leaf.leaf.id);
|
|
7636
8306
|
}
|
|
7637
8307
|
const signingCommitments = await sparkClient.get_signing_commitments({
|
|
7638
|
-
nodeIds: nodes
|
|
8308
|
+
nodeIds: nodes,
|
|
8309
|
+
count: 3
|
|
7639
8310
|
});
|
|
7640
|
-
const
|
|
8311
|
+
const {
|
|
8312
|
+
cpfpLeafSigningJobs,
|
|
8313
|
+
directLeafSigningJobs,
|
|
8314
|
+
directFromCpfpLeafSigningJobs
|
|
8315
|
+
} = await this.signingService.signRefunds(
|
|
7641
8316
|
leaves,
|
|
7642
|
-
|
|
7643
|
-
|
|
8317
|
+
receiverIdentityPubkey,
|
|
8318
|
+
signingCommitments.signingCommitments.slice(0, leaves.length),
|
|
8319
|
+
signingCommitments.signingCommitments.slice(
|
|
8320
|
+
leaves.length,
|
|
8321
|
+
2 * leaves.length
|
|
8322
|
+
),
|
|
8323
|
+
signingCommitments.signingCommitments.slice(2 * leaves.length)
|
|
7644
8324
|
);
|
|
7645
8325
|
const encryptedKeyTweaks = {};
|
|
7646
8326
|
for (const [key, value] of keyTweakInputMap) {
|
|
@@ -7660,12 +8340,11 @@ var BaseTransferService = class {
|
|
|
7660
8340
|
encryptedKeyTweaks[key] = Uint8Array.from(encryptedProto);
|
|
7661
8341
|
}
|
|
7662
8342
|
const transferPackage = {
|
|
7663
|
-
leavesToSend:
|
|
8343
|
+
leavesToSend: cpfpLeafSigningJobs,
|
|
7664
8344
|
keyTweakPackage: encryptedKeyTweaks,
|
|
7665
8345
|
userSignature: new Uint8Array(),
|
|
7666
|
-
|
|
7667
|
-
|
|
7668
|
-
directFromCpfpLeavesToSend: []
|
|
8346
|
+
directLeavesToSend: directLeafSigningJobs,
|
|
8347
|
+
directFromCpfpLeavesToSend: directFromCpfpLeafSigningJobs
|
|
7669
8348
|
};
|
|
7670
8349
|
const transferPackageSigningPayload = getTransferPackageSigningPayload(
|
|
7671
8350
|
transferID,
|
|
@@ -7725,7 +8404,7 @@ var BaseTransferService = class {
|
|
|
7725
8404
|
}
|
|
7726
8405
|
return updatedTransfer;
|
|
7727
8406
|
}
|
|
7728
|
-
async signRefunds(leafDataMap, operatorSigningResults,
|
|
8407
|
+
async signRefunds(leafDataMap, operatorSigningResults, cpfpAdaptorPubKey, directAdaptorPubKey, directFromCpfpAdaptorPubKey) {
|
|
7729
8408
|
const nodeSignatures = [];
|
|
7730
8409
|
for (const operatorSigningResult of operatorSigningResults) {
|
|
7731
8410
|
const leafData = leafDataMap.get(operatorSigningResult.leafId);
|
|
@@ -7740,54 +8419,120 @@ var BaseTransferService = class {
|
|
|
7740
8419
|
`Output not found for leaf ${operatorSigningResult.leafId}`
|
|
7741
8420
|
);
|
|
7742
8421
|
}
|
|
7743
|
-
const
|
|
8422
|
+
const cpfpRefundTxSighash = getSigHashFromTx(
|
|
8423
|
+
leafData.refundTx,
|
|
8424
|
+
0,
|
|
8425
|
+
txOutput
|
|
8426
|
+
);
|
|
7744
8427
|
const publicKey = await this.config.signer.getPublicKeyFromDerivation(
|
|
7745
8428
|
leafData.keyDerivation
|
|
7746
8429
|
);
|
|
7747
|
-
const
|
|
7748
|
-
message:
|
|
8430
|
+
const cpfpUserSignature = await this.config.signer.signFrost({
|
|
8431
|
+
message: cpfpRefundTxSighash,
|
|
7749
8432
|
publicKey,
|
|
7750
8433
|
keyDerivation: leafData.keyDerivation,
|
|
7751
8434
|
selfCommitment: leafData.signingNonceCommitment,
|
|
7752
8435
|
statechainCommitments: operatorSigningResult.refundTxSigningResult?.signingNonceCommitments,
|
|
7753
|
-
adaptorPubKey,
|
|
8436
|
+
adaptorPubKey: cpfpAdaptorPubKey,
|
|
7754
8437
|
verifyingKey: operatorSigningResult.verifyingKey
|
|
7755
8438
|
});
|
|
7756
|
-
const
|
|
7757
|
-
message:
|
|
8439
|
+
const cpfpRefundAggregate = await this.config.signer.aggregateFrost({
|
|
8440
|
+
message: cpfpRefundTxSighash,
|
|
7758
8441
|
statechainSignatures: operatorSigningResult.refundTxSigningResult?.signatureShares,
|
|
7759
8442
|
statechainPublicKeys: operatorSigningResult.refundTxSigningResult?.publicKeys,
|
|
7760
8443
|
verifyingKey: operatorSigningResult.verifyingKey,
|
|
7761
8444
|
statechainCommitments: operatorSigningResult.refundTxSigningResult?.signingNonceCommitments,
|
|
7762
8445
|
selfCommitment: leafData.signingNonceCommitment,
|
|
7763
8446
|
publicKey,
|
|
7764
|
-
selfSignature:
|
|
7765
|
-
adaptorPubKey
|
|
7766
|
-
});
|
|
8447
|
+
selfSignature: cpfpUserSignature,
|
|
8448
|
+
adaptorPubKey: cpfpAdaptorPubKey
|
|
8449
|
+
});
|
|
8450
|
+
let directRefundAggregate;
|
|
8451
|
+
let directFromCpfpRefundAggregate;
|
|
8452
|
+
if (leafData.directTx) {
|
|
8453
|
+
const directTxOutput = leafData.directTx.getOutput(0);
|
|
8454
|
+
if (leafData.directRefundTx) {
|
|
8455
|
+
const directRefundTxSighash = getSigHashFromTx(
|
|
8456
|
+
leafData.directRefundTx,
|
|
8457
|
+
0,
|
|
8458
|
+
directTxOutput
|
|
8459
|
+
);
|
|
8460
|
+
const directUserSignature = await this.config.signer.signFrost({
|
|
8461
|
+
message: directRefundTxSighash,
|
|
8462
|
+
publicKey,
|
|
8463
|
+
keyDerivation: leafData.keyDerivation,
|
|
8464
|
+
selfCommitment: leafData.directSigningNonceCommitment,
|
|
8465
|
+
statechainCommitments: operatorSigningResult.directRefundTxSigningResult?.signingNonceCommitments,
|
|
8466
|
+
adaptorPubKey: directAdaptorPubKey,
|
|
8467
|
+
verifyingKey: operatorSigningResult.verifyingKey
|
|
8468
|
+
});
|
|
8469
|
+
directRefundAggregate = await this.config.signer.aggregateFrost({
|
|
8470
|
+
message: directRefundTxSighash,
|
|
8471
|
+
statechainSignatures: operatorSigningResult.directRefundTxSigningResult?.signatureShares,
|
|
8472
|
+
statechainPublicKeys: operatorSigningResult.directRefundTxSigningResult?.publicKeys,
|
|
8473
|
+
verifyingKey: operatorSigningResult.verifyingKey,
|
|
8474
|
+
statechainCommitments: operatorSigningResult.directRefundTxSigningResult?.signingNonceCommitments,
|
|
8475
|
+
selfCommitment: leafData.directSigningNonceCommitment,
|
|
8476
|
+
publicKey,
|
|
8477
|
+
selfSignature: directUserSignature,
|
|
8478
|
+
adaptorPubKey: directAdaptorPubKey
|
|
8479
|
+
});
|
|
8480
|
+
}
|
|
8481
|
+
if (leafData.directFromCpfpRefundTx) {
|
|
8482
|
+
const directFromCpfpRefundTxSighash = getSigHashFromTx(
|
|
8483
|
+
leafData.directFromCpfpRefundTx,
|
|
8484
|
+
0,
|
|
8485
|
+
txOutput
|
|
8486
|
+
);
|
|
8487
|
+
const directFromCpfpUserSignature = await this.config.signer.signFrost({
|
|
8488
|
+
message: directFromCpfpRefundTxSighash,
|
|
8489
|
+
publicKey,
|
|
8490
|
+
keyDerivation: leafData.keyDerivation,
|
|
8491
|
+
selfCommitment: leafData.directFromCpfpRefundSigningNonceCommitment,
|
|
8492
|
+
statechainCommitments: operatorSigningResult.directFromCpfpRefundTxSigningResult?.signingNonceCommitments,
|
|
8493
|
+
adaptorPubKey: directFromCpfpAdaptorPubKey,
|
|
8494
|
+
verifyingKey: operatorSigningResult.verifyingKey
|
|
8495
|
+
});
|
|
8496
|
+
directFromCpfpRefundAggregate = await this.config.signer.aggregateFrost({
|
|
8497
|
+
message: directFromCpfpRefundTxSighash,
|
|
8498
|
+
statechainSignatures: operatorSigningResult.directFromCpfpRefundTxSigningResult?.signatureShares,
|
|
8499
|
+
statechainPublicKeys: operatorSigningResult.directFromCpfpRefundTxSigningResult?.publicKeys,
|
|
8500
|
+
verifyingKey: operatorSigningResult.verifyingKey,
|
|
8501
|
+
statechainCommitments: operatorSigningResult.directFromCpfpRefundTxSigningResult?.signingNonceCommitments,
|
|
8502
|
+
selfCommitment: leafData.directFromCpfpRefundSigningNonceCommitment,
|
|
8503
|
+
publicKey,
|
|
8504
|
+
selfSignature: directFromCpfpUserSignature,
|
|
8505
|
+
adaptorPubKey: directFromCpfpAdaptorPubKey
|
|
8506
|
+
});
|
|
8507
|
+
}
|
|
8508
|
+
}
|
|
7767
8509
|
nodeSignatures.push({
|
|
7768
8510
|
nodeId: operatorSigningResult.leafId,
|
|
7769
|
-
refundTxSignature: refundAggregate,
|
|
7770
8511
|
nodeTxSignature: new Uint8Array(),
|
|
7771
|
-
// TODO: Add direct refund signature
|
|
7772
8512
|
directNodeTxSignature: new Uint8Array(),
|
|
7773
|
-
|
|
7774
|
-
|
|
8513
|
+
refundTxSignature: cpfpRefundAggregate,
|
|
8514
|
+
directRefundTxSignature: directRefundAggregate ?? new Uint8Array(),
|
|
8515
|
+
directFromCpfpRefundTxSignature: directFromCpfpRefundAggregate ?? new Uint8Array()
|
|
7775
8516
|
});
|
|
7776
8517
|
}
|
|
7777
8518
|
return nodeSignatures;
|
|
7778
8519
|
}
|
|
7779
|
-
async prepareSendTransferKeyTweaks(transferID, receiverIdentityPubkey, leaves,
|
|
8520
|
+
async prepareSendTransferKeyTweaks(transferID, receiverIdentityPubkey, leaves, cpfpRefundSignatureMap, directRefundSignatureMap, directFromCpfpRefundSignatureMap) {
|
|
7780
8521
|
const receiverEciesPubKey = ecies2.PublicKey.fromHex(
|
|
7781
8522
|
bytesToHex10(receiverIdentityPubkey)
|
|
7782
8523
|
);
|
|
7783
8524
|
const leavesTweaksMap = /* @__PURE__ */ new Map();
|
|
7784
8525
|
for (const leaf of leaves) {
|
|
7785
|
-
const
|
|
8526
|
+
const cpfpRefundSignature = cpfpRefundSignatureMap.get(leaf.leaf.id);
|
|
8527
|
+
const directRefundSignature = directRefundSignatureMap.get(leaf.leaf.id);
|
|
8528
|
+
const directFromCpfpRefundSignature = directFromCpfpRefundSignatureMap.get(leaf.leaf.id);
|
|
7786
8529
|
const leafTweaksMap = await this.prepareSingleSendTransferKeyTweak(
|
|
7787
8530
|
transferID,
|
|
7788
8531
|
leaf,
|
|
7789
8532
|
receiverEciesPubKey,
|
|
7790
|
-
|
|
8533
|
+
cpfpRefundSignature,
|
|
8534
|
+
directRefundSignature,
|
|
8535
|
+
directFromCpfpRefundSignature
|
|
7791
8536
|
);
|
|
7792
8537
|
for (const [identifier, leafTweak] of leafTweaksMap) {
|
|
7793
8538
|
leavesTweaksMap.set(identifier, [
|
|
@@ -7798,7 +8543,7 @@ var BaseTransferService = class {
|
|
|
7798
8543
|
}
|
|
7799
8544
|
return leavesTweaksMap;
|
|
7800
8545
|
}
|
|
7801
|
-
async prepareSingleSendTransferKeyTweak(transferID, leaf, receiverEciesPubKey,
|
|
8546
|
+
async prepareSingleSendTransferKeyTweak(transferID, leaf, receiverEciesPubKey, cpfpRefundSignature, directRefundSignature, directFromCpfpRefundSignature) {
|
|
7802
8547
|
const signingOperators = this.config.getSigningOperators();
|
|
7803
8548
|
const { shares, secretCipher } = await this.config.signer.subtractSplitAndEncrypt({
|
|
7804
8549
|
first: leaf.keyDerivation,
|
|
@@ -7846,10 +8591,9 @@ var BaseTransferService = class {
|
|
|
7846
8591
|
pubkeySharesTweak: Object.fromEntries(pubkeySharesTweak),
|
|
7847
8592
|
secretCipher,
|
|
7848
8593
|
signature,
|
|
7849
|
-
refundSignature:
|
|
7850
|
-
|
|
7851
|
-
|
|
7852
|
-
directFromCpfpRefundSignature: new Uint8Array()
|
|
8594
|
+
refundSignature: cpfpRefundSignature ?? new Uint8Array(),
|
|
8595
|
+
directRefundSignature: directRefundSignature ?? new Uint8Array(),
|
|
8596
|
+
directFromCpfpRefundSignature: directFromCpfpRefundSignature ?? new Uint8Array()
|
|
7853
8597
|
});
|
|
7854
8598
|
}
|
|
7855
8599
|
return leafTweaksMap;
|
|
@@ -7879,7 +8623,12 @@ var TransferService = class extends BaseTransferService {
|
|
|
7879
8623
|
* Deprecated in v0.1.32
|
|
7880
8624
|
*/
|
|
7881
8625
|
async sendTransfer(leaves, receiverIdentityPubkey) {
|
|
7882
|
-
const {
|
|
8626
|
+
const {
|
|
8627
|
+
transfer,
|
|
8628
|
+
signatureMap,
|
|
8629
|
+
directSignatureMap,
|
|
8630
|
+
directFromCpfpSignatureMap
|
|
8631
|
+
} = await this.sendTransferSignRefund(
|
|
7883
8632
|
leaves,
|
|
7884
8633
|
receiverIdentityPubkey,
|
|
7885
8634
|
new Date(Date.now() + DEFAULT_EXPIRY_TIME)
|
|
@@ -7887,7 +8636,9 @@ var TransferService = class extends BaseTransferService {
|
|
|
7887
8636
|
const transferWithTweakedKeys = await this.sendTransferTweakKey(
|
|
7888
8637
|
transfer,
|
|
7889
8638
|
leaves,
|
|
7890
|
-
signatureMap
|
|
8639
|
+
signatureMap,
|
|
8640
|
+
directSignatureMap,
|
|
8641
|
+
directFromCpfpSignatureMap
|
|
7891
8642
|
);
|
|
7892
8643
|
return transferWithTweakedKeys;
|
|
7893
8644
|
}
|
|
@@ -7991,7 +8742,13 @@ var TransferService = class extends BaseTransferService {
|
|
|
7991
8742
|
return transferResp.transfers[0];
|
|
7992
8743
|
}
|
|
7993
8744
|
async sendTransferSignRefund(leaves, receiverIdentityPubkey, expiryTime) {
|
|
7994
|
-
const {
|
|
8745
|
+
const {
|
|
8746
|
+
transfer,
|
|
8747
|
+
signatureMap,
|
|
8748
|
+
directSignatureMap,
|
|
8749
|
+
directFromCpfpSignatureMap,
|
|
8750
|
+
leafDataMap
|
|
8751
|
+
} = await this.sendTransferSignRefundInternal(
|
|
7995
8752
|
leaves,
|
|
7996
8753
|
receiverIdentityPubkey,
|
|
7997
8754
|
expiryTime,
|
|
@@ -8000,11 +8757,19 @@ var TransferService = class extends BaseTransferService {
|
|
|
8000
8757
|
return {
|
|
8001
8758
|
transfer,
|
|
8002
8759
|
signatureMap,
|
|
8760
|
+
directSignatureMap,
|
|
8761
|
+
directFromCpfpSignatureMap,
|
|
8003
8762
|
leafDataMap
|
|
8004
8763
|
};
|
|
8005
8764
|
}
|
|
8006
8765
|
async startSwapSignRefund(leaves, receiverIdentityPubkey, expiryTime) {
|
|
8007
|
-
const {
|
|
8766
|
+
const {
|
|
8767
|
+
transfer,
|
|
8768
|
+
signatureMap,
|
|
8769
|
+
directSignatureMap,
|
|
8770
|
+
directFromCpfpSignatureMap,
|
|
8771
|
+
leafDataMap
|
|
8772
|
+
} = await this.sendTransferSignRefundInternal(
|
|
8008
8773
|
leaves,
|
|
8009
8774
|
receiverIdentityPubkey,
|
|
8010
8775
|
expiryTime,
|
|
@@ -8013,31 +8778,45 @@ var TransferService = class extends BaseTransferService {
|
|
|
8013
8778
|
return {
|
|
8014
8779
|
transfer,
|
|
8015
8780
|
signatureMap,
|
|
8781
|
+
directSignatureMap,
|
|
8782
|
+
directFromCpfpSignatureMap,
|
|
8016
8783
|
leafDataMap
|
|
8017
8784
|
};
|
|
8018
8785
|
}
|
|
8019
|
-
async counterSwapSignRefund(leaves, receiverIdentityPubkey, expiryTime,
|
|
8786
|
+
async counterSwapSignRefund(leaves, receiverIdentityPubkey, expiryTime, cpfpAdaptorPubKey, directAdaptorPubKey, directFromCpfpAdaptorPubKey) {
|
|
8020
8787
|
return this.sendTransferSignRefundInternal(
|
|
8021
8788
|
leaves,
|
|
8022
8789
|
receiverIdentityPubkey,
|
|
8023
8790
|
expiryTime,
|
|
8024
8791
|
true,
|
|
8025
|
-
|
|
8792
|
+
cpfpAdaptorPubKey,
|
|
8793
|
+
directAdaptorPubKey,
|
|
8794
|
+
directFromCpfpAdaptorPubKey
|
|
8026
8795
|
);
|
|
8027
8796
|
}
|
|
8028
|
-
async sendTransferSignRefundInternal(leaves, receiverIdentityPubkey, expiryTime, forSwap,
|
|
8797
|
+
async sendTransferSignRefundInternal(leaves, receiverIdentityPubkey, expiryTime, forSwap, cpfpAdaptorPubKey, directAdaptorPubKey, directFromCpfpAdaptorPubKey) {
|
|
8029
8798
|
const transferId = uuidv72();
|
|
8030
8799
|
const leafDataMap = /* @__PURE__ */ new Map();
|
|
8031
8800
|
for (const leaf of leaves) {
|
|
8032
8801
|
const signingNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
8802
|
+
const directSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
8803
|
+
const directFromCpfpRefundSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
8033
8804
|
const tx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
8034
8805
|
const refundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
8806
|
+
const directTx = leaf.leaf.directTx.length > 0 ? getTxFromRawTxBytes(leaf.leaf.directTx) : void 0;
|
|
8807
|
+
const directRefundTx = leaf.leaf.directRefundTx.length > 0 ? getTxFromRawTxBytes(leaf.leaf.directRefundTx) : void 0;
|
|
8808
|
+
const directFromCpfpRefundTx = leaf.leaf.directFromCpfpRefundTx.length > 0 ? getTxFromRawTxBytes(leaf.leaf.directFromCpfpRefundTx) : void 0;
|
|
8035
8809
|
leafDataMap.set(leaf.leaf.id, {
|
|
8036
8810
|
keyDerivation: leaf.keyDerivation,
|
|
8037
8811
|
receivingPubkey: receiverIdentityPubkey,
|
|
8038
8812
|
signingNonceCommitment,
|
|
8813
|
+
directSigningNonceCommitment,
|
|
8039
8814
|
tx,
|
|
8815
|
+
directTx,
|
|
8040
8816
|
refundTx,
|
|
8817
|
+
directRefundTx,
|
|
8818
|
+
directFromCpfpRefundTx,
|
|
8819
|
+
directFromCpfpRefundSigningNonceCommitment,
|
|
8041
8820
|
vout: leaf.leaf.vout
|
|
8042
8821
|
});
|
|
8043
8822
|
}
|
|
@@ -8050,8 +8829,8 @@ var TransferService = class extends BaseTransferService {
|
|
|
8050
8829
|
);
|
|
8051
8830
|
let response;
|
|
8052
8831
|
try {
|
|
8053
|
-
if (
|
|
8054
|
-
response = await sparkClient.
|
|
8832
|
+
if (cpfpAdaptorPubKey !== void 0 || directAdaptorPubKey !== void 0 || directFromCpfpAdaptorPubKey !== void 0) {
|
|
8833
|
+
response = await sparkClient.counter_leaf_swap_v2({
|
|
8055
8834
|
transfer: {
|
|
8056
8835
|
transferId,
|
|
8057
8836
|
leavesToSend: signingJobs,
|
|
@@ -8060,10 +8839,12 @@ var TransferService = class extends BaseTransferService {
|
|
|
8060
8839
|
expiryTime
|
|
8061
8840
|
},
|
|
8062
8841
|
swapId: uuidv72(),
|
|
8063
|
-
adaptorPublicKey:
|
|
8842
|
+
adaptorPublicKey: cpfpAdaptorPubKey,
|
|
8843
|
+
directAdaptorPublicKey: directAdaptorPubKey,
|
|
8844
|
+
directFromCpfpAdaptorPublicKey: directFromCpfpAdaptorPubKey
|
|
8064
8845
|
});
|
|
8065
8846
|
} else if (forSwap) {
|
|
8066
|
-
response = await sparkClient.
|
|
8847
|
+
response = await sparkClient.start_leaf_swap_v2({
|
|
8067
8848
|
transferId,
|
|
8068
8849
|
leavesToSend: signingJobs,
|
|
8069
8850
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
@@ -8071,7 +8852,7 @@ var TransferService = class extends BaseTransferService {
|
|
|
8071
8852
|
expiryTime
|
|
8072
8853
|
});
|
|
8073
8854
|
} else {
|
|
8074
|
-
response = await sparkClient.
|
|
8855
|
+
response = await sparkClient.start_transfer_v2({
|
|
8075
8856
|
transferId,
|
|
8076
8857
|
leavesToSend: signingJobs,
|
|
8077
8858
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
@@ -8088,15 +8869,29 @@ var TransferService = class extends BaseTransferService {
|
|
|
8088
8869
|
const signatures = await this.signRefunds(
|
|
8089
8870
|
leafDataMap,
|
|
8090
8871
|
response.signingResults,
|
|
8091
|
-
|
|
8872
|
+
cpfpAdaptorPubKey,
|
|
8873
|
+
directAdaptorPubKey,
|
|
8874
|
+
directFromCpfpAdaptorPubKey
|
|
8092
8875
|
);
|
|
8093
|
-
const
|
|
8876
|
+
const cpfpSignatureMap = /* @__PURE__ */ new Map();
|
|
8877
|
+
const directSignatureMap = /* @__PURE__ */ new Map();
|
|
8878
|
+
const directFromCpfpSignatureMap = /* @__PURE__ */ new Map();
|
|
8094
8879
|
for (const signature of signatures) {
|
|
8095
|
-
|
|
8880
|
+
cpfpSignatureMap.set(signature.nodeId, signature.refundTxSignature);
|
|
8881
|
+
directSignatureMap.set(
|
|
8882
|
+
signature.nodeId,
|
|
8883
|
+
signature.directRefundTxSignature
|
|
8884
|
+
);
|
|
8885
|
+
directFromCpfpSignatureMap.set(
|
|
8886
|
+
signature.nodeId,
|
|
8887
|
+
signature.directFromCpfpRefundTxSignature
|
|
8888
|
+
);
|
|
8096
8889
|
}
|
|
8097
8890
|
return {
|
|
8098
8891
|
transfer: response.transfer,
|
|
8099
|
-
signatureMap,
|
|
8892
|
+
signatureMap: cpfpSignatureMap,
|
|
8893
|
+
directSignatureMap,
|
|
8894
|
+
directFromCpfpSignatureMap,
|
|
8100
8895
|
leafDataMap,
|
|
8101
8896
|
signingResults: response.signingResults
|
|
8102
8897
|
};
|
|
@@ -8109,38 +8904,68 @@ var TransferService = class extends BaseTransferService {
|
|
|
8109
8904
|
throw new Error(`Leaf data not found for leaf ${leaf.leaf.id}`);
|
|
8110
8905
|
}
|
|
8111
8906
|
const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
8112
|
-
const
|
|
8907
|
+
const cpfpNodeOutPoint = {
|
|
8113
8908
|
txid: hexToBytes8(getTxId(nodeTx)),
|
|
8114
8909
|
index: 0
|
|
8115
8910
|
};
|
|
8911
|
+
let directNodeTx;
|
|
8912
|
+
let directNodeOutPoint;
|
|
8913
|
+
if (leaf.leaf.directTx.length > 0) {
|
|
8914
|
+
directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
|
|
8915
|
+
directNodeOutPoint = {
|
|
8916
|
+
txid: hexToBytes8(getTxId(directNodeTx)),
|
|
8917
|
+
index: 0
|
|
8918
|
+
};
|
|
8919
|
+
}
|
|
8116
8920
|
const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
8117
|
-
const
|
|
8921
|
+
const sequence = currRefundTx.getInput(0).sequence;
|
|
8922
|
+
if (!sequence) {
|
|
8923
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
8924
|
+
field: "sequence",
|
|
8925
|
+
value: currRefundTx.getInput(0),
|
|
8926
|
+
expected: "Non-null sequence"
|
|
8927
|
+
});
|
|
8928
|
+
}
|
|
8929
|
+
const { nextSequence, nextDirectSequence } = isForClaim ? getTransactionSequence(sequence) : getNextTransactionSequence(sequence);
|
|
8118
8930
|
const amountSats = currRefundTx.getOutput(0).amount;
|
|
8119
8931
|
if (amountSats === void 0) {
|
|
8120
8932
|
throw new Error("Amount not found in signRefunds");
|
|
8121
8933
|
}
|
|
8122
|
-
const
|
|
8123
|
-
nextSequence,
|
|
8124
|
-
|
|
8934
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
8935
|
+
sequence: nextSequence,
|
|
8936
|
+
directSequence: nextDirectSequence,
|
|
8937
|
+
input: cpfpNodeOutPoint,
|
|
8938
|
+
directInput: directNodeOutPoint,
|
|
8125
8939
|
amountSats,
|
|
8126
|
-
refundSigningData.receivingPubkey,
|
|
8127
|
-
this.config.getNetwork()
|
|
8940
|
+
receivingPubkey: refundSigningData.receivingPubkey,
|
|
8941
|
+
network: this.config.getNetwork()
|
|
8942
|
+
});
|
|
8943
|
+
refundSigningData.refundTx = cpfpRefundTx;
|
|
8944
|
+
refundSigningData.directRefundTx = directRefundTx;
|
|
8945
|
+
refundSigningData.directFromCpfpRefundTx = directFromCpfpRefundTx;
|
|
8946
|
+
const cpfpRefundNonceCommitmentProto = refundSigningData.signingNonceCommitment;
|
|
8947
|
+
const directRefundNonceCommitmentProto = refundSigningData.directSigningNonceCommitment;
|
|
8948
|
+
const directFromCpfpRefundNonceCommitmentProto = refundSigningData.directFromCpfpRefundSigningNonceCommitment;
|
|
8949
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(
|
|
8950
|
+
refundSigningData.keyDerivation
|
|
8128
8951
|
);
|
|
8129
|
-
refundSigningData.refundTx = refundTx;
|
|
8130
|
-
const refundNonceCommitmentProto = refundSigningData.signingNonceCommitment;
|
|
8131
8952
|
signingJobs.push({
|
|
8132
8953
|
leafId: leaf.leaf.id,
|
|
8133
8954
|
refundTxSigningJob: {
|
|
8134
|
-
signingPublicKey
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
rawTx: refundTx.toBytes(),
|
|
8138
|
-
signingNonceCommitment: refundNonceCommitmentProto.commitment
|
|
8955
|
+
signingPublicKey,
|
|
8956
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
8957
|
+
signingNonceCommitment: cpfpRefundNonceCommitmentProto.commitment
|
|
8139
8958
|
},
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
8143
|
-
|
|
8959
|
+
directRefundTxSigningJob: directRefundTx ? {
|
|
8960
|
+
signingPublicKey,
|
|
8961
|
+
rawTx: directRefundTx.toBytes(),
|
|
8962
|
+
signingNonceCommitment: directRefundNonceCommitmentProto.commitment
|
|
8963
|
+
} : void 0,
|
|
8964
|
+
directFromCpfpRefundTxSigningJob: directFromCpfpRefundTx ? {
|
|
8965
|
+
signingPublicKey,
|
|
8966
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
8967
|
+
signingNonceCommitment: directFromCpfpRefundNonceCommitmentProto.commitment
|
|
8968
|
+
} : void 0
|
|
8144
8969
|
});
|
|
8145
8970
|
}
|
|
8146
8971
|
return signingJobs;
|
|
@@ -8261,13 +9086,17 @@ var TransferService = class extends BaseTransferService {
|
|
|
8261
9086
|
const leafDataMap = /* @__PURE__ */ new Map();
|
|
8262
9087
|
for (const leafKey of leafKeys) {
|
|
8263
9088
|
const tx = getTxFromRawTxBytes(leafKey.leaf.nodeTx);
|
|
9089
|
+
const directTx = leafKey.leaf.directTx.length > 0 ? getTxFromRawTxBytes(leafKey.leaf.directTx) : void 0;
|
|
8264
9090
|
leafDataMap.set(leafKey.leaf.id, {
|
|
8265
9091
|
keyDerivation: leafKey.newKeyDerivation,
|
|
8266
9092
|
receivingPubkey: await this.config.signer.getPublicKeyFromDerivation(
|
|
8267
9093
|
leafKey.newKeyDerivation
|
|
8268
9094
|
),
|
|
8269
9095
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9096
|
+
directSigningNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9097
|
+
directFromCpfpRefundSigningNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
8270
9098
|
tx,
|
|
9099
|
+
directTx,
|
|
8271
9100
|
vout: leafKey.leaf.vout
|
|
8272
9101
|
});
|
|
8273
9102
|
}
|
|
@@ -8289,7 +9118,7 @@ var TransferService = class extends BaseTransferService {
|
|
|
8289
9118
|
}
|
|
8290
9119
|
}
|
|
8291
9120
|
try {
|
|
8292
|
-
resp = await sparkClient.
|
|
9121
|
+
resp = await sparkClient.claim_transfer_sign_refunds_v2({
|
|
8293
9122
|
transferId: transfer.id,
|
|
8294
9123
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
8295
9124
|
signingJobs
|
|
@@ -8304,7 +9133,7 @@ var TransferService = class extends BaseTransferService {
|
|
|
8304
9133
|
this.config.getCoordinatorAddress()
|
|
8305
9134
|
);
|
|
8306
9135
|
try {
|
|
8307
|
-
return await sparkClient.
|
|
9136
|
+
return await sparkClient.finalize_node_signatures_v2({
|
|
8308
9137
|
intent: 1 /* TRANSFER */,
|
|
8309
9138
|
nodeSignatures
|
|
8310
9139
|
});
|
|
@@ -8343,109 +9172,134 @@ var TransferService = class extends BaseTransferService {
|
|
|
8343
9172
|
throw new Error(`Error querying pending transfers by sender: ${error}`);
|
|
8344
9173
|
}
|
|
8345
9174
|
}
|
|
8346
|
-
async
|
|
8347
|
-
if (nodes.length === 0) {
|
|
8348
|
-
throw Error("no nodes to refresh");
|
|
8349
|
-
}
|
|
9175
|
+
async refreshTimelockNodesInternal(node, parentNode, useTestUnilateralSequence) {
|
|
8350
9176
|
const signingJobs = [];
|
|
8351
|
-
const
|
|
8352
|
-
|
|
8353
|
-
|
|
8354
|
-
|
|
8355
|
-
|
|
8356
|
-
|
|
8357
|
-
|
|
8358
|
-
|
|
8359
|
-
|
|
8360
|
-
|
|
8361
|
-
|
|
8362
|
-
|
|
8363
|
-
|
|
8364
|
-
|
|
8365
|
-
|
|
8366
|
-
|
|
8367
|
-
|
|
8368
|
-
|
|
8369
|
-
|
|
8370
|
-
|
|
8371
|
-
|
|
8372
|
-
|
|
8373
|
-
|
|
8374
|
-
|
|
8375
|
-
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
|
|
8379
|
-
|
|
8380
|
-
|
|
8381
|
-
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
|
|
8388
|
-
|
|
8389
|
-
|
|
9177
|
+
const parentNodeTx = getTxFromRawTxBytes(parentNode.nodeTx);
|
|
9178
|
+
const parentNodeOutput = parentNodeTx.getOutput(0);
|
|
9179
|
+
if (!parentNodeOutput) {
|
|
9180
|
+
throw Error("Could not get parent node output");
|
|
9181
|
+
}
|
|
9182
|
+
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
9183
|
+
const nodeInput = nodeTx.getInput(0);
|
|
9184
|
+
const nodeOutput = nodeTx.getOutput(0);
|
|
9185
|
+
if (!nodeOutput) {
|
|
9186
|
+
throw Error("Could not get node output");
|
|
9187
|
+
}
|
|
9188
|
+
let directNodeTx;
|
|
9189
|
+
let directNodeInput;
|
|
9190
|
+
if (node.directTx.length > 0) {
|
|
9191
|
+
directNodeTx = getTxFromRawTxBytes(node.directTx);
|
|
9192
|
+
directNodeInput = directNodeTx.getInput(0);
|
|
9193
|
+
}
|
|
9194
|
+
const currSequence = nodeInput.sequence;
|
|
9195
|
+
if (!currSequence) {
|
|
9196
|
+
throw new ValidationError("Invalid node transaction", {
|
|
9197
|
+
field: "sequence",
|
|
9198
|
+
value: nodeInput,
|
|
9199
|
+
expected: "Non-null sequence"
|
|
9200
|
+
});
|
|
9201
|
+
}
|
|
9202
|
+
let { nextSequence, nextDirectSequence } = getNextTransactionSequence(
|
|
9203
|
+
currSequence,
|
|
9204
|
+
true
|
|
9205
|
+
);
|
|
9206
|
+
const output = {
|
|
9207
|
+
script: parentNodeOutput.script,
|
|
9208
|
+
amount: parentNodeOutput.amount
|
|
9209
|
+
};
|
|
9210
|
+
const newNodeInput = {
|
|
9211
|
+
txid: nodeInput.txid,
|
|
9212
|
+
index: nodeInput.index,
|
|
9213
|
+
sequence: useTestUnilateralSequence ? TEST_UNILATERAL_SEQUENCE : nextSequence
|
|
9214
|
+
};
|
|
9215
|
+
const newDirectInput = directNodeTx && directNodeInput ? {
|
|
9216
|
+
txid: directNodeInput.txid,
|
|
9217
|
+
index: directNodeInput.index,
|
|
9218
|
+
sequence: useTestUnilateralSequence ? TEST_UNILATERAL_DIRECT_SEQUENCE : nextDirectSequence
|
|
9219
|
+
} : void 0;
|
|
9220
|
+
const { cpfpNodeTx, directNodeTx: newDirectNodeTx } = createNodeTxs(
|
|
9221
|
+
output,
|
|
9222
|
+
newNodeInput,
|
|
9223
|
+
newDirectInput
|
|
9224
|
+
);
|
|
9225
|
+
const newCpfpNodeOutput = cpfpNodeTx.getOutput(0);
|
|
9226
|
+
if (!newCpfpNodeOutput) {
|
|
9227
|
+
throw Error("Could not get new cpfp node output");
|
|
9228
|
+
}
|
|
9229
|
+
const newDirectNodeOutput = newDirectNodeTx?.getOutput(0);
|
|
9230
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation({
|
|
9231
|
+
type: "leaf" /* LEAF */,
|
|
9232
|
+
path: node.id
|
|
9233
|
+
});
|
|
9234
|
+
signingJobs.push({
|
|
9235
|
+
signingPublicKey,
|
|
9236
|
+
rawTx: cpfpNodeTx.toBytes(),
|
|
9237
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9238
|
+
type: "node",
|
|
9239
|
+
parentTxOut: parentNodeOutput
|
|
9240
|
+
});
|
|
9241
|
+
if (newDirectNodeTx) {
|
|
8390
9242
|
signingJobs.push({
|
|
8391
|
-
signingPublicKey
|
|
8392
|
-
|
|
8393
|
-
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
9243
|
+
signingPublicKey,
|
|
9244
|
+
rawTx: newDirectNodeTx.toBytes(),
|
|
9245
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9246
|
+
type: "directNode",
|
|
9247
|
+
parentTxOut: parentNodeOutput
|
|
8397
9248
|
});
|
|
8398
|
-
newNodeTxs[i] = newTx;
|
|
8399
9249
|
}
|
|
8400
|
-
const
|
|
8401
|
-
|
|
8402
|
-
|
|
9250
|
+
const newCpfpRefundOutPoint = {
|
|
9251
|
+
txid: hexToBytes8(getTxId(cpfpNodeTx)),
|
|
9252
|
+
index: 0
|
|
9253
|
+
};
|
|
9254
|
+
let newDirectRefundOutPoint;
|
|
9255
|
+
if (newDirectNodeTx) {
|
|
9256
|
+
newDirectRefundOutPoint = {
|
|
9257
|
+
txid: hexToBytes8(getTxId(newDirectNodeTx)),
|
|
9258
|
+
index: 0
|
|
9259
|
+
};
|
|
8403
9260
|
}
|
|
8404
|
-
const
|
|
8405
|
-
|
|
8406
|
-
|
|
8407
|
-
|
|
9261
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
9262
|
+
sequence: INITIAL_SEQUENCE,
|
|
9263
|
+
directSequence: INITIAL_DIRECT_SEQUENCE,
|
|
9264
|
+
input: newCpfpRefundOutPoint,
|
|
9265
|
+
directInput: newDirectRefundOutPoint,
|
|
9266
|
+
amountSats: nodeOutput.amount,
|
|
9267
|
+
receivingPubkey: await this.config.signer.getPublicKeyFromDerivation({
|
|
9268
|
+
type: "leaf" /* LEAF */,
|
|
9269
|
+
path: node.id
|
|
9270
|
+
}),
|
|
9271
|
+
network: this.config.getNetwork()
|
|
8408
9272
|
});
|
|
8409
|
-
|
|
8410
|
-
|
|
8411
|
-
|
|
8412
|
-
|
|
8413
|
-
|
|
8414
|
-
|
|
8415
|
-
amount: originalRefundOutput.amount
|
|
9273
|
+
signingJobs.push({
|
|
9274
|
+
signingPublicKey,
|
|
9275
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
9276
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9277
|
+
type: "cpfp",
|
|
9278
|
+
parentTxOut: newCpfpNodeOutput
|
|
8416
9279
|
});
|
|
8417
|
-
|
|
8418
|
-
|
|
8419
|
-
|
|
8420
|
-
|
|
8421
|
-
|
|
8422
|
-
|
|
8423
|
-
|
|
8424
|
-
|
|
8425
|
-
throw Error("refund tx doesn't have input");
|
|
9280
|
+
if (directRefundTx && newDirectNodeOutput) {
|
|
9281
|
+
signingJobs.push({
|
|
9282
|
+
signingPublicKey,
|
|
9283
|
+
rawTx: directRefundTx.toBytes(),
|
|
9284
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9285
|
+
type: "direct",
|
|
9286
|
+
parentTxOut: newDirectNodeOutput
|
|
9287
|
+
});
|
|
8426
9288
|
}
|
|
8427
|
-
if (
|
|
8428
|
-
|
|
9289
|
+
if (directFromCpfpRefundTx && newCpfpNodeOutput) {
|
|
9290
|
+
signingJobs.push({
|
|
9291
|
+
signingPublicKey,
|
|
9292
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
9293
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9294
|
+
type: "directFromCpfp",
|
|
9295
|
+
parentTxOut: newCpfpNodeOutput
|
|
9296
|
+
});
|
|
8429
9297
|
}
|
|
8430
|
-
newRefundTx.addInput({
|
|
8431
|
-
...refundTxInput,
|
|
8432
|
-
sequence: initialSequence(),
|
|
8433
|
-
txid: getTxId(newNodeTxs[newNodeTxs.length - 1])
|
|
8434
|
-
});
|
|
8435
|
-
const refundSigningJob = {
|
|
8436
|
-
signingPublicKey: await this.config.signer.getPublicKeyFromDerivation({
|
|
8437
|
-
type: "leaf" /* LEAF */,
|
|
8438
|
-
path: leaf.id
|
|
8439
|
-
}),
|
|
8440
|
-
rawTx: newRefundTx.toBytes(),
|
|
8441
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
8442
|
-
};
|
|
8443
|
-
signingJobs.push(refundSigningJob);
|
|
8444
9298
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
8445
9299
|
this.config.getCoordinatorAddress()
|
|
8446
9300
|
);
|
|
8447
|
-
const response = await sparkClient.
|
|
8448
|
-
leafId:
|
|
9301
|
+
const response = await sparkClient.refresh_timelock_v2({
|
|
9302
|
+
leafId: node.id,
|
|
8449
9303
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
8450
9304
|
signingJobs: signingJobs.map(getSigningJobProto)
|
|
8451
9305
|
});
|
|
@@ -8455,45 +9309,27 @@ var TransferService = class extends BaseTransferService {
|
|
|
8455
9309
|
);
|
|
8456
9310
|
}
|
|
8457
9311
|
let nodeSignatures = [];
|
|
8458
|
-
let
|
|
8459
|
-
let
|
|
8460
|
-
let
|
|
8461
|
-
|
|
8462
|
-
|
|
9312
|
+
let leafCpfpSignature;
|
|
9313
|
+
let leafDirectSignature;
|
|
9314
|
+
let cpfpRefundSignature;
|
|
9315
|
+
let directRefundSignature;
|
|
9316
|
+
let directFromCpfpRefundSignature;
|
|
9317
|
+
for (const [i, signingResult] of response.signingResults.entries()) {
|
|
8463
9318
|
const signingJob = signingJobs[i];
|
|
8464
9319
|
if (!signingJob || !signingResult) {
|
|
8465
9320
|
throw Error("Signing job does not exist");
|
|
8466
9321
|
}
|
|
8467
|
-
if (!signingJob.signingNonceCommitment) {
|
|
8468
|
-
throw Error("nonce commitment does not exist");
|
|
8469
|
-
}
|
|
8470
9322
|
const rawTx = getTxFromRawTxBytes(signingJob.rawTx);
|
|
8471
|
-
|
|
8472
|
-
|
|
8473
|
-
|
|
8474
|
-
if (i === nodes.length) {
|
|
8475
|
-
nodeId = nodes[i - 1]?.id;
|
|
8476
|
-
parentTx = newNodeTxs[i - 1];
|
|
8477
|
-
vout = 0;
|
|
8478
|
-
} else if (i === 0) {
|
|
8479
|
-
nodeId = nodes[i]?.id;
|
|
8480
|
-
parentTx = getTxFromRawTxBytes(parentNode.nodeTx);
|
|
8481
|
-
vout = nodes[i]?.vout;
|
|
8482
|
-
} else {
|
|
8483
|
-
nodeId = nodes[i]?.id;
|
|
8484
|
-
parentTx = newNodeTxs[i - 1];
|
|
8485
|
-
vout = nodes[i]?.vout;
|
|
9323
|
+
const txOut = signingJob.parentTxOut;
|
|
9324
|
+
if (!txOut) {
|
|
9325
|
+
throw Error("Could not get tx out");
|
|
8486
9326
|
}
|
|
8487
|
-
if (!parentTx || !nodeId || vout === void 0) {
|
|
8488
|
-
throw Error("Could not parse signing results");
|
|
8489
|
-
}
|
|
8490
|
-
const txOut = parentTx.getOutput(vout);
|
|
8491
9327
|
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
8492
9328
|
const userSignature = await this.config.signer.signFrost({
|
|
8493
9329
|
message: rawTxSighash,
|
|
8494
9330
|
keyDerivation: {
|
|
8495
9331
|
type: "leaf" /* LEAF */,
|
|
8496
|
-
path:
|
|
9332
|
+
path: node.id
|
|
8497
9333
|
},
|
|
8498
9334
|
publicKey: signingJob.signingPublicKey,
|
|
8499
9335
|
verifyingKey: signingResult.verifyingKey,
|
|
@@ -8512,41 +9348,35 @@ var TransferService = class extends BaseTransferService {
|
|
|
8512
9348
|
selfSignature: userSignature,
|
|
8513
9349
|
adaptorPubKey: new Uint8Array()
|
|
8514
9350
|
});
|
|
8515
|
-
if (
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
|
|
8522
|
-
|
|
8523
|
-
|
|
8524
|
-
|
|
8525
|
-
} else if (i === nodes.length) {
|
|
8526
|
-
refundSignature = signature;
|
|
8527
|
-
} else if (i === nodes.length - 1) {
|
|
8528
|
-
leafNodeId = nodeId;
|
|
8529
|
-
leafSignature = signature;
|
|
9351
|
+
if (signingJob.type === "node") {
|
|
9352
|
+
leafCpfpSignature = signature;
|
|
9353
|
+
} else if (signingJob.type === "directNode") {
|
|
9354
|
+
leafDirectSignature = signature;
|
|
9355
|
+
} else if (signingJob.type === "cpfp") {
|
|
9356
|
+
cpfpRefundSignature = signature;
|
|
9357
|
+
} else if (signingJob.type === "direct") {
|
|
9358
|
+
directRefundSignature = signature;
|
|
9359
|
+
} else if (signingJob.type === "directFromCpfp") {
|
|
9360
|
+
directFromCpfpRefundSignature = signature;
|
|
8530
9361
|
}
|
|
8531
9362
|
}
|
|
8532
|
-
if (!leafSignature || !refundSignature || !leafNodeId) {
|
|
8533
|
-
throw Error("leaf or refund signature does not exist");
|
|
8534
|
-
}
|
|
8535
9363
|
nodeSignatures.push({
|
|
8536
|
-
nodeId:
|
|
8537
|
-
nodeTxSignature:
|
|
8538
|
-
|
|
8539
|
-
|
|
8540
|
-
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8544
|
-
const result = await sparkClient.finalize_node_signatures({
|
|
9364
|
+
nodeId: node.id,
|
|
9365
|
+
nodeTxSignature: leafCpfpSignature || new Uint8Array(),
|
|
9366
|
+
directNodeTxSignature: leafDirectSignature || new Uint8Array(),
|
|
9367
|
+
refundTxSignature: cpfpRefundSignature || new Uint8Array(),
|
|
9368
|
+
directRefundTxSignature: directRefundSignature || new Uint8Array(),
|
|
9369
|
+
directFromCpfpRefundTxSignature: directFromCpfpRefundSignature || new Uint8Array()
|
|
9370
|
+
});
|
|
9371
|
+
const result = await sparkClient.finalize_node_signatures_v2({
|
|
8545
9372
|
intent: 3 /* REFRESH */,
|
|
8546
9373
|
nodeSignatures
|
|
8547
9374
|
});
|
|
8548
9375
|
return result;
|
|
8549
9376
|
}
|
|
9377
|
+
async refreshTimelockNodes(node, parentNode) {
|
|
9378
|
+
return await this.refreshTimelockNodesInternal(node, parentNode);
|
|
9379
|
+
}
|
|
8550
9380
|
async extendTimelock(node) {
|
|
8551
9381
|
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
8552
9382
|
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
@@ -8555,7 +9385,10 @@ var TransferService = class extends BaseTransferService {
|
|
|
8555
9385
|
txid: hexToBytes8(getTxId(nodeTx)),
|
|
8556
9386
|
index: 0
|
|
8557
9387
|
};
|
|
8558
|
-
const {
|
|
9388
|
+
const {
|
|
9389
|
+
nextSequence: newNodeSequence,
|
|
9390
|
+
nextDirectSequence: newDirectNodeSequence
|
|
9391
|
+
} = getNextTransactionSequence(refundSequence);
|
|
8559
9392
|
const newNodeTx = new Transaction5({
|
|
8560
9393
|
version: 3,
|
|
8561
9394
|
allowUnknownOutputs: true
|
|
@@ -8568,81 +9401,122 @@ var TransferService = class extends BaseTransferService {
|
|
|
8568
9401
|
newNodeTx.addOutput({
|
|
8569
9402
|
script: originalOutput.script,
|
|
8570
9403
|
amount: originalOutput.amount
|
|
8571
|
-
// feeReducedAmount,
|
|
8572
9404
|
});
|
|
8573
9405
|
newNodeTx.addOutput(getEphemeralAnchorOutput());
|
|
8574
|
-
|
|
9406
|
+
let newDirectNodeTx;
|
|
9407
|
+
if (node.directTx.length > 0) {
|
|
9408
|
+
newDirectNodeTx = new Transaction5({
|
|
9409
|
+
version: 3,
|
|
9410
|
+
allowUnknownOutputs: true
|
|
9411
|
+
});
|
|
9412
|
+
newDirectNodeTx.addInput({
|
|
9413
|
+
...newNodeOutPoint,
|
|
9414
|
+
sequence: newDirectNodeSequence
|
|
9415
|
+
});
|
|
9416
|
+
newDirectNodeTx.addOutput({
|
|
9417
|
+
script: originalOutput.script,
|
|
9418
|
+
amount: maybeApplyFee(originalOutput.amount)
|
|
9419
|
+
});
|
|
9420
|
+
}
|
|
9421
|
+
const newCpfpRefundOutPoint = {
|
|
8575
9422
|
txid: hexToBytes8(getTxId(newNodeTx)),
|
|
8576
9423
|
index: 0
|
|
8577
9424
|
};
|
|
9425
|
+
let newDirectRefundOutPoint;
|
|
9426
|
+
if (newDirectNodeTx) {
|
|
9427
|
+
newDirectRefundOutPoint = {
|
|
9428
|
+
txid: hexToBytes8(getTxId(newDirectNodeTx)),
|
|
9429
|
+
index: 0
|
|
9430
|
+
};
|
|
9431
|
+
}
|
|
8578
9432
|
const amountSats = refundTx.getOutput(0).amount;
|
|
8579
9433
|
if (amountSats === void 0) {
|
|
8580
9434
|
throw new Error("Amount not found in extendTimelock");
|
|
8581
9435
|
}
|
|
8582
|
-
const
|
|
9436
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation({
|
|
8583
9437
|
type: "leaf" /* LEAF */,
|
|
8584
9438
|
path: node.id
|
|
8585
9439
|
});
|
|
8586
|
-
const
|
|
8587
|
-
|
|
8588
|
-
|
|
9440
|
+
const {
|
|
9441
|
+
cpfpRefundTx: newCpfpRefundTx,
|
|
9442
|
+
directRefundTx: newDirectRefundTx,
|
|
9443
|
+
directFromCpfpRefundTx: newDirectFromCpfpRefundTx
|
|
9444
|
+
} = createRefundTxs({
|
|
9445
|
+
sequence: INITIAL_SEQUENCE,
|
|
9446
|
+
directSequence: INITIAL_DIRECT_SEQUENCE,
|
|
9447
|
+
input: newCpfpRefundOutPoint,
|
|
9448
|
+
directInput: newDirectRefundOutPoint,
|
|
8589
9449
|
amountSats,
|
|
8590
|
-
|
|
8591
|
-
|
|
8592
|
-
|
|
8593
|
-
)
|
|
9450
|
+
receivingPubkey: signingPublicKey,
|
|
9451
|
+
network: this.config.getNetwork()
|
|
9452
|
+
});
|
|
9453
|
+
if (!newCpfpRefundTx) {
|
|
9454
|
+
throw new ValidationError(
|
|
9455
|
+
"Failed to create refund transactions in extendTimelock"
|
|
9456
|
+
);
|
|
9457
|
+
}
|
|
8594
9458
|
const nodeSighash = getSigHashFromTx(newNodeTx, 0, nodeTx.getOutput(0));
|
|
8595
|
-
const
|
|
8596
|
-
|
|
9459
|
+
const directNodeSighash = newDirectNodeTx ? getSigHashFromTx(newDirectNodeTx, 0, nodeTx.getOutput(0)) : void 0;
|
|
9460
|
+
const cpfpRefundSighash = getSigHashFromTx(
|
|
9461
|
+
newCpfpRefundTx,
|
|
8597
9462
|
0,
|
|
8598
9463
|
newNodeTx.getOutput(0)
|
|
8599
9464
|
);
|
|
9465
|
+
const directRefundSighash = newDirectNodeTx && newDirectRefundTx ? getSigHashFromTx(newDirectRefundTx, 0, newDirectNodeTx.getOutput(0)) : void 0;
|
|
9466
|
+
const directFromCpfpRefundSighash = newDirectFromCpfpRefundTx ? getSigHashFromTx(newDirectFromCpfpRefundTx, 0, newNodeTx.getOutput(0)) : void 0;
|
|
8600
9467
|
const newNodeSigningJob = {
|
|
8601
|
-
signingPublicKey
|
|
9468
|
+
signingPublicKey,
|
|
8602
9469
|
rawTx: newNodeTx.toBytes(),
|
|
8603
9470
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
8604
9471
|
};
|
|
8605
|
-
const
|
|
8606
|
-
signingPublicKey
|
|
8607
|
-
rawTx:
|
|
9472
|
+
const newDirectNodeSigningJob = newDirectNodeTx ? {
|
|
9473
|
+
signingPublicKey,
|
|
9474
|
+
rawTx: newDirectNodeTx.toBytes(),
|
|
9475
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
9476
|
+
} : void 0;
|
|
9477
|
+
const newCpfpRefundSigningJob = {
|
|
9478
|
+
signingPublicKey,
|
|
9479
|
+
rawTx: newCpfpRefundTx.toBytes(),
|
|
8608
9480
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
8609
9481
|
};
|
|
9482
|
+
const newDirectRefundSigningJob = newDirectRefundTx ? {
|
|
9483
|
+
signingPublicKey,
|
|
9484
|
+
rawTx: newDirectRefundTx.toBytes(),
|
|
9485
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
9486
|
+
} : void 0;
|
|
9487
|
+
const newDirectFromCpfpRefundSigningJob = newDirectFromCpfpRefundTx ? {
|
|
9488
|
+
signingPublicKey,
|
|
9489
|
+
rawTx: newDirectFromCpfpRefundTx.toBytes(),
|
|
9490
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
9491
|
+
} : void 0;
|
|
8610
9492
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
8611
9493
|
this.config.getCoordinatorAddress()
|
|
8612
9494
|
);
|
|
8613
|
-
const response = await sparkClient.
|
|
9495
|
+
const response = await sparkClient.extend_leaf_v2({
|
|
8614
9496
|
leafId: node.id,
|
|
8615
9497
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
8616
9498
|
nodeTxSigningJob: getSigningJobProto(newNodeSigningJob),
|
|
8617
|
-
|
|
9499
|
+
directNodeTxSigningJob: newDirectNodeSigningJob ? getSigningJobProto(newDirectNodeSigningJob) : void 0,
|
|
9500
|
+
refundTxSigningJob: getSigningJobProto(newCpfpRefundSigningJob),
|
|
9501
|
+
directRefundTxSigningJob: newDirectRefundSigningJob ? getSigningJobProto(newDirectRefundSigningJob) : void 0,
|
|
9502
|
+
directFromCpfpRefundTxSigningJob: newDirectFromCpfpRefundSigningJob ? getSigningJobProto(newDirectFromCpfpRefundSigningJob) : void 0
|
|
8618
9503
|
});
|
|
8619
9504
|
if (!response.nodeTxSigningResult || !response.refundTxSigningResult) {
|
|
8620
9505
|
throw new Error("Signing result does not exist");
|
|
8621
9506
|
}
|
|
9507
|
+
const keyDerivation = {
|
|
9508
|
+
type: "leaf" /* LEAF */,
|
|
9509
|
+
path: node.id
|
|
9510
|
+
};
|
|
8622
9511
|
const nodeUserSig = await this.config.signer.signFrost({
|
|
8623
9512
|
message: nodeSighash,
|
|
8624
|
-
keyDerivation
|
|
8625
|
-
|
|
8626
|
-
path: node.id
|
|
8627
|
-
},
|
|
8628
|
-
publicKey: signingPubKey,
|
|
9513
|
+
keyDerivation,
|
|
9514
|
+
publicKey: signingPublicKey,
|
|
8629
9515
|
verifyingKey: response.nodeTxSigningResult.verifyingKey,
|
|
8630
9516
|
selfCommitment: newNodeSigningJob.signingNonceCommitment,
|
|
8631
9517
|
statechainCommitments: response.nodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
8632
9518
|
adaptorPubKey: new Uint8Array()
|
|
8633
9519
|
});
|
|
8634
|
-
const refundUserSig = await this.config.signer.signFrost({
|
|
8635
|
-
message: refundSighash,
|
|
8636
|
-
keyDerivation: {
|
|
8637
|
-
type: "leaf" /* LEAF */,
|
|
8638
|
-
path: node.id
|
|
8639
|
-
},
|
|
8640
|
-
publicKey: signingPubKey,
|
|
8641
|
-
verifyingKey: response.refundTxSigningResult.verifyingKey,
|
|
8642
|
-
selfCommitment: newRefundSigningJob.signingNonceCommitment,
|
|
8643
|
-
statechainCommitments: response.refundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
8644
|
-
adaptorPubKey: new Uint8Array()
|
|
8645
|
-
});
|
|
8646
9520
|
const nodeSig = await this.config.signer.aggregateFrost({
|
|
8647
9521
|
message: nodeSighash,
|
|
8648
9522
|
statechainSignatures: response.nodeTxSigningResult.signingResult?.signatureShares,
|
|
@@ -8650,122 +9524,253 @@ var TransferService = class extends BaseTransferService {
|
|
|
8650
9524
|
verifyingKey: response.nodeTxSigningResult.verifyingKey,
|
|
8651
9525
|
statechainCommitments: response.nodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
8652
9526
|
selfCommitment: newNodeSigningJob.signingNonceCommitment,
|
|
8653
|
-
publicKey:
|
|
9527
|
+
publicKey: signingPublicKey,
|
|
8654
9528
|
selfSignature: nodeUserSig,
|
|
8655
9529
|
adaptorPubKey: new Uint8Array()
|
|
8656
9530
|
});
|
|
8657
|
-
|
|
8658
|
-
|
|
9531
|
+
let directNodeSig;
|
|
9532
|
+
if (directNodeSighash && newDirectNodeSigningJob && response.directNodeTxSigningResult) {
|
|
9533
|
+
const directNodeUserSig = await this.config.signer.signFrost({
|
|
9534
|
+
message: directNodeSighash,
|
|
9535
|
+
keyDerivation,
|
|
9536
|
+
publicKey: signingPublicKey,
|
|
9537
|
+
verifyingKey: response.directNodeTxSigningResult.verifyingKey,
|
|
9538
|
+
selfCommitment: newDirectNodeSigningJob.signingNonceCommitment,
|
|
9539
|
+
statechainCommitments: response.directNodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9540
|
+
adaptorPubKey: new Uint8Array()
|
|
9541
|
+
});
|
|
9542
|
+
directNodeSig = await this.config.signer.aggregateFrost({
|
|
9543
|
+
message: directNodeSighash,
|
|
9544
|
+
statechainSignatures: response.directNodeTxSigningResult.signingResult?.signatureShares,
|
|
9545
|
+
statechainPublicKeys: response.directNodeTxSigningResult.signingResult?.publicKeys,
|
|
9546
|
+
verifyingKey: response.directNodeTxSigningResult.verifyingKey,
|
|
9547
|
+
statechainCommitments: response.directNodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9548
|
+
selfCommitment: newDirectNodeSigningJob.signingNonceCommitment,
|
|
9549
|
+
publicKey: signingPublicKey,
|
|
9550
|
+
selfSignature: directNodeUserSig,
|
|
9551
|
+
adaptorPubKey: new Uint8Array()
|
|
9552
|
+
});
|
|
9553
|
+
}
|
|
9554
|
+
const cpfpRefundUserSig = await this.config.signer.signFrost({
|
|
9555
|
+
message: cpfpRefundSighash,
|
|
9556
|
+
keyDerivation,
|
|
9557
|
+
publicKey: signingPublicKey,
|
|
9558
|
+
verifyingKey: response.refundTxSigningResult.verifyingKey,
|
|
9559
|
+
selfCommitment: newCpfpRefundSigningJob.signingNonceCommitment,
|
|
9560
|
+
statechainCommitments: response.refundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9561
|
+
adaptorPubKey: new Uint8Array()
|
|
9562
|
+
});
|
|
9563
|
+
const cpfpRefundSig = await this.config.signer.aggregateFrost({
|
|
9564
|
+
message: cpfpRefundSighash,
|
|
8659
9565
|
statechainSignatures: response.refundTxSigningResult.signingResult?.signatureShares,
|
|
8660
9566
|
statechainPublicKeys: response.refundTxSigningResult.signingResult?.publicKeys,
|
|
8661
9567
|
verifyingKey: response.refundTxSigningResult.verifyingKey,
|
|
8662
9568
|
statechainCommitments: response.refundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
8663
|
-
selfCommitment:
|
|
8664
|
-
publicKey:
|
|
8665
|
-
selfSignature:
|
|
9569
|
+
selfCommitment: newCpfpRefundSigningJob.signingNonceCommitment,
|
|
9570
|
+
publicKey: signingPublicKey,
|
|
9571
|
+
selfSignature: cpfpRefundUserSig,
|
|
8666
9572
|
adaptorPubKey: new Uint8Array()
|
|
8667
9573
|
});
|
|
8668
|
-
|
|
9574
|
+
let directRefundSig;
|
|
9575
|
+
if (directRefundSighash && newDirectRefundSigningJob && response.directRefundTxSigningResult) {
|
|
9576
|
+
const directRefundUserSig = await this.config.signer.signFrost({
|
|
9577
|
+
message: directRefundSighash,
|
|
9578
|
+
keyDerivation,
|
|
9579
|
+
publicKey: signingPublicKey,
|
|
9580
|
+
verifyingKey: response.directRefundTxSigningResult.verifyingKey,
|
|
9581
|
+
selfCommitment: newDirectRefundSigningJob.signingNonceCommitment,
|
|
9582
|
+
statechainCommitments: response.directRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9583
|
+
adaptorPubKey: new Uint8Array()
|
|
9584
|
+
});
|
|
9585
|
+
directRefundSig = await this.config.signer.aggregateFrost({
|
|
9586
|
+
message: directRefundSighash,
|
|
9587
|
+
statechainSignatures: response.directRefundTxSigningResult.signingResult?.signatureShares,
|
|
9588
|
+
statechainPublicKeys: response.directRefundTxSigningResult.signingResult?.publicKeys,
|
|
9589
|
+
verifyingKey: response.directRefundTxSigningResult.verifyingKey,
|
|
9590
|
+
statechainCommitments: response.directRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9591
|
+
selfCommitment: newDirectRefundSigningJob.signingNonceCommitment,
|
|
9592
|
+
publicKey: signingPublicKey,
|
|
9593
|
+
selfSignature: directRefundUserSig,
|
|
9594
|
+
adaptorPubKey: new Uint8Array()
|
|
9595
|
+
});
|
|
9596
|
+
}
|
|
9597
|
+
let directFromCpfpRefundSig;
|
|
9598
|
+
if (directFromCpfpRefundSighash && newDirectFromCpfpRefundSigningJob && response.directFromCpfpRefundTxSigningResult) {
|
|
9599
|
+
const directFromCpfpRefundUserSig = await this.config.signer.signFrost({
|
|
9600
|
+
message: directFromCpfpRefundSighash,
|
|
9601
|
+
keyDerivation,
|
|
9602
|
+
publicKey: signingPublicKey,
|
|
9603
|
+
verifyingKey: response.directFromCpfpRefundTxSigningResult.verifyingKey,
|
|
9604
|
+
selfCommitment: newDirectFromCpfpRefundSigningJob.signingNonceCommitment,
|
|
9605
|
+
statechainCommitments: response.directFromCpfpRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9606
|
+
adaptorPubKey: new Uint8Array()
|
|
9607
|
+
});
|
|
9608
|
+
directFromCpfpRefundSig = await this.config.signer.aggregateFrost({
|
|
9609
|
+
message: directFromCpfpRefundSighash,
|
|
9610
|
+
statechainSignatures: response.directFromCpfpRefundTxSigningResult.signingResult?.signatureShares,
|
|
9611
|
+
statechainPublicKeys: response.directFromCpfpRefundTxSigningResult.signingResult?.publicKeys,
|
|
9612
|
+
verifyingKey: response.directFromCpfpRefundTxSigningResult.verifyingKey,
|
|
9613
|
+
statechainCommitments: response.directFromCpfpRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9614
|
+
selfCommitment: newDirectFromCpfpRefundSigningJob.signingNonceCommitment,
|
|
9615
|
+
publicKey: signingPublicKey,
|
|
9616
|
+
selfSignature: directFromCpfpRefundUserSig,
|
|
9617
|
+
adaptorPubKey: new Uint8Array()
|
|
9618
|
+
});
|
|
9619
|
+
}
|
|
9620
|
+
return await sparkClient.finalize_node_signatures_v2({
|
|
8669
9621
|
intent: 4 /* EXTEND */,
|
|
8670
9622
|
nodeSignatures: [
|
|
8671
9623
|
{
|
|
8672
9624
|
nodeId: response.leafId,
|
|
8673
9625
|
nodeTxSignature: nodeSig,
|
|
8674
|
-
|
|
9626
|
+
directNodeTxSignature: directNodeSig,
|
|
9627
|
+
refundTxSignature: cpfpRefundSig,
|
|
9628
|
+
directRefundTxSignature: directRefundSig,
|
|
9629
|
+
directFromCpfpRefundTxSignature: directFromCpfpRefundSig
|
|
8675
9630
|
}
|
|
8676
9631
|
]
|
|
8677
9632
|
});
|
|
8678
9633
|
}
|
|
8679
|
-
async
|
|
9634
|
+
async testonly_expireTimeLockNodeTx(node, parentNode) {
|
|
9635
|
+
return await this.refreshTimelockNodesInternal(node, parentNode, true);
|
|
9636
|
+
}
|
|
9637
|
+
async testonly_expireTimeLockRefundtx(node) {
|
|
8680
9638
|
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
8681
|
-
const
|
|
8682
|
-
const
|
|
8683
|
-
const
|
|
8684
|
-
const
|
|
9639
|
+
const directNodeTx = node.directTx.length > 0 ? getTxFromRawTxBytes(node.directTx) : void 0;
|
|
9640
|
+
const cpfpRefundTx = getTxFromRawTxBytes(node.refundTx);
|
|
9641
|
+
const currSequence = cpfpRefundTx.getInput(0).sequence || 0;
|
|
9642
|
+
const currTimelock = getCurrentTimelock(currSequence);
|
|
9643
|
+
if (currTimelock <= 100) {
|
|
9644
|
+
throw new ValidationError("Cannot expire timelock below 100", {
|
|
9645
|
+
field: "currTimelock",
|
|
9646
|
+
value: currTimelock,
|
|
9647
|
+
expected: "Timelock greater than 100"
|
|
9648
|
+
});
|
|
9649
|
+
}
|
|
9650
|
+
const nextSequence = TEST_UNILATERAL_SEQUENCE;
|
|
9651
|
+
const nextDirectSequence = TEST_UNILATERAL_SEQUENCE + DIRECT_TIMELOCK_OFFSET;
|
|
9652
|
+
const nodeOutput = nodeTx.getOutput(0);
|
|
9653
|
+
if (!nodeOutput) {
|
|
9654
|
+
throw Error("Could not get node output");
|
|
9655
|
+
}
|
|
9656
|
+
const keyDerivation = {
|
|
8685
9657
|
type: "leaf" /* LEAF */,
|
|
8686
9658
|
path: node.id
|
|
8687
|
-
}
|
|
8688
|
-
const
|
|
8689
|
-
|
|
8690
|
-
|
|
8691
|
-
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
9659
|
+
};
|
|
9660
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
9661
|
+
const cpfpRefundOutPoint = {
|
|
9662
|
+
txid: hexToBytes8(getTxId(nodeTx)),
|
|
9663
|
+
index: 0
|
|
9664
|
+
};
|
|
9665
|
+
let directRefundOutPoint;
|
|
9666
|
+
if (directNodeTx) {
|
|
9667
|
+
directRefundOutPoint = {
|
|
9668
|
+
txid: hexToBytes8(getTxId(directNodeTx)),
|
|
9669
|
+
index: 0
|
|
9670
|
+
};
|
|
8695
9671
|
}
|
|
8696
|
-
|
|
8697
|
-
|
|
8698
|
-
|
|
9672
|
+
const {
|
|
9673
|
+
cpfpRefundTx: newCpfpRefundTx,
|
|
9674
|
+
directRefundTx: newDirectRefundTx,
|
|
9675
|
+
directFromCpfpRefundTx: newDirectFromCpfpRefundTx
|
|
9676
|
+
} = createRefundTxs({
|
|
9677
|
+
sequence: nextSequence,
|
|
9678
|
+
directSequence: nextDirectSequence,
|
|
9679
|
+
input: cpfpRefundOutPoint,
|
|
9680
|
+
directInput: directRefundOutPoint,
|
|
9681
|
+
amountSats: nodeOutput.amount,
|
|
9682
|
+
receivingPubkey: signingPublicKey,
|
|
9683
|
+
network: this.config.getNetwork()
|
|
8699
9684
|
});
|
|
8700
|
-
|
|
8701
|
-
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
9685
|
+
const signingJobs = [];
|
|
9686
|
+
signingJobs.push({
|
|
9687
|
+
signingPublicKey,
|
|
9688
|
+
rawTx: newCpfpRefundTx.toBytes(),
|
|
9689
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9690
|
+
type: "cpfp",
|
|
9691
|
+
parentTxOut: nodeOutput
|
|
9692
|
+
});
|
|
9693
|
+
const directNodeTxOut = directNodeTx?.getOutput(0);
|
|
9694
|
+
if (newDirectRefundTx && directNodeTxOut) {
|
|
9695
|
+
signingJobs.push({
|
|
9696
|
+
signingPublicKey,
|
|
9697
|
+
rawTx: newDirectRefundTx.toBytes(),
|
|
9698
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9699
|
+
type: "direct",
|
|
9700
|
+
parentTxOut: directNodeTxOut
|
|
9701
|
+
});
|
|
8705
9702
|
}
|
|
8706
|
-
|
|
8707
|
-
|
|
8708
|
-
|
|
9703
|
+
if (newDirectFromCpfpRefundTx) {
|
|
9704
|
+
signingJobs.push({
|
|
9705
|
+
signingPublicKey,
|
|
9706
|
+
rawTx: newDirectFromCpfpRefundTx.toBytes(),
|
|
9707
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9708
|
+
type: "directFromCpfp",
|
|
9709
|
+
parentTxOut: nodeOutput
|
|
9710
|
+
});
|
|
8709
9711
|
}
|
|
8710
|
-
newRefundTx.addInput({
|
|
8711
|
-
...refundTxInput,
|
|
8712
|
-
sequence: nextSequence
|
|
8713
|
-
});
|
|
8714
|
-
const refundSigningJob = {
|
|
8715
|
-
signingPublicKey: signingPubKey,
|
|
8716
|
-
rawTx: newRefundTx.toBytes(),
|
|
8717
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
8718
|
-
};
|
|
8719
9712
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
8720
9713
|
this.config.getCoordinatorAddress()
|
|
8721
9714
|
);
|
|
8722
|
-
const response = await sparkClient.
|
|
9715
|
+
const response = await sparkClient.refresh_timelock_v2({
|
|
8723
9716
|
leafId: node.id,
|
|
8724
9717
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
8725
|
-
signingJobs:
|
|
9718
|
+
signingJobs: signingJobs.map(getSigningJobProto)
|
|
8726
9719
|
});
|
|
8727
|
-
if (response.signingResults.length !==
|
|
9720
|
+
if (response.signingResults.length !== signingJobs.length) {
|
|
8728
9721
|
throw Error(
|
|
8729
|
-
`Expected
|
|
9722
|
+
`Expected ${signingJobs.length} signing results, got ${response.signingResults.length}`
|
|
8730
9723
|
);
|
|
8731
9724
|
}
|
|
8732
|
-
|
|
8733
|
-
|
|
8734
|
-
|
|
9725
|
+
let cpfpRefundSignature;
|
|
9726
|
+
let directRefundSignature;
|
|
9727
|
+
let directFromCpfpRefundSignature;
|
|
9728
|
+
for (const [i, signingJob] of signingJobs.entries()) {
|
|
9729
|
+
const signingResult = response.signingResults[i];
|
|
9730
|
+
if (!signingResult) {
|
|
9731
|
+
throw Error("Signing result does not exist");
|
|
9732
|
+
}
|
|
9733
|
+
const rawTx = getTxFromRawTxBytes(signingJob.rawTx);
|
|
9734
|
+
const txOut = signingJob.parentTxOut;
|
|
9735
|
+
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
9736
|
+
const userSignature = await this.config.signer.signFrost({
|
|
9737
|
+
message: rawTxSighash,
|
|
9738
|
+
keyDerivation,
|
|
9739
|
+
publicKey: signingPublicKey,
|
|
9740
|
+
verifyingKey: signingResult.verifyingKey,
|
|
9741
|
+
selfCommitment: signingJob.signingNonceCommitment,
|
|
9742
|
+
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
9743
|
+
adaptorPubKey: new Uint8Array()
|
|
9744
|
+
});
|
|
9745
|
+
const signature = await this.config.signer.aggregateFrost({
|
|
9746
|
+
message: rawTxSighash,
|
|
9747
|
+
statechainSignatures: signingResult.signingResult?.signatureShares,
|
|
9748
|
+
statechainPublicKeys: signingResult.signingResult?.publicKeys,
|
|
9749
|
+
verifyingKey: signingResult.verifyingKey,
|
|
9750
|
+
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
9751
|
+
selfCommitment: signingJob.signingNonceCommitment,
|
|
9752
|
+
publicKey: signingPublicKey,
|
|
9753
|
+
selfSignature: userSignature,
|
|
9754
|
+
adaptorPubKey: new Uint8Array()
|
|
9755
|
+
});
|
|
9756
|
+
if (signingJob.type === "cpfp") {
|
|
9757
|
+
cpfpRefundSignature = signature;
|
|
9758
|
+
} else if (signingJob.type === "direct") {
|
|
9759
|
+
directRefundSignature = signature;
|
|
9760
|
+
} else if (signingJob.type === "directFromCpfp") {
|
|
9761
|
+
directFromCpfpRefundSignature = signature;
|
|
9762
|
+
}
|
|
8735
9763
|
}
|
|
8736
|
-
const
|
|
8737
|
-
const txOut = nodeTx.getOutput(0);
|
|
8738
|
-
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
8739
|
-
const userSignature = await this.config.signer.signFrost({
|
|
8740
|
-
message: rawTxSighash,
|
|
8741
|
-
keyDerivation: {
|
|
8742
|
-
type: "leaf" /* LEAF */,
|
|
8743
|
-
path: node.id
|
|
8744
|
-
},
|
|
8745
|
-
publicKey: signingPubKey,
|
|
8746
|
-
verifyingKey: signingResult.verifyingKey,
|
|
8747
|
-
selfCommitment: refundSigningJob.signingNonceCommitment,
|
|
8748
|
-
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
8749
|
-
adaptorPubKey: new Uint8Array()
|
|
8750
|
-
});
|
|
8751
|
-
const signature = await this.config.signer.aggregateFrost({
|
|
8752
|
-
message: rawTxSighash,
|
|
8753
|
-
statechainSignatures: signingResult.signingResult?.signatureShares,
|
|
8754
|
-
statechainPublicKeys: signingResult.signingResult?.publicKeys,
|
|
8755
|
-
verifyingKey: signingResult.verifyingKey,
|
|
8756
|
-
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
8757
|
-
selfCommitment: refundSigningJob.signingNonceCommitment,
|
|
8758
|
-
publicKey: signingPubKey,
|
|
8759
|
-
selfSignature: userSignature,
|
|
8760
|
-
adaptorPubKey: new Uint8Array()
|
|
8761
|
-
});
|
|
8762
|
-
const result = await sparkClient.finalize_node_signatures({
|
|
9764
|
+
const result = await sparkClient.finalize_node_signatures_v2({
|
|
8763
9765
|
intent: 3 /* REFRESH */,
|
|
8764
9766
|
nodeSignatures: [
|
|
8765
9767
|
{
|
|
8766
9768
|
nodeId: node.id,
|
|
8767
9769
|
nodeTxSignature: new Uint8Array(),
|
|
8768
|
-
|
|
9770
|
+
directNodeTxSignature: new Uint8Array(),
|
|
9771
|
+
refundTxSignature: cpfpRefundSignature,
|
|
9772
|
+
directRefundTxSignature: directRefundSignature,
|
|
9773
|
+
directFromCpfpRefundTxSignature: directFromCpfpRefundSignature
|
|
8769
9774
|
}
|
|
8770
9775
|
]
|
|
8771
9776
|
});
|
|
@@ -8784,7 +9789,12 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
8784
9789
|
connectorOutputs,
|
|
8785
9790
|
receiverPubKey
|
|
8786
9791
|
}) {
|
|
8787
|
-
const {
|
|
9792
|
+
const {
|
|
9793
|
+
transfer,
|
|
9794
|
+
signaturesMap,
|
|
9795
|
+
directSignaturesMap,
|
|
9796
|
+
directFromCpfpSignaturesMap
|
|
9797
|
+
} = await this.signCoopExitRefunds(
|
|
8788
9798
|
leaves,
|
|
8789
9799
|
exitTxId,
|
|
8790
9800
|
connectorOutputs,
|
|
@@ -8793,34 +9803,81 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
8793
9803
|
const transferTweak = await this.deliverTransferPackage(
|
|
8794
9804
|
transfer,
|
|
8795
9805
|
leaves,
|
|
8796
|
-
signaturesMap
|
|
9806
|
+
signaturesMap,
|
|
9807
|
+
directSignaturesMap,
|
|
9808
|
+
directFromCpfpSignaturesMap
|
|
8797
9809
|
);
|
|
8798
|
-
return {
|
|
9810
|
+
return {
|
|
9811
|
+
transfer: transferTweak,
|
|
9812
|
+
signaturesMap,
|
|
9813
|
+
directSignaturesMap,
|
|
9814
|
+
directFromCpfpSignaturesMap
|
|
9815
|
+
};
|
|
8799
9816
|
}
|
|
8800
|
-
|
|
8801
|
-
const
|
|
8802
|
-
if (!
|
|
8803
|
-
throw new ValidationError("Invalid node outpoint", {
|
|
8804
|
-
field: "
|
|
8805
|
-
value: { txid:
|
|
9817
|
+
createConnectorRefundTransactions(sequence, directSequence, cpfpNodeOutPoint, directNodeOutPoint, connectorOutput, amountSats, receiverPubKey) {
|
|
9818
|
+
const cpfpRefundTx = new Transaction6();
|
|
9819
|
+
if (!cpfpNodeOutPoint.txid || cpfpNodeOutPoint.index === void 0) {
|
|
9820
|
+
throw new ValidationError("Invalid CPFP node outpoint", {
|
|
9821
|
+
field: "cpfpNodeOutPoint",
|
|
9822
|
+
value: { txid: cpfpNodeOutPoint.txid, index: cpfpNodeOutPoint.index },
|
|
8806
9823
|
expected: "Both txid and index must be defined"
|
|
8807
9824
|
});
|
|
8808
9825
|
}
|
|
8809
|
-
|
|
8810
|
-
txid:
|
|
8811
|
-
index:
|
|
9826
|
+
cpfpRefundTx.addInput({
|
|
9827
|
+
txid: cpfpNodeOutPoint.txid,
|
|
9828
|
+
index: cpfpNodeOutPoint.index,
|
|
8812
9829
|
sequence
|
|
8813
9830
|
});
|
|
8814
|
-
|
|
9831
|
+
cpfpRefundTx.addInput(connectorOutput);
|
|
8815
9832
|
const receiverScript = getP2TRScriptFromPublicKey(
|
|
8816
9833
|
receiverPubKey,
|
|
8817
9834
|
this.config.getNetwork()
|
|
8818
9835
|
);
|
|
8819
|
-
|
|
9836
|
+
cpfpRefundTx.addOutput({
|
|
8820
9837
|
script: receiverScript,
|
|
8821
9838
|
amount: amountSats
|
|
8822
9839
|
});
|
|
8823
|
-
|
|
9840
|
+
let directRefundTx;
|
|
9841
|
+
let directFromCpfpRefundTx;
|
|
9842
|
+
if (directNodeOutPoint) {
|
|
9843
|
+
if (!directNodeOutPoint.txid || directNodeOutPoint.index === void 0) {
|
|
9844
|
+
throw new ValidationError("Invalid direct node outpoint", {
|
|
9845
|
+
field: "directNodeOutPoint",
|
|
9846
|
+
value: {
|
|
9847
|
+
txid: directNodeOutPoint.txid,
|
|
9848
|
+
index: directNodeOutPoint.index
|
|
9849
|
+
},
|
|
9850
|
+
expected: "Both txid and index must be defined"
|
|
9851
|
+
});
|
|
9852
|
+
}
|
|
9853
|
+
directRefundTx = new Transaction6();
|
|
9854
|
+
directRefundTx.addInput({
|
|
9855
|
+
txid: directNodeOutPoint.txid,
|
|
9856
|
+
index: directNodeOutPoint.index,
|
|
9857
|
+
sequence: directSequence
|
|
9858
|
+
});
|
|
9859
|
+
directRefundTx.addInput(connectorOutput);
|
|
9860
|
+
directRefundTx.addOutput({
|
|
9861
|
+
script: receiverScript,
|
|
9862
|
+
amount: maybeApplyFee(amountSats)
|
|
9863
|
+
});
|
|
9864
|
+
directFromCpfpRefundTx = new Transaction6();
|
|
9865
|
+
directFromCpfpRefundTx.addInput({
|
|
9866
|
+
txid: cpfpNodeOutPoint.txid,
|
|
9867
|
+
index: cpfpNodeOutPoint.index,
|
|
9868
|
+
sequence: directSequence
|
|
9869
|
+
});
|
|
9870
|
+
directFromCpfpRefundTx.addInput(connectorOutput);
|
|
9871
|
+
directFromCpfpRefundTx.addOutput({
|
|
9872
|
+
script: receiverScript,
|
|
9873
|
+
amount: maybeApplyFee(amountSats)
|
|
9874
|
+
});
|
|
9875
|
+
}
|
|
9876
|
+
return {
|
|
9877
|
+
cpfpRefundTx,
|
|
9878
|
+
directRefundTx,
|
|
9879
|
+
directFromCpfpRefundTx
|
|
9880
|
+
};
|
|
8824
9881
|
}
|
|
8825
9882
|
async signCoopExitRefunds(leaves, exitTxId, connectorOutputs, receiverPubKey) {
|
|
8826
9883
|
if (leaves.length !== connectorOutputs.length) {
|
|
@@ -8856,39 +9913,67 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
8856
9913
|
});
|
|
8857
9914
|
}
|
|
8858
9915
|
const currentRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
8859
|
-
const
|
|
8860
|
-
|
|
8861
|
-
|
|
8862
|
-
|
|
9916
|
+
const sequence = currentRefundTx.getInput(0).sequence;
|
|
9917
|
+
if (!sequence) {
|
|
9918
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
9919
|
+
field: "sequence",
|
|
9920
|
+
value: currentRefundTx.getInput(0),
|
|
9921
|
+
expected: "Non-null sequence"
|
|
9922
|
+
});
|
|
9923
|
+
}
|
|
9924
|
+
const { nextSequence, nextDirectSequence } = getNextTransactionSequence(sequence);
|
|
9925
|
+
let currentDirectRefundTx;
|
|
9926
|
+
if (leaf.leaf.directRefundTx.length > 0) {
|
|
9927
|
+
currentDirectRefundTx = getTxFromRawTxBytes(leaf.leaf.directRefundTx);
|
|
9928
|
+
}
|
|
9929
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = this.createConnectorRefundTransactions(
|
|
8863
9930
|
nextSequence,
|
|
9931
|
+
nextDirectSequence,
|
|
8864
9932
|
currentRefundTx.getInput(0),
|
|
9933
|
+
currentDirectRefundTx?.getInput(0),
|
|
8865
9934
|
connectorOutput,
|
|
8866
9935
|
BigInt(leaf.leaf.value),
|
|
8867
9936
|
receiverPubKey
|
|
8868
9937
|
);
|
|
8869
9938
|
const signingNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
9939
|
+
const directSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
9940
|
+
const directFromCpfpSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
9941
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(leaf.keyDerivation);
|
|
8870
9942
|
const signingJob = {
|
|
8871
9943
|
leafId: leaf.leaf.id,
|
|
8872
9944
|
refundTxSigningJob: {
|
|
8873
9945
|
signingPublicKey: await this.config.signer.getPublicKeyFromDerivation(
|
|
8874
9946
|
leaf.keyDerivation
|
|
8875
9947
|
),
|
|
8876
|
-
rawTx:
|
|
9948
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
8877
9949
|
signingNonceCommitment: signingNonceCommitment.commitment
|
|
8878
9950
|
},
|
|
8879
|
-
|
|
8880
|
-
|
|
8881
|
-
|
|
9951
|
+
directRefundTxSigningJob: directRefundTx ? {
|
|
9952
|
+
signingPublicKey,
|
|
9953
|
+
rawTx: directRefundTx.toBytes(),
|
|
9954
|
+
signingNonceCommitment: directSigningNonceCommitment.commitment
|
|
9955
|
+
} : void 0,
|
|
9956
|
+
directFromCpfpRefundTxSigningJob: directFromCpfpRefundTx ? {
|
|
9957
|
+
signingPublicKey,
|
|
9958
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
9959
|
+
signingNonceCommitment: directFromCpfpSigningNonceCommitment.commitment
|
|
9960
|
+
} : void 0
|
|
8882
9961
|
};
|
|
8883
9962
|
signingJobs.push(signingJob);
|
|
8884
9963
|
const tx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
9964
|
+
const directTx = leaf.leaf.directTx.length > 0 ? getTxFromRawTxBytes(leaf.leaf.directTx) : void 0;
|
|
8885
9965
|
leafDataMap.set(leaf.leaf.id, {
|
|
8886
9966
|
keyDerivation: leaf.keyDerivation,
|
|
8887
|
-
|
|
9967
|
+
receivingPubkey: receiverPubKey,
|
|
8888
9968
|
signingNonceCommitment,
|
|
9969
|
+
directSigningNonceCommitment,
|
|
8889
9970
|
tx,
|
|
8890
|
-
|
|
8891
|
-
|
|
9971
|
+
directTx,
|
|
9972
|
+
refundTx: cpfpRefundTx,
|
|
9973
|
+
directRefundTx,
|
|
9974
|
+
directFromCpfpRefundTx,
|
|
9975
|
+
directFromCpfpRefundSigningNonceCommitment: directFromCpfpSigningNonceCommitment,
|
|
9976
|
+
vout: leaf.leaf.vout
|
|
8892
9977
|
});
|
|
8893
9978
|
}
|
|
8894
9979
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
@@ -8896,7 +9981,7 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
8896
9981
|
);
|
|
8897
9982
|
let response;
|
|
8898
9983
|
try {
|
|
8899
|
-
response = await sparkClient.
|
|
9984
|
+
response = await sparkClient.cooperative_exit_v2({
|
|
8900
9985
|
transfer: {
|
|
8901
9986
|
transferId: uuidv73(),
|
|
8902
9987
|
leavesToSend: signingJobs,
|
|
@@ -8930,10 +10015,25 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
8930
10015
|
response.signingResults
|
|
8931
10016
|
);
|
|
8932
10017
|
const signaturesMap = /* @__PURE__ */ new Map();
|
|
10018
|
+
const directSignaturesMap = /* @__PURE__ */ new Map();
|
|
10019
|
+
const directFromCpfpSignaturesMap = /* @__PURE__ */ new Map();
|
|
8933
10020
|
for (const signature of signatures) {
|
|
8934
10021
|
signaturesMap.set(signature.nodeId, signature.refundTxSignature);
|
|
10022
|
+
directSignaturesMap.set(
|
|
10023
|
+
signature.nodeId,
|
|
10024
|
+
signature.directRefundTxSignature
|
|
10025
|
+
);
|
|
10026
|
+
directFromCpfpSignaturesMap.set(
|
|
10027
|
+
signature.nodeId,
|
|
10028
|
+
signature.directFromCpfpRefundTxSignature
|
|
10029
|
+
);
|
|
8935
10030
|
}
|
|
8936
|
-
return {
|
|
10031
|
+
return {
|
|
10032
|
+
transfer: response.transfer,
|
|
10033
|
+
signaturesMap,
|
|
10034
|
+
directSignaturesMap,
|
|
10035
|
+
directFromCpfpSignaturesMap
|
|
10036
|
+
};
|
|
8937
10037
|
}
|
|
8938
10038
|
};
|
|
8939
10039
|
|
|
@@ -9130,7 +10230,8 @@ var LightningService = class {
|
|
|
9130
10230
|
let signingCommitments;
|
|
9131
10231
|
try {
|
|
9132
10232
|
signingCommitments = await sparkClient.get_signing_commitments({
|
|
9133
|
-
nodeIds: leaves.map((leaf) => leaf.leaf.id)
|
|
10233
|
+
nodeIds: leaves.map((leaf) => leaf.leaf.id),
|
|
10234
|
+
count: 3
|
|
9134
10235
|
});
|
|
9135
10236
|
} catch (error) {
|
|
9136
10237
|
throw new NetworkError(
|
|
@@ -9143,10 +10244,19 @@ var LightningService = class {
|
|
|
9143
10244
|
error
|
|
9144
10245
|
);
|
|
9145
10246
|
}
|
|
9146
|
-
const
|
|
10247
|
+
const {
|
|
10248
|
+
cpfpLeafSigningJobs,
|
|
10249
|
+
directLeafSigningJobs,
|
|
10250
|
+
directFromCpfpLeafSigningJobs
|
|
10251
|
+
} = await this.signingService.signRefunds(
|
|
9147
10252
|
leaves,
|
|
9148
|
-
|
|
9149
|
-
|
|
10253
|
+
receiverIdentityPubkey,
|
|
10254
|
+
signingCommitments.signingCommitments.slice(0, leaves.length),
|
|
10255
|
+
signingCommitments.signingCommitments.slice(
|
|
10256
|
+
leaves.length,
|
|
10257
|
+
2 * leaves.length
|
|
10258
|
+
),
|
|
10259
|
+
signingCommitments.signingCommitments.slice(2 * leaves.length)
|
|
9150
10260
|
);
|
|
9151
10261
|
const transferId = uuidv74();
|
|
9152
10262
|
let bolt11String = "";
|
|
@@ -9183,7 +10293,7 @@ var LightningService = class {
|
|
|
9183
10293
|
const reason = isInboundPayment ? 1 /* REASON_RECEIVE */ : 0 /* REASON_SEND */;
|
|
9184
10294
|
let response;
|
|
9185
10295
|
try {
|
|
9186
|
-
response = await sparkClient.
|
|
10296
|
+
response = await sparkClient.initiate_preimage_swap_v2({
|
|
9187
10297
|
paymentHash,
|
|
9188
10298
|
invoiceAmount: {
|
|
9189
10299
|
invoiceAmountProof: {
|
|
@@ -9195,7 +10305,9 @@ var LightningService = class {
|
|
|
9195
10305
|
transfer: {
|
|
9196
10306
|
transferId,
|
|
9197
10307
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
9198
|
-
leavesToSend:
|
|
10308
|
+
leavesToSend: cpfpLeafSigningJobs,
|
|
10309
|
+
directLeavesToSend: directLeafSigningJobs,
|
|
10310
|
+
directFromCpfpLeavesToSend: directFromCpfpLeafSigningJobs,
|
|
9199
10311
|
receiverIdentityPublicKey: receiverIdentityPubkey,
|
|
9200
10312
|
expiryTime: new Date(Date.now() + 2 * 60 * 1e3)
|
|
9201
10313
|
},
|
|
@@ -9278,14 +10390,7 @@ var LightningService = class {
|
|
|
9278
10390
|
|
|
9279
10391
|
// src/services/tree-creation.ts
|
|
9280
10392
|
import { hexToBytes as hexToBytes10 } from "@noble/curves/abstract/utils";
|
|
9281
|
-
import { Address as
|
|
9282
|
-
var INITIAL_TIME_LOCK3 = 2e3;
|
|
9283
|
-
function maybeApplyFee2(amount) {
|
|
9284
|
-
if (amount > BigInt(DEFAULT_FEE_SATS)) {
|
|
9285
|
-
return amount - BigInt(DEFAULT_FEE_SATS);
|
|
9286
|
-
}
|
|
9287
|
-
return amount;
|
|
9288
|
-
}
|
|
10393
|
+
import { Address as Address3, OutScript as OutScript3 } from "@scure/btc-signer";
|
|
9289
10394
|
var TreeCreationService = class {
|
|
9290
10395
|
config;
|
|
9291
10396
|
connectionManager;
|
|
@@ -9400,7 +10505,7 @@ var TreeCreationService = class {
|
|
|
9400
10505
|
);
|
|
9401
10506
|
let response;
|
|
9402
10507
|
try {
|
|
9403
|
-
response = await sparkClient.
|
|
10508
|
+
response = await sparkClient.create_tree_v2(request);
|
|
9404
10509
|
} catch (error) {
|
|
9405
10510
|
throw new Error(`Error creating tree: ${error}`);
|
|
9406
10511
|
}
|
|
@@ -9417,7 +10522,7 @@ var TreeCreationService = class {
|
|
|
9417
10522
|
);
|
|
9418
10523
|
let finalizeResp;
|
|
9419
10524
|
try {
|
|
9420
|
-
finalizeResp = await sparkClient.
|
|
10525
|
+
finalizeResp = await sparkClient.finalize_node_signatures_v2({
|
|
9421
10526
|
nodeSignatures
|
|
9422
10527
|
});
|
|
9423
10528
|
} catch (error) {
|
|
@@ -9482,91 +10587,111 @@ var TreeCreationService = class {
|
|
|
9482
10587
|
async buildChildCreationNode(node, parentTx, vout, network) {
|
|
9483
10588
|
const internalCreationNode = {
|
|
9484
10589
|
nodeTxSigningJob: void 0,
|
|
9485
|
-
refundTxSigningJob: void 0,
|
|
9486
|
-
children: [],
|
|
9487
10590
|
directNodeTxSigningJob: void 0,
|
|
10591
|
+
refundTxSigningJob: void 0,
|
|
9488
10592
|
directRefundTxSigningJob: void 0,
|
|
9489
|
-
directFromCpfpRefundTxSigningJob: void 0
|
|
10593
|
+
directFromCpfpRefundTxSigningJob: void 0,
|
|
10594
|
+
children: []
|
|
9490
10595
|
};
|
|
9491
|
-
const tx = new Transaction7({ version: 3 });
|
|
9492
|
-
tx.addInput({
|
|
9493
|
-
txid: getTxId(parentTx),
|
|
9494
|
-
index: vout
|
|
9495
|
-
});
|
|
9496
10596
|
const parentTxOut = parentTx.getOutput(vout);
|
|
9497
10597
|
if (!parentTxOut?.script || !parentTxOut?.amount) {
|
|
9498
10598
|
throw new Error("parentTxOut is undefined");
|
|
9499
10599
|
}
|
|
9500
|
-
|
|
10600
|
+
const parentOutPoint = {
|
|
10601
|
+
txid: hexToBytes10(getTxId(parentTx)),
|
|
10602
|
+
index: vout
|
|
10603
|
+
};
|
|
10604
|
+
const parentTxOutObj = {
|
|
9501
10605
|
script: parentTxOut.script,
|
|
9502
10606
|
amount: parentTxOut.amount
|
|
9503
|
-
|
|
9504
|
-
}
|
|
9505
|
-
|
|
9506
|
-
|
|
9507
|
-
|
|
10607
|
+
};
|
|
10608
|
+
const { cpfpNodeTx, directNodeTx } = createNodeTxs(
|
|
10609
|
+
parentTxOutObj,
|
|
10610
|
+
parentOutPoint
|
|
10611
|
+
);
|
|
10612
|
+
const cpfpNodeSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
10613
|
+
const directNodeSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
10614
|
+
const cpfpNodeSigningJob = {
|
|
9508
10615
|
signingPublicKey: node.signingPublicKey,
|
|
9509
|
-
rawTx:
|
|
9510
|
-
signingNonceCommitment:
|
|
10616
|
+
rawTx: cpfpNodeTx.toBytes(),
|
|
10617
|
+
signingNonceCommitment: cpfpNodeSigningCommitment.commitment
|
|
9511
10618
|
};
|
|
9512
|
-
|
|
9513
|
-
|
|
9514
|
-
|
|
10619
|
+
const directNodeSigningJob = directNodeTx ? {
|
|
10620
|
+
signingPublicKey: node.signingPublicKey,
|
|
10621
|
+
rawTx: directNodeTx.toBytes(),
|
|
10622
|
+
signingNonceCommitment: directNodeSigningCommitment.commitment
|
|
10623
|
+
} : void 0;
|
|
10624
|
+
internalCreationNode.nodeTxSigningCommitment = cpfpNodeSigningCommitment;
|
|
10625
|
+
internalCreationNode.directNodeTxSigningCommitment = directNodeSigningCommitment;
|
|
10626
|
+
internalCreationNode.nodeTxSigningJob = cpfpNodeSigningJob;
|
|
10627
|
+
internalCreationNode.directNodeTxSigningJob = directNodeSigningJob;
|
|
10628
|
+
const sequence = INITIAL_SEQUENCE;
|
|
10629
|
+
const directSequence = INITIAL_DIRECT_SEQUENCE;
|
|
9515
10630
|
const childCreationNode = {
|
|
9516
10631
|
nodeTxSigningJob: void 0,
|
|
9517
|
-
refundTxSigningJob: void 0,
|
|
9518
|
-
children: [],
|
|
9519
10632
|
directNodeTxSigningJob: void 0,
|
|
10633
|
+
refundTxSigningJob: void 0,
|
|
9520
10634
|
directRefundTxSigningJob: void 0,
|
|
9521
|
-
directFromCpfpRefundTxSigningJob: void 0
|
|
10635
|
+
directFromCpfpRefundTxSigningJob: void 0,
|
|
10636
|
+
children: []
|
|
9522
10637
|
};
|
|
9523
|
-
const
|
|
9524
|
-
|
|
9525
|
-
|
|
9526
|
-
index: 0,
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9530
|
-
|
|
9531
|
-
|
|
9532
|
-
|
|
9533
|
-
|
|
9534
|
-
childTx.addOutput(getEphemeralAnchorOutput());
|
|
9535
|
-
const childSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
9536
|
-
const childSigningJob = {
|
|
10638
|
+
const [cpfpLeafTx, directLeafTx] = createLeafNodeTx(
|
|
10639
|
+
sequence,
|
|
10640
|
+
directSequence,
|
|
10641
|
+
{ txid: hexToBytes10(getTxId(cpfpNodeTx)), index: 0 },
|
|
10642
|
+
parentTxOutObj,
|
|
10643
|
+
true
|
|
10644
|
+
// shouldCalculateFee
|
|
10645
|
+
);
|
|
10646
|
+
const cpfpLeafSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
10647
|
+
const directLeafSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
10648
|
+
const cpfpLeafSigningJob = {
|
|
9537
10649
|
signingPublicKey: node.signingPublicKey,
|
|
9538
|
-
rawTx:
|
|
9539
|
-
signingNonceCommitment:
|
|
10650
|
+
rawTx: cpfpLeafTx.toBytes(),
|
|
10651
|
+
signingNonceCommitment: cpfpLeafSigningCommitment.commitment
|
|
9540
10652
|
};
|
|
9541
|
-
|
|
9542
|
-
|
|
9543
|
-
|
|
9544
|
-
|
|
9545
|
-
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
9550
|
-
|
|
10653
|
+
const directLeafSigningJob = {
|
|
10654
|
+
signingPublicKey: node.signingPublicKey,
|
|
10655
|
+
rawTx: directLeafTx.toBytes(),
|
|
10656
|
+
signingNonceCommitment: directLeafSigningCommitment.commitment
|
|
10657
|
+
};
|
|
10658
|
+
childCreationNode.nodeTxSigningCommitment = cpfpLeafSigningCommitment;
|
|
10659
|
+
childCreationNode.directNodeTxSigningCommitment = directLeafSigningCommitment;
|
|
10660
|
+
childCreationNode.nodeTxSigningJob = cpfpLeafSigningJob;
|
|
10661
|
+
childCreationNode.directNodeTxSigningJob = directLeafSigningJob;
|
|
10662
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
10663
|
+
sequence,
|
|
10664
|
+
directSequence,
|
|
10665
|
+
input: { txid: hexToBytes10(getTxId(cpfpLeafTx)), index: 0 },
|
|
10666
|
+
directInput: { txid: hexToBytes10(getTxId(directLeafTx)), index: 0 },
|
|
10667
|
+
amountSats: parentTxOut.amount,
|
|
10668
|
+
receivingPubkey: node.signingPublicKey,
|
|
9551
10669
|
network
|
|
9552
|
-
);
|
|
9553
|
-
const refundAddress = Address4(getNetwork(network)).decode(
|
|
9554
|
-
refundP2trAddress
|
|
9555
|
-
);
|
|
9556
|
-
const refundPkScript = OutScript4.encode(refundAddress);
|
|
9557
|
-
refundTx.addOutput({
|
|
9558
|
-
script: refundPkScript,
|
|
9559
|
-
amount: maybeApplyFee2(parentTxOut.amount)
|
|
9560
10670
|
});
|
|
9561
|
-
|
|
9562
|
-
const
|
|
9563
|
-
const
|
|
10671
|
+
const cpfpRefundSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
10672
|
+
const directRefundSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
10673
|
+
const directFromCpfpRefundSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
10674
|
+
const cpfpRefundSigningJob = {
|
|
9564
10675
|
signingPublicKey: node.signingPublicKey,
|
|
9565
|
-
rawTx:
|
|
9566
|
-
signingNonceCommitment:
|
|
10676
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
10677
|
+
signingNonceCommitment: cpfpRefundSigningCommitment.commitment
|
|
9567
10678
|
};
|
|
9568
|
-
|
|
9569
|
-
|
|
10679
|
+
const directRefundSigningJob = directRefundTx ? {
|
|
10680
|
+
signingPublicKey: node.signingPublicKey,
|
|
10681
|
+
rawTx: directRefundTx.toBytes(),
|
|
10682
|
+
signingNonceCommitment: directRefundSigningCommitment.commitment
|
|
10683
|
+
} : void 0;
|
|
10684
|
+
const directFromCpfpRefundSigningJob = directFromCpfpRefundTx ? {
|
|
10685
|
+
signingPublicKey: node.signingPublicKey,
|
|
10686
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
10687
|
+
signingNonceCommitment: directFromCpfpRefundSigningCommitment.commitment
|
|
10688
|
+
} : void 0;
|
|
10689
|
+
childCreationNode.refundTxSigningCommitment = cpfpRefundSigningCommitment;
|
|
10690
|
+
childCreationNode.directRefundTxSigningCommitment = directRefundSigningCommitment;
|
|
10691
|
+
childCreationNode.directFromCpfpRefundTxSigningCommitment = directFromCpfpRefundSigningCommitment;
|
|
10692
|
+
childCreationNode.refundTxSigningJob = cpfpRefundSigningJob;
|
|
10693
|
+
childCreationNode.directRefundTxSigningJob = directRefundSigningJob;
|
|
10694
|
+
childCreationNode.directFromCpfpRefundTxSigningJob = directFromCpfpRefundSigningJob;
|
|
9570
10695
|
internalCreationNode.children.push(childCreationNode);
|
|
9571
10696
|
return internalCreationNode;
|
|
9572
10697
|
}
|
|
@@ -9575,40 +10700,49 @@ var TreeCreationService = class {
|
|
|
9575
10700
|
if (!parentTxOutput?.script || !parentTxOutput?.amount) {
|
|
9576
10701
|
throw new Error("parentTxOutput is undefined");
|
|
9577
10702
|
}
|
|
9578
|
-
const
|
|
9579
|
-
rootNodeTx.addInput({
|
|
9580
|
-
txid: getTxId(parentTx),
|
|
9581
|
-
index: vout
|
|
9582
|
-
});
|
|
10703
|
+
const childTxOuts = [];
|
|
9583
10704
|
for (let i = 0; i < root.children.length; i++) {
|
|
9584
10705
|
const child = root.children[i];
|
|
9585
10706
|
if (!child || !child.address) {
|
|
9586
10707
|
throw new Error("child address is undefined");
|
|
9587
10708
|
}
|
|
9588
|
-
const childAddress =
|
|
9589
|
-
const childPkScript =
|
|
9590
|
-
|
|
10709
|
+
const childAddress = Address3(getNetwork(network)).decode(child.address);
|
|
10710
|
+
const childPkScript = OutScript3.encode(childAddress);
|
|
10711
|
+
childTxOuts.push({
|
|
9591
10712
|
script: childPkScript,
|
|
9592
10713
|
amount: parentTxOutput.amount / 2n
|
|
9593
|
-
// feeAdjustedAmount / 2n,
|
|
9594
10714
|
});
|
|
9595
10715
|
}
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
10716
|
+
const parentOutPoint = {
|
|
10717
|
+
txid: hexToBytes10(getTxId(parentTx)),
|
|
10718
|
+
index: vout
|
|
10719
|
+
};
|
|
10720
|
+
const [cpfpSplitTx, directSplitTx] = createSplitTx(
|
|
10721
|
+
parentOutPoint,
|
|
10722
|
+
childTxOuts
|
|
10723
|
+
);
|
|
10724
|
+
const cpfpSplitSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
10725
|
+
const directSplitSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
10726
|
+
const cpfpSplitSigningJob = {
|
|
10727
|
+
signingPublicKey: root.signingPublicKey,
|
|
10728
|
+
rawTx: cpfpSplitTx.toBytes(),
|
|
10729
|
+
signingNonceCommitment: cpfpSplitSigningCommitment.commitment
|
|
10730
|
+
};
|
|
10731
|
+
const directSplitSigningJob = {
|
|
9599
10732
|
signingPublicKey: root.signingPublicKey,
|
|
9600
|
-
rawTx:
|
|
9601
|
-
signingNonceCommitment:
|
|
10733
|
+
rawTx: directSplitTx.toBytes(),
|
|
10734
|
+
signingNonceCommitment: directSplitSigningCommitment.commitment
|
|
9602
10735
|
};
|
|
9603
10736
|
const rootCreationNode = {
|
|
9604
|
-
nodeTxSigningJob:
|
|
10737
|
+
nodeTxSigningJob: cpfpSplitSigningJob,
|
|
10738
|
+
directNodeTxSigningJob: directSplitSigningJob,
|
|
9605
10739
|
refundTxSigningJob: void 0,
|
|
9606
|
-
children: [],
|
|
9607
|
-
directNodeTxSigningJob: void 0,
|
|
9608
10740
|
directRefundTxSigningJob: void 0,
|
|
9609
|
-
directFromCpfpRefundTxSigningJob: void 0
|
|
10741
|
+
directFromCpfpRefundTxSigningJob: void 0,
|
|
10742
|
+
children: []
|
|
9610
10743
|
};
|
|
9611
|
-
rootCreationNode.nodeTxSigningCommitment =
|
|
10744
|
+
rootCreationNode.nodeTxSigningCommitment = cpfpSplitSigningCommitment;
|
|
10745
|
+
rootCreationNode.directNodeTxSigningCommitment = directSplitSigningCommitment;
|
|
9612
10746
|
const leftChild = root.children[0];
|
|
9613
10747
|
const rightChild = root.children[1];
|
|
9614
10748
|
if (!leftChild || !rightChild) {
|
|
@@ -9616,13 +10750,15 @@ var TreeCreationService = class {
|
|
|
9616
10750
|
}
|
|
9617
10751
|
const leftChildCreationNode = await this.buildChildCreationNode(
|
|
9618
10752
|
leftChild,
|
|
9619
|
-
|
|
10753
|
+
cpfpSplitTx,
|
|
10754
|
+
// Use CPFP version for children
|
|
9620
10755
|
0,
|
|
9621
10756
|
network
|
|
9622
10757
|
);
|
|
9623
10758
|
const rightChildCreationNode = await this.buildChildCreationNode(
|
|
9624
10759
|
rightChild,
|
|
9625
|
-
|
|
10760
|
+
cpfpSplitTx,
|
|
10761
|
+
// Use CPFP version for children
|
|
9626
10762
|
1,
|
|
9627
10763
|
network
|
|
9628
10764
|
);
|
|
@@ -9631,19 +10767,19 @@ var TreeCreationService = class {
|
|
|
9631
10767
|
return rootCreationNode;
|
|
9632
10768
|
}
|
|
9633
10769
|
async signNodeCreation(parentTx, vout, internalNode, creationNode, creationResponseNode) {
|
|
9634
|
-
if (!creationNode.nodeTxSigningJob?.signingPublicKey || !internalNode.verificationKey) {
|
|
10770
|
+
if (!creationNode.nodeTxSigningJob?.signingPublicKey || !creationNode.directNodeTxSigningJob?.signingPublicKey || !internalNode.verificationKey) {
|
|
9635
10771
|
throw new Error("signingPublicKey or verificationKey is undefined");
|
|
9636
10772
|
}
|
|
9637
10773
|
const parentTxOutput = parentTx.getOutput(vout);
|
|
9638
10774
|
if (!parentTxOutput) {
|
|
9639
10775
|
throw new Error("parentTxOutput is undefined");
|
|
9640
10776
|
}
|
|
9641
|
-
const
|
|
9642
|
-
const
|
|
9643
|
-
let
|
|
10777
|
+
const cpfpNodeTx = getTxFromRawTxBytes(creationNode.nodeTxSigningJob.rawTx);
|
|
10778
|
+
const cpfpNodeTxSighash = getSigHashFromTx(cpfpNodeTx, 0, parentTxOutput);
|
|
10779
|
+
let cpfpNodeTxSignature = new Uint8Array();
|
|
9644
10780
|
if (creationNode.nodeTxSigningCommitment) {
|
|
9645
|
-
const
|
|
9646
|
-
message:
|
|
10781
|
+
const cpfpUserSignature = await this.config.signer.signFrost({
|
|
10782
|
+
message: cpfpNodeTxSighash,
|
|
9647
10783
|
publicKey: creationNode.nodeTxSigningJob.signingPublicKey,
|
|
9648
10784
|
keyDerivation: {
|
|
9649
10785
|
type: "leaf" /* LEAF */,
|
|
@@ -9653,30 +10789,84 @@ var TreeCreationService = class {
|
|
|
9653
10789
|
statechainCommitments: creationResponseNode.nodeTxSigningResult?.signingNonceCommitments,
|
|
9654
10790
|
verifyingKey: internalNode.verificationKey
|
|
9655
10791
|
});
|
|
9656
|
-
|
|
9657
|
-
message:
|
|
10792
|
+
cpfpNodeTxSignature = await this.config.signer.aggregateFrost({
|
|
10793
|
+
message: cpfpNodeTxSighash,
|
|
9658
10794
|
statechainSignatures: creationResponseNode.nodeTxSigningResult?.signatureShares,
|
|
9659
10795
|
statechainPublicKeys: creationResponseNode.nodeTxSigningResult?.publicKeys,
|
|
9660
10796
|
verifyingKey: internalNode.verificationKey,
|
|
9661
10797
|
statechainCommitments: creationResponseNode.nodeTxSigningResult?.signingNonceCommitments,
|
|
9662
10798
|
selfCommitment: creationNode.nodeTxSigningCommitment,
|
|
9663
|
-
selfSignature:
|
|
10799
|
+
selfSignature: cpfpUserSignature,
|
|
10800
|
+
publicKey: internalNode.signingPublicKey
|
|
10801
|
+
});
|
|
10802
|
+
}
|
|
10803
|
+
const directNodeTx = getTxFromRawTxBytes(
|
|
10804
|
+
creationNode.directNodeTxSigningJob.rawTx
|
|
10805
|
+
);
|
|
10806
|
+
const directNodeTxSighash = getSigHashFromTx(
|
|
10807
|
+
directNodeTx,
|
|
10808
|
+
0,
|
|
10809
|
+
parentTxOutput
|
|
10810
|
+
);
|
|
10811
|
+
let directNodeTxSignature = new Uint8Array();
|
|
10812
|
+
if (creationNode.directNodeTxSigningCommitment) {
|
|
10813
|
+
const directUserSignature = await this.config.signer.signFrost({
|
|
10814
|
+
message: directNodeTxSighash,
|
|
10815
|
+
publicKey: creationNode.directNodeTxSigningJob.signingPublicKey,
|
|
10816
|
+
keyDerivation: {
|
|
10817
|
+
type: "leaf" /* LEAF */,
|
|
10818
|
+
path: creationResponseNode.nodeId
|
|
10819
|
+
},
|
|
10820
|
+
selfCommitment: creationNode.directNodeTxSigningCommitment,
|
|
10821
|
+
statechainCommitments: creationResponseNode.directNodeTxSigningResult?.signingNonceCommitments,
|
|
10822
|
+
verifyingKey: internalNode.verificationKey
|
|
10823
|
+
});
|
|
10824
|
+
directNodeTxSignature = await this.config.signer.aggregateFrost({
|
|
10825
|
+
message: directNodeTxSighash,
|
|
10826
|
+
statechainSignatures: creationResponseNode.directNodeTxSigningResult?.signatureShares,
|
|
10827
|
+
statechainPublicKeys: creationResponseNode.directNodeTxSigningResult?.publicKeys,
|
|
10828
|
+
verifyingKey: internalNode.verificationKey,
|
|
10829
|
+
statechainCommitments: creationResponseNode.directNodeTxSigningResult?.signingNonceCommitments,
|
|
10830
|
+
selfCommitment: creationNode.directNodeTxSigningCommitment,
|
|
10831
|
+
selfSignature: directUserSignature,
|
|
9664
10832
|
publicKey: internalNode.signingPublicKey
|
|
9665
10833
|
});
|
|
9666
10834
|
}
|
|
9667
|
-
let
|
|
9668
|
-
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
|
|
10835
|
+
let cpfpRefundTxSignature = new Uint8Array();
|
|
10836
|
+
let directRefundTxSignature = new Uint8Array();
|
|
10837
|
+
let directFromCpfpRefundTxSignature = new Uint8Array();
|
|
10838
|
+
if (creationNode.refundTxSigningCommitment && creationNode.directRefundTxSigningCommitment && creationNode.directFromCpfpRefundTxSigningCommitment) {
|
|
10839
|
+
const rawCpfpRefundTx = creationNode.refundTxSigningJob?.rawTx;
|
|
10840
|
+
const rawDirectRefundTx = creationNode.directRefundTxSigningJob?.rawTx;
|
|
10841
|
+
const rawDirectFromCpfpRefundTx = creationNode.directFromCpfpRefundTxSigningJob?.rawTx;
|
|
10842
|
+
if (!rawCpfpRefundTx || !rawDirectRefundTx || !rawDirectFromCpfpRefundTx) {
|
|
10843
|
+
throw new Error("refund transaction rawTx is undefined");
|
|
9672
10844
|
}
|
|
9673
|
-
if (!creationNode.refundTxSigningJob?.signingPublicKey) {
|
|
9674
|
-
throw new Error("signingPublicKey is undefined");
|
|
10845
|
+
if (!creationNode.refundTxSigningJob?.signingPublicKey || !creationNode.directRefundTxSigningJob?.signingPublicKey || !creationNode.directFromCpfpRefundTxSigningJob?.signingPublicKey) {
|
|
10846
|
+
throw new Error("refund transaction signingPublicKey is undefined");
|
|
9675
10847
|
}
|
|
9676
|
-
const
|
|
9677
|
-
const
|
|
9678
|
-
const
|
|
9679
|
-
|
|
10848
|
+
const cpfpRefundTx = getTxFromRawTxBytes(rawCpfpRefundTx);
|
|
10849
|
+
const directRefundTx = getTxFromRawTxBytes(rawDirectRefundTx);
|
|
10850
|
+
const directFromCpfpRefundTx = getTxFromRawTxBytes(
|
|
10851
|
+
rawDirectFromCpfpRefundTx
|
|
10852
|
+
);
|
|
10853
|
+
const cpfpRefundTxSighash = getSigHashFromTx(
|
|
10854
|
+
cpfpRefundTx,
|
|
10855
|
+
0,
|
|
10856
|
+
cpfpNodeTx.getOutput(0)
|
|
10857
|
+
);
|
|
10858
|
+
const directRefundTxSighash = getSigHashFromTx(
|
|
10859
|
+
directRefundTx,
|
|
10860
|
+
0,
|
|
10861
|
+
directNodeTx.getOutput(0)
|
|
10862
|
+
);
|
|
10863
|
+
const directFromCpfpRefundTxSighash = getSigHashFromTx(
|
|
10864
|
+
directFromCpfpRefundTx,
|
|
10865
|
+
0,
|
|
10866
|
+
cpfpNodeTx.getOutput(0)
|
|
10867
|
+
);
|
|
10868
|
+
const cpfpRefundUserSignature = await this.config.signer.signFrost({
|
|
10869
|
+
message: cpfpRefundTxSighash,
|
|
9680
10870
|
publicKey: creationNode.refundTxSigningJob.signingPublicKey,
|
|
9681
10871
|
keyDerivation: {
|
|
9682
10872
|
type: "leaf" /* LEAF */,
|
|
@@ -9686,27 +10876,69 @@ var TreeCreationService = class {
|
|
|
9686
10876
|
statechainCommitments: creationResponseNode.refundTxSigningResult?.signingNonceCommitments,
|
|
9687
10877
|
verifyingKey: internalNode.verificationKey
|
|
9688
10878
|
});
|
|
9689
|
-
|
|
9690
|
-
message:
|
|
10879
|
+
cpfpRefundTxSignature = await this.config.signer.aggregateFrost({
|
|
10880
|
+
message: cpfpRefundTxSighash,
|
|
9691
10881
|
statechainSignatures: creationResponseNode.refundTxSigningResult?.signatureShares,
|
|
9692
10882
|
statechainPublicKeys: creationResponseNode.refundTxSigningResult?.publicKeys,
|
|
9693
10883
|
verifyingKey: internalNode.verificationKey,
|
|
9694
10884
|
statechainCommitments: creationResponseNode.refundTxSigningResult?.signingNonceCommitments,
|
|
9695
10885
|
selfCommitment: creationNode.refundTxSigningCommitment,
|
|
9696
|
-
selfSignature:
|
|
10886
|
+
selfSignature: cpfpRefundUserSignature,
|
|
10887
|
+
publicKey: internalNode.signingPublicKey
|
|
10888
|
+
});
|
|
10889
|
+
const keyDerivation = {
|
|
10890
|
+
type: "leaf" /* LEAF */,
|
|
10891
|
+
path: creationResponseNode.nodeId
|
|
10892
|
+
};
|
|
10893
|
+
const directRefundUserSignature = await this.config.signer.signFrost({
|
|
10894
|
+
message: directRefundTxSighash,
|
|
10895
|
+
publicKey: creationNode.directRefundTxSigningJob.signingPublicKey,
|
|
10896
|
+
keyDerivation,
|
|
10897
|
+
selfCommitment: creationNode.directRefundTxSigningCommitment,
|
|
10898
|
+
statechainCommitments: creationResponseNode.directRefundTxSigningResult?.signingNonceCommitments,
|
|
10899
|
+
verifyingKey: internalNode.verificationKey
|
|
10900
|
+
});
|
|
10901
|
+
directRefundTxSignature = await this.config.signer.aggregateFrost({
|
|
10902
|
+
message: directRefundTxSighash,
|
|
10903
|
+
statechainSignatures: creationResponseNode.directRefundTxSigningResult?.signatureShares,
|
|
10904
|
+
statechainPublicKeys: creationResponseNode.directRefundTxSigningResult?.publicKeys,
|
|
10905
|
+
verifyingKey: internalNode.verificationKey,
|
|
10906
|
+
statechainCommitments: creationResponseNode.directRefundTxSigningResult?.signingNonceCommitments,
|
|
10907
|
+
selfCommitment: creationNode.directRefundTxSigningCommitment,
|
|
10908
|
+
selfSignature: directRefundUserSignature,
|
|
9697
10909
|
publicKey: internalNode.signingPublicKey
|
|
9698
10910
|
});
|
|
10911
|
+
const directFromCpfpRefundUserSignature = await this.config.signer.signFrost({
|
|
10912
|
+
message: directFromCpfpRefundTxSighash,
|
|
10913
|
+
publicKey: creationNode.directFromCpfpRefundTxSigningJob.signingPublicKey,
|
|
10914
|
+
keyDerivation,
|
|
10915
|
+
selfCommitment: creationNode.directFromCpfpRefundTxSigningCommitment,
|
|
10916
|
+
statechainCommitments: creationResponseNode.directFromCpfpRefundTxSigningResult?.signingNonceCommitments,
|
|
10917
|
+
verifyingKey: internalNode.verificationKey
|
|
10918
|
+
});
|
|
10919
|
+
directFromCpfpRefundTxSignature = await this.config.signer.aggregateFrost(
|
|
10920
|
+
{
|
|
10921
|
+
message: directFromCpfpRefundTxSighash,
|
|
10922
|
+
statechainSignatures: creationResponseNode.directFromCpfpRefundTxSigningResult?.signatureShares,
|
|
10923
|
+
statechainPublicKeys: creationResponseNode.directFromCpfpRefundTxSigningResult?.publicKeys,
|
|
10924
|
+
verifyingKey: internalNode.verificationKey,
|
|
10925
|
+
statechainCommitments: creationResponseNode.directFromCpfpRefundTxSigningResult?.signingNonceCommitments,
|
|
10926
|
+
selfCommitment: creationNode.directFromCpfpRefundTxSigningCommitment,
|
|
10927
|
+
selfSignature: directFromCpfpRefundUserSignature,
|
|
10928
|
+
publicKey: internalNode.signingPublicKey
|
|
10929
|
+
}
|
|
10930
|
+
);
|
|
9699
10931
|
}
|
|
9700
10932
|
return {
|
|
9701
|
-
tx,
|
|
10933
|
+
tx: cpfpNodeTx,
|
|
10934
|
+
// Return CPFP version for children
|
|
9702
10935
|
signature: {
|
|
9703
10936
|
nodeId: creationResponseNode.nodeId,
|
|
9704
|
-
nodeTxSignature,
|
|
9705
|
-
|
|
9706
|
-
|
|
9707
|
-
|
|
9708
|
-
|
|
9709
|
-
directFromCpfpRefundTxSignature: new Uint8Array()
|
|
10937
|
+
nodeTxSignature: cpfpNodeTxSignature,
|
|
10938
|
+
directNodeTxSignature,
|
|
10939
|
+
refundTxSignature: cpfpRefundTxSignature,
|
|
10940
|
+
directRefundTxSignature,
|
|
10941
|
+
directFromCpfpRefundTxSignature
|
|
9710
10942
|
}
|
|
9711
10943
|
};
|
|
9712
10944
|
}
|
|
@@ -9768,8 +11000,45 @@ var SigningService = class {
|
|
|
9768
11000
|
constructor(config) {
|
|
9769
11001
|
this.config = config;
|
|
9770
11002
|
}
|
|
9771
|
-
async
|
|
9772
|
-
const leafSigningJobs = [];
|
|
11003
|
+
async signRefundsInternal(refundTx, sighash, leaf, signingCommitments) {
|
|
11004
|
+
const leafSigningJobs = [];
|
|
11005
|
+
const signingCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
11006
|
+
if (!signingCommitments) {
|
|
11007
|
+
throw new ValidationError("Invalid signing commitments", {
|
|
11008
|
+
field: "signingNonceCommitments",
|
|
11009
|
+
value: signingCommitments,
|
|
11010
|
+
expected: "Non-null signing commitments"
|
|
11011
|
+
});
|
|
11012
|
+
}
|
|
11013
|
+
const signingResult = await this.config.signer.signFrost({
|
|
11014
|
+
message: sighash,
|
|
11015
|
+
keyDerivation: leaf.keyDerivation,
|
|
11016
|
+
publicKey: await this.config.signer.getPublicKeyFromDerivation(
|
|
11017
|
+
leaf.keyDerivation
|
|
11018
|
+
),
|
|
11019
|
+
selfCommitment: signingCommitment,
|
|
11020
|
+
statechainCommitments: signingCommitments,
|
|
11021
|
+
adaptorPubKey: new Uint8Array(),
|
|
11022
|
+
verifyingKey: leaf.leaf.verifyingPublicKey
|
|
11023
|
+
});
|
|
11024
|
+
leafSigningJobs.push({
|
|
11025
|
+
leafId: leaf.leaf.id,
|
|
11026
|
+
signingPublicKey: await this.config.signer.getPublicKeyFromDerivation(
|
|
11027
|
+
leaf.keyDerivation
|
|
11028
|
+
),
|
|
11029
|
+
rawTx: refundTx.toBytes(),
|
|
11030
|
+
signingNonceCommitment: signingCommitment.commitment,
|
|
11031
|
+
userSignature: signingResult,
|
|
11032
|
+
signingCommitments: {
|
|
11033
|
+
signingCommitments
|
|
11034
|
+
}
|
|
11035
|
+
});
|
|
11036
|
+
return leafSigningJobs;
|
|
11037
|
+
}
|
|
11038
|
+
async signRefunds(leaves, receiverIdentityPubkey, cpfpSigningCommitments, directSigningCommitments, directFromCpfpSigningCommitments) {
|
|
11039
|
+
const cpfpLeafSigningJobs = [];
|
|
11040
|
+
const directLeafSigningJobs = [];
|
|
11041
|
+
const directFromCpfpLeafSigningJobs = [];
|
|
9773
11042
|
for (let i = 0; i < leaves.length; i++) {
|
|
9774
11043
|
const leaf = leaves[i];
|
|
9775
11044
|
if (!leaf?.leaf) {
|
|
@@ -9780,14 +11049,20 @@ var SigningService = class {
|
|
|
9780
11049
|
});
|
|
9781
11050
|
}
|
|
9782
11051
|
const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
9783
|
-
const
|
|
11052
|
+
const cpfpNodeOutPoint = {
|
|
9784
11053
|
txid: hexToBytes11(getTxId(nodeTx)),
|
|
9785
11054
|
index: 0
|
|
9786
11055
|
};
|
|
9787
11056
|
const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
9788
|
-
const
|
|
9789
|
-
|
|
9790
|
-
|
|
11057
|
+
const sequence = currRefundTx.getInput(0).sequence;
|
|
11058
|
+
if (!sequence) {
|
|
11059
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
11060
|
+
field: "sequence",
|
|
11061
|
+
value: currRefundTx.getInput(0),
|
|
11062
|
+
expected: "Non-null sequence"
|
|
11063
|
+
});
|
|
11064
|
+
}
|
|
11065
|
+
const { nextSequence, nextDirectSequence } = getNextTransactionSequence(sequence);
|
|
9791
11066
|
const amountSats = currRefundTx.getOutput(0).amount;
|
|
9792
11067
|
if (amountSats === void 0) {
|
|
9793
11068
|
throw new ValidationError("Invalid refund transaction", {
|
|
@@ -9796,48 +11071,90 @@ var SigningService = class {
|
|
|
9796
11071
|
expected: "Non-null amount"
|
|
9797
11072
|
});
|
|
9798
11073
|
}
|
|
9799
|
-
|
|
9800
|
-
|
|
9801
|
-
|
|
9802
|
-
|
|
9803
|
-
|
|
9804
|
-
|
|
9805
|
-
|
|
9806
|
-
|
|
9807
|
-
const signingCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
9808
|
-
const signingNonceCommitments = signingCommitments[i]?.signingNonceCommitments;
|
|
9809
|
-
if (!signingNonceCommitments) {
|
|
9810
|
-
throw new ValidationError("Invalid signing commitments", {
|
|
9811
|
-
field: "signingNonceCommitments",
|
|
9812
|
-
value: signingCommitments[i],
|
|
9813
|
-
expected: "Non-null signing nonce commitments"
|
|
9814
|
-
});
|
|
11074
|
+
let directNodeTx;
|
|
11075
|
+
let directNodeOutPoint;
|
|
11076
|
+
if (leaf.leaf.directTx.length > 0) {
|
|
11077
|
+
directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
|
|
11078
|
+
directNodeOutPoint = {
|
|
11079
|
+
txid: hexToBytes11(getTxId(directNodeTx)),
|
|
11080
|
+
index: 0
|
|
11081
|
+
};
|
|
9815
11082
|
}
|
|
9816
|
-
const
|
|
9817
|
-
|
|
9818
|
-
|
|
9819
|
-
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
|
|
9824
|
-
adaptorPubKey: new Uint8Array(),
|
|
9825
|
-
verifyingKey: leaf.leaf.verifyingPublicKey
|
|
11083
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
11084
|
+
sequence: nextSequence,
|
|
11085
|
+
directSequence: nextDirectSequence,
|
|
11086
|
+
input: cpfpNodeOutPoint,
|
|
11087
|
+
directInput: directNodeOutPoint,
|
|
11088
|
+
amountSats,
|
|
11089
|
+
receivingPubkey: receiverIdentityPubkey,
|
|
11090
|
+
network: this.config.getNetwork()
|
|
9826
11091
|
});
|
|
9827
|
-
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
|
|
9835
|
-
|
|
9836
|
-
|
|
11092
|
+
const refundSighash = getSigHashFromTx(
|
|
11093
|
+
cpfpRefundTx,
|
|
11094
|
+
0,
|
|
11095
|
+
nodeTx.getOutput(0)
|
|
11096
|
+
);
|
|
11097
|
+
const signingJobs = await this.signRefundsInternal(
|
|
11098
|
+
cpfpRefundTx,
|
|
11099
|
+
refundSighash,
|
|
11100
|
+
leaf,
|
|
11101
|
+
cpfpSigningCommitments[i]?.signingNonceCommitments
|
|
11102
|
+
);
|
|
11103
|
+
cpfpLeafSigningJobs.push(...signingJobs);
|
|
11104
|
+
if (directRefundTx) {
|
|
11105
|
+
if (!directNodeTx) {
|
|
11106
|
+
throw new ValidationError(
|
|
11107
|
+
"Direct node transaction undefined while direct refund transaction is defined",
|
|
11108
|
+
{
|
|
11109
|
+
field: "directNodeTx",
|
|
11110
|
+
value: directNodeTx,
|
|
11111
|
+
expected: "Non-null direct node transaction"
|
|
11112
|
+
}
|
|
11113
|
+
);
|
|
9837
11114
|
}
|
|
9838
|
-
|
|
11115
|
+
const refundSighash2 = getSigHashFromTx(
|
|
11116
|
+
directRefundTx,
|
|
11117
|
+
0,
|
|
11118
|
+
directNodeTx.getOutput(0)
|
|
11119
|
+
);
|
|
11120
|
+
const signingJobs2 = await this.signRefundsInternal(
|
|
11121
|
+
directRefundTx,
|
|
11122
|
+
refundSighash2,
|
|
11123
|
+
leaf,
|
|
11124
|
+
directSigningCommitments[i]?.signingNonceCommitments
|
|
11125
|
+
);
|
|
11126
|
+
directLeafSigningJobs.push(...signingJobs2);
|
|
11127
|
+
}
|
|
11128
|
+
if (directFromCpfpRefundTx) {
|
|
11129
|
+
if (!directNodeTx) {
|
|
11130
|
+
throw new ValidationError(
|
|
11131
|
+
"Direct node transaction undefined while direct from CPFP refund transaction is defined",
|
|
11132
|
+
{
|
|
11133
|
+
field: "directNodeTx",
|
|
11134
|
+
value: directNodeTx,
|
|
11135
|
+
expected: "Non-null direct node transaction"
|
|
11136
|
+
}
|
|
11137
|
+
);
|
|
11138
|
+
}
|
|
11139
|
+
const refundSighash2 = getSigHashFromTx(
|
|
11140
|
+
directFromCpfpRefundTx,
|
|
11141
|
+
0,
|
|
11142
|
+
nodeTx.getOutput(0)
|
|
11143
|
+
);
|
|
11144
|
+
const signingJobs2 = await this.signRefundsInternal(
|
|
11145
|
+
directFromCpfpRefundTx,
|
|
11146
|
+
refundSighash2,
|
|
11147
|
+
leaf,
|
|
11148
|
+
directFromCpfpSigningCommitments[i]?.signingNonceCommitments
|
|
11149
|
+
);
|
|
11150
|
+
directFromCpfpLeafSigningJobs.push(...signingJobs2);
|
|
11151
|
+
}
|
|
9839
11152
|
}
|
|
9840
|
-
return
|
|
11153
|
+
return {
|
|
11154
|
+
cpfpLeafSigningJobs,
|
|
11155
|
+
directLeafSigningJobs,
|
|
11156
|
+
directFromCpfpLeafSigningJobs
|
|
11157
|
+
};
|
|
9841
11158
|
}
|
|
9842
11159
|
};
|
|
9843
11160
|
|
|
@@ -10077,31 +11394,37 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
10077
11394
|
}
|
|
10078
11395
|
}
|
|
10079
11396
|
async getLeaves(isBalanceCheck = false) {
|
|
10080
|
-
const
|
|
10081
|
-
|
|
10082
|
-
|
|
10083
|
-
|
|
10084
|
-
|
|
10085
|
-
|
|
10086
|
-
|
|
10087
|
-
}
|
|
11397
|
+
const operatorToLeaves = /* @__PURE__ */ new Map();
|
|
11398
|
+
const ownerIdentityPubkey = await this.config.signer.getIdentityPublicKey();
|
|
11399
|
+
let signingOperators = Object.entries(this.config.getSigningOperators());
|
|
11400
|
+
if (isBalanceCheck) {
|
|
11401
|
+
signingOperators = signingOperators.filter(
|
|
11402
|
+
([id, _]) => id === this.config.getCoordinatorIdentifier()
|
|
11403
|
+
);
|
|
11404
|
+
}
|
|
11405
|
+
await Promise.all(
|
|
11406
|
+
signingOperators.map(async ([id, operator]) => {
|
|
11407
|
+
const leaves2 = await this.queryNodes(
|
|
11408
|
+
{
|
|
11409
|
+
source: {
|
|
11410
|
+
$case: "ownerIdentityPubkey",
|
|
11411
|
+
ownerIdentityPubkey
|
|
11412
|
+
},
|
|
11413
|
+
includeParents: false,
|
|
11414
|
+
network: NetworkToProto[this.config.getNetwork()]
|
|
11415
|
+
},
|
|
11416
|
+
operator.address
|
|
11417
|
+
);
|
|
11418
|
+
operatorToLeaves.set(id, leaves2);
|
|
11419
|
+
})
|
|
11420
|
+
);
|
|
11421
|
+
const leaves = operatorToLeaves.get(
|
|
11422
|
+
this.config.getCoordinatorIdentifier()
|
|
11423
|
+
);
|
|
10088
11424
|
const leavesToIgnore = /* @__PURE__ */ new Set();
|
|
10089
11425
|
if (!isBalanceCheck) {
|
|
10090
|
-
for (const [id,
|
|
10091
|
-
this.config.getSigningOperators()
|
|
10092
|
-
)) {
|
|
11426
|
+
for (const [id, operatorLeaves] of operatorToLeaves) {
|
|
10093
11427
|
if (id !== this.config.getCoordinatorIdentifier()) {
|
|
10094
|
-
const operatorLeaves = await this.queryNodes(
|
|
10095
|
-
{
|
|
10096
|
-
source: {
|
|
10097
|
-
$case: "ownerIdentityPubkey",
|
|
10098
|
-
ownerIdentityPubkey: await this.config.signer.getIdentityPublicKey()
|
|
10099
|
-
},
|
|
10100
|
-
includeParents: false,
|
|
10101
|
-
network: NetworkToProto[this.config.getNetwork()]
|
|
10102
|
-
},
|
|
10103
|
-
operator.address
|
|
10104
|
-
);
|
|
10105
11428
|
for (const [nodeId, leaf] of Object.entries(leaves.nodes)) {
|
|
10106
11429
|
const operatorLeaf = operatorLeaves.nodes[nodeId];
|
|
10107
11430
|
if (!operatorLeaf) {
|
|
@@ -10542,21 +11865,68 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
10542
11865
|
}
|
|
10543
11866
|
}))
|
|
10544
11867
|
);
|
|
10545
|
-
const {
|
|
11868
|
+
const {
|
|
11869
|
+
transfer,
|
|
11870
|
+
signatureMap,
|
|
11871
|
+
directSignatureMap,
|
|
11872
|
+
directFromCpfpSignatureMap
|
|
11873
|
+
} = await this.transferService.startSwapSignRefund(
|
|
10546
11874
|
leafKeyTweaks,
|
|
10547
11875
|
hexToBytes12(this.config.getSspIdentityPublicKey()),
|
|
10548
11876
|
new Date(Date.now() + 2 * 60 * 1e3)
|
|
10549
11877
|
);
|
|
10550
11878
|
try {
|
|
10551
11879
|
if (!transfer.leaves[0]?.leaf) {
|
|
11880
|
+
console.error("[processSwapBatch] First leaf is missing");
|
|
10552
11881
|
throw new Error("Failed to get leaf");
|
|
10553
11882
|
}
|
|
10554
|
-
const
|
|
10555
|
-
if (!
|
|
10556
|
-
|
|
11883
|
+
const cpfpRefundSignature = signatureMap.get(transfer.leaves[0].leaf.id);
|
|
11884
|
+
if (!cpfpRefundSignature) {
|
|
11885
|
+
console.error(
|
|
11886
|
+
"[processSwapBatch] Missing CPFP refund signature for first leaf"
|
|
11887
|
+
);
|
|
11888
|
+
throw new Error("Failed to get CPFP refund signature");
|
|
11889
|
+
}
|
|
11890
|
+
const directRefundSignature = directSignatureMap.get(
|
|
11891
|
+
transfer.leaves[0].leaf.id
|
|
11892
|
+
);
|
|
11893
|
+
if (!directRefundSignature) {
|
|
11894
|
+
console.error(
|
|
11895
|
+
"[processSwapBatch] Missing direct refund signature for first leaf"
|
|
11896
|
+
);
|
|
11897
|
+
throw new Error("Failed to get direct refund signature");
|
|
11898
|
+
}
|
|
11899
|
+
const directFromCpfpRefundSignature = directFromCpfpSignatureMap.get(
|
|
11900
|
+
transfer.leaves[0].leaf.id
|
|
11901
|
+
);
|
|
11902
|
+
if (!directFromCpfpRefundSignature) {
|
|
11903
|
+
console.error(
|
|
11904
|
+
"[processSwapBatch] Missing direct from CPFP refund signature for first leaf"
|
|
11905
|
+
);
|
|
11906
|
+
throw new Error("Failed to get direct from CPFP refund signature");
|
|
11907
|
+
}
|
|
11908
|
+
const {
|
|
11909
|
+
adaptorPrivateKey: cpfpAdaptorPrivateKey,
|
|
11910
|
+
adaptorSignature: cpfpAdaptorSignature
|
|
11911
|
+
} = generateAdaptorFromSignature(cpfpRefundSignature);
|
|
11912
|
+
let directAdaptorPrivateKey = new Uint8Array();
|
|
11913
|
+
let directAdaptorSignature = new Uint8Array();
|
|
11914
|
+
let directFromCpfpAdaptorPrivateKey = new Uint8Array();
|
|
11915
|
+
let directFromCpfpAdaptorSignature = new Uint8Array();
|
|
11916
|
+
if (directRefundSignature.length > 0) {
|
|
11917
|
+
const { adaptorPrivateKey, adaptorSignature } = generateAdaptorFromSignature(directRefundSignature);
|
|
11918
|
+
directAdaptorPrivateKey = adaptorPrivateKey;
|
|
11919
|
+
directAdaptorSignature = adaptorSignature;
|
|
11920
|
+
}
|
|
11921
|
+
if (directFromCpfpRefundSignature.length > 0) {
|
|
11922
|
+
const { adaptorPrivateKey, adaptorSignature } = generateAdaptorFromSignature(directFromCpfpRefundSignature);
|
|
11923
|
+
directFromCpfpAdaptorPrivateKey = adaptorPrivateKey;
|
|
11924
|
+
directFromCpfpAdaptorSignature = adaptorSignature;
|
|
10557
11925
|
}
|
|
10558
|
-
const { adaptorPrivateKey, adaptorSignature } = generateAdaptorFromSignature(refundSignature);
|
|
10559
11926
|
if (!transfer.leaves[0].leaf) {
|
|
11927
|
+
console.error(
|
|
11928
|
+
"[processSwapBatch] First leaf missing when preparing user leaves"
|
|
11929
|
+
);
|
|
10560
11930
|
throw new Error("Failed to get leaf");
|
|
10561
11931
|
}
|
|
10562
11932
|
const userLeaves = [];
|
|
@@ -10565,37 +11935,113 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
10565
11935
|
raw_unsigned_refund_transaction: bytesToHex11(
|
|
10566
11936
|
transfer.leaves[0].intermediateRefundTx
|
|
10567
11937
|
),
|
|
10568
|
-
|
|
11938
|
+
direct_raw_unsigned_refund_transaction: bytesToHex11(
|
|
11939
|
+
transfer.leaves[0].intermediateDirectRefundTx
|
|
11940
|
+
),
|
|
11941
|
+
direct_from_cpfp_raw_unsigned_refund_transaction: bytesToHex11(
|
|
11942
|
+
transfer.leaves[0].intermediateDirectFromCpfpRefundTx
|
|
11943
|
+
),
|
|
11944
|
+
adaptor_added_signature: bytesToHex11(cpfpAdaptorSignature),
|
|
11945
|
+
direct_adaptor_added_signature: bytesToHex11(directAdaptorSignature),
|
|
11946
|
+
direct_from_cpfp_adaptor_added_signature: bytesToHex11(
|
|
11947
|
+
directFromCpfpAdaptorSignature
|
|
11948
|
+
)
|
|
10569
11949
|
});
|
|
10570
11950
|
for (let i = 1; i < transfer.leaves.length; i++) {
|
|
10571
11951
|
const leaf = transfer.leaves[i];
|
|
10572
11952
|
if (!leaf?.leaf) {
|
|
11953
|
+
console.error(`[processSwapBatch] Leaf ${i + 1} is missing`);
|
|
10573
11954
|
throw new Error("Failed to get leaf");
|
|
10574
11955
|
}
|
|
10575
|
-
const
|
|
10576
|
-
if (!
|
|
10577
|
-
|
|
11956
|
+
const cpfpRefundSignature2 = signatureMap.get(leaf.leaf.id);
|
|
11957
|
+
if (!cpfpRefundSignature2) {
|
|
11958
|
+
console.error(
|
|
11959
|
+
`[processSwapBatch] Missing CPFP refund signature for leaf ${i + 1}`
|
|
11960
|
+
);
|
|
11961
|
+
throw new Error("Failed to get CPFP refund signature");
|
|
11962
|
+
}
|
|
11963
|
+
const directRefundSignature2 = directSignatureMap.get(leaf.leaf.id);
|
|
11964
|
+
if (!directRefundSignature2) {
|
|
11965
|
+
console.error(
|
|
11966
|
+
`[processSwapBatch] Missing direct refund signature for leaf ${i + 1}`
|
|
11967
|
+
);
|
|
11968
|
+
throw new Error("Failed to get direct refund signature");
|
|
11969
|
+
}
|
|
11970
|
+
const directFromCpfpRefundSignature2 = directFromCpfpSignatureMap.get(
|
|
11971
|
+
leaf.leaf.id
|
|
11972
|
+
);
|
|
11973
|
+
if (!directFromCpfpRefundSignature2) {
|
|
11974
|
+
console.error(
|
|
11975
|
+
`[processSwapBatch] Missing direct from CPFP refund signature for leaf ${i + 1}`
|
|
11976
|
+
);
|
|
11977
|
+
throw new Error("Failed to get direct from CPFP refund signature");
|
|
10578
11978
|
}
|
|
10579
|
-
const
|
|
10580
|
-
|
|
10581
|
-
|
|
11979
|
+
const cpfpSignature = generateSignatureFromExistingAdaptor(
|
|
11980
|
+
cpfpRefundSignature2,
|
|
11981
|
+
cpfpAdaptorPrivateKey
|
|
10582
11982
|
);
|
|
11983
|
+
let directSignature = new Uint8Array();
|
|
11984
|
+
if (directRefundSignature2.length > 0) {
|
|
11985
|
+
directSignature = generateSignatureFromExistingAdaptor(
|
|
11986
|
+
directRefundSignature2,
|
|
11987
|
+
directAdaptorPrivateKey
|
|
11988
|
+
);
|
|
11989
|
+
}
|
|
11990
|
+
let directFromCpfpSignature = new Uint8Array();
|
|
11991
|
+
if (directFromCpfpRefundSignature2.length > 0) {
|
|
11992
|
+
directFromCpfpSignature = generateSignatureFromExistingAdaptor(
|
|
11993
|
+
directFromCpfpRefundSignature2,
|
|
11994
|
+
directFromCpfpAdaptorPrivateKey
|
|
11995
|
+
);
|
|
11996
|
+
}
|
|
10583
11997
|
userLeaves.push({
|
|
10584
11998
|
leaf_id: leaf.leaf.id,
|
|
10585
11999
|
raw_unsigned_refund_transaction: bytesToHex11(
|
|
10586
12000
|
leaf.intermediateRefundTx
|
|
10587
12001
|
),
|
|
10588
|
-
|
|
12002
|
+
direct_raw_unsigned_refund_transaction: bytesToHex11(
|
|
12003
|
+
leaf.intermediateDirectRefundTx
|
|
12004
|
+
),
|
|
12005
|
+
direct_from_cpfp_raw_unsigned_refund_transaction: bytesToHex11(
|
|
12006
|
+
leaf.intermediateDirectFromCpfpRefundTx
|
|
12007
|
+
),
|
|
12008
|
+
adaptor_added_signature: bytesToHex11(cpfpSignature),
|
|
12009
|
+
direct_adaptor_added_signature: bytesToHex11(directSignature),
|
|
12010
|
+
direct_from_cpfp_adaptor_added_signature: bytesToHex11(
|
|
12011
|
+
directFromCpfpSignature
|
|
12012
|
+
)
|
|
10589
12013
|
});
|
|
10590
12014
|
}
|
|
10591
12015
|
const sspClient = this.getSspClient();
|
|
10592
|
-
const
|
|
10593
|
-
secp256k114.getPublicKey(
|
|
12016
|
+
const cpfpAdaptorPubkey = bytesToHex11(
|
|
12017
|
+
secp256k114.getPublicKey(cpfpAdaptorPrivateKey)
|
|
10594
12018
|
);
|
|
12019
|
+
if (!cpfpAdaptorPubkey) {
|
|
12020
|
+
throw new Error("Failed to generate CPFP adaptor pubkey");
|
|
12021
|
+
}
|
|
12022
|
+
let directAdaptorPubkey;
|
|
12023
|
+
if (directAdaptorPrivateKey.length > 0) {
|
|
12024
|
+
directAdaptorPubkey = bytesToHex11(
|
|
12025
|
+
secp256k114.getPublicKey(directAdaptorPrivateKey)
|
|
12026
|
+
);
|
|
12027
|
+
}
|
|
12028
|
+
let directFromCpfpAdaptorPubkey;
|
|
12029
|
+
if (directFromCpfpAdaptorPrivateKey.length > 0) {
|
|
12030
|
+
directFromCpfpAdaptorPubkey = bytesToHex11(
|
|
12031
|
+
secp256k114.getPublicKey(directFromCpfpAdaptorPrivateKey)
|
|
12032
|
+
);
|
|
12033
|
+
}
|
|
10595
12034
|
let request = null;
|
|
12035
|
+
const targetAmountSats = targetAmounts?.reduce((acc, amount) => acc + amount, 0) || leavesBatch.reduce((acc, leaf) => acc + leaf.value, 0);
|
|
12036
|
+
const totalAmountSats = leavesBatch.reduce(
|
|
12037
|
+
(acc, leaf) => acc + leaf.value,
|
|
12038
|
+
0
|
|
12039
|
+
);
|
|
10596
12040
|
request = await sspClient.requestLeaveSwap({
|
|
10597
12041
|
userLeaves,
|
|
10598
|
-
adaptorPubkey,
|
|
12042
|
+
adaptorPubkey: cpfpAdaptorPubkey,
|
|
12043
|
+
directAdaptorPubkey,
|
|
12044
|
+
directFromCpfpAdaptorPubkey,
|
|
10599
12045
|
targetAmountSats: targetAmounts?.reduce((acc, amount) => acc + amount, 0) || leavesBatch.reduce((acc, leaf) => acc + leaf.value, 0),
|
|
10600
12046
|
totalAmountSats: leavesBatch.reduce((acc, leaf) => acc + leaf.value, 0),
|
|
10601
12047
|
targetAmountSatsList: targetAmounts,
|
|
@@ -10604,6 +12050,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
10604
12050
|
idempotencyKey: uuidv75()
|
|
10605
12051
|
});
|
|
10606
12052
|
if (!request) {
|
|
12053
|
+
console.error("[processSwapBatch] Leave swap request returned null");
|
|
10607
12054
|
throw new Error("Failed to request leaves swap. No response returned.");
|
|
10608
12055
|
}
|
|
10609
12056
|
const nodes = await this.queryNodes({
|
|
@@ -10617,50 +12064,140 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
10617
12064
|
network: NetworkToProto[this.config.getNetwork()]
|
|
10618
12065
|
});
|
|
10619
12066
|
if (Object.values(nodes.nodes).length !== request.swapLeaves.length) {
|
|
12067
|
+
console.error("[processSwapBatch] Node count mismatch:", {
|
|
12068
|
+
actual: Object.values(nodes.nodes).length,
|
|
12069
|
+
expected: request.swapLeaves.length
|
|
12070
|
+
});
|
|
10620
12071
|
throw new Error("Expected same number of nodes as swapLeaves");
|
|
10621
12072
|
}
|
|
10622
12073
|
for (const [nodeId, node] of Object.entries(nodes.nodes)) {
|
|
10623
12074
|
if (!node.nodeTx) {
|
|
12075
|
+
console.error(`[processSwapBatch] Node tx missing for ${nodeId}`);
|
|
10624
12076
|
throw new Error(`Node tx not found for leaf ${nodeId}`);
|
|
10625
12077
|
}
|
|
10626
12078
|
if (!node.verifyingPublicKey) {
|
|
12079
|
+
console.error(
|
|
12080
|
+
`[processSwapBatch] Verifying public key missing for ${nodeId}`
|
|
12081
|
+
);
|
|
10627
12082
|
throw new Error(`Node public key not found for leaf ${nodeId}`);
|
|
10628
12083
|
}
|
|
10629
12084
|
const leaf = request.swapLeaves.find((leaf2) => leaf2.leafId === nodeId);
|
|
10630
12085
|
if (!leaf) {
|
|
12086
|
+
console.error(`[processSwapBatch] Leaf not found for node ${nodeId}`);
|
|
10631
12087
|
throw new Error(`Leaf not found for node ${nodeId}`);
|
|
10632
12088
|
}
|
|
10633
|
-
const
|
|
10634
|
-
const
|
|
10635
|
-
const
|
|
10636
|
-
const
|
|
12089
|
+
const cpfpNodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
12090
|
+
const cpfpRefundTxBytes = hexToBytes12(leaf.rawUnsignedRefundTransaction);
|
|
12091
|
+
const cpfpRefundTx = getTxFromRawTxBytes(cpfpRefundTxBytes);
|
|
12092
|
+
const cpfpSighash = getSigHashFromTx(
|
|
12093
|
+
cpfpRefundTx,
|
|
12094
|
+
0,
|
|
12095
|
+
cpfpNodeTx.getOutput(0)
|
|
12096
|
+
);
|
|
10637
12097
|
const nodePublicKey = node.verifyingPublicKey;
|
|
10638
12098
|
const taprootKey = computeTaprootKeyNoScript(nodePublicKey.slice(1));
|
|
10639
|
-
const
|
|
12099
|
+
const cpfpAdaptorSignatureBytes = hexToBytes12(
|
|
12100
|
+
leaf.adaptorSignedSignature
|
|
12101
|
+
);
|
|
12102
|
+
applyAdaptorToSignature(
|
|
12103
|
+
taprootKey.slice(1),
|
|
12104
|
+
cpfpSighash,
|
|
12105
|
+
cpfpAdaptorSignatureBytes,
|
|
12106
|
+
cpfpAdaptorPrivateKey
|
|
12107
|
+
);
|
|
12108
|
+
if (!leaf.directRawUnsignedRefundTransaction) {
|
|
12109
|
+
throw new Error(
|
|
12110
|
+
`Direct raw unsigned refund transaction missing for node ${nodeId}`
|
|
12111
|
+
);
|
|
12112
|
+
}
|
|
12113
|
+
if (!leaf.directAdaptorSignedSignature) {
|
|
12114
|
+
throw new Error(
|
|
12115
|
+
`Direct adaptor signed signature missing for node ${nodeId}`
|
|
12116
|
+
);
|
|
12117
|
+
}
|
|
12118
|
+
const directNodeTx = getTxFromRawTxBytes(node.directTx);
|
|
12119
|
+
const directRefundTxBytes = hexToBytes12(
|
|
12120
|
+
leaf.directRawUnsignedRefundTransaction
|
|
12121
|
+
);
|
|
12122
|
+
const directRefundTx = getTxFromRawTxBytes(directRefundTxBytes);
|
|
12123
|
+
const directSighash = getSigHashFromTx(
|
|
12124
|
+
directRefundTx,
|
|
12125
|
+
0,
|
|
12126
|
+
directNodeTx.getOutput(0)
|
|
12127
|
+
);
|
|
12128
|
+
if (!leaf.directFromCpfpAdaptorSignedSignature) {
|
|
12129
|
+
throw new Error(
|
|
12130
|
+
`Direct adaptor signed signature missing for node ${nodeId}`
|
|
12131
|
+
);
|
|
12132
|
+
}
|
|
12133
|
+
const directAdaptorSignatureBytes = hexToBytes12(
|
|
12134
|
+
leaf.directAdaptorSignedSignature
|
|
12135
|
+
);
|
|
12136
|
+
applyAdaptorToSignature(
|
|
12137
|
+
taprootKey.slice(1),
|
|
12138
|
+
directSighash,
|
|
12139
|
+
directAdaptorSignatureBytes,
|
|
12140
|
+
directAdaptorPrivateKey
|
|
12141
|
+
);
|
|
12142
|
+
if (!leaf.directRawUnsignedRefundTransaction) {
|
|
12143
|
+
throw new Error(
|
|
12144
|
+
`Direct raw unsigned refund transaction missing for node ${nodeId}`
|
|
12145
|
+
);
|
|
12146
|
+
}
|
|
12147
|
+
if (!leaf.directFromCpfpRawUnsignedRefundTransaction) {
|
|
12148
|
+
throw new Error(
|
|
12149
|
+
`Direct raw unsigned refund transaction missing for node ${nodeId}`
|
|
12150
|
+
);
|
|
12151
|
+
}
|
|
12152
|
+
const directFromCpfpRefundTxBytes = hexToBytes12(
|
|
12153
|
+
leaf.directFromCpfpRawUnsignedRefundTransaction
|
|
12154
|
+
);
|
|
12155
|
+
const directFromCpfpRefundTx = getTxFromRawTxBytes(
|
|
12156
|
+
directFromCpfpRefundTxBytes
|
|
12157
|
+
);
|
|
12158
|
+
const directFromCpfpSighash = getSigHashFromTx(
|
|
12159
|
+
directFromCpfpRefundTx,
|
|
12160
|
+
0,
|
|
12161
|
+
cpfpNodeTx.getOutput(0)
|
|
12162
|
+
);
|
|
12163
|
+
const directFromCpfpAdaptorSignatureBytes = hexToBytes12(
|
|
12164
|
+
leaf.directFromCpfpAdaptorSignedSignature
|
|
12165
|
+
);
|
|
10640
12166
|
applyAdaptorToSignature(
|
|
10641
12167
|
taprootKey.slice(1),
|
|
10642
|
-
|
|
10643
|
-
|
|
10644
|
-
|
|
12168
|
+
directFromCpfpSighash,
|
|
12169
|
+
directFromCpfpAdaptorSignatureBytes,
|
|
12170
|
+
directFromCpfpAdaptorPrivateKey
|
|
10645
12171
|
);
|
|
10646
12172
|
}
|
|
10647
12173
|
await this.transferService.deliverTransferPackage(
|
|
10648
12174
|
transfer,
|
|
10649
12175
|
leafKeyTweaks,
|
|
10650
|
-
signatureMap
|
|
12176
|
+
signatureMap,
|
|
12177
|
+
directSignatureMap,
|
|
12178
|
+
directFromCpfpSignatureMap
|
|
10651
12179
|
);
|
|
10652
12180
|
const completeResponse = await sspClient.completeLeaveSwap({
|
|
10653
|
-
adaptorSecretKey: bytesToHex11(
|
|
12181
|
+
adaptorSecretKey: bytesToHex11(cpfpAdaptorPrivateKey),
|
|
12182
|
+
directAdaptorSecretKey: bytesToHex11(directAdaptorPrivateKey),
|
|
12183
|
+
directFromCpfpAdaptorSecretKey: bytesToHex11(
|
|
12184
|
+
directFromCpfpAdaptorPrivateKey
|
|
12185
|
+
),
|
|
10654
12186
|
userOutboundTransferExternalId: transfer.id,
|
|
10655
12187
|
leavesSwapRequestId: request.id
|
|
10656
12188
|
});
|
|
10657
12189
|
if (!completeResponse || !completeResponse.inboundTransfer?.sparkId) {
|
|
12190
|
+
console.error(
|
|
12191
|
+
"[processSwapBatch] Invalid complete response:",
|
|
12192
|
+
completeResponse
|
|
12193
|
+
);
|
|
10658
12194
|
throw new Error("Failed to complete leaves swap");
|
|
10659
12195
|
}
|
|
10660
12196
|
const incomingTransfer = await this.transferService.queryTransfer(
|
|
10661
12197
|
completeResponse.inboundTransfer.sparkId
|
|
10662
12198
|
);
|
|
10663
12199
|
if (!incomingTransfer) {
|
|
12200
|
+
console.error("[processSwapBatch] No incoming transfer found");
|
|
10664
12201
|
throw new Error("Failed to get incoming transfer");
|
|
10665
12202
|
}
|
|
10666
12203
|
return await this.claimTransfer({
|
|
@@ -10670,6 +12207,11 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
10670
12207
|
optimize: false
|
|
10671
12208
|
});
|
|
10672
12209
|
} catch (e) {
|
|
12210
|
+
console.error("[processSwapBatch] Error details:", {
|
|
12211
|
+
error: e,
|
|
12212
|
+
message: e.message,
|
|
12213
|
+
stack: e.stack
|
|
12214
|
+
});
|
|
10673
12215
|
await this.cancelAllSenderInitiatedTransfers();
|
|
10674
12216
|
throw new Error(`Failed to request leaves swap: ${e}`);
|
|
10675
12217
|
}
|
|
@@ -10689,9 +12231,22 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
10689
12231
|
const identityPublicKey = bytesToHex11(
|
|
10690
12232
|
await this.config.signer.getIdentityPublicKey()
|
|
10691
12233
|
);
|
|
12234
|
+
const userRequests = await this.sspClient?.getTransfers(
|
|
12235
|
+
transfers.transfers.map((transfer) => transfer.id)
|
|
12236
|
+
);
|
|
12237
|
+
const userRequestsMap = /* @__PURE__ */ new Map();
|
|
12238
|
+
for (const userRequest of userRequests || []) {
|
|
12239
|
+
if (userRequest && userRequest.sparkId && userRequest.userRequest) {
|
|
12240
|
+
userRequestsMap.set(userRequest.sparkId, userRequest.userRequest);
|
|
12241
|
+
}
|
|
12242
|
+
}
|
|
10692
12243
|
return {
|
|
10693
12244
|
transfers: transfers.transfers.map(
|
|
10694
|
-
(transfer) => mapTransferToWalletTransfer(
|
|
12245
|
+
(transfer) => mapTransferToWalletTransfer(
|
|
12246
|
+
transfer,
|
|
12247
|
+
identityPublicKey,
|
|
12248
|
+
userRequestsMap.get(transfer.id)
|
|
12249
|
+
)
|
|
10695
12250
|
),
|
|
10696
12251
|
offset: transfers.offset
|
|
10697
12252
|
};
|
|
@@ -10874,7 +12429,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
10874
12429
|
network = BitcoinNetwork_default.REGTEST;
|
|
10875
12430
|
}
|
|
10876
12431
|
if (outputIndex === void 0) {
|
|
10877
|
-
outputIndex = await this.getDepositTransactionVout(
|
|
12432
|
+
outputIndex = await this.getDepositTransactionVout({
|
|
12433
|
+
txid: transactionId
|
|
12434
|
+
});
|
|
10878
12435
|
}
|
|
10879
12436
|
const quote = await sspClient.getClaimDepositQuote({
|
|
10880
12437
|
transactionId,
|
|
@@ -10905,7 +12462,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
10905
12462
|
throw new Error("SSP client not initialized");
|
|
10906
12463
|
}
|
|
10907
12464
|
if (outputIndex === void 0) {
|
|
10908
|
-
outputIndex = await this.getDepositTransactionVout(
|
|
12465
|
+
outputIndex = await this.getDepositTransactionVout({
|
|
12466
|
+
txid: transactionId
|
|
12467
|
+
});
|
|
10909
12468
|
}
|
|
10910
12469
|
let network = this.config.getSspNetwork();
|
|
10911
12470
|
if (network === BitcoinNetwork_default.FUTURE_VALUE) {
|
|
@@ -10939,25 +12498,94 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
10939
12498
|
}
|
|
10940
12499
|
return response;
|
|
10941
12500
|
}
|
|
12501
|
+
/**
|
|
12502
|
+
* Get a quote on how much credit you can claim for a deposit from the SSP. If the quote charges less fees than the max fee, claim the deposit.
|
|
12503
|
+
*
|
|
12504
|
+
* @param {Object} params - The parameters object
|
|
12505
|
+
* @param {string} params.transactionId - The ID of the transaction
|
|
12506
|
+
* @param {number} params.maxFee - The maximum fee to claim the deposit for
|
|
12507
|
+
* @param {number} [params.outputIndex] - The index of the output
|
|
12508
|
+
* @returns {Promise<StaticDepositQuoteOutput>} Quote for claiming a deposit to a static deposit address
|
|
12509
|
+
*/
|
|
12510
|
+
async claimStaticDepositWithMaxFee({
|
|
12511
|
+
transactionId,
|
|
12512
|
+
maxFee,
|
|
12513
|
+
outputIndex
|
|
12514
|
+
}) {
|
|
12515
|
+
const sspClient = this.getSspClient();
|
|
12516
|
+
let network = this.config.getSspNetwork();
|
|
12517
|
+
if (network === BitcoinNetwork_default.FUTURE_VALUE) {
|
|
12518
|
+
network = BitcoinNetwork_default.REGTEST;
|
|
12519
|
+
}
|
|
12520
|
+
const depositTx = await this.getDepositTransaction(transactionId);
|
|
12521
|
+
if (outputIndex === void 0) {
|
|
12522
|
+
outputIndex = await this.getDepositTransactionVout({
|
|
12523
|
+
txid: transactionId,
|
|
12524
|
+
depositTx
|
|
12525
|
+
});
|
|
12526
|
+
}
|
|
12527
|
+
const depositAmount = Number(depositTx.getOutput(outputIndex).amount);
|
|
12528
|
+
const quote = await sspClient.getClaimDepositQuote({
|
|
12529
|
+
transactionId,
|
|
12530
|
+
outputIndex,
|
|
12531
|
+
network
|
|
12532
|
+
});
|
|
12533
|
+
if (!quote) {
|
|
12534
|
+
throw new Error("Failed to get claim deposit quote");
|
|
12535
|
+
}
|
|
12536
|
+
const { creditAmountSats, signature: sspSignature } = quote;
|
|
12537
|
+
const feeCharged = depositAmount - creditAmountSats;
|
|
12538
|
+
if (feeCharged > maxFee) {
|
|
12539
|
+
throw new ValidationError("Fee larger than max fee", {
|
|
12540
|
+
field: "feeCharged",
|
|
12541
|
+
value: feeCharged
|
|
12542
|
+
});
|
|
12543
|
+
}
|
|
12544
|
+
const response = await this.claimStaticDeposit({
|
|
12545
|
+
transactionId,
|
|
12546
|
+
creditAmountSats,
|
|
12547
|
+
sspSignature,
|
|
12548
|
+
outputIndex
|
|
12549
|
+
});
|
|
12550
|
+
if (!response) {
|
|
12551
|
+
throw new Error("Failed to claim static deposit");
|
|
12552
|
+
}
|
|
12553
|
+
return response;
|
|
12554
|
+
}
|
|
10942
12555
|
/**
|
|
10943
12556
|
* Refunds a static deposit to a destination address.
|
|
10944
12557
|
*
|
|
10945
|
-
* @param {
|
|
10946
|
-
* @param {
|
|
10947
|
-
* @param {
|
|
10948
|
-
* @param {
|
|
12558
|
+
* @param {Object} params - The refund parameters
|
|
12559
|
+
* @param {string} params.depositTransactionId - The ID of the transaction
|
|
12560
|
+
* @param {number} [params.outputIndex] - The index of the output
|
|
12561
|
+
* @param {string} params.destinationAddress - The destination address
|
|
12562
|
+
* @param {number} [params.fee] - **@deprecated** The fee to refund
|
|
12563
|
+
* @param {number} [params.satsPerVbyteFee] - The fee per vbyte to refund
|
|
10949
12564
|
* @returns {Promise<string>} The hex of the refund transaction
|
|
10950
12565
|
*/
|
|
10951
12566
|
async refundStaticDeposit({
|
|
10952
12567
|
depositTransactionId,
|
|
10953
12568
|
outputIndex,
|
|
10954
12569
|
destinationAddress,
|
|
10955
|
-
fee
|
|
12570
|
+
fee,
|
|
12571
|
+
satsPerVbyteFee
|
|
10956
12572
|
}) {
|
|
10957
|
-
if (fee
|
|
12573
|
+
if (fee !== void 0) {
|
|
12574
|
+
console.warn(
|
|
12575
|
+
`refundStaticDeposit(): \`fee\` parameter is deprecated and will be removed; please switch to \`satsPerVbyteFee\`.`
|
|
12576
|
+
);
|
|
12577
|
+
}
|
|
12578
|
+
if (fee === void 0 && satsPerVbyteFee === void 0) {
|
|
12579
|
+
throw new ValidationError("Fee or satsPerVbyteFee must be provided");
|
|
12580
|
+
}
|
|
12581
|
+
if (satsPerVbyteFee && satsPerVbyteFee > 150) {
|
|
12582
|
+
throw new ValidationError("satsPerVbyteFee must be less than 150");
|
|
12583
|
+
}
|
|
12584
|
+
const finalFee = satsPerVbyteFee ? satsPerVbyteFee * getTxEstimatedVbytesSizeByNumberOfInputsOutputs(1, 1) : fee;
|
|
12585
|
+
if (finalFee <= 200) {
|
|
10958
12586
|
throw new ValidationError("Fee must be greater than 300", {
|
|
10959
12587
|
field: "fee",
|
|
10960
|
-
value:
|
|
12588
|
+
value: finalFee
|
|
10961
12589
|
});
|
|
10962
12590
|
}
|
|
10963
12591
|
let network = this.config.getNetwork();
|
|
@@ -10965,10 +12593,13 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
10965
12593
|
const networkJSON = networkToJSON(networkType);
|
|
10966
12594
|
const depositTx = await this.getDepositTransaction(depositTransactionId);
|
|
10967
12595
|
if (outputIndex === void 0) {
|
|
10968
|
-
outputIndex = await this.getDepositTransactionVout(
|
|
12596
|
+
outputIndex = await this.getDepositTransactionVout({
|
|
12597
|
+
txid: depositTransactionId,
|
|
12598
|
+
depositTx
|
|
12599
|
+
});
|
|
10969
12600
|
}
|
|
10970
12601
|
const totalAmount = depositTx.getOutput(outputIndex).amount;
|
|
10971
|
-
const creditAmountSats = Number(totalAmount) -
|
|
12602
|
+
const creditAmountSats = Number(totalAmount) - finalFee;
|
|
10972
12603
|
if (creditAmountSats <= 0) {
|
|
10973
12604
|
throw new ValidationError(
|
|
10974
12605
|
"Fee too large. Credit amount must be greater than 0",
|
|
@@ -10984,10 +12615,10 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
10984
12615
|
index: outputIndex,
|
|
10985
12616
|
witnessScript: new Uint8Array()
|
|
10986
12617
|
});
|
|
10987
|
-
const addressDecoded =
|
|
12618
|
+
const addressDecoded = Address4(getNetwork(network)).decode(
|
|
10988
12619
|
destinationAddress
|
|
10989
12620
|
);
|
|
10990
|
-
const outputScript =
|
|
12621
|
+
const outputScript = OutScript4.encode(addressDecoded);
|
|
10991
12622
|
tx.addOutput({
|
|
10992
12623
|
script: outputScript,
|
|
10993
12624
|
amount: BigInt(creditAmountSats)
|
|
@@ -11016,26 +12647,14 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
11016
12647
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
11017
12648
|
this.config.getCoordinatorAddress()
|
|
11018
12649
|
);
|
|
11019
|
-
const
|
|
11020
|
-
const swapResponse = await sparkClient.initiate_utxo_swap({
|
|
12650
|
+
const swapResponse = await sparkClient.initiate_static_deposit_utxo_refund({
|
|
11021
12651
|
onChainUtxo: {
|
|
11022
12652
|
txid: hexToBytes12(depositTransactionId),
|
|
11023
12653
|
vout: outputIndex,
|
|
11024
12654
|
network: networkType
|
|
11025
12655
|
},
|
|
11026
|
-
requestType: 2 /* Refund */,
|
|
11027
|
-
amount: {
|
|
11028
|
-
creditAmountSats: 0,
|
|
11029
|
-
$case: "creditAmountSats"
|
|
11030
|
-
},
|
|
11031
12656
|
userSignature: swapResponseUserSignature,
|
|
11032
|
-
|
|
11033
|
-
transfer: {
|
|
11034
|
-
transferId,
|
|
11035
|
-
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
11036
|
-
receiverIdentityPublicKey: await this.config.signer.getIdentityPublicKey()
|
|
11037
|
-
},
|
|
11038
|
-
spendTxSigningJob: signingJob
|
|
12657
|
+
refundTxSigningJob: signingJob
|
|
11039
12658
|
});
|
|
11040
12659
|
if (!swapResponse) {
|
|
11041
12660
|
throw new Error("Failed to initiate utxo swap");
|
|
@@ -11048,15 +12667,15 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
11048
12667
|
path: 0
|
|
11049
12668
|
},
|
|
11050
12669
|
selfCommitment: signingNonceCommitment,
|
|
11051
|
-
statechainCommitments: swapResponse.
|
|
12670
|
+
statechainCommitments: swapResponse.refundTxSigningResult.signingNonceCommitments,
|
|
11052
12671
|
verifyingKey: swapResponse.depositAddress.verifyingPublicKey
|
|
11053
12672
|
});
|
|
11054
12673
|
const signatureResult = await this.config.signer.aggregateFrost({
|
|
11055
12674
|
message: spendTxSighash,
|
|
11056
|
-
statechainSignatures: swapResponse.
|
|
11057
|
-
statechainPublicKeys: swapResponse.
|
|
12675
|
+
statechainSignatures: swapResponse.refundTxSigningResult.signatureShares,
|
|
12676
|
+
statechainPublicKeys: swapResponse.refundTxSigningResult.publicKeys,
|
|
11058
12677
|
verifyingKey: swapResponse.depositAddress.verifyingPublicKey,
|
|
11059
|
-
statechainCommitments: swapResponse.
|
|
12678
|
+
statechainCommitments: swapResponse.refundTxSigningResult.signingNonceCommitments,
|
|
11060
12679
|
selfCommitment: signingNonceCommitment,
|
|
11061
12680
|
publicKey: await this.config.signer.getStaticDepositSigningKey(0),
|
|
11062
12681
|
selfSignature: userSignature
|
|
@@ -11109,8 +12728,13 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
11109
12728
|
}
|
|
11110
12729
|
return payload;
|
|
11111
12730
|
}
|
|
11112
|
-
async getDepositTransactionVout(
|
|
11113
|
-
|
|
12731
|
+
async getDepositTransactionVout({
|
|
12732
|
+
txid,
|
|
12733
|
+
depositTx
|
|
12734
|
+
}) {
|
|
12735
|
+
if (!depositTx) {
|
|
12736
|
+
depositTx = await this.getDepositTransaction(txid);
|
|
12737
|
+
}
|
|
11114
12738
|
const staticDepositAddresses = new Set(
|
|
11115
12739
|
await this.queryStaticDepositAddresses()
|
|
11116
12740
|
);
|
|
@@ -11120,8 +12744,8 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
11120
12744
|
if (!output) {
|
|
11121
12745
|
continue;
|
|
11122
12746
|
}
|
|
11123
|
-
const parsedScript =
|
|
11124
|
-
const address2 =
|
|
12747
|
+
const parsedScript = OutScript4.decode(output.script);
|
|
12748
|
+
const address2 = Address4(getNetwork(this.config.getNetwork())).encode(
|
|
11125
12749
|
parsedScript
|
|
11126
12750
|
);
|
|
11127
12751
|
if (staticDepositAddresses.has(address2)) {
|
|
@@ -11140,8 +12764,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
11140
12764
|
field: "txid"
|
|
11141
12765
|
});
|
|
11142
12766
|
}
|
|
12767
|
+
const { fetch: fetch2, Headers: Headers2 } = getFetch();
|
|
11143
12768
|
const baseUrl = this.config.getElectrsUrl();
|
|
11144
|
-
const headers =
|
|
12769
|
+
const headers = new Headers2();
|
|
11145
12770
|
let txHex;
|
|
11146
12771
|
if (this.config.getNetwork() === 4 /* LOCAL */) {
|
|
11147
12772
|
const localFaucet = BitcoinFaucet.getInstance();
|
|
@@ -11152,9 +12777,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
11152
12777
|
const auth = btoa(
|
|
11153
12778
|
`${ELECTRS_CREDENTIALS.username}:${ELECTRS_CREDENTIALS.password}`
|
|
11154
12779
|
);
|
|
11155
|
-
headers
|
|
12780
|
+
headers.set("Authorization", `Basic ${auth}`);
|
|
11156
12781
|
}
|
|
11157
|
-
const response = await
|
|
12782
|
+
const response = await fetch2(`${baseUrl}/tx/${txid}/hex`, {
|
|
11158
12783
|
headers
|
|
11159
12784
|
});
|
|
11160
12785
|
txHex = await response.text();
|
|
@@ -11282,8 +12907,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
11282
12907
|
this.mutexes.set(txid, mutex);
|
|
11283
12908
|
}
|
|
11284
12909
|
const nodes = await mutex.runExclusive(async () => {
|
|
12910
|
+
const { fetch: fetch2, Headers: Headers2 } = getFetch();
|
|
11285
12911
|
const baseUrl = this.config.getElectrsUrl();
|
|
11286
|
-
const headers =
|
|
12912
|
+
const headers = new Headers2();
|
|
11287
12913
|
let txHex;
|
|
11288
12914
|
if (this.config.getNetwork() === 4 /* LOCAL */) {
|
|
11289
12915
|
const localFaucet = BitcoinFaucet.getInstance();
|
|
@@ -11294,9 +12920,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
11294
12920
|
const auth = btoa(
|
|
11295
12921
|
`${ELECTRS_CREDENTIALS.username}:${ELECTRS_CREDENTIALS.password}`
|
|
11296
12922
|
);
|
|
11297
|
-
headers
|
|
12923
|
+
headers.set("Authorization", `Basic ${auth}`);
|
|
11298
12924
|
}
|
|
11299
|
-
const response = await
|
|
12925
|
+
const response = await fetch2(`${baseUrl}/tx/${txid}/hex`, {
|
|
11300
12926
|
headers
|
|
11301
12927
|
});
|
|
11302
12928
|
txHex = await response.text();
|
|
@@ -11324,8 +12950,8 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
11324
12950
|
if (!output) {
|
|
11325
12951
|
continue;
|
|
11326
12952
|
}
|
|
11327
|
-
const parsedScript =
|
|
11328
|
-
const address2 =
|
|
12953
|
+
const parsedScript = OutScript4.decode(output.script);
|
|
12954
|
+
const address2 = Address4(getNetwork(this.config.getNetwork())).encode(
|
|
11329
12955
|
parsedScript
|
|
11330
12956
|
);
|
|
11331
12957
|
if (unusedDepositAddresses.has(address2)) {
|
|
@@ -11385,8 +13011,8 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
11385
13011
|
if (!output) {
|
|
11386
13012
|
continue;
|
|
11387
13013
|
}
|
|
11388
|
-
const parsedScript =
|
|
11389
|
-
const address2 =
|
|
13014
|
+
const parsedScript = OutScript4.decode(output.script);
|
|
13015
|
+
const address2 = Address4(getNetwork(this.config.getNetwork())).encode(
|
|
11390
13016
|
parsedScript
|
|
11391
13017
|
);
|
|
11392
13018
|
const unusedDepositAddress = unusedDepositAddresses.get(address2);
|
|
@@ -11538,10 +13164,16 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
11538
13164
|
const validNodes = [];
|
|
11539
13165
|
for (const node of nodes) {
|
|
11540
13166
|
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
11541
|
-
const
|
|
11542
|
-
|
|
11543
|
-
|
|
11544
|
-
|
|
13167
|
+
const sequence = nodeTx.getInput(0).sequence;
|
|
13168
|
+
if (!sequence) {
|
|
13169
|
+
throw new ValidationError("Invalid node transaction", {
|
|
13170
|
+
field: "sequence",
|
|
13171
|
+
value: nodeTx.getInput(0),
|
|
13172
|
+
expected: "Non-null sequence"
|
|
13173
|
+
});
|
|
13174
|
+
}
|
|
13175
|
+
const needsRefresh = doesLeafNeedRefresh(sequence, true);
|
|
13176
|
+
if (needsRefresh) {
|
|
11545
13177
|
nodesToExtend.push(node);
|
|
11546
13178
|
nodeIds.push(node.id);
|
|
11547
13179
|
} else {
|
|
@@ -11578,11 +13210,16 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
11578
13210
|
const validNodes = [];
|
|
11579
13211
|
for (const node of nodes) {
|
|
11580
13212
|
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
11581
|
-
const
|
|
11582
|
-
|
|
11583
|
-
|
|
11584
|
-
|
|
11585
|
-
|
|
13213
|
+
const sequence = refundTx.getInput(0).sequence;
|
|
13214
|
+
if (!sequence) {
|
|
13215
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
13216
|
+
field: "sequence",
|
|
13217
|
+
value: refundTx.getInput(0),
|
|
13218
|
+
expected: "Non-null sequence"
|
|
13219
|
+
});
|
|
13220
|
+
}
|
|
13221
|
+
const needsRefresh = doesLeafNeedRefresh(sequence);
|
|
13222
|
+
if (needsRefresh) {
|
|
11586
13223
|
nodesToRefresh.push(node);
|
|
11587
13224
|
nodeIds.push(node.id);
|
|
11588
13225
|
} else {
|
|
@@ -11616,7 +13253,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
11616
13253
|
throw new Error(`parent node ${node.parentNodeId} not found`);
|
|
11617
13254
|
}
|
|
11618
13255
|
const { nodes: nodes2 } = await this.transferService.refreshTimelockNodes(
|
|
11619
|
-
|
|
13256
|
+
node,
|
|
11620
13257
|
parentNode
|
|
11621
13258
|
);
|
|
11622
13259
|
if (nodes2.length !== 1) {
|
|
@@ -11665,7 +13302,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
11665
13302
|
leavesToClaim.push({
|
|
11666
13303
|
leaf: {
|
|
11667
13304
|
...leaf.leaf,
|
|
11668
|
-
refundTx: leaf.intermediateRefundTx
|
|
13305
|
+
refundTx: leaf.intermediateRefundTx,
|
|
13306
|
+
directRefundTx: leaf.intermediateDirectRefundTx,
|
|
13307
|
+
directFromCpfpRefundTx: leaf.intermediateDirectFromCpfpRefundTx
|
|
11669
13308
|
},
|
|
11670
13309
|
keyDerivation: {
|
|
11671
13310
|
type: "ecies" /* ECIES */,
|
|
@@ -11741,7 +13380,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
11741
13380
|
if (type && transfer.type !== type) {
|
|
11742
13381
|
continue;
|
|
11743
13382
|
}
|
|
11744
|
-
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 */) {
|
|
13383
|
+
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 */ && transfer.status !== 9 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAK_LOCKED */) {
|
|
11745
13384
|
continue;
|
|
11746
13385
|
}
|
|
11747
13386
|
promises.push(
|
|
@@ -12029,6 +13668,8 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
12029
13668
|
await this.transferService.deliverTransferPackage(
|
|
12030
13669
|
swapResponse.transfer,
|
|
12031
13670
|
leavesToSend,
|
|
13671
|
+
/* @__PURE__ */ new Map(),
|
|
13672
|
+
/* @__PURE__ */ new Map(),
|
|
12032
13673
|
/* @__PURE__ */ new Map()
|
|
12033
13674
|
);
|
|
12034
13675
|
const sspResponse = await sspClient.requestLightningSend({
|
|
@@ -12308,11 +13949,12 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
12308
13949
|
* Gets a transfer that has been sent by the SSP to the wallet.
|
|
12309
13950
|
*
|
|
12310
13951
|
* @param {string} id - The ID of the transfer
|
|
12311
|
-
* @returns {Promise<
|
|
13952
|
+
* @returns {Promise<TransferWithUserRequest | undefined>} The transfer
|
|
12312
13953
|
*/
|
|
12313
13954
|
async getTransferFromSsp(id) {
|
|
12314
13955
|
const sspClient = this.getSspClient();
|
|
12315
|
-
|
|
13956
|
+
const transfers = await sspClient.getTransfers([id]);
|
|
13957
|
+
return transfers?.[0];
|
|
12316
13958
|
}
|
|
12317
13959
|
/**
|
|
12318
13960
|
* Gets a transfer, that the wallet is a participant of, in the Spark network.
|
|
@@ -12791,87 +14433,64 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
12791
14433
|
},
|
|
12792
14434
|
includeParents: true
|
|
12793
14435
|
});
|
|
12794
|
-
|
|
12795
|
-
if (!
|
|
14436
|
+
let leaf = response.nodes[nodeId];
|
|
14437
|
+
if (!leaf) {
|
|
12796
14438
|
throw new ValidationError("Node not found", {
|
|
12797
14439
|
field: "nodeId",
|
|
12798
14440
|
value: nodeId
|
|
12799
14441
|
});
|
|
12800
14442
|
}
|
|
12801
|
-
|
|
12802
|
-
|
|
12803
|
-
|
|
12804
|
-
|
|
12805
|
-
|
|
12806
|
-
|
|
12807
|
-
|
|
12808
|
-
|
|
12809
|
-
|
|
12810
|
-
|
|
12811
|
-
|
|
12812
|
-
});
|
|
12813
|
-
}
|
|
12814
|
-
const result = await this.transferService.refreshTimelockNodes(
|
|
12815
|
-
[node],
|
|
12816
|
-
parentNode
|
|
12817
|
-
);
|
|
12818
|
-
const leafIndex = this.leaves.findIndex((leaf) => leaf.id === node.id);
|
|
12819
|
-
if (leafIndex !== -1 && result.nodes.length > 0) {
|
|
12820
|
-
const newNode = result.nodes[0];
|
|
12821
|
-
if (newNode) {
|
|
12822
|
-
this.leaves[leafIndex] = newNode;
|
|
14443
|
+
let parentNode;
|
|
14444
|
+
let hasParentNode = false;
|
|
14445
|
+
if (!leaf.parentNodeId) {
|
|
14446
|
+
} else {
|
|
14447
|
+
hasParentNode = true;
|
|
14448
|
+
parentNode = response.nodes[leaf.parentNodeId];
|
|
14449
|
+
if (!parentNode) {
|
|
14450
|
+
throw new ValidationError("Parent node not found", {
|
|
14451
|
+
field: "parentNodeId",
|
|
14452
|
+
value: leaf.parentNodeId
|
|
14453
|
+
});
|
|
12823
14454
|
}
|
|
12824
14455
|
}
|
|
12825
|
-
|
|
12826
|
-
|
|
12827
|
-
|
|
12828
|
-
|
|
12829
|
-
|
|
12830
|
-
|
|
12831
|
-
|
|
12832
|
-
|
|
12833
|
-
|
|
12834
|
-
|
|
12835
|
-
|
|
12836
|
-
|
|
12837
|
-
|
|
12838
|
-
|
|
12839
|
-
* @returns {Promise<void>} Promise that resolves when the refund timelock is refreshed
|
|
12840
|
-
*/
|
|
12841
|
-
async testOnly_expireTimelockRefundTx(nodeId) {
|
|
12842
|
-
const sparkClient = await this.connectionManager.createSparkClient(
|
|
12843
|
-
this.config.getCoordinatorAddress()
|
|
12844
|
-
);
|
|
12845
|
-
try {
|
|
12846
|
-
const response = await sparkClient.query_nodes({
|
|
12847
|
-
source: {
|
|
12848
|
-
$case: "nodeIds",
|
|
12849
|
-
nodeIds: {
|
|
12850
|
-
nodeIds: [nodeId]
|
|
14456
|
+
const nodeTx = getTxFromRawTxBytes(leaf.nodeTx);
|
|
14457
|
+
const refundTx = getTxFromRawTxBytes(leaf.refundTx);
|
|
14458
|
+
if (hasParentNode) {
|
|
14459
|
+
const nodeTimelock = getCurrentTimelock(nodeTx.getInput(0).sequence);
|
|
14460
|
+
if (nodeTimelock > 100) {
|
|
14461
|
+
const expiredNodeTxLeaf = await this.transferService.testonly_expireTimeLockNodeTx(
|
|
14462
|
+
leaf,
|
|
14463
|
+
parentNode
|
|
14464
|
+
);
|
|
14465
|
+
if (!expiredNodeTxLeaf.nodes[0]) {
|
|
14466
|
+
throw new ValidationError("No expired node tx leaf", {
|
|
14467
|
+
field: "expiredNodeTxLeaf",
|
|
14468
|
+
value: expiredNodeTxLeaf
|
|
14469
|
+
});
|
|
12851
14470
|
}
|
|
12852
|
-
|
|
12853
|
-
|
|
12854
|
-
});
|
|
12855
|
-
const node = response.nodes[nodeId];
|
|
12856
|
-
if (!node) {
|
|
12857
|
-
throw new ValidationError("Node not found", {
|
|
12858
|
-
field: "nodeId",
|
|
12859
|
-
value: nodeId
|
|
12860
|
-
});
|
|
14471
|
+
leaf = expiredNodeTxLeaf.nodes[0];
|
|
14472
|
+
}
|
|
12861
14473
|
}
|
|
12862
|
-
const
|
|
12863
|
-
|
|
12864
|
-
|
|
12865
|
-
|
|
12866
|
-
|
|
12867
|
-
|
|
14474
|
+
const refundTimelock = getCurrentTimelock(refundTx.getInput(0).sequence);
|
|
14475
|
+
if (refundTimelock > 100) {
|
|
14476
|
+
const expiredTxLeaf = await this.transferService.testonly_expireTimeLockRefundtx(leaf);
|
|
14477
|
+
if (!expiredTxLeaf.nodes[0]) {
|
|
14478
|
+
throw new ValidationError("No expired tx leaf", {
|
|
14479
|
+
field: "expiredTxLeaf",
|
|
14480
|
+
value: expiredTxLeaf
|
|
14481
|
+
});
|
|
12868
14482
|
}
|
|
14483
|
+
leaf = expiredTxLeaf.nodes[0];
|
|
14484
|
+
}
|
|
14485
|
+
const leafIndex = this.leaves.findIndex((leaf2) => leaf2.id === leaf2.id);
|
|
14486
|
+
if (leafIndex !== -1) {
|
|
14487
|
+
this.leaves[leafIndex] = leaf;
|
|
12869
14488
|
}
|
|
12870
14489
|
} catch (error) {
|
|
12871
14490
|
throw new NetworkError(
|
|
12872
|
-
"Failed to refresh
|
|
14491
|
+
"Failed to refresh timelock",
|
|
12873
14492
|
{
|
|
12874
|
-
method: "
|
|
14493
|
+
method: "refresh_timelock"
|
|
12875
14494
|
},
|
|
12876
14495
|
error
|
|
12877
14496
|
);
|
|
@@ -12933,16 +14552,17 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
12933
14552
|
|
|
12934
14553
|
// src/utils/mempool.ts
|
|
12935
14554
|
async function getLatestDepositTxId(address2) {
|
|
14555
|
+
const { fetch: fetch2, Headers: Headers2 } = getFetch();
|
|
12936
14556
|
const network = getNetworkFromAddress(address2);
|
|
12937
14557
|
const baseUrl = network === BitcoinNetwork_default.REGTEST ? getElectrsUrl("REGTEST") : getElectrsUrl("MAINNET");
|
|
12938
|
-
const headers =
|
|
14558
|
+
const headers = new Headers2();
|
|
12939
14559
|
if (network === BitcoinNetwork_default.REGTEST) {
|
|
12940
14560
|
const auth = btoa(
|
|
12941
14561
|
`${ELECTRS_CREDENTIALS.username}:${ELECTRS_CREDENTIALS.password}`
|
|
12942
14562
|
);
|
|
12943
|
-
headers
|
|
14563
|
+
headers.set("Authorization", `Basic ${auth}`);
|
|
12944
14564
|
}
|
|
12945
|
-
const response = await
|
|
14565
|
+
const response = await fetch2(`${baseUrl}/address/${address2}/txs`, {
|
|
12946
14566
|
headers
|
|
12947
14567
|
});
|
|
12948
14568
|
const addressTxs = await response.json();
|
|
@@ -12959,14 +14579,15 @@ async function getLatestDepositTxId(address2) {
|
|
|
12959
14579
|
return null;
|
|
12960
14580
|
}
|
|
12961
14581
|
async function isTxBroadcast(txid, baseUrl, network) {
|
|
12962
|
-
const
|
|
14582
|
+
const { fetch: fetch2, Headers: Headers2 } = getFetch();
|
|
14583
|
+
const headers = new Headers2();
|
|
12963
14584
|
if (network === 3 /* REGTEST */) {
|
|
12964
14585
|
const auth = btoa(
|
|
12965
14586
|
`${ELECTRS_CREDENTIALS.username}:${ELECTRS_CREDENTIALS.password}`
|
|
12966
14587
|
);
|
|
12967
|
-
headers
|
|
14588
|
+
headers.set("Authorization", `Basic ${auth}`);
|
|
12968
14589
|
}
|
|
12969
|
-
const response = await
|
|
14590
|
+
const response = await fetch2(`${baseUrl}/tx/${txid}`, {
|
|
12970
14591
|
headers
|
|
12971
14592
|
});
|
|
12972
14593
|
const tx = await response.json();
|
|
@@ -12980,7 +14601,7 @@ async function isTxBroadcast(txid, baseUrl, network) {
|
|
|
12980
14601
|
import { bytesToHex as bytesToHex12, hexToBytes as hexToBytes13 } from "@noble/curves/abstract/utils";
|
|
12981
14602
|
import { ripemd160 } from "@noble/hashes/legacy";
|
|
12982
14603
|
import { sha256 as sha25612 } from "@noble/hashes/sha2";
|
|
12983
|
-
import * as
|
|
14604
|
+
import * as btc4 from "@scure/btc-signer";
|
|
12984
14605
|
function isEphemeralAnchorOutput(script, amount) {
|
|
12985
14606
|
return Boolean(
|
|
12986
14607
|
amount === 0n && script && // Pattern 1: Bare OP_TRUE (single byte 0x51)
|
|
@@ -13195,7 +14816,7 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
13195
14816
|
usedUtxos,
|
|
13196
14817
|
correctedParentTx
|
|
13197
14818
|
} = constructFeeBumpTx(nodeTxHex, availableUtxos, feeRate, void 0);
|
|
13198
|
-
const feeBumpTx =
|
|
14819
|
+
const feeBumpTx = btc4.Transaction.fromPSBT(hexToBytes13(nodeFeeBumpPsbt));
|
|
13199
14820
|
var feeBumpOut = feeBumpTx.outputsLength === 1 ? feeBumpTx.getOutput(0) : null;
|
|
13200
14821
|
var feeBumpOutPubKey = null;
|
|
13201
14822
|
for (const usedUtxo of usedUtxos) {
|
|
@@ -13249,7 +14870,7 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
13249
14870
|
feeRate,
|
|
13250
14871
|
void 0
|
|
13251
14872
|
);
|
|
13252
|
-
const feeBumpTx2 =
|
|
14873
|
+
const feeBumpTx2 = btc4.Transaction.fromPSBT(
|
|
13253
14874
|
hexToBytes13(refundFeeBump.feeBumpPsbt)
|
|
13254
14875
|
);
|
|
13255
14876
|
var feeBumpOut = feeBumpTx2.outputsLength === 1 ? feeBumpTx2.getOutput(0) : null;
|
|
@@ -13353,7 +14974,7 @@ function constructFeeBumpTx(txHex, utxos, feeRate, previousFeeBumpTx) {
|
|
|
13353
14974
|
if (utxos.length === 0) {
|
|
13354
14975
|
throw new Error("No UTXOs available for fee bump");
|
|
13355
14976
|
}
|
|
13356
|
-
const builder = new
|
|
14977
|
+
const builder = new btc4.Transaction({
|
|
13357
14978
|
version: 3,
|
|
13358
14979
|
allowUnknown: true,
|
|
13359
14980
|
allowLegacyWitnessUtxo: true
|
|
@@ -13445,19 +15066,19 @@ function constructFeeBumpTx(txHex, utxos, feeRate, previousFeeBumpTx) {
|
|
|
13445
15066
|
}
|
|
13446
15067
|
|
|
13447
15068
|
// src/utils/xchain-address.ts
|
|
13448
|
-
import * as
|
|
15069
|
+
import * as btc5 from "@scure/btc-signer";
|
|
13449
15070
|
var networkByType = {
|
|
13450
|
-
MAINNET:
|
|
13451
|
-
TESTNET:
|
|
15071
|
+
MAINNET: btc5.NETWORK,
|
|
15072
|
+
TESTNET: btc5.TEST_NETWORK,
|
|
13452
15073
|
REGTEST: {
|
|
13453
|
-
...
|
|
15074
|
+
...btc5.TEST_NETWORK,
|
|
13454
15075
|
bech32: "bcrt"
|
|
13455
15076
|
}
|
|
13456
15077
|
};
|
|
13457
15078
|
function getSparkAddressFromTaproot(taprootAddress) {
|
|
13458
15079
|
for (const networkType of ["MAINNET", "TESTNET", "REGTEST"]) {
|
|
13459
15080
|
try {
|
|
13460
|
-
const result =
|
|
15081
|
+
const result = btc5.Address(networkByType[networkType]).decode(taprootAddress);
|
|
13461
15082
|
if (result.type === "tr") {
|
|
13462
15083
|
const outputPublicKey = result.pubkey;
|
|
13463
15084
|
return encodeSparkAddress({
|
|
@@ -13478,10 +15099,15 @@ function getSparkAddressFromTaproot(taprootAddress) {
|
|
|
13478
15099
|
var utils_exports = {};
|
|
13479
15100
|
__export(utils_exports, {
|
|
13480
15101
|
DEFAULT_FEE_SATS: () => DEFAULT_FEE_SATS,
|
|
15102
|
+
DIRECT_TIMELOCK_OFFSET: () => DIRECT_TIMELOCK_OFFSET,
|
|
15103
|
+
INITIAL_DIRECT_SEQUENCE: () => INITIAL_DIRECT_SEQUENCE,
|
|
15104
|
+
INITIAL_SEQUENCE: () => INITIAL_SEQUENCE,
|
|
13481
15105
|
LRC_WALLET_NETWORK: () => LRC_WALLET_NETWORK,
|
|
13482
15106
|
LRC_WALLET_NETWORK_TYPE: () => LRC_WALLET_NETWORK_TYPE,
|
|
13483
15107
|
Network: () => Network2,
|
|
13484
15108
|
NetworkToProto: () => NetworkToProto,
|
|
15109
|
+
TEST_UNILATERAL_DIRECT_SEQUENCE: () => TEST_UNILATERAL_DIRECT_SEQUENCE,
|
|
15110
|
+
TEST_UNILATERAL_SEQUENCE: () => TEST_UNILATERAL_SEQUENCE,
|
|
13485
15111
|
addPrivateKeys: () => addPrivateKeys,
|
|
13486
15112
|
addPublicKeys: () => addPublicKeys,
|
|
13487
15113
|
applyAdaptorToSignature: () => applyAdaptorToSignature,
|
|
@@ -13495,13 +15121,21 @@ __export(utils_exports, {
|
|
|
13495
15121
|
constructFeeBumpTx: () => constructFeeBumpTx,
|
|
13496
15122
|
constructUnilateralExitFeeBumpPackages: () => constructUnilateralExitFeeBumpPackages,
|
|
13497
15123
|
constructUnilateralExitTxs: () => constructUnilateralExitTxs,
|
|
15124
|
+
createConnectorRefundTransactions: () => createConnectorRefundTransactions,
|
|
15125
|
+
createLeafNodeTx: () => createLeafNodeTx,
|
|
15126
|
+
createNodeTx: () => createNodeTx,
|
|
15127
|
+
createNodeTxs: () => createNodeTxs,
|
|
13498
15128
|
createRefundTx: () => createRefundTx,
|
|
15129
|
+
createRefundTxs: () => createRefundTxs,
|
|
15130
|
+
createRootTx: () => createRootTx,
|
|
13499
15131
|
createSigningCommitment: () => createSigningCommitment,
|
|
13500
15132
|
createSigningNonce: () => createSigningNonce,
|
|
15133
|
+
createSplitTx: () => createSplitTx,
|
|
13501
15134
|
decodeBech32mTokenIdentifier: () => decodeBech32mTokenIdentifier,
|
|
13502
15135
|
decodeBytesToSigningCommitment: () => decodeBytesToSigningCommitment,
|
|
13503
15136
|
decodeBytesToSigningNonce: () => decodeBytesToSigningNonce,
|
|
13504
15137
|
decodeSparkAddress: () => decodeSparkAddress,
|
|
15138
|
+
doesLeafNeedRefresh: () => doesLeafNeedRefresh,
|
|
13505
15139
|
encodeBech32mTokenIdentifier: () => encodeBech32mTokenIdentifier,
|
|
13506
15140
|
encodeSigningCommitmentToBytes: () => encodeSigningCommitmentToBytes,
|
|
13507
15141
|
encodeSigningNonceToBytes: () => encodeSigningNonceToBytes,
|
|
@@ -13530,6 +15164,7 @@ __export(utils_exports, {
|
|
|
13530
15164
|
getSparkAddressFromTaproot: () => getSparkAddressFromTaproot,
|
|
13531
15165
|
getTransactionSequence: () => getTransactionSequence,
|
|
13532
15166
|
getTransferPackageSigningPayload: () => getTransferPackageSigningPayload,
|
|
15167
|
+
getTxEstimatedVbytesSizeByNumberOfInputsOutputs: () => getTxEstimatedVbytesSizeByNumberOfInputsOutputs,
|
|
13533
15168
|
getTxFromRawTxBytes: () => getTxFromRawTxBytes,
|
|
13534
15169
|
getTxFromRawTxHex: () => getTxFromRawTxHex,
|
|
13535
15170
|
getTxId: () => getTxId,
|
|
@@ -13617,12 +15252,26 @@ export {
|
|
|
13617
15252
|
getSigHashFromTx,
|
|
13618
15253
|
getTxId,
|
|
13619
15254
|
getTxIdNoReverse,
|
|
15255
|
+
getTxEstimatedVbytesSizeByNumberOfInputsOutputs,
|
|
15256
|
+
DIRECT_TIMELOCK_OFFSET,
|
|
15257
|
+
INITIAL_SEQUENCE,
|
|
15258
|
+
INITIAL_DIRECT_SEQUENCE,
|
|
15259
|
+
TEST_UNILATERAL_SEQUENCE,
|
|
15260
|
+
TEST_UNILATERAL_DIRECT_SEQUENCE,
|
|
13620
15261
|
DEFAULT_FEE_SATS,
|
|
13621
15262
|
maybeApplyFee,
|
|
15263
|
+
createRootTx,
|
|
15264
|
+
createSplitTx,
|
|
15265
|
+
createNodeTx,
|
|
15266
|
+
createNodeTxs,
|
|
15267
|
+
createLeafNodeTx,
|
|
13622
15268
|
createRefundTx,
|
|
15269
|
+
createRefundTxs,
|
|
15270
|
+
createConnectorRefundTransactions,
|
|
13623
15271
|
getCurrentTimelock,
|
|
13624
15272
|
getTransactionSequence,
|
|
13625
15273
|
checkIfValidSequence,
|
|
15274
|
+
doesLeafNeedRefresh,
|
|
13626
15275
|
getNextTransactionSequence,
|
|
13627
15276
|
getEphemeralAnchorOutput,
|
|
13628
15277
|
getTransferPackageSigningPayload,
|