@buildonspark/spark-sdk 0.3.8 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/bare/index.cjs +1021 -1205
- package/dist/bare/index.d.cts +102 -66
- package/dist/bare/index.d.ts +102 -66
- package/dist/bare/index.js +946 -1138
- package/dist/{chunk-5ASXVNTM.js → chunk-4YFT7DAE.js} +1 -1
- package/dist/{chunk-XI6FCNYG.js → chunk-JLF6WJ7K.js} +1 -1
- package/dist/{chunk-5HU5W56H.js → chunk-MFCM6GUD.js} +2 -2
- package/dist/{chunk-FP2CRVQH.js → chunk-O4C4HGQL.js} +727 -1170
- package/dist/{chunk-FXIESWE6.js → chunk-S55NZT4P.js} +1 -1
- package/dist/{chunk-3LPEQGVJ.js → chunk-WRE2T22S.js} +1 -1
- package/dist/{chunk-VFN34EOX.js → chunk-YEBEN7XD.js} +258 -0
- package/dist/{client-pNpGP15j.d.cts → client-BIqiUNy4.d.cts} +1 -1
- package/dist/{client-By-N7oJS.d.ts → client-BaQf-5gD.d.ts} +1 -1
- package/dist/debug.cjs +1009 -1194
- package/dist/debug.d.cts +19 -16
- package/dist/debug.d.ts +19 -16
- package/dist/debug.js +5 -5
- package/dist/graphql/objects/index.d.cts +3 -3
- package/dist/graphql/objects/index.d.ts +3 -3
- package/dist/index.cjs +1041 -1223
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +30 -24
- package/dist/index.node.cjs +1041 -1223
- package/dist/index.node.d.cts +7 -7
- package/dist/index.node.d.ts +7 -7
- package/dist/index.node.js +29 -23
- package/dist/{logging-DMFVY384.d.ts → logging-CXhvuqJJ.d.cts} +41 -37
- package/dist/{logging-DxLp34Xm.d.cts → logging-DDeMLsVN.d.ts} +41 -37
- package/dist/native/index.react-native.cjs +1040 -1222
- package/dist/native/index.react-native.d.cts +92 -56
- package/dist/native/index.react-native.d.ts +92 -56
- package/dist/native/index.react-native.js +952 -1144
- package/dist/proto/spark.cjs +258 -0
- package/dist/proto/spark.d.cts +1 -1
- package/dist/proto/spark.d.ts +1 -1
- package/dist/proto/spark.js +5 -1
- package/dist/proto/spark_token.d.cts +1 -1
- package/dist/proto/spark_token.d.ts +1 -1
- package/dist/proto/spark_token.js +2 -2
- package/dist/{spark-By6yHsrk.d.cts → spark-DOpheE8_.d.cts} +39 -2
- package/dist/{spark-By6yHsrk.d.ts → spark-DOpheE8_.d.ts} +39 -2
- package/dist/{spark-wallet.browser-CNMo3IvO.d.cts → spark-wallet.browser-CbYo8A_U.d.cts} +2 -2
- package/dist/{spark-wallet.browser-C1dQknVj.d.ts → spark-wallet.browser-Cz8c4kOW.d.ts} +2 -2
- package/dist/{spark-wallet.node-BZJhJZKq.d.cts → spark-wallet.node-4WQgWwB2.d.cts} +2 -2
- package/dist/{spark-wallet.node-Og6__NMh.d.ts → spark-wallet.node-CmIvxtcC.d.ts} +2 -2
- package/dist/tests/test-utils.cjs +984 -1094
- package/dist/tests/test-utils.d.cts +4 -4
- package/dist/tests/test-utils.d.ts +4 -4
- package/dist/tests/test-utils.js +7 -7
- package/dist/{token-transactions-C7yefB2S.d.ts → token-transactions-Bu023ztN.d.ts} +2 -2
- package/dist/{token-transactions-CLR3rnYi.d.cts → token-transactions-CV8QD3I7.d.cts} +2 -2
- package/dist/types/index.cjs +256 -0
- package/dist/types/index.d.cts +2 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.js +2 -2
- package/dist/{wallet-config-BoyMVa6n.d.ts → wallet-config-Bmk2eAn8.d.ts} +31 -33
- package/dist/{wallet-config-xom-9UFF.d.cts → wallet-config-DQw5llqA.d.cts} +31 -33
- package/package.json +1 -1
- package/src/proto/spark.ts +348 -4
- package/src/services/coop-exit.ts +26 -107
- package/src/services/deposit.ts +12 -48
- package/src/services/signing.ts +62 -49
- package/src/services/transfer.ts +437 -722
- package/src/spark-wallet/proto-descriptors.ts +1 -1
- package/src/spark-wallet/spark-wallet.ts +64 -239
- package/src/spark-wallet/types.ts +2 -2
- package/src/spark_descriptors.pb +0 -0
- package/src/tests/integration/lightning.test.ts +7 -5
- package/src/tests/integration/static_deposit.test.ts +2 -1
- package/src/utils/transaction.ts +250 -249
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
} from "./chunk-NX5KPN5F.js";
|
|
5
5
|
import {
|
|
6
6
|
SparkTokenServiceDefinition
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-JLF6WJ7K.js";
|
|
8
8
|
import {
|
|
9
9
|
mapTransferToWalletTransfer,
|
|
10
10
|
mapTreeNodeToWalletLeaf
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-4YFT7DAE.js";
|
|
12
12
|
import {
|
|
13
13
|
SatsPayment,
|
|
14
14
|
SendLeafKeyTweaks,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
TokensPayment,
|
|
19
19
|
TreeNode,
|
|
20
20
|
networkToJSON
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-YEBEN7XD.js";
|
|
22
22
|
import {
|
|
23
23
|
BitcoinNetwork_default,
|
|
24
24
|
ClaimStaticDepositFromJson,
|
|
@@ -700,6 +700,7 @@ function getTxEstimatedVbytesSizeByNumberOfInputsOutputs(numInputs, numOutputs)
|
|
|
700
700
|
}
|
|
701
701
|
|
|
702
702
|
// src/utils/transaction.ts
|
|
703
|
+
import { hexToBytes as hexToBytes2 } from "@noble/hashes/utils";
|
|
703
704
|
import { Transaction as Transaction2 } from "@scure/btc-signer";
|
|
704
705
|
var INITIAL_TIMELOCK = 2e3;
|
|
705
706
|
var TEST_UNILATERAL_TIMELOCK = 100;
|
|
@@ -708,9 +709,9 @@ var DIRECT_TIMELOCK_OFFSET = 50;
|
|
|
708
709
|
var HTLC_TIMELOCK_OFFSET = 70;
|
|
709
710
|
var DIRECT_HTLC_TIMELOCK_OFFSET = 85;
|
|
710
711
|
var INITIAL_SEQUENCE = 1 << 30 | INITIAL_TIMELOCK;
|
|
711
|
-
var INITIAL_DIRECT_SEQUENCE = 1 << 30 | INITIAL_TIMELOCK + DIRECT_TIMELOCK_OFFSET;
|
|
712
712
|
var TEST_UNILATERAL_SEQUENCE = 1 << 30 | TEST_UNILATERAL_TIMELOCK;
|
|
713
713
|
var TEST_UNILATERAL_DIRECT_SEQUENCE = 1 << 30 | TEST_UNILATERAL_TIMELOCK + DIRECT_TIMELOCK_OFFSET;
|
|
714
|
+
var INITIAL_ROOT_NODE_SEQUENCE = 1 << 30 | 0;
|
|
714
715
|
var ESTIMATED_TX_SIZE = 191;
|
|
715
716
|
var DEFAULT_SATS_PER_VBYTE = 5;
|
|
716
717
|
var DEFAULT_FEE_SATS = ESTIMATED_TX_SIZE * DEFAULT_SATS_PER_VBYTE;
|
|
@@ -720,63 +721,8 @@ function maybeApplyFee(amount) {
|
|
|
720
721
|
}
|
|
721
722
|
return amount;
|
|
722
723
|
}
|
|
723
|
-
function createRootTx(depositOutPoint, depositTxOut) {
|
|
724
|
-
const cpfpRootTx = new Transaction2({
|
|
725
|
-
version: 3,
|
|
726
|
-
allowUnknownOutputs: true
|
|
727
|
-
});
|
|
728
|
-
cpfpRootTx.addInput(depositOutPoint);
|
|
729
|
-
cpfpRootTx.addOutput(depositTxOut);
|
|
730
|
-
cpfpRootTx.addOutput(getEphemeralAnchorOutput());
|
|
731
|
-
const directRootTx = new Transaction2({
|
|
732
|
-
version: 3,
|
|
733
|
-
allowUnknownOutputs: true
|
|
734
|
-
});
|
|
735
|
-
directRootTx.addInput(depositOutPoint);
|
|
736
|
-
directRootTx.addOutput({
|
|
737
|
-
script: depositTxOut.script,
|
|
738
|
-
amount: maybeApplyFee(depositTxOut.amount ?? 0n)
|
|
739
|
-
});
|
|
740
|
-
return [cpfpRootTx, directRootTx];
|
|
741
|
-
}
|
|
742
|
-
function createSplitTx(parentOutPoint, childTxOuts) {
|
|
743
|
-
const cpfpSplitTx = new Transaction2({
|
|
744
|
-
version: 3,
|
|
745
|
-
allowUnknownOutputs: true
|
|
746
|
-
});
|
|
747
|
-
cpfpSplitTx.addInput(parentOutPoint);
|
|
748
|
-
for (const txOut of childTxOuts) {
|
|
749
|
-
cpfpSplitTx.addOutput(txOut);
|
|
750
|
-
}
|
|
751
|
-
cpfpSplitTx.addOutput(getEphemeralAnchorOutput());
|
|
752
|
-
const directSplitTx = new Transaction2({
|
|
753
|
-
version: 3,
|
|
754
|
-
allowUnknownOutputs: true
|
|
755
|
-
});
|
|
756
|
-
directSplitTx.addInput(parentOutPoint);
|
|
757
|
-
let totalOutputAmount = 0n;
|
|
758
|
-
for (const txOut of childTxOuts) {
|
|
759
|
-
totalOutputAmount += txOut.amount ?? 0n;
|
|
760
|
-
}
|
|
761
|
-
if (totalOutputAmount > BigInt(DEFAULT_FEE_SATS)) {
|
|
762
|
-
const feeRatio = Number(DEFAULT_FEE_SATS) / Number(totalOutputAmount);
|
|
763
|
-
for (const txOut of childTxOuts) {
|
|
764
|
-
const adjustedAmount = BigInt(
|
|
765
|
-
Math.floor(Number(txOut.amount ?? 0n) * (1 - feeRatio))
|
|
766
|
-
);
|
|
767
|
-
directSplitTx.addOutput({
|
|
768
|
-
script: txOut.script,
|
|
769
|
-
amount: adjustedAmount
|
|
770
|
-
});
|
|
771
|
-
}
|
|
772
|
-
} else {
|
|
773
|
-
for (const txOut of childTxOuts) {
|
|
774
|
-
directSplitTx.addOutput(txOut);
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
return [cpfpSplitTx, directSplitTx];
|
|
778
|
-
}
|
|
779
724
|
function createNodeTx({
|
|
725
|
+
sequence,
|
|
780
726
|
txOut,
|
|
781
727
|
parentOutPoint,
|
|
782
728
|
applyFee,
|
|
@@ -786,7 +732,10 @@ function createNodeTx({
|
|
|
786
732
|
version: 3,
|
|
787
733
|
allowUnknownOutputs: true
|
|
788
734
|
});
|
|
789
|
-
nodeTx.addInput(
|
|
735
|
+
nodeTx.addInput({
|
|
736
|
+
...parentOutPoint,
|
|
737
|
+
sequence
|
|
738
|
+
});
|
|
790
739
|
if (applyFee) {
|
|
791
740
|
nodeTx.addOutput({
|
|
792
741
|
script: txOut.script,
|
|
@@ -800,52 +749,92 @@ function createNodeTx({
|
|
|
800
749
|
}
|
|
801
750
|
return nodeTx;
|
|
802
751
|
}
|
|
803
|
-
function createNodeTxs(
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
if (
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
includeAnchor: false,
|
|
815
|
-
applyFee: true
|
|
752
|
+
function createNodeTxs({
|
|
753
|
+
parentTx,
|
|
754
|
+
sequence,
|
|
755
|
+
directSequence,
|
|
756
|
+
vout
|
|
757
|
+
}) {
|
|
758
|
+
const parentOutput = parentTx.getOutput(vout);
|
|
759
|
+
if (!parentOutput.amount || !parentOutput.script) {
|
|
760
|
+
throw new ValidationError("Parent output amount or script not found", {
|
|
761
|
+
field: "parentOutput",
|
|
762
|
+
value: parentOutput
|
|
816
763
|
});
|
|
817
764
|
}
|
|
818
|
-
|
|
765
|
+
const output = {
|
|
766
|
+
script: parentOutput.script,
|
|
767
|
+
amount: parentOutput.amount
|
|
768
|
+
};
|
|
769
|
+
const input = {
|
|
770
|
+
txid: hexToBytes2(getTxId(parentTx)),
|
|
771
|
+
index: vout
|
|
772
|
+
};
|
|
773
|
+
const nodeTx = createNodeTx({
|
|
774
|
+
sequence,
|
|
775
|
+
txOut: output,
|
|
776
|
+
parentOutPoint: input,
|
|
777
|
+
includeAnchor: true
|
|
778
|
+
});
|
|
779
|
+
const directNodeTx = createNodeTx({
|
|
780
|
+
sequence: directSequence ?? sequence + DIRECT_TIMELOCK_OFFSET,
|
|
781
|
+
txOut: output,
|
|
782
|
+
parentOutPoint: input,
|
|
783
|
+
includeAnchor: false,
|
|
784
|
+
applyFee: true
|
|
785
|
+
});
|
|
786
|
+
return { nodeTx, directNodeTx };
|
|
819
787
|
}
|
|
820
|
-
function
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
788
|
+
function createRootNodeTx(parentTx, vout) {
|
|
789
|
+
return createNodeTxs({
|
|
790
|
+
parentTx,
|
|
791
|
+
sequence: INITIAL_ROOT_NODE_SEQUENCE,
|
|
792
|
+
vout
|
|
824
793
|
});
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
794
|
+
}
|
|
795
|
+
function createZeroTimelockNodeTx(parentTx) {
|
|
796
|
+
return createNodeTxs({
|
|
797
|
+
parentTx,
|
|
798
|
+
sequence: INITIAL_ROOT_NODE_SEQUENCE,
|
|
799
|
+
directSequence: DIRECT_TIMELOCK_OFFSET,
|
|
800
|
+
vout: 0
|
|
828
801
|
});
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
802
|
+
}
|
|
803
|
+
function createInitialTimelockNodeTx(parentTx) {
|
|
804
|
+
return createNodeTxs({
|
|
805
|
+
parentTx,
|
|
806
|
+
sequence: INITIAL_SEQUENCE,
|
|
807
|
+
vout: 0
|
|
834
808
|
});
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
809
|
+
}
|
|
810
|
+
function createDecrementedTimelockNodeTx(parentTx, currentTx) {
|
|
811
|
+
const currentSequence = currentTx.getInput(0).sequence;
|
|
812
|
+
if (!currentSequence) {
|
|
813
|
+
throw new ValidationError("Current sequence not found", {
|
|
814
|
+
field: "currentSequence",
|
|
815
|
+
value: currentSequence
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
return createNodeTxs({
|
|
819
|
+
parentTx,
|
|
820
|
+
sequence: getNextTransactionSequence(currentSequence).nextSequence,
|
|
821
|
+
vout: 0
|
|
838
822
|
});
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
823
|
+
}
|
|
824
|
+
function createTestUnilateralTimelockNodeTx(parentTx, nodeTx) {
|
|
825
|
+
const sequence = nodeTx.getInput(0).sequence;
|
|
826
|
+
if (!sequence) {
|
|
827
|
+
throw new ValidationError("Sequence not found", {
|
|
828
|
+
field: "sequence",
|
|
829
|
+
value: sequence
|
|
830
|
+
});
|
|
843
831
|
}
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
832
|
+
const isBit30Defined = (sequence || 0) & 1 << 30;
|
|
833
|
+
return createNodeTxs({
|
|
834
|
+
parentTx,
|
|
835
|
+
sequence: isBit30Defined | TEST_UNILATERAL_TIMELOCK,
|
|
836
|
+
vout: 0
|
|
847
837
|
});
|
|
848
|
-
return [cpfpLeafTx, directLeafTx];
|
|
849
838
|
}
|
|
850
839
|
function createRefundTx({
|
|
851
840
|
sequence,
|
|
@@ -901,110 +890,109 @@ function getNextHTLCTransactionSequence(currSequence, isNodeTx) {
|
|
|
901
890
|
};
|
|
902
891
|
}
|
|
903
892
|
function createRefundTxs({
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
input,
|
|
907
|
-
directInput,
|
|
908
|
-
amountSats,
|
|
893
|
+
nodeTx,
|
|
894
|
+
directNodeTx,
|
|
909
895
|
receivingPubkey,
|
|
910
|
-
network
|
|
896
|
+
network,
|
|
897
|
+
sequence
|
|
911
898
|
}) {
|
|
912
|
-
const
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
899
|
+
const refundInput = {
|
|
900
|
+
txid: hexToBytes2(getTxId(nodeTx)),
|
|
901
|
+
index: 0
|
|
902
|
+
};
|
|
903
|
+
const nodeAmountSats = nodeTx.getOutput(0).amount;
|
|
904
|
+
if (nodeAmountSats === void 0) {
|
|
905
|
+
throw new ValidationError("Node amount not found", {
|
|
906
|
+
field: "nodeAmountSats",
|
|
907
|
+
value: nodeAmountSats
|
|
908
|
+
});
|
|
909
|
+
}
|
|
921
910
|
let directRefundTx;
|
|
922
|
-
|
|
923
|
-
|
|
911
|
+
if (directNodeTx) {
|
|
912
|
+
const directRefundInput = {
|
|
913
|
+
txid: hexToBytes2(getTxId(directNodeTx)),
|
|
914
|
+
index: 0
|
|
915
|
+
};
|
|
916
|
+
const directAmountSats = directNodeTx.getOutput(0).amount;
|
|
917
|
+
if (directAmountSats === void 0) {
|
|
918
|
+
throw new ValidationError("Direct amount not found", {
|
|
919
|
+
field: "directAmountSats",
|
|
920
|
+
value: directAmountSats
|
|
921
|
+
});
|
|
922
|
+
}
|
|
924
923
|
directRefundTx = createRefundTx({
|
|
925
|
-
sequence:
|
|
926
|
-
input:
|
|
927
|
-
amountSats,
|
|
928
|
-
receivingPubkey,
|
|
929
|
-
network,
|
|
930
|
-
shouldCalculateFee: true,
|
|
931
|
-
includeAnchor: false
|
|
932
|
-
});
|
|
933
|
-
directFromCpfpRefundTx = createRefundTx({
|
|
934
|
-
sequence: directSequence,
|
|
935
|
-
input,
|
|
936
|
-
amountSats,
|
|
924
|
+
sequence: sequence + DIRECT_TIMELOCK_OFFSET,
|
|
925
|
+
input: directRefundInput,
|
|
926
|
+
amountSats: directAmountSats,
|
|
937
927
|
receivingPubkey,
|
|
938
928
|
network,
|
|
939
929
|
shouldCalculateFee: true,
|
|
940
930
|
includeAnchor: false
|
|
941
931
|
});
|
|
942
|
-
} else if (directInput && !directSequence) {
|
|
943
|
-
throw new ValidationError(
|
|
944
|
-
"directSequence must be provided if directInput is",
|
|
945
|
-
{
|
|
946
|
-
field: "directSequence",
|
|
947
|
-
value: directSequence
|
|
948
|
-
}
|
|
949
|
-
);
|
|
950
932
|
}
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
933
|
+
const cpfpRefundTx = createRefundTx({
|
|
934
|
+
sequence,
|
|
935
|
+
input: refundInput,
|
|
936
|
+
amountSats: nodeAmountSats,
|
|
937
|
+
receivingPubkey,
|
|
938
|
+
network,
|
|
939
|
+
shouldCalculateFee: false,
|
|
940
|
+
includeAnchor: true
|
|
957
941
|
});
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
942
|
+
const directFromCpfpRefundTx = createRefundTx({
|
|
943
|
+
sequence: sequence + DIRECT_TIMELOCK_OFFSET,
|
|
944
|
+
input: refundInput,
|
|
945
|
+
amountSats: nodeAmountSats,
|
|
946
|
+
receivingPubkey,
|
|
947
|
+
network,
|
|
948
|
+
shouldCalculateFee: true,
|
|
949
|
+
includeAnchor: false
|
|
961
950
|
});
|
|
962
|
-
cpfpRefundTx
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
951
|
+
return { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx };
|
|
952
|
+
}
|
|
953
|
+
function createInitialTimelockRefundTxs(params) {
|
|
954
|
+
return createRefundTxs({
|
|
955
|
+
...params,
|
|
956
|
+
sequence: INITIAL_SEQUENCE
|
|
967
957
|
});
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
958
|
+
}
|
|
959
|
+
function createDecrementedTimelockRefundTxs(params) {
|
|
960
|
+
const nextSequence = getNextTransactionSequence(params.sequence).nextSequence;
|
|
961
|
+
return createRefundTxs({
|
|
962
|
+
...params,
|
|
963
|
+
sequence: nextSequence
|
|
971
964
|
});
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
965
|
+
}
|
|
966
|
+
function createCurrentTimelockRefundTxs(params) {
|
|
967
|
+
return createRefundTxs(params);
|
|
968
|
+
}
|
|
969
|
+
function createTestUnilateralRefundTxs(params) {
|
|
970
|
+
return createRefundTxs({
|
|
971
|
+
...params,
|
|
972
|
+
sequence: TEST_UNILATERAL_SEQUENCE
|
|
975
973
|
});
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
974
|
+
}
|
|
975
|
+
function createConnectorRefundTxs(params) {
|
|
976
|
+
const { connectorOutput, ...baseParams } = params;
|
|
977
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createDecrementedTimelockRefundTxs(baseParams);
|
|
978
|
+
cpfpRefundTx.addInput(connectorOutput);
|
|
979
|
+
if (directRefundTx) {
|
|
980
|
+
directRefundTx.addInput(connectorOutput);
|
|
980
981
|
}
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
}
|
|
985
|
-
const directFromCpfpTx = new Transaction2({
|
|
986
|
-
version: 3,
|
|
987
|
-
allowUnknownOutputs: true
|
|
988
|
-
});
|
|
989
|
-
directFromCpfpTx.addInput({
|
|
990
|
-
...cpfpNodeOutPoint,
|
|
991
|
-
sequence
|
|
992
|
-
});
|
|
993
|
-
directFromCpfpTx.addInput(connectorOutput);
|
|
994
|
-
directFromCpfpTx.addOutput({
|
|
995
|
-
script: receiverScript,
|
|
996
|
-
amount: outputAmount
|
|
997
|
-
});
|
|
998
|
-
return [cpfpRefundTx, directRefundTx, directFromCpfpTx];
|
|
982
|
+
if (directFromCpfpRefundTx) {
|
|
983
|
+
directFromCpfpRefundTx.addInput(connectorOutput);
|
|
984
|
+
}
|
|
985
|
+
return { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx };
|
|
999
986
|
}
|
|
1000
987
|
function getCurrentTimelock(currSequence) {
|
|
1001
988
|
return (currSequence || 0) & 65535;
|
|
1002
989
|
}
|
|
1003
990
|
function getTransactionSequence(currSequence) {
|
|
1004
991
|
const timelock = getCurrentTimelock(currSequence);
|
|
992
|
+
const isBit30Defined = (currSequence || 0) & 1 << 30;
|
|
1005
993
|
return {
|
|
1006
|
-
nextSequence:
|
|
1007
|
-
nextDirectSequence:
|
|
994
|
+
nextSequence: isBit30Defined | timelock,
|
|
995
|
+
nextDirectSequence: isBit30Defined | timelock + DIRECT_TIMELOCK_OFFSET
|
|
1008
996
|
};
|
|
1009
997
|
}
|
|
1010
998
|
function checkIfValidSequence(currSequence) {
|
|
@@ -1023,6 +1011,13 @@ function checkIfValidSequence(currSequence) {
|
|
|
1023
1011
|
});
|
|
1024
1012
|
}
|
|
1025
1013
|
}
|
|
1014
|
+
function isZeroTimelock(currSequence) {
|
|
1015
|
+
return getCurrentTimelock(currSequence) === 0;
|
|
1016
|
+
}
|
|
1017
|
+
function doesTxnNeedRenewed(currSequence) {
|
|
1018
|
+
const currentTimelock = getCurrentTimelock(currSequence);
|
|
1019
|
+
return currentTimelock <= 100;
|
|
1020
|
+
}
|
|
1026
1021
|
function doesLeafNeedRefresh(currSequence, isNodeTx) {
|
|
1027
1022
|
const currentTimelock = getCurrentTimelock(currSequence);
|
|
1028
1023
|
if (isNodeTx) {
|
|
@@ -1033,6 +1028,7 @@ function doesLeafNeedRefresh(currSequence, isNodeTx) {
|
|
|
1033
1028
|
function getNextTransactionSequence(currSequence, isNodeTx) {
|
|
1034
1029
|
const currentTimelock = getCurrentTimelock(currSequence);
|
|
1035
1030
|
const nextTimelock = currentTimelock - TIME_LOCK_INTERVAL;
|
|
1031
|
+
const isBit30Defined = (currSequence || 0) & 1 << 30;
|
|
1036
1032
|
if (isNodeTx && nextTimelock < 0) {
|
|
1037
1033
|
throw new ValidationError("timelock interval is less than 0", {
|
|
1038
1034
|
field: "nextTimelock",
|
|
@@ -1047,8 +1043,8 @@ function getNextTransactionSequence(currSequence, isNodeTx) {
|
|
|
1047
1043
|
});
|
|
1048
1044
|
}
|
|
1049
1045
|
return {
|
|
1050
|
-
nextSequence:
|
|
1051
|
-
nextDirectSequence:
|
|
1046
|
+
nextSequence: isBit30Defined | nextTimelock,
|
|
1047
|
+
nextDirectSequence: isBit30Defined | nextTimelock + DIRECT_TIMELOCK_OFFSET
|
|
1052
1048
|
};
|
|
1053
1049
|
}
|
|
1054
1050
|
function getEphemeralAnchorOutput() {
|
|
@@ -1070,7 +1066,7 @@ var KeyDerivationType = /* @__PURE__ */ ((KeyDerivationType2) => {
|
|
|
1070
1066
|
})(KeyDerivationType || {});
|
|
1071
1067
|
|
|
1072
1068
|
// src/utils/transfer_package.ts
|
|
1073
|
-
import { hexToBytes as
|
|
1069
|
+
import { hexToBytes as hexToBytes3 } from "@noble/curves/utils";
|
|
1074
1070
|
import { sha256 as sha2562 } from "@noble/hashes/sha2";
|
|
1075
1071
|
function getTransferPackageSigningPayload(transferID, transferPackage) {
|
|
1076
1072
|
const encryptedPayload = transferPackage.keyTweakPackage;
|
|
@@ -1079,7 +1075,7 @@ function getTransferPackageSigningPayload(transferID, transferPackage) {
|
|
|
1079
1075
|
).map(([key, value]) => ({ key, value }));
|
|
1080
1076
|
pairs.sort((a, b) => a.key.localeCompare(b.key));
|
|
1081
1077
|
const encoder = new TextEncoder();
|
|
1082
|
-
let message =
|
|
1078
|
+
let message = hexToBytes3(transferID.replaceAll("-", ""));
|
|
1083
1079
|
for (const pair of pairs) {
|
|
1084
1080
|
const keyPart = encoder.encode(pair.key + ":");
|
|
1085
1081
|
const separator = encoder.encode(";");
|
|
@@ -1207,7 +1203,7 @@ function proofOfPossessionMessageHashForDepositAddress(userPubkey, operatorPubke
|
|
|
1207
1203
|
// src/services/deposit.ts
|
|
1208
1204
|
import { schnorr as schnorr2, secp256k1 as secp256k13 } from "@noble/curves/secp256k1";
|
|
1209
1205
|
import { sha256 as sha2564 } from "@noble/hashes/sha2";
|
|
1210
|
-
import { hexToBytes as
|
|
1206
|
+
import { hexToBytes as hexToBytes4 } from "@noble/hashes/utils";
|
|
1211
1207
|
import { p2tr as p2tr2 } from "@scure/btc-signer";
|
|
1212
1208
|
import { equalBytes } from "@scure/btc-signer/utils";
|
|
1213
1209
|
var DepositService = class {
|
|
@@ -1261,7 +1257,7 @@ var DepositService = class {
|
|
|
1261
1257
|
if (operator.identifier === this.config.getCoordinatorIdentifier() && !verifyCoordinatorProof) {
|
|
1262
1258
|
continue;
|
|
1263
1259
|
}
|
|
1264
|
-
const operatorPubkey2 =
|
|
1260
|
+
const operatorPubkey2 = hexToBytes4(operator.identityPublicKey);
|
|
1265
1261
|
const operatorSig = address.depositAddressProof.addressSignatures[operator.identifier];
|
|
1266
1262
|
if (!operatorSig) {
|
|
1267
1263
|
throw new ValidationError("Operator signature not found", {
|
|
@@ -1380,38 +1376,18 @@ var DepositService = class {
|
|
|
1380
1376
|
expected: "Valid output index"
|
|
1381
1377
|
});
|
|
1382
1378
|
}
|
|
1383
|
-
const
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
throw new ValidationError("No script or amount found in deposit tx", {
|
|
1387
|
-
field: "output",
|
|
1388
|
-
value: output,
|
|
1389
|
-
expected: "Output with script and amount"
|
|
1390
|
-
});
|
|
1391
|
-
}
|
|
1392
|
-
const depositOutPoint = {
|
|
1393
|
-
txid: hexToBytes3(getTxId(depositTx)),
|
|
1394
|
-
index: vout
|
|
1395
|
-
};
|
|
1396
|
-
const depositTxOut = {
|
|
1397
|
-
script,
|
|
1398
|
-
amount
|
|
1399
|
-
};
|
|
1400
|
-
const [cpfpRootTx, directRootTx] = createRootTx(
|
|
1401
|
-
depositOutPoint,
|
|
1402
|
-
depositTxOut
|
|
1379
|
+
const { nodeTx: cpfpRootTx, directNodeTx: directRootTx } = createRootNodeTx(
|
|
1380
|
+
depositTx,
|
|
1381
|
+
vout
|
|
1403
1382
|
);
|
|
1404
1383
|
const cpfpRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
1405
1384
|
const directRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
1406
1385
|
const cpfpRootTxSighash = getSigHashFromTx(cpfpRootTx, 0, output);
|
|
1407
1386
|
const directRootTxSighash = getSigHashFromTx(directRootTx, 0, output);
|
|
1408
1387
|
const signingPubKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
1409
|
-
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } =
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
input: { txid: hexToBytes3(getTxId(cpfpRootTx)), index: 0 },
|
|
1413
|
-
directInput: { txid: hexToBytes3(getTxId(directRootTx)), index: 0 },
|
|
1414
|
-
amountSats: amount,
|
|
1388
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createInitialTimelockRefundTxs({
|
|
1389
|
+
nodeTx: cpfpRootTx,
|
|
1390
|
+
directNodeTx: directRootTx,
|
|
1415
1391
|
receivingPubkey: signingPubKey,
|
|
1416
1392
|
network: this.config.getNetwork()
|
|
1417
1393
|
});
|
|
@@ -1703,22 +1679,12 @@ var DepositService = class {
|
|
|
1703
1679
|
expected: "Output with script and amount"
|
|
1704
1680
|
});
|
|
1705
1681
|
}
|
|
1706
|
-
const
|
|
1707
|
-
txid: hexToBytes3(getTxId(depositTx)),
|
|
1708
|
-
index: vout
|
|
1709
|
-
};
|
|
1710
|
-
const depositTxOut = {
|
|
1711
|
-
script,
|
|
1712
|
-
amount
|
|
1713
|
-
};
|
|
1714
|
-
const [cpfpRootTx, _] = createRootTx(depositOutPoint, depositTxOut);
|
|
1682
|
+
const { nodeTx: cpfpRootTx } = createRootNodeTx(depositTx, vout);
|
|
1715
1683
|
const cpfpRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
1716
1684
|
const cpfpRootTxSighash = getSigHashFromTx(cpfpRootTx, 0, output);
|
|
1717
1685
|
const signingPubKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
1718
|
-
const { cpfpRefundTx } =
|
|
1719
|
-
|
|
1720
|
-
input: { txid: hexToBytes3(getTxId(cpfpRootTx)), index: 0 },
|
|
1721
|
-
amountSats: amount,
|
|
1686
|
+
const { cpfpRefundTx } = createInitialTimelockRefundTxs({
|
|
1687
|
+
nodeTx: cpfpRootTx,
|
|
1722
1688
|
receivingPubkey: signingPubKey,
|
|
1723
1689
|
network: this.config.getNetwork()
|
|
1724
1690
|
});
|
|
@@ -1879,7 +1845,7 @@ var setCrypto = (cryptoImplParam) => {
|
|
|
1879
1845
|
import { BinaryWriter } from "@bufbuild/protobuf/wire";
|
|
1880
1846
|
import { schnorr as schnorr3, secp256k1 as secp256k14 } from "@noble/curves/secp256k1";
|
|
1881
1847
|
import { bytesToNumberBE as bytesToNumberBE2 } from "@noble/curves/utils";
|
|
1882
|
-
import { bytesToHex as bytesToHex3, hexToBytes as
|
|
1848
|
+
import { bytesToHex as bytesToHex3, hexToBytes as hexToBytes5 } from "@noble/hashes/utils";
|
|
1883
1849
|
import { bech32m as bech32m2 } from "@scure/base";
|
|
1884
1850
|
import { UUID } from "uuidv7";
|
|
1885
1851
|
|
|
@@ -2071,7 +2037,7 @@ function encodeSparkAddress(payload) {
|
|
|
2071
2037
|
function encodeSparkAddressWithSignature(payload, signature) {
|
|
2072
2038
|
try {
|
|
2073
2039
|
isValidPublicKey(payload.identityPublicKey);
|
|
2074
|
-
const identityPublicKey =
|
|
2040
|
+
const identityPublicKey = hexToBytes5(payload.identityPublicKey);
|
|
2075
2041
|
let sparkInvoiceFields;
|
|
2076
2042
|
if (payload.sparkInvoiceFields) {
|
|
2077
2043
|
validateSparkInvoiceFields(payload.sparkInvoiceFields);
|
|
@@ -2575,7 +2541,7 @@ import {
|
|
|
2575
2541
|
bytesToNumberBE as bytesToNumberBE4,
|
|
2576
2542
|
numberToBytesBE as numberToBytesBE2
|
|
2577
2543
|
} from "@noble/curves/utils";
|
|
2578
|
-
import { hexToBytes as
|
|
2544
|
+
import { hexToBytes as hexToBytes6 } from "@noble/hashes/utils";
|
|
2579
2545
|
|
|
2580
2546
|
// src/utils/token-hashing.ts
|
|
2581
2547
|
import { sha256 as sha2566 } from "@noble/hashes/sha2";
|
|
@@ -3895,14 +3861,14 @@ var TokenTransactionService = class {
|
|
|
3895
3861
|
}
|
|
3896
3862
|
if (receiverAddress.sparkInvoiceFields) {
|
|
3897
3863
|
return {
|
|
3898
|
-
receiverPublicKey:
|
|
3864
|
+
receiverPublicKey: hexToBytes6(receiverAddress.identityPublicKey),
|
|
3899
3865
|
rawTokenIdentifier,
|
|
3900
3866
|
tokenAmount: transfer.tokenAmount,
|
|
3901
3867
|
sparkInvoice: transfer.receiverSparkAddress
|
|
3902
3868
|
};
|
|
3903
3869
|
}
|
|
3904
3870
|
return {
|
|
3905
|
-
receiverPublicKey:
|
|
3871
|
+
receiverPublicKey: hexToBytes6(receiverAddress.identityPublicKey),
|
|
3906
3872
|
rawTokenIdentifier,
|
|
3907
3873
|
tokenAmount: transfer.tokenAmount
|
|
3908
3874
|
};
|
|
@@ -3968,7 +3934,7 @@ var TokenTransactionService = class {
|
|
|
3968
3934
|
for (const [_, operator] of Object.entries(
|
|
3969
3935
|
this.config.getSigningOperators()
|
|
3970
3936
|
)) {
|
|
3971
|
-
operatorKeys.push(
|
|
3937
|
+
operatorKeys.push(hexToBytes6(operator.identityPublicKey));
|
|
3972
3938
|
}
|
|
3973
3939
|
return operatorKeys;
|
|
3974
3940
|
}
|
|
@@ -4231,8 +4197,8 @@ var TokenTransactionService = class {
|
|
|
4231
4197
|
this.config.getCoordinatorAddress()
|
|
4232
4198
|
);
|
|
4233
4199
|
let queryParams = {
|
|
4234
|
-
issuerPublicKeys: issuerPublicKeys?.map(
|
|
4235
|
-
ownerPublicKeys: ownerPublicKeys?.map(
|
|
4200
|
+
issuerPublicKeys: issuerPublicKeys?.map(hexToBytes6),
|
|
4201
|
+
ownerPublicKeys: ownerPublicKeys?.map(hexToBytes6),
|
|
4236
4202
|
tokenIdentifiers: tokenIdentifiers?.map((identifier) => {
|
|
4237
4203
|
const { tokenIdentifier } = decodeBech32mTokenIdentifier(
|
|
4238
4204
|
identifier,
|
|
@@ -4240,7 +4206,7 @@ var TokenTransactionService = class {
|
|
|
4240
4206
|
);
|
|
4241
4207
|
return tokenIdentifier;
|
|
4242
4208
|
}),
|
|
4243
|
-
tokenTransactionHashes: tokenTransactionHashes?.map(
|
|
4209
|
+
tokenTransactionHashes: tokenTransactionHashes?.map(hexToBytes6),
|
|
4244
4210
|
outputIds: outputIds || [],
|
|
4245
4211
|
limit: pageSize,
|
|
4246
4212
|
offset
|
|
@@ -4345,7 +4311,7 @@ var TokenTransactionService = class {
|
|
|
4345
4311
|
}
|
|
4346
4312
|
const payload = {
|
|
4347
4313
|
finalTokenTransactionHash,
|
|
4348
|
-
operatorIdentityPublicKey:
|
|
4314
|
+
operatorIdentityPublicKey: hexToBytes6(operator.identityPublicKey)
|
|
4349
4315
|
};
|
|
4350
4316
|
const payloadHash = await hashOperatorSpecificTokenTransactionSignablePayload(payload);
|
|
4351
4317
|
const ownerSignature = await this.signMessageWithKey(
|
|
@@ -4367,7 +4333,7 @@ var TokenTransactionService = class {
|
|
|
4367
4333
|
}
|
|
4368
4334
|
const payload = {
|
|
4369
4335
|
finalTokenTransactionHash,
|
|
4370
|
-
operatorIdentityPublicKey:
|
|
4336
|
+
operatorIdentityPublicKey: hexToBytes6(operator.identityPublicKey)
|
|
4371
4337
|
};
|
|
4372
4338
|
const payloadHash = await hashOperatorSpecificTokenTransactionSignablePayload(payload);
|
|
4373
4339
|
const ownerSignature = await this.signMessageWithKey(
|
|
@@ -4383,7 +4349,7 @@ var TokenTransactionService = class {
|
|
|
4383
4349
|
for (let i = 0; i < transferInput.outputsToSpend.length; i++) {
|
|
4384
4350
|
const payload = {
|
|
4385
4351
|
finalTokenTransactionHash,
|
|
4386
|
-
operatorIdentityPublicKey:
|
|
4352
|
+
operatorIdentityPublicKey: hexToBytes6(operator.identityPublicKey)
|
|
4387
4353
|
};
|
|
4388
4354
|
const payloadHash = await hashOperatorSpecificTokenTransactionSignablePayload(payload);
|
|
4389
4355
|
let ownerSignature;
|
|
@@ -4400,7 +4366,7 @@ var TokenTransactionService = class {
|
|
|
4400
4366
|
}
|
|
4401
4367
|
inputTtxoSignaturesPerOperator.push({
|
|
4402
4368
|
ttxoSignatures,
|
|
4403
|
-
operatorIdentityPublicKey:
|
|
4369
|
+
operatorIdentityPublicKey: hexToBytes6(operator.identityPublicKey)
|
|
4404
4370
|
});
|
|
4405
4371
|
}
|
|
4406
4372
|
return inputTtxoSignaturesPerOperator;
|
|
@@ -4830,7 +4796,7 @@ import {
|
|
|
4830
4796
|
bytesToHex as bytesToHex6,
|
|
4831
4797
|
bytesToNumberBE as bytesToNumberBE6,
|
|
4832
4798
|
equalBytes as equalBytes4,
|
|
4833
|
-
hexToBytes as
|
|
4799
|
+
hexToBytes as hexToBytes7
|
|
4834
4800
|
} from "@noble/curves/utils";
|
|
4835
4801
|
import { sha256 as sha2567 } from "@noble/hashes/sha2";
|
|
4836
4802
|
import { HDKey } from "@scure/bip32";
|
|
@@ -4848,7 +4814,7 @@ var isWebExtension = (
|
|
|
4848
4814
|
"chrome" in globalThis && globalThis.chrome.runtime?.id
|
|
4849
4815
|
);
|
|
4850
4816
|
var userAgent = "navigator" in globalThis ? globalThis.navigator.userAgent || "unknown-user-agent" : void 0;
|
|
4851
|
-
var packageVersion = true ? "0.3.
|
|
4817
|
+
var packageVersion = true ? "0.3.9" : "unknown";
|
|
4852
4818
|
var baseEnvStr = "unknown";
|
|
4853
4819
|
if (isBun) {
|
|
4854
4820
|
const bunVersion = "version" in globalThis.Bun ? globalThis.Bun.version : "unknown-version";
|
|
@@ -5228,7 +5194,7 @@ var DefaultSparkSigner = class {
|
|
|
5228
5194
|
}
|
|
5229
5195
|
async createSparkWalletFromSeed(seed, accountNumber) {
|
|
5230
5196
|
if (typeof seed === "string") {
|
|
5231
|
-
seed =
|
|
5197
|
+
seed = hexToBytes7(seed);
|
|
5232
5198
|
}
|
|
5233
5199
|
const {
|
|
5234
5200
|
identityKey,
|
|
@@ -5367,7 +5333,7 @@ var TaprootSparkSigner = class extends DefaultSparkSigner {
|
|
|
5367
5333
|
|
|
5368
5334
|
// src/tests/utils/test-faucet.ts
|
|
5369
5335
|
import { schnorr as schnorr6, secp256k1 as secp256k19 } from "@noble/curves/secp256k1";
|
|
5370
|
-
import { bytesToHex as bytesToHex7, hexToBytes as
|
|
5336
|
+
import { bytesToHex as bytesToHex7, hexToBytes as hexToBytes8 } from "@noble/curves/utils";
|
|
5371
5337
|
import * as btc3 from "@scure/btc-signer";
|
|
5372
5338
|
import { Address as Address2, OutScript as OutScript2, SigHash as SigHash2, Transaction as Transaction4 } from "@scure/btc-signer";
|
|
5373
5339
|
import { taprootTweakPrivKey as taprootTweakPrivKey2 } from "@scure/btc-signer/utils";
|
|
@@ -5394,10 +5360,10 @@ var getFetch = () => {
|
|
|
5394
5360
|
};
|
|
5395
5361
|
|
|
5396
5362
|
// src/tests/utils/test-faucet.ts
|
|
5397
|
-
var STATIC_FAUCET_KEY =
|
|
5363
|
+
var STATIC_FAUCET_KEY = hexToBytes8(
|
|
5398
5364
|
"deadbeef1337cafe4242424242424242deadbeef1337cafe4242424242424242"
|
|
5399
5365
|
);
|
|
5400
|
-
var STATIC_MINING_KEY =
|
|
5366
|
+
var STATIC_MINING_KEY = hexToBytes8(
|
|
5401
5367
|
"1337cafe4242deadbeef4242424242421337cafe4242deadbeef424242424242"
|
|
5402
5368
|
);
|
|
5403
5369
|
var SATS_PER_BTC = 1e8;
|
|
@@ -5480,7 +5446,7 @@ var BitcoinFaucet = class _BitcoinFaucet {
|
|
|
5480
5446
|
);
|
|
5481
5447
|
await this.generateToAddress(1, address);
|
|
5482
5448
|
const fundingTxRaw = await this.getRawTransaction(fundingTxid);
|
|
5483
|
-
const fundingTx = Transaction4.fromRaw(
|
|
5449
|
+
const fundingTx = Transaction4.fromRaw(hexToBytes8(fundingTxRaw.hex));
|
|
5484
5450
|
for (let i = 0; i < fundingTx.outputsLength; i++) {
|
|
5485
5451
|
const output = fundingTx.getOutput(i);
|
|
5486
5452
|
if (!output.script || !output.amount) continue;
|
|
@@ -5546,7 +5512,7 @@ var BitcoinFaucet = class _BitcoinFaucet {
|
|
|
5546
5512
|
this.coins.push({
|
|
5547
5513
|
key: STATIC_FAUCET_KEY,
|
|
5548
5514
|
outpoint: {
|
|
5549
|
-
txid:
|
|
5515
|
+
txid: hexToBytes8(splitTxId),
|
|
5550
5516
|
index: i
|
|
5551
5517
|
},
|
|
5552
5518
|
txout: signedSplitTx.getOutput(i)
|
|
@@ -6635,7 +6601,7 @@ function collectResponses(responses) {
|
|
|
6635
6601
|
}
|
|
6636
6602
|
|
|
6637
6603
|
// src/utils/unilateral-exit.ts
|
|
6638
|
-
import { bytesToHex as bytesToHex8, hexToBytes as
|
|
6604
|
+
import { bytesToHex as bytesToHex8, hexToBytes as hexToBytes9 } from "@noble/curves/utils";
|
|
6639
6605
|
import { ripemd160 } from "@noble/hashes/legacy";
|
|
6640
6606
|
import { sha256 as sha2569 } from "@noble/hashes/sha2";
|
|
6641
6607
|
import * as btc4 from "@scure/btc-signer";
|
|
@@ -6650,7 +6616,7 @@ function isEphemeralAnchorOutput(script, amount) {
|
|
|
6650
6616
|
}
|
|
6651
6617
|
async function constructUnilateralExitTxs(nodeHexStrings, sparkClient, network) {
|
|
6652
6618
|
const result = [];
|
|
6653
|
-
const nodes = nodeHexStrings.map((hex) => TreeNode.decode(
|
|
6619
|
+
const nodes = nodeHexStrings.map((hex) => TreeNode.decode(hexToBytes9(hex)));
|
|
6654
6620
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
6655
6621
|
for (const node of nodes) {
|
|
6656
6622
|
nodeMap.set(node.id, node);
|
|
@@ -6739,7 +6705,7 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
6739
6705
|
`Node hex string at index ${i} appears to be a raw transaction hex, not a TreeNode protobuf. Use 'leafidtohex' command to convert node IDs to proper hex strings.`
|
|
6740
6706
|
);
|
|
6741
6707
|
}
|
|
6742
|
-
const nodeBytes =
|
|
6708
|
+
const nodeBytes = hexToBytes9(hex);
|
|
6743
6709
|
const node = TreeNode.decode(nodeBytes);
|
|
6744
6710
|
if (!node.id) {
|
|
6745
6711
|
throw new Error(
|
|
@@ -6853,7 +6819,7 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
6853
6819
|
usedUtxos,
|
|
6854
6820
|
correctedParentTx
|
|
6855
6821
|
} = constructFeeBumpTx(nodeTxHex, availableUtxos, feeRate, void 0);
|
|
6856
|
-
const feeBumpTx = btc4.Transaction.fromPSBT(
|
|
6822
|
+
const feeBumpTx = btc4.Transaction.fromPSBT(hexToBytes9(nodeFeeBumpPsbt));
|
|
6857
6823
|
var feeBumpOut = feeBumpTx.outputsLength === 1 ? feeBumpTx.getOutput(0) : null;
|
|
6858
6824
|
var feeBumpOutPubKey = null;
|
|
6859
6825
|
for (const usedUtxo of usedUtxos) {
|
|
@@ -6908,7 +6874,7 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
6908
6874
|
void 0
|
|
6909
6875
|
);
|
|
6910
6876
|
const feeBumpTx2 = btc4.Transaction.fromPSBT(
|
|
6911
|
-
|
|
6877
|
+
hexToBytes9(refundFeeBump.feeBumpPsbt)
|
|
6912
6878
|
);
|
|
6913
6879
|
var feeBumpOut = feeBumpTx2.outputsLength === 1 ? feeBumpTx2.getOutput(0) : null;
|
|
6914
6880
|
var feeBumpOutPubKey = null;
|
|
@@ -7023,9 +6989,9 @@ function constructFeeBumpTx(txHex, utxos, feeRate, previousFeeBumpTx) {
|
|
|
7023
6989
|
if (!fundingUtxo) {
|
|
7024
6990
|
throw new Error(`UTXO at index ${i} is undefined`);
|
|
7025
6991
|
}
|
|
7026
|
-
const pubKeyHash = hash160(
|
|
6992
|
+
const pubKeyHash = hash160(hexToBytes9(fundingUtxo.publicKey));
|
|
7027
6993
|
const scriptToUse = new Uint8Array([0, 20, ...pubKeyHash]);
|
|
7028
|
-
const providedScript =
|
|
6994
|
+
const providedScript = hexToBytes9(fundingUtxo.script);
|
|
7029
6995
|
if (bytesToHex8(scriptToUse) !== bytesToHex8(providedScript)) {
|
|
7030
6996
|
throw new Error(
|
|
7031
6997
|
`\u274C Derived script doesn't match provided script for UTXO ${i + 1}.`
|
|
@@ -7139,7 +7105,6 @@ __export(utils_exports, {
|
|
|
7139
7105
|
DIRECT_HTLC_TIMELOCK_OFFSET: () => DIRECT_HTLC_TIMELOCK_OFFSET,
|
|
7140
7106
|
DIRECT_TIMELOCK_OFFSET: () => DIRECT_TIMELOCK_OFFSET,
|
|
7141
7107
|
HTLC_TIMELOCK_OFFSET: () => HTLC_TIMELOCK_OFFSET,
|
|
7142
|
-
INITIAL_DIRECT_SEQUENCE: () => INITIAL_DIRECT_SEQUENCE,
|
|
7143
7108
|
INITIAL_SEQUENCE: () => INITIAL_SEQUENCE,
|
|
7144
7109
|
LOGGER_NAMES: () => LOGGER_NAMES,
|
|
7145
7110
|
Network: () => Network2,
|
|
@@ -7162,21 +7127,24 @@ __export(utils_exports, {
|
|
|
7162
7127
|
constructFeeBumpTx: () => constructFeeBumpTx,
|
|
7163
7128
|
constructUnilateralExitFeeBumpPackages: () => constructUnilateralExitFeeBumpPackages,
|
|
7164
7129
|
constructUnilateralExitTxs: () => constructUnilateralExitTxs,
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7130
|
+
createConnectorRefundTxs: () => createConnectorRefundTxs,
|
|
7131
|
+
createCurrentTimelockRefundTxs: () => createCurrentTimelockRefundTxs,
|
|
7132
|
+
createDecrementedTimelockNodeTx: () => createDecrementedTimelockNodeTx,
|
|
7133
|
+
createDecrementedTimelockRefundTxs: () => createDecrementedTimelockRefundTxs,
|
|
7134
|
+
createInitialTimelockNodeTx: () => createInitialTimelockNodeTx,
|
|
7135
|
+
createInitialTimelockRefundTxs: () => createInitialTimelockRefundTxs,
|
|
7136
|
+
createRootNodeTx: () => createRootNodeTx,
|
|
7172
7137
|
createSigningCommitment: () => createSigningCommitment,
|
|
7173
7138
|
createSigningNonce: () => createSigningNonce,
|
|
7174
|
-
|
|
7139
|
+
createTestUnilateralRefundTxs: () => createTestUnilateralRefundTxs,
|
|
7140
|
+
createTestUnilateralTimelockNodeTx: () => createTestUnilateralTimelockNodeTx,
|
|
7141
|
+
createZeroTimelockNodeTx: () => createZeroTimelockNodeTx,
|
|
7175
7142
|
decodeBech32mTokenIdentifier: () => decodeBech32mTokenIdentifier,
|
|
7176
7143
|
decodeBytesToSigningCommitment: () => decodeBytesToSigningCommitment,
|
|
7177
7144
|
decodeBytesToSigningNonce: () => decodeBytesToSigningNonce,
|
|
7178
7145
|
decodeSparkAddress: () => decodeSparkAddress,
|
|
7179
7146
|
doesLeafNeedRefresh: () => doesLeafNeedRefresh,
|
|
7147
|
+
doesTxnNeedRenewed: () => doesTxnNeedRenewed,
|
|
7180
7148
|
encodeBech32mTokenIdentifier: () => encodeBech32mTokenIdentifier,
|
|
7181
7149
|
encodeSigningCommitmentToBytes: () => encodeSigningCommitmentToBytes,
|
|
7182
7150
|
encodeSigningNonceToBytes: () => encodeSigningNonceToBytes,
|
|
@@ -7220,6 +7188,7 @@ __export(utils_exports, {
|
|
|
7220
7188
|
isTxBroadcast: () => isTxBroadcast,
|
|
7221
7189
|
isValidPublicKey: () => isValidPublicKey,
|
|
7222
7190
|
isValidSparkAddress: () => isValidSparkAddress,
|
|
7191
|
+
isZeroTimelock: () => isZeroTimelock,
|
|
7223
7192
|
lastKeyWithTarget: () => lastKeyWithTarget,
|
|
7224
7193
|
maybeApplyFee: () => maybeApplyFee,
|
|
7225
7194
|
modInverse: () => modInverse,
|
|
@@ -7246,11 +7215,11 @@ import {
|
|
|
7246
7215
|
bytesToHex as bytesToHex11,
|
|
7247
7216
|
bytesToNumberBE as bytesToNumberBE8,
|
|
7248
7217
|
equalBytes as equalBytes6,
|
|
7249
|
-
hexToBytes as
|
|
7218
|
+
hexToBytes as hexToBytes12
|
|
7250
7219
|
} from "@noble/curves/utils";
|
|
7251
7220
|
import { validateMnemonic } from "@scure/bip39";
|
|
7252
7221
|
import { wordlist as wordlist2 } from "@scure/bip39/wordlists/english";
|
|
7253
|
-
import { Address as Address4, OutScript as OutScript3, Transaction as
|
|
7222
|
+
import { Address as Address4, OutScript as OutScript3, Transaction as Transaction7 } from "@scure/btc-signer";
|
|
7254
7223
|
import { Mutex } from "async-mutex";
|
|
7255
7224
|
import { uuidv7 as uuidv74 } from "uuidv7";
|
|
7256
7225
|
|
|
@@ -8372,28 +8341,14 @@ var SparkAuthProvider = class {
|
|
|
8372
8341
|
};
|
|
8373
8342
|
|
|
8374
8343
|
// src/services/coop-exit.ts
|
|
8375
|
-
import { Transaction as Transaction7 } from "@scure/btc-signer";
|
|
8376
8344
|
import { uuidv7 as uuidv72 } from "uuidv7";
|
|
8377
8345
|
|
|
8378
8346
|
// src/services/transfer.ts
|
|
8379
8347
|
import { secp256k1 as secp256k110 } from "@noble/curves/secp256k1";
|
|
8380
|
-
import {
|
|
8381
|
-
bytesToHex as bytesToHex10,
|
|
8382
|
-
equalBytes as equalBytes5,
|
|
8383
|
-
hexToBytes as hexToBytes9,
|
|
8384
|
-
numberToBytesBE as numberToBytesBE4
|
|
8385
|
-
} from "@noble/curves/utils";
|
|
8348
|
+
import { bytesToHex as bytesToHex10, equalBytes as equalBytes5, numberToBytesBE as numberToBytesBE4 } from "@noble/curves/utils";
|
|
8386
8349
|
import { sha256 as sha25611 } from "@noble/hashes/sha2";
|
|
8387
|
-
import { Transaction as Transaction6 } from "@scure/btc-signer";
|
|
8388
8350
|
import * as ecies2 from "eciesjs";
|
|
8389
8351
|
import { uuidv7 } from "uuidv7";
|
|
8390
|
-
function getSigningJobProto(signingJob) {
|
|
8391
|
-
return {
|
|
8392
|
-
signingPublicKey: signingJob.signingPublicKey,
|
|
8393
|
-
rawTx: signingJob.rawTx,
|
|
8394
|
-
signingNonceCommitment: signingJob.signingNonceCommitment.commitment
|
|
8395
|
-
};
|
|
8396
|
-
}
|
|
8397
8352
|
var BaseTransferService = class {
|
|
8398
8353
|
config;
|
|
8399
8354
|
connectionManager;
|
|
@@ -9075,42 +9030,27 @@ var TransferService = class extends BaseTransferService {
|
|
|
9075
9030
|
throw new Error(`Leaf data not found for leaf ${leaf.leaf.id}`);
|
|
9076
9031
|
}
|
|
9077
9032
|
const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
9078
|
-
const cpfpNodeOutPoint = {
|
|
9079
|
-
txid: hexToBytes9(getTxId(nodeTx)),
|
|
9080
|
-
index: 0
|
|
9081
|
-
};
|
|
9082
9033
|
let directNodeTx;
|
|
9083
|
-
let directNodeOutPoint;
|
|
9084
9034
|
if (leaf.leaf.directTx.length > 0) {
|
|
9085
9035
|
directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
|
|
9086
|
-
directNodeOutPoint = {
|
|
9087
|
-
txid: hexToBytes9(getTxId(directNodeTx)),
|
|
9088
|
-
index: 0
|
|
9089
|
-
};
|
|
9090
9036
|
}
|
|
9091
9037
|
const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
9092
|
-
const
|
|
9093
|
-
if (!
|
|
9038
|
+
const currentSequence = currRefundTx.getInput(0).sequence;
|
|
9039
|
+
if (!currentSequence) {
|
|
9094
9040
|
throw new ValidationError("Invalid refund transaction", {
|
|
9095
9041
|
field: "sequence",
|
|
9096
9042
|
value: currRefundTx.getInput(0),
|
|
9097
9043
|
expected: "Non-null sequence"
|
|
9098
9044
|
});
|
|
9099
9045
|
}
|
|
9100
|
-
const
|
|
9101
|
-
|
|
9102
|
-
|
|
9103
|
-
|
|
9104
|
-
}
|
|
9105
|
-
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
9106
|
-
sequence: nextSequence,
|
|
9107
|
-
directSequence: nextDirectSequence,
|
|
9108
|
-
input: cpfpNodeOutPoint,
|
|
9109
|
-
directInput: directNodeOutPoint,
|
|
9110
|
-
amountSats,
|
|
9046
|
+
const refundTxsParams = {
|
|
9047
|
+
nodeTx,
|
|
9048
|
+
directNodeTx,
|
|
9049
|
+
sequence: currentSequence,
|
|
9111
9050
|
receivingPubkey: refundSigningData.receivingPubkey,
|
|
9112
9051
|
network: this.config.getNetwork()
|
|
9113
|
-
}
|
|
9052
|
+
};
|
|
9053
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = isForClaim ? createCurrentTimelockRefundTxs(refundTxsParams) : createDecrementedTimelockRefundTxs(refundTxsParams);
|
|
9114
9054
|
refundSigningData.refundTx = cpfpRefundTx;
|
|
9115
9055
|
refundSigningData.directRefundTx = directRefundTx;
|
|
9116
9056
|
refundSigningData.directFromCpfpRefundTx = directFromCpfpRefundTx;
|
|
@@ -9323,71 +9263,127 @@ var TransferService = class extends BaseTransferService {
|
|
|
9323
9263
|
throw new Error(`Error querying pending transfers by sender: ${error}`);
|
|
9324
9264
|
}
|
|
9325
9265
|
}
|
|
9326
|
-
async
|
|
9266
|
+
async renewRefundTxn(node, parentNode) {
|
|
9267
|
+
const sparkClient = await this.connectionManager.createSparkClient(
|
|
9268
|
+
this.config.getCoordinatorAddress()
|
|
9269
|
+
);
|
|
9270
|
+
const signingJobs = await this.createRenewRefundSigningJobs(
|
|
9271
|
+
node,
|
|
9272
|
+
parentNode
|
|
9273
|
+
);
|
|
9274
|
+
const statechainCommitments = await sparkClient.get_signing_commitments({
|
|
9275
|
+
nodeIds: [node.id],
|
|
9276
|
+
count: signingJobs.length
|
|
9277
|
+
});
|
|
9278
|
+
const mappedSigningJobs = signingJobs.map((signingJob, index) => {
|
|
9279
|
+
const signingNonceCommitments = statechainCommitments.signingCommitments[index]?.signingNonceCommitments;
|
|
9280
|
+
if (!signingNonceCommitments) {
|
|
9281
|
+
throw new Error("Signing nonce commitments not found");
|
|
9282
|
+
}
|
|
9283
|
+
return {
|
|
9284
|
+
...signingJob,
|
|
9285
|
+
signingNonceCommitments
|
|
9286
|
+
};
|
|
9287
|
+
});
|
|
9288
|
+
const userSignedTxSigningJobs = await this.signingService.signSigningJobs(mappedSigningJobs);
|
|
9289
|
+
const renewRefundTimelockSigningJob = {
|
|
9290
|
+
nodeTxSigningJob: userSignedTxSigningJobs.get("node"),
|
|
9291
|
+
refundTxSigningJob: userSignedTxSigningJobs.get("cpfp"),
|
|
9292
|
+
directNodeTxSigningJob: userSignedTxSigningJobs.get("directNode"),
|
|
9293
|
+
directRefundTxSigningJob: userSignedTxSigningJobs.get("direct"),
|
|
9294
|
+
directFromCpfpRefundTxSigningJob: userSignedTxSigningJobs.get("directFromCpfp")
|
|
9295
|
+
};
|
|
9296
|
+
const response = await sparkClient.renew_leaf({
|
|
9297
|
+
leafId: node.id,
|
|
9298
|
+
signingJobs: {
|
|
9299
|
+
$case: "renewRefundTimelockSigningJob",
|
|
9300
|
+
renewRefundTimelockSigningJob
|
|
9301
|
+
}
|
|
9302
|
+
});
|
|
9303
|
+
if (response.renewResult?.$case !== "renewRefundTimelockResult" || !response.renewResult?.renewRefundTimelockResult.node) {
|
|
9304
|
+
throw new ValidationError("Unexpected renew result", {
|
|
9305
|
+
field: "renewResult",
|
|
9306
|
+
value: response.renewResult
|
|
9307
|
+
});
|
|
9308
|
+
}
|
|
9309
|
+
return response.renewResult?.renewRefundTimelockResult.node;
|
|
9310
|
+
}
|
|
9311
|
+
async renewNodeTxn(node, parentNode) {
|
|
9312
|
+
const sparkClient = await this.connectionManager.createSparkClient(
|
|
9313
|
+
this.config.getCoordinatorAddress()
|
|
9314
|
+
);
|
|
9315
|
+
const signingJobs = await this.createRenewNodeSigningJobs(node, parentNode);
|
|
9316
|
+
const statechainCommitments = await sparkClient.get_signing_commitments({
|
|
9317
|
+
nodeIds: [node.id],
|
|
9318
|
+
count: signingJobs.length
|
|
9319
|
+
});
|
|
9320
|
+
const mappedSigningJobs = signingJobs.map((signingJob, index) => {
|
|
9321
|
+
const signingNonceCommitments = statechainCommitments.signingCommitments[index]?.signingNonceCommitments;
|
|
9322
|
+
if (!signingNonceCommitments) {
|
|
9323
|
+
throw new Error("Signing nonce commitments not found");
|
|
9324
|
+
}
|
|
9325
|
+
return {
|
|
9326
|
+
...signingJob,
|
|
9327
|
+
signingNonceCommitments
|
|
9328
|
+
};
|
|
9329
|
+
});
|
|
9330
|
+
const userSignedTxSigningJobs = await this.signingService.signSigningJobs(mappedSigningJobs);
|
|
9331
|
+
const response = await sparkClient.renew_leaf({
|
|
9332
|
+
leafId: node.id,
|
|
9333
|
+
signingJobs: {
|
|
9334
|
+
$case: "renewNodeTimelockSigningJob",
|
|
9335
|
+
renewNodeTimelockSigningJob: {
|
|
9336
|
+
splitNodeTxSigningJob: userSignedTxSigningJobs.get("split"),
|
|
9337
|
+
splitNodeDirectTxSigningJob: userSignedTxSigningJobs.get("directSplit"),
|
|
9338
|
+
nodeTxSigningJob: userSignedTxSigningJobs.get("node"),
|
|
9339
|
+
directNodeTxSigningJob: userSignedTxSigningJobs.get("directNode"),
|
|
9340
|
+
refundTxSigningJob: userSignedTxSigningJobs.get("cpfp"),
|
|
9341
|
+
directRefundTxSigningJob: userSignedTxSigningJobs.get("direct"),
|
|
9342
|
+
directFromCpfpRefundTxSigningJob: userSignedTxSigningJobs.get("directFromCpfp")
|
|
9343
|
+
}
|
|
9344
|
+
}
|
|
9345
|
+
});
|
|
9346
|
+
if (response.renewResult?.$case !== "renewNodeTimelockResult" || !response.renewResult?.renewNodeTimelockResult.node) {
|
|
9347
|
+
throw new ValidationError("Unexpected renew result", {
|
|
9348
|
+
field: "renewResult",
|
|
9349
|
+
value: response.renewResult
|
|
9350
|
+
});
|
|
9351
|
+
}
|
|
9352
|
+
return response.renewResult.renewNodeTimelockResult.node;
|
|
9353
|
+
}
|
|
9354
|
+
async createRenewRefundSigningJobs(node, parentNode) {
|
|
9327
9355
|
const signingJobs = [];
|
|
9328
|
-
const
|
|
9329
|
-
const parentNodeOutput =
|
|
9356
|
+
const parentTx = getTxFromRawTxBytes(parentNode.nodeTx);
|
|
9357
|
+
const parentNodeOutput = getTxFromRawTxBytes(parentNode.nodeTx).getOutput(
|
|
9358
|
+
0
|
|
9359
|
+
);
|
|
9330
9360
|
if (!parentNodeOutput) {
|
|
9331
|
-
throw Error("
|
|
9361
|
+
throw new Error("Parent node output not found");
|
|
9332
9362
|
}
|
|
9333
|
-
const
|
|
9334
|
-
const nodeInput = nodeTx.getInput(0);
|
|
9335
|
-
const nodeOutput = nodeTx.getOutput(0);
|
|
9336
|
-
if (!nodeOutput) {
|
|
9337
|
-
throw Error("Could not get node output");
|
|
9338
|
-
}
|
|
9339
|
-
let directNodeTx;
|
|
9340
|
-
let directNodeInput;
|
|
9341
|
-
if (node.directTx.length > 0) {
|
|
9342
|
-
directNodeTx = getTxFromRawTxBytes(node.directTx);
|
|
9343
|
-
directNodeInput = directNodeTx.getInput(0);
|
|
9344
|
-
}
|
|
9345
|
-
const currSequence = nodeInput.sequence;
|
|
9346
|
-
if (!currSequence) {
|
|
9347
|
-
throw new ValidationError("Invalid node transaction", {
|
|
9348
|
-
field: "sequence",
|
|
9349
|
-
value: nodeInput,
|
|
9350
|
-
expected: "Non-null sequence"
|
|
9351
|
-
});
|
|
9352
|
-
}
|
|
9353
|
-
let { nextSequence, nextDirectSequence } = getNextTransactionSequence(
|
|
9354
|
-
currSequence,
|
|
9355
|
-
true
|
|
9356
|
-
);
|
|
9357
|
-
const output = {
|
|
9363
|
+
const unsignedParentNodeOutput = {
|
|
9358
9364
|
script: parentNodeOutput.script,
|
|
9359
9365
|
amount: parentNodeOutput.amount
|
|
9360
9366
|
};
|
|
9361
|
-
const
|
|
9362
|
-
txid: nodeInput.txid,
|
|
9363
|
-
index: nodeInput.index,
|
|
9364
|
-
sequence: useTestUnilateralSequence ? TEST_UNILATERAL_SEQUENCE : nextSequence
|
|
9365
|
-
};
|
|
9366
|
-
const newDirectInput = directNodeTx && directNodeInput ? {
|
|
9367
|
-
txid: directNodeInput.txid,
|
|
9368
|
-
index: directNodeInput.index,
|
|
9369
|
-
sequence: useTestUnilateralSequence ? TEST_UNILATERAL_DIRECT_SEQUENCE : nextDirectSequence
|
|
9370
|
-
} : void 0;
|
|
9371
|
-
const { cpfpNodeTx, directNodeTx: newDirectNodeTx } = createNodeTxs(
|
|
9372
|
-
output,
|
|
9373
|
-
newNodeInput,
|
|
9374
|
-
newDirectInput
|
|
9375
|
-
);
|
|
9376
|
-
const newCpfpNodeOutput = cpfpNodeTx.getOutput(0);
|
|
9377
|
-
if (!newCpfpNodeOutput) {
|
|
9378
|
-
throw Error("Could not get new cpfp node output");
|
|
9379
|
-
}
|
|
9380
|
-
const newDirectNodeOutput = newDirectNodeTx?.getOutput(0);
|
|
9381
|
-
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation({
|
|
9367
|
+
const keyDerivation = {
|
|
9382
9368
|
type: "leaf" /* LEAF */,
|
|
9383
9369
|
path: node.id
|
|
9384
|
-
}
|
|
9370
|
+
};
|
|
9371
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
9372
|
+
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
9373
|
+
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
9374
|
+
const { nodeTx: newNodeTx, directNodeTx: newDirectNodeTx } = createDecrementedTimelockNodeTx(parentTx, nodeTx);
|
|
9385
9375
|
signingJobs.push({
|
|
9386
9376
|
signingPublicKey,
|
|
9387
|
-
rawTx:
|
|
9377
|
+
rawTx: newNodeTx.toBytes(),
|
|
9388
9378
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9389
9379
|
type: "node",
|
|
9390
|
-
parentTxOut:
|
|
9380
|
+
parentTxOut: unsignedParentNodeOutput,
|
|
9381
|
+
leafId: node.id,
|
|
9382
|
+
keyDerivation: {
|
|
9383
|
+
type: "leaf" /* LEAF */,
|
|
9384
|
+
path: node.id
|
|
9385
|
+
},
|
|
9386
|
+
verifyingKey: node.verifyingPublicKey
|
|
9391
9387
|
});
|
|
9392
9388
|
if (newDirectNodeTx) {
|
|
9393
9389
|
signingJobs.push({
|
|
@@ -9395,537 +9391,299 @@ var TransferService = class extends BaseTransferService {
|
|
|
9395
9391
|
rawTx: newDirectNodeTx.toBytes(),
|
|
9396
9392
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9397
9393
|
type: "directNode",
|
|
9398
|
-
parentTxOut:
|
|
9394
|
+
parentTxOut: unsignedParentNodeOutput,
|
|
9395
|
+
leafId: node.id,
|
|
9396
|
+
keyDerivation: {
|
|
9397
|
+
type: "leaf" /* LEAF */,
|
|
9398
|
+
path: node.id
|
|
9399
|
+
},
|
|
9400
|
+
verifyingKey: node.verifyingPublicKey
|
|
9399
9401
|
});
|
|
9400
9402
|
}
|
|
9401
|
-
const
|
|
9402
|
-
|
|
9403
|
-
|
|
9404
|
-
};
|
|
9405
|
-
let newDirectRefundOutPoint;
|
|
9406
|
-
if (newDirectNodeTx) {
|
|
9407
|
-
newDirectRefundOutPoint = {
|
|
9408
|
-
txid: hexToBytes9(getTxId(newDirectNodeTx)),
|
|
9409
|
-
index: 0
|
|
9410
|
-
};
|
|
9411
|
-
}
|
|
9412
|
-
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
9413
|
-
sequence: INITIAL_SEQUENCE,
|
|
9414
|
-
directSequence: INITIAL_DIRECT_SEQUENCE,
|
|
9415
|
-
input: newCpfpRefundOutPoint,
|
|
9416
|
-
directInput: newDirectRefundOutPoint,
|
|
9417
|
-
amountSats: nodeOutput.amount,
|
|
9418
|
-
receivingPubkey: await this.config.signer.getPublicKeyFromDerivation({
|
|
9419
|
-
type: "leaf" /* LEAF */,
|
|
9420
|
-
path: node.id
|
|
9421
|
-
}),
|
|
9422
|
-
network: this.config.getNetwork()
|
|
9423
|
-
});
|
|
9424
|
-
signingJobs.push({
|
|
9425
|
-
signingPublicKey,
|
|
9426
|
-
rawTx: cpfpRefundTx.toBytes(),
|
|
9427
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9428
|
-
type: "cpfp",
|
|
9429
|
-
parentTxOut: newCpfpNodeOutput
|
|
9430
|
-
});
|
|
9431
|
-
if (directRefundTx && newDirectNodeOutput) {
|
|
9432
|
-
signingJobs.push({
|
|
9433
|
-
signingPublicKey,
|
|
9434
|
-
rawTx: directRefundTx.toBytes(),
|
|
9435
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9436
|
-
type: "direct",
|
|
9437
|
-
parentTxOut: newDirectNodeOutput
|
|
9438
|
-
});
|
|
9439
|
-
}
|
|
9440
|
-
if (directFromCpfpRefundTx && newCpfpNodeOutput) {
|
|
9441
|
-
signingJobs.push({
|
|
9442
|
-
signingPublicKey,
|
|
9443
|
-
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
9444
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9445
|
-
type: "directFromCpfp",
|
|
9446
|
-
parentTxOut: newCpfpNodeOutput
|
|
9447
|
-
});
|
|
9448
|
-
}
|
|
9449
|
-
const sparkClient = await this.connectionManager.createSparkClient(
|
|
9450
|
-
this.config.getCoordinatorAddress()
|
|
9451
|
-
);
|
|
9452
|
-
const response = await sparkClient.refresh_timelock_v2({
|
|
9453
|
-
leafId: node.id,
|
|
9454
|
-
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
9455
|
-
signingJobs: signingJobs.map(getSigningJobProto)
|
|
9456
|
-
});
|
|
9457
|
-
if (signingJobs.length !== response.signingResults.length) {
|
|
9458
|
-
throw Error(
|
|
9459
|
-
`number of signing jobs and signing results do not match: ${signingJobs.length} !== ${response.signingResults.length}`
|
|
9460
|
-
);
|
|
9461
|
-
}
|
|
9462
|
-
let nodeSignatures = [];
|
|
9463
|
-
let leafCpfpSignature;
|
|
9464
|
-
let leafDirectSignature;
|
|
9465
|
-
let cpfpRefundSignature;
|
|
9466
|
-
let directRefundSignature;
|
|
9467
|
-
let directFromCpfpRefundSignature;
|
|
9468
|
-
for (const [i, signingResult] of response.signingResults.entries()) {
|
|
9469
|
-
const signingJob = signingJobs[i];
|
|
9470
|
-
if (!signingJob || !signingResult) {
|
|
9471
|
-
throw Error("Signing job does not exist");
|
|
9472
|
-
}
|
|
9473
|
-
const rawTx = getTxFromRawTxBytes(signingJob.rawTx);
|
|
9474
|
-
const txOut = signingJob.parentTxOut;
|
|
9475
|
-
if (!txOut) {
|
|
9476
|
-
throw Error("Could not get tx out");
|
|
9477
|
-
}
|
|
9478
|
-
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
9479
|
-
const userSignature = await this.config.signer.signFrost({
|
|
9480
|
-
message: rawTxSighash,
|
|
9481
|
-
keyDerivation: {
|
|
9482
|
-
type: "leaf" /* LEAF */,
|
|
9483
|
-
path: node.id
|
|
9484
|
-
},
|
|
9485
|
-
publicKey: signingJob.signingPublicKey,
|
|
9486
|
-
verifyingKey: signingResult.verifyingKey,
|
|
9487
|
-
selfCommitment: signingJob.signingNonceCommitment,
|
|
9488
|
-
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
9489
|
-
adaptorPubKey: new Uint8Array()
|
|
9490
|
-
});
|
|
9491
|
-
const signature = await this.config.signer.aggregateFrost({
|
|
9492
|
-
message: rawTxSighash,
|
|
9493
|
-
statechainSignatures: signingResult.signingResult?.signatureShares,
|
|
9494
|
-
statechainPublicKeys: signingResult.signingResult?.publicKeys,
|
|
9495
|
-
verifyingKey: signingResult.verifyingKey,
|
|
9496
|
-
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
9497
|
-
selfCommitment: signingJob.signingNonceCommitment,
|
|
9498
|
-
publicKey: signingJob.signingPublicKey,
|
|
9499
|
-
selfSignature: userSignature,
|
|
9500
|
-
adaptorPubKey: new Uint8Array()
|
|
9501
|
-
});
|
|
9502
|
-
if (signingJob.type === "node") {
|
|
9503
|
-
leafCpfpSignature = signature;
|
|
9504
|
-
} else if (signingJob.type === "directNode") {
|
|
9505
|
-
leafDirectSignature = signature;
|
|
9506
|
-
} else if (signingJob.type === "cpfp") {
|
|
9507
|
-
cpfpRefundSignature = signature;
|
|
9508
|
-
} else if (signingJob.type === "direct") {
|
|
9509
|
-
directRefundSignature = signature;
|
|
9510
|
-
} else if (signingJob.type === "directFromCpfp") {
|
|
9511
|
-
directFromCpfpRefundSignature = signature;
|
|
9512
|
-
}
|
|
9513
|
-
}
|
|
9514
|
-
nodeSignatures.push({
|
|
9515
|
-
nodeId: node.id,
|
|
9516
|
-
nodeTxSignature: leafCpfpSignature || new Uint8Array(),
|
|
9517
|
-
directNodeTxSignature: leafDirectSignature || new Uint8Array(),
|
|
9518
|
-
refundTxSignature: cpfpRefundSignature || new Uint8Array(),
|
|
9519
|
-
directRefundTxSignature: directRefundSignature || new Uint8Array(),
|
|
9520
|
-
directFromCpfpRefundTxSignature: directFromCpfpRefundSignature || new Uint8Array()
|
|
9521
|
-
});
|
|
9522
|
-
const result = await sparkClient.finalize_node_signatures_v2({
|
|
9523
|
-
intent: 3 /* REFRESH */,
|
|
9524
|
-
nodeSignatures
|
|
9525
|
-
});
|
|
9526
|
-
return result;
|
|
9527
|
-
}
|
|
9528
|
-
async refreshTimelockNodes(node, parentNode) {
|
|
9529
|
-
return await this.refreshTimelockNodesInternal(node, parentNode);
|
|
9530
|
-
}
|
|
9531
|
-
async extendTimelock(node) {
|
|
9532
|
-
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
9533
|
-
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
9534
|
-
const refundSequence = refundTx.getInput(0).sequence || 0;
|
|
9535
|
-
const newNodeOutPoint = {
|
|
9536
|
-
txid: hexToBytes9(getTxId(nodeTx)),
|
|
9537
|
-
index: 0
|
|
9538
|
-
};
|
|
9539
|
-
const {
|
|
9540
|
-
nextSequence: newNodeSequence,
|
|
9541
|
-
nextDirectSequence: newDirectNodeSequence
|
|
9542
|
-
} = getNextTransactionSequence(refundSequence);
|
|
9543
|
-
const newNodeTx = new Transaction6({
|
|
9544
|
-
version: 3,
|
|
9545
|
-
allowUnknownOutputs: true
|
|
9546
|
-
});
|
|
9547
|
-
newNodeTx.addInput({ ...newNodeOutPoint, sequence: newNodeSequence });
|
|
9548
|
-
const originalOutput = nodeTx.getOutput(0);
|
|
9549
|
-
if (!originalOutput) {
|
|
9550
|
-
throw Error("Could not get original node output");
|
|
9551
|
-
}
|
|
9552
|
-
newNodeTx.addOutput({
|
|
9553
|
-
script: originalOutput.script,
|
|
9554
|
-
amount: originalOutput.amount
|
|
9555
|
-
});
|
|
9556
|
-
newNodeTx.addOutput(getEphemeralAnchorOutput());
|
|
9557
|
-
let newDirectNodeTx;
|
|
9558
|
-
if (node.directTx.length > 0) {
|
|
9559
|
-
newDirectNodeTx = new Transaction6({
|
|
9560
|
-
version: 3,
|
|
9561
|
-
allowUnknownOutputs: true
|
|
9562
|
-
});
|
|
9563
|
-
newDirectNodeTx.addInput({
|
|
9564
|
-
...newNodeOutPoint,
|
|
9565
|
-
sequence: newDirectNodeSequence
|
|
9566
|
-
});
|
|
9567
|
-
newDirectNodeTx.addOutput({
|
|
9568
|
-
script: originalOutput.script,
|
|
9569
|
-
amount: maybeApplyFee(originalOutput.amount)
|
|
9570
|
-
});
|
|
9571
|
-
}
|
|
9572
|
-
const newCpfpRefundOutPoint = {
|
|
9573
|
-
txid: hexToBytes9(getTxId(newNodeTx)),
|
|
9574
|
-
index: 0
|
|
9575
|
-
};
|
|
9576
|
-
let newDirectRefundOutPoint;
|
|
9577
|
-
if (newDirectNodeTx) {
|
|
9578
|
-
newDirectRefundOutPoint = {
|
|
9579
|
-
txid: hexToBytes9(getTxId(newDirectNodeTx)),
|
|
9580
|
-
index: 0
|
|
9581
|
-
};
|
|
9403
|
+
const newCpfpNodeOutput = newNodeTx.getOutput(0);
|
|
9404
|
+
if (!newCpfpNodeOutput) {
|
|
9405
|
+
throw Error("Could not get new cpfp node output");
|
|
9582
9406
|
}
|
|
9407
|
+
const newDirectNodeOutput = newDirectNodeTx?.getOutput(0);
|
|
9583
9408
|
const amountSats = refundTx.getOutput(0).amount;
|
|
9584
9409
|
if (amountSats === void 0) {
|
|
9585
9410
|
throw new Error("Amount not found in extendTimelock");
|
|
9586
9411
|
}
|
|
9587
|
-
const
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
}
|
|
9412
|
+
const directAmountSats = newDirectNodeOutput?.amount;
|
|
9413
|
+
if (directAmountSats === void 0) {
|
|
9414
|
+
throw new Error("Amount not found in extendTimelock");
|
|
9415
|
+
}
|
|
9591
9416
|
const {
|
|
9592
|
-
cpfpRefundTx:
|
|
9417
|
+
cpfpRefundTx: newRefundTx,
|
|
9593
9418
|
directRefundTx: newDirectRefundTx,
|
|
9594
9419
|
directFromCpfpRefundTx: newDirectFromCpfpRefundTx
|
|
9595
|
-
} =
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
input: newCpfpRefundOutPoint,
|
|
9599
|
-
directInput: newDirectRefundOutPoint,
|
|
9600
|
-
amountSats,
|
|
9420
|
+
} = createInitialTimelockRefundTxs({
|
|
9421
|
+
nodeTx: newNodeTx,
|
|
9422
|
+
directNodeTx: newDirectNodeTx,
|
|
9601
9423
|
receivingPubkey: signingPublicKey,
|
|
9602
9424
|
network: this.config.getNetwork()
|
|
9603
9425
|
});
|
|
9604
|
-
|
|
9605
|
-
throw new ValidationError(
|
|
9606
|
-
"Failed to create refund transactions in extendTimelock"
|
|
9607
|
-
);
|
|
9608
|
-
}
|
|
9609
|
-
const nodeSighash = getSigHashFromTx(newNodeTx, 0, nodeTx.getOutput(0));
|
|
9610
|
-
const directNodeSighash = newDirectNodeTx ? getSigHashFromTx(newDirectNodeTx, 0, nodeTx.getOutput(0)) : void 0;
|
|
9611
|
-
const cpfpRefundSighash = getSigHashFromTx(
|
|
9612
|
-
newCpfpRefundTx,
|
|
9613
|
-
0,
|
|
9614
|
-
newNodeTx.getOutput(0)
|
|
9615
|
-
);
|
|
9616
|
-
const directRefundSighash = newDirectNodeTx && newDirectRefundTx ? getSigHashFromTx(newDirectRefundTx, 0, newDirectNodeTx.getOutput(0)) : void 0;
|
|
9617
|
-
const directFromCpfpRefundSighash = newDirectFromCpfpRefundTx ? getSigHashFromTx(newDirectFromCpfpRefundTx, 0, newNodeTx.getOutput(0)) : void 0;
|
|
9618
|
-
const newNodeSigningJob = {
|
|
9619
|
-
signingPublicKey,
|
|
9620
|
-
rawTx: newNodeTx.toBytes(),
|
|
9621
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
9622
|
-
};
|
|
9623
|
-
const newDirectNodeSigningJob = newDirectNodeTx ? {
|
|
9624
|
-
signingPublicKey,
|
|
9625
|
-
rawTx: newDirectNodeTx.toBytes(),
|
|
9626
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
9627
|
-
} : void 0;
|
|
9628
|
-
const newCpfpRefundSigningJob = {
|
|
9629
|
-
signingPublicKey,
|
|
9630
|
-
rawTx: newCpfpRefundTx.toBytes(),
|
|
9631
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
9632
|
-
};
|
|
9633
|
-
const newDirectRefundSigningJob = newDirectRefundTx ? {
|
|
9634
|
-
signingPublicKey,
|
|
9635
|
-
rawTx: newDirectRefundTx.toBytes(),
|
|
9636
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
9637
|
-
} : void 0;
|
|
9638
|
-
const newDirectFromCpfpRefundSigningJob = newDirectFromCpfpRefundTx ? {
|
|
9426
|
+
signingJobs.push({
|
|
9639
9427
|
signingPublicKey,
|
|
9640
|
-
rawTx:
|
|
9641
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
9642
|
-
|
|
9643
|
-
|
|
9644
|
-
this.config.getCoordinatorAddress()
|
|
9645
|
-
);
|
|
9646
|
-
const response = await sparkClient.extend_leaf_v2({
|
|
9428
|
+
rawTx: newRefundTx.toBytes(),
|
|
9429
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9430
|
+
type: "cpfp",
|
|
9431
|
+
parentTxOut: newCpfpNodeOutput,
|
|
9647
9432
|
leafId: node.id,
|
|
9648
|
-
|
|
9649
|
-
|
|
9650
|
-
directNodeTxSigningJob: newDirectNodeSigningJob ? getSigningJobProto(newDirectNodeSigningJob) : void 0,
|
|
9651
|
-
refundTxSigningJob: getSigningJobProto(newCpfpRefundSigningJob),
|
|
9652
|
-
directRefundTxSigningJob: newDirectRefundSigningJob ? getSigningJobProto(newDirectRefundSigningJob) : void 0,
|
|
9653
|
-
directFromCpfpRefundTxSigningJob: newDirectFromCpfpRefundSigningJob ? getSigningJobProto(newDirectFromCpfpRefundSigningJob) : void 0
|
|
9433
|
+
keyDerivation,
|
|
9434
|
+
verifyingKey: node.verifyingPublicKey
|
|
9654
9435
|
});
|
|
9655
|
-
if (
|
|
9656
|
-
|
|
9436
|
+
if (newDirectRefundTx && newDirectNodeOutput) {
|
|
9437
|
+
signingJobs.push({
|
|
9438
|
+
signingPublicKey,
|
|
9439
|
+
rawTx: newDirectRefundTx.toBytes(),
|
|
9440
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9441
|
+
type: "direct",
|
|
9442
|
+
parentTxOut: newDirectNodeOutput,
|
|
9443
|
+
leafId: node.id,
|
|
9444
|
+
keyDerivation,
|
|
9445
|
+
verifyingKey: node.verifyingPublicKey
|
|
9446
|
+
});
|
|
9447
|
+
}
|
|
9448
|
+
if (newDirectFromCpfpRefundTx && newDirectNodeOutput) {
|
|
9449
|
+
signingJobs.push({
|
|
9450
|
+
signingPublicKey,
|
|
9451
|
+
rawTx: newDirectFromCpfpRefundTx.toBytes(),
|
|
9452
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9453
|
+
type: "directFromCpfp",
|
|
9454
|
+
parentTxOut: newCpfpNodeOutput,
|
|
9455
|
+
leafId: node.id,
|
|
9456
|
+
keyDerivation,
|
|
9457
|
+
verifyingKey: node.verifyingPublicKey
|
|
9458
|
+
});
|
|
9657
9459
|
}
|
|
9460
|
+
return signingJobs;
|
|
9461
|
+
}
|
|
9462
|
+
async createRenewNodeSigningJobs(node, parentNode) {
|
|
9463
|
+
const signingJobs = [];
|
|
9464
|
+
const parentTx = getTxFromRawTxBytes(parentNode.nodeTx);
|
|
9465
|
+
const parentNodeOutput = getTxFromRawTxBytes(parentNode.nodeTx).getOutput(
|
|
9466
|
+
0
|
|
9467
|
+
);
|
|
9468
|
+
const unsignedParentNodeOutput = {
|
|
9469
|
+
script: parentNodeOutput.script,
|
|
9470
|
+
amount: parentNodeOutput.amount
|
|
9471
|
+
};
|
|
9658
9472
|
const keyDerivation = {
|
|
9659
9473
|
type: "leaf" /* LEAF */,
|
|
9660
9474
|
path: node.id
|
|
9661
9475
|
};
|
|
9662
|
-
const
|
|
9663
|
-
|
|
9476
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
9477
|
+
const { nodeTx: splitNodeTx, directNodeTx: splitNodeDirectTx } = createZeroTimelockNodeTx(parentTx);
|
|
9478
|
+
signingJobs.push({
|
|
9479
|
+
signingPublicKey,
|
|
9480
|
+
rawTx: splitNodeTx.toBytes(),
|
|
9481
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9482
|
+
type: "split",
|
|
9483
|
+
parentTxOut: unsignedParentNodeOutput,
|
|
9484
|
+
leafId: node.id,
|
|
9664
9485
|
keyDerivation,
|
|
9665
|
-
|
|
9666
|
-
verifyingKey: response.nodeTxSigningResult.verifyingKey,
|
|
9667
|
-
selfCommitment: newNodeSigningJob.signingNonceCommitment,
|
|
9668
|
-
statechainCommitments: response.nodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9669
|
-
adaptorPubKey: new Uint8Array()
|
|
9670
|
-
});
|
|
9671
|
-
const nodeSig = await this.config.signer.aggregateFrost({
|
|
9672
|
-
message: nodeSighash,
|
|
9673
|
-
statechainSignatures: response.nodeTxSigningResult.signingResult?.signatureShares,
|
|
9674
|
-
statechainPublicKeys: response.nodeTxSigningResult.signingResult?.publicKeys,
|
|
9675
|
-
verifyingKey: response.nodeTxSigningResult.verifyingKey,
|
|
9676
|
-
statechainCommitments: response.nodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9677
|
-
selfCommitment: newNodeSigningJob.signingNonceCommitment,
|
|
9678
|
-
publicKey: signingPublicKey,
|
|
9679
|
-
selfSignature: nodeUserSig,
|
|
9680
|
-
adaptorPubKey: new Uint8Array()
|
|
9486
|
+
verifyingKey: node.verifyingPublicKey
|
|
9681
9487
|
});
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9488
|
+
if (splitNodeDirectTx) {
|
|
9489
|
+
signingJobs.push({
|
|
9490
|
+
signingPublicKey,
|
|
9491
|
+
rawTx: splitNodeDirectTx.toBytes(),
|
|
9492
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9493
|
+
type: "directSplit",
|
|
9494
|
+
parentTxOut: unsignedParentNodeOutput,
|
|
9495
|
+
leafId: node.id,
|
|
9686
9496
|
keyDerivation,
|
|
9687
|
-
|
|
9688
|
-
verifyingKey: response.directNodeTxSigningResult.verifyingKey,
|
|
9689
|
-
selfCommitment: newDirectNodeSigningJob.signingNonceCommitment,
|
|
9690
|
-
statechainCommitments: response.directNodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9691
|
-
adaptorPubKey: new Uint8Array()
|
|
9692
|
-
});
|
|
9693
|
-
directNodeSig = await this.config.signer.aggregateFrost({
|
|
9694
|
-
message: directNodeSighash,
|
|
9695
|
-
statechainSignatures: response.directNodeTxSigningResult.signingResult?.signatureShares,
|
|
9696
|
-
statechainPublicKeys: response.directNodeTxSigningResult.signingResult?.publicKeys,
|
|
9697
|
-
verifyingKey: response.directNodeTxSigningResult.verifyingKey,
|
|
9698
|
-
statechainCommitments: response.directNodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9699
|
-
selfCommitment: newDirectNodeSigningJob.signingNonceCommitment,
|
|
9700
|
-
publicKey: signingPublicKey,
|
|
9701
|
-
selfSignature: directNodeUserSig,
|
|
9702
|
-
adaptorPubKey: new Uint8Array()
|
|
9497
|
+
verifyingKey: node.verifyingPublicKey
|
|
9703
9498
|
});
|
|
9704
9499
|
}
|
|
9705
|
-
const
|
|
9706
|
-
|
|
9500
|
+
const splitNodeOutput = splitNodeTx.getOutput(0);
|
|
9501
|
+
const splitNodeDirectOutput = splitNodeDirectTx.getOutput(0);
|
|
9502
|
+
if (!splitNodeDirectOutput.amount || !splitNodeDirectOutput.script) {
|
|
9503
|
+
throw new Error("Could not get split node output");
|
|
9504
|
+
}
|
|
9505
|
+
const unsignedSplitNodeOutput = {
|
|
9506
|
+
script: splitNodeDirectOutput.script,
|
|
9507
|
+
amount: splitNodeDirectOutput.amount
|
|
9508
|
+
};
|
|
9509
|
+
const { nodeTx: newNodeTx, directNodeTx: newDirectNodeTx } = createInitialTimelockNodeTx(splitNodeTx);
|
|
9510
|
+
signingJobs.push({
|
|
9511
|
+
signingPublicKey,
|
|
9512
|
+
rawTx: newNodeTx.toBytes(),
|
|
9513
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9514
|
+
type: "node",
|
|
9515
|
+
parentTxOut: splitNodeOutput,
|
|
9516
|
+
leafId: node.id,
|
|
9707
9517
|
keyDerivation,
|
|
9708
|
-
|
|
9709
|
-
verifyingKey: response.refundTxSigningResult.verifyingKey,
|
|
9710
|
-
selfCommitment: newCpfpRefundSigningJob.signingNonceCommitment,
|
|
9711
|
-
statechainCommitments: response.refundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9712
|
-
adaptorPubKey: new Uint8Array()
|
|
9713
|
-
});
|
|
9714
|
-
const cpfpRefundSig = await this.config.signer.aggregateFrost({
|
|
9715
|
-
message: cpfpRefundSighash,
|
|
9716
|
-
statechainSignatures: response.refundTxSigningResult.signingResult?.signatureShares,
|
|
9717
|
-
statechainPublicKeys: response.refundTxSigningResult.signingResult?.publicKeys,
|
|
9718
|
-
verifyingKey: response.refundTxSigningResult.verifyingKey,
|
|
9719
|
-
statechainCommitments: response.refundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9720
|
-
selfCommitment: newCpfpRefundSigningJob.signingNonceCommitment,
|
|
9721
|
-
publicKey: signingPublicKey,
|
|
9722
|
-
selfSignature: cpfpRefundUserSig,
|
|
9723
|
-
adaptorPubKey: new Uint8Array()
|
|
9518
|
+
verifyingKey: node.verifyingPublicKey
|
|
9724
9519
|
});
|
|
9725
|
-
|
|
9726
|
-
|
|
9727
|
-
|
|
9728
|
-
|
|
9729
|
-
|
|
9730
|
-
|
|
9731
|
-
|
|
9732
|
-
|
|
9733
|
-
statechainCommitments: response.directRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9734
|
-
adaptorPubKey: new Uint8Array()
|
|
9735
|
-
});
|
|
9736
|
-
directRefundSig = await this.config.signer.aggregateFrost({
|
|
9737
|
-
message: directRefundSighash,
|
|
9738
|
-
statechainSignatures: response.directRefundTxSigningResult.signingResult?.signatureShares,
|
|
9739
|
-
statechainPublicKeys: response.directRefundTxSigningResult.signingResult?.publicKeys,
|
|
9740
|
-
verifyingKey: response.directRefundTxSigningResult.verifyingKey,
|
|
9741
|
-
statechainCommitments: response.directRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9742
|
-
selfCommitment: newDirectRefundSigningJob.signingNonceCommitment,
|
|
9743
|
-
publicKey: signingPublicKey,
|
|
9744
|
-
selfSignature: directRefundUserSig,
|
|
9745
|
-
adaptorPubKey: new Uint8Array()
|
|
9746
|
-
});
|
|
9747
|
-
}
|
|
9748
|
-
let directFromCpfpRefundSig;
|
|
9749
|
-
if (directFromCpfpRefundSighash && newDirectFromCpfpRefundSigningJob && response.directFromCpfpRefundTxSigningResult) {
|
|
9750
|
-
const directFromCpfpRefundUserSig = await this.config.signer.signFrost({
|
|
9751
|
-
message: directFromCpfpRefundSighash,
|
|
9520
|
+
if (newDirectNodeTx) {
|
|
9521
|
+
signingJobs.push({
|
|
9522
|
+
signingPublicKey,
|
|
9523
|
+
rawTx: newDirectNodeTx.toBytes(),
|
|
9524
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9525
|
+
type: "directNode",
|
|
9526
|
+
parentTxOut: splitNodeOutput,
|
|
9527
|
+
leafId: node.id,
|
|
9752
9528
|
keyDerivation,
|
|
9753
|
-
|
|
9754
|
-
verifyingKey: response.directFromCpfpRefundTxSigningResult.verifyingKey,
|
|
9755
|
-
selfCommitment: newDirectFromCpfpRefundSigningJob.signingNonceCommitment,
|
|
9756
|
-
statechainCommitments: response.directFromCpfpRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9757
|
-
adaptorPubKey: new Uint8Array()
|
|
9529
|
+
verifyingKey: node.verifyingPublicKey
|
|
9758
9530
|
});
|
|
9759
|
-
directFromCpfpRefundSig = await this.config.signer.aggregateFrost({
|
|
9760
|
-
message: directFromCpfpRefundSighash,
|
|
9761
|
-
statechainSignatures: response.directFromCpfpRefundTxSigningResult.signingResult?.signatureShares,
|
|
9762
|
-
statechainPublicKeys: response.directFromCpfpRefundTxSigningResult.signingResult?.publicKeys,
|
|
9763
|
-
verifyingKey: response.directFromCpfpRefundTxSigningResult.verifyingKey,
|
|
9764
|
-
statechainCommitments: response.directFromCpfpRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
9765
|
-
selfCommitment: newDirectFromCpfpRefundSigningJob.signingNonceCommitment,
|
|
9766
|
-
publicKey: signingPublicKey,
|
|
9767
|
-
selfSignature: directFromCpfpRefundUserSig,
|
|
9768
|
-
adaptorPubKey: new Uint8Array()
|
|
9769
|
-
});
|
|
9770
|
-
}
|
|
9771
|
-
return await sparkClient.finalize_node_signatures_v2({
|
|
9772
|
-
intent: 4 /* EXTEND */,
|
|
9773
|
-
nodeSignatures: [
|
|
9774
|
-
{
|
|
9775
|
-
nodeId: response.leafId,
|
|
9776
|
-
nodeTxSignature: nodeSig,
|
|
9777
|
-
directNodeTxSignature: directNodeSig,
|
|
9778
|
-
refundTxSignature: cpfpRefundSig,
|
|
9779
|
-
directRefundTxSignature: directRefundSig,
|
|
9780
|
-
directFromCpfpRefundTxSignature: directFromCpfpRefundSig
|
|
9781
|
-
}
|
|
9782
|
-
]
|
|
9783
|
-
});
|
|
9784
|
-
}
|
|
9785
|
-
async testonly_expireTimeLockNodeTx(node, parentNode) {
|
|
9786
|
-
return await this.refreshTimelockNodesInternal(node, parentNode, true);
|
|
9787
|
-
}
|
|
9788
|
-
async testonly_expireTimeLockRefundtx(node) {
|
|
9789
|
-
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
9790
|
-
const directNodeTx = node.directTx.length > 0 ? getTxFromRawTxBytes(node.directTx) : void 0;
|
|
9791
|
-
const cpfpRefundTx = getTxFromRawTxBytes(node.refundTx);
|
|
9792
|
-
const currSequence = cpfpRefundTx.getInput(0).sequence || 0;
|
|
9793
|
-
const currTimelock = getCurrentTimelock(currSequence);
|
|
9794
|
-
if (currTimelock <= 100) {
|
|
9795
|
-
throw new ValidationError("Cannot expire timelock below 100", {
|
|
9796
|
-
field: "currTimelock",
|
|
9797
|
-
value: currTimelock,
|
|
9798
|
-
expected: "Timelock greater than 100"
|
|
9799
|
-
});
|
|
9800
|
-
}
|
|
9801
|
-
const nextSequence = TEST_UNILATERAL_SEQUENCE;
|
|
9802
|
-
const nextDirectSequence = TEST_UNILATERAL_SEQUENCE + DIRECT_TIMELOCK_OFFSET;
|
|
9803
|
-
const nodeOutput = nodeTx.getOutput(0);
|
|
9804
|
-
if (!nodeOutput) {
|
|
9805
|
-
throw Error("Could not get node output");
|
|
9806
9531
|
}
|
|
9807
|
-
const
|
|
9808
|
-
|
|
9809
|
-
|
|
9810
|
-
};
|
|
9811
|
-
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
9812
|
-
const cpfpRefundOutPoint = {
|
|
9813
|
-
txid: hexToBytes9(getTxId(nodeTx)),
|
|
9814
|
-
index: 0
|
|
9815
|
-
};
|
|
9816
|
-
let directRefundOutPoint;
|
|
9817
|
-
if (directNodeTx) {
|
|
9818
|
-
directRefundOutPoint = {
|
|
9819
|
-
txid: hexToBytes9(getTxId(directNodeTx)),
|
|
9820
|
-
index: 0
|
|
9821
|
-
};
|
|
9532
|
+
const newCpfpNodeOutput = newNodeTx.getOutput(0);
|
|
9533
|
+
if (!newCpfpNodeOutput) {
|
|
9534
|
+
throw Error("Could not get new cpfp node output");
|
|
9822
9535
|
}
|
|
9536
|
+
const newDirectNodeOutput = newDirectNodeTx?.getOutput(0);
|
|
9823
9537
|
const {
|
|
9824
|
-
cpfpRefundTx:
|
|
9538
|
+
cpfpRefundTx: newRefundTx,
|
|
9825
9539
|
directRefundTx: newDirectRefundTx,
|
|
9826
9540
|
directFromCpfpRefundTx: newDirectFromCpfpRefundTx
|
|
9827
|
-
} =
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
input: cpfpRefundOutPoint,
|
|
9831
|
-
directInput: directRefundOutPoint,
|
|
9832
|
-
amountSats: nodeOutput.amount,
|
|
9541
|
+
} = createInitialTimelockRefundTxs({
|
|
9542
|
+
nodeTx: newNodeTx,
|
|
9543
|
+
directNodeTx: newDirectNodeTx,
|
|
9833
9544
|
receivingPubkey: signingPublicKey,
|
|
9834
9545
|
network: this.config.getNetwork()
|
|
9835
9546
|
});
|
|
9836
|
-
const signingJobs = [];
|
|
9837
9547
|
signingJobs.push({
|
|
9838
9548
|
signingPublicKey,
|
|
9839
|
-
rawTx:
|
|
9549
|
+
rawTx: newRefundTx.toBytes(),
|
|
9840
9550
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9841
9551
|
type: "cpfp",
|
|
9842
|
-
parentTxOut:
|
|
9552
|
+
parentTxOut: newCpfpNodeOutput,
|
|
9553
|
+
leafId: node.id,
|
|
9554
|
+
keyDerivation,
|
|
9555
|
+
verifyingKey: node.verifyingPublicKey
|
|
9843
9556
|
});
|
|
9844
|
-
|
|
9845
|
-
if (newDirectRefundTx && directNodeTxOut) {
|
|
9557
|
+
if (newDirectRefundTx && newDirectNodeOutput) {
|
|
9846
9558
|
signingJobs.push({
|
|
9847
9559
|
signingPublicKey,
|
|
9848
9560
|
rawTx: newDirectRefundTx.toBytes(),
|
|
9849
9561
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9850
9562
|
type: "direct",
|
|
9851
|
-
parentTxOut:
|
|
9563
|
+
parentTxOut: newDirectNodeOutput,
|
|
9564
|
+
leafId: node.id,
|
|
9565
|
+
keyDerivation,
|
|
9566
|
+
verifyingKey: node.verifyingPublicKey
|
|
9852
9567
|
});
|
|
9853
9568
|
}
|
|
9854
|
-
if (newDirectFromCpfpRefundTx) {
|
|
9569
|
+
if (newDirectFromCpfpRefundTx && newDirectNodeOutput) {
|
|
9855
9570
|
signingJobs.push({
|
|
9856
9571
|
signingPublicKey,
|
|
9857
9572
|
rawTx: newDirectFromCpfpRefundTx.toBytes(),
|
|
9858
9573
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9859
9574
|
type: "directFromCpfp",
|
|
9860
|
-
parentTxOut:
|
|
9575
|
+
parentTxOut: newCpfpNodeOutput,
|
|
9576
|
+
leafId: node.id,
|
|
9577
|
+
keyDerivation,
|
|
9578
|
+
verifyingKey: node.verifyingPublicKey
|
|
9861
9579
|
});
|
|
9862
9580
|
}
|
|
9581
|
+
return signingJobs;
|
|
9582
|
+
}
|
|
9583
|
+
async renewZeroTimelockNodeTxn(node) {
|
|
9863
9584
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
9864
9585
|
this.config.getCoordinatorAddress()
|
|
9865
9586
|
);
|
|
9866
|
-
const
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
|
|
9587
|
+
const signingJobs = await this.createRenewZeroTimelockNodeSigningJobs(node);
|
|
9588
|
+
const statechainCommitments = await sparkClient.get_signing_commitments({
|
|
9589
|
+
nodeIds: [node.id],
|
|
9590
|
+
count: signingJobs.length
|
|
9591
|
+
});
|
|
9592
|
+
const mappedSigningJobs = signingJobs.map((signingJob, index) => {
|
|
9593
|
+
const signingNonceCommitments = statechainCommitments.signingCommitments[index]?.signingNonceCommitments;
|
|
9594
|
+
if (!signingNonceCommitments) {
|
|
9595
|
+
throw new ValidationError("Signing nonce commitments not found", {
|
|
9596
|
+
field: "signingNonceCommitments",
|
|
9597
|
+
value: signingNonceCommitments
|
|
9598
|
+
});
|
|
9599
|
+
}
|
|
9600
|
+
return {
|
|
9601
|
+
...signingJob,
|
|
9602
|
+
signingNonceCommitments
|
|
9603
|
+
};
|
|
9870
9604
|
});
|
|
9871
|
-
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
)
|
|
9875
|
-
|
|
9876
|
-
|
|
9877
|
-
|
|
9878
|
-
|
|
9879
|
-
|
|
9880
|
-
|
|
9881
|
-
|
|
9882
|
-
|
|
9605
|
+
const userSignedTxSigningJobs = await this.signingService.signSigningJobs(mappedSigningJobs);
|
|
9606
|
+
const renewZeroTimelockNodeSigningJob = {
|
|
9607
|
+
nodeTxSigningJob: userSignedTxSigningJobs.get("node"),
|
|
9608
|
+
refundTxSigningJob: userSignedTxSigningJobs.get("cpfp"),
|
|
9609
|
+
directNodeTxSigningJob: userSignedTxSigningJobs.get("directNode"),
|
|
9610
|
+
directRefundTxSigningJob: void 0,
|
|
9611
|
+
directFromCpfpRefundTxSigningJob: userSignedTxSigningJobs.get("directFromCpfp")
|
|
9612
|
+
};
|
|
9613
|
+
const response = await sparkClient.renew_leaf({
|
|
9614
|
+
leafId: node.id,
|
|
9615
|
+
signingJobs: {
|
|
9616
|
+
$case: "renewNodeZeroTimelockSigningJob",
|
|
9617
|
+
renewNodeZeroTimelockSigningJob: renewZeroTimelockNodeSigningJob
|
|
9883
9618
|
}
|
|
9884
|
-
|
|
9885
|
-
|
|
9886
|
-
|
|
9887
|
-
|
|
9888
|
-
|
|
9889
|
-
keyDerivation,
|
|
9890
|
-
publicKey: signingPublicKey,
|
|
9891
|
-
verifyingKey: signingResult.verifyingKey,
|
|
9892
|
-
selfCommitment: signingJob.signingNonceCommitment,
|
|
9893
|
-
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
9894
|
-
adaptorPubKey: new Uint8Array()
|
|
9895
|
-
});
|
|
9896
|
-
const signature = await this.config.signer.aggregateFrost({
|
|
9897
|
-
message: rawTxSighash,
|
|
9898
|
-
statechainSignatures: signingResult.signingResult?.signatureShares,
|
|
9899
|
-
statechainPublicKeys: signingResult.signingResult?.publicKeys,
|
|
9900
|
-
verifyingKey: signingResult.verifyingKey,
|
|
9901
|
-
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
9902
|
-
selfCommitment: signingJob.signingNonceCommitment,
|
|
9903
|
-
publicKey: signingPublicKey,
|
|
9904
|
-
selfSignature: userSignature,
|
|
9905
|
-
adaptorPubKey: new Uint8Array()
|
|
9619
|
+
});
|
|
9620
|
+
if (response.renewResult?.$case !== "renewNodeZeroTimelockResult" || !response.renewResult?.renewNodeZeroTimelockResult.node) {
|
|
9621
|
+
throw new ValidationError("Unexpected renew result", {
|
|
9622
|
+
field: "renewResult",
|
|
9623
|
+
value: response.renewResult
|
|
9906
9624
|
});
|
|
9907
|
-
if (signingJob.type === "cpfp") {
|
|
9908
|
-
cpfpRefundSignature = signature;
|
|
9909
|
-
} else if (signingJob.type === "direct") {
|
|
9910
|
-
directRefundSignature = signature;
|
|
9911
|
-
} else if (signingJob.type === "directFromCpfp") {
|
|
9912
|
-
directFromCpfpRefundSignature = signature;
|
|
9913
|
-
}
|
|
9914
9625
|
}
|
|
9915
|
-
|
|
9916
|
-
|
|
9917
|
-
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
|
|
9923
|
-
|
|
9924
|
-
|
|
9925
|
-
|
|
9926
|
-
|
|
9626
|
+
return response.renewResult.renewNodeZeroTimelockResult.node;
|
|
9627
|
+
}
|
|
9628
|
+
async createRenewZeroTimelockNodeSigningJobs(node) {
|
|
9629
|
+
const signingJobs = [];
|
|
9630
|
+
const keyDerivation = {
|
|
9631
|
+
type: "leaf" /* LEAF */,
|
|
9632
|
+
path: node.id
|
|
9633
|
+
};
|
|
9634
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
9635
|
+
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
9636
|
+
const { nodeTx: newNodeTx, directNodeTx: newDirectNodeTx } = createZeroTimelockNodeTx(nodeTx);
|
|
9637
|
+
signingJobs.push({
|
|
9638
|
+
signingPublicKey,
|
|
9639
|
+
rawTx: newNodeTx.toBytes(),
|
|
9640
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9641
|
+
type: "node",
|
|
9642
|
+
parentTxOut: nodeTx.getOutput(0),
|
|
9643
|
+
leafId: node.id,
|
|
9644
|
+
keyDerivation,
|
|
9645
|
+
verifyingKey: node.verifyingPublicKey
|
|
9927
9646
|
});
|
|
9928
|
-
|
|
9647
|
+
signingJobs.push({
|
|
9648
|
+
signingPublicKey,
|
|
9649
|
+
rawTx: newDirectNodeTx.toBytes(),
|
|
9650
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9651
|
+
type: "directNode",
|
|
9652
|
+
parentTxOut: nodeTx.getOutput(0),
|
|
9653
|
+
leafId: node.id,
|
|
9654
|
+
keyDerivation,
|
|
9655
|
+
verifyingKey: node.verifyingPublicKey
|
|
9656
|
+
});
|
|
9657
|
+
const { cpfpRefundTx, directFromCpfpRefundTx } = createInitialTimelockRefundTxs({
|
|
9658
|
+
nodeTx: newNodeTx,
|
|
9659
|
+
directNodeTx: newDirectNodeTx,
|
|
9660
|
+
receivingPubkey: signingPublicKey,
|
|
9661
|
+
network: this.config.getNetwork()
|
|
9662
|
+
});
|
|
9663
|
+
signingJobs.push({
|
|
9664
|
+
signingPublicKey,
|
|
9665
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
9666
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9667
|
+
type: "cpfp",
|
|
9668
|
+
parentTxOut: newNodeTx.getOutput(0),
|
|
9669
|
+
leafId: node.id,
|
|
9670
|
+
keyDerivation,
|
|
9671
|
+
verifyingKey: node.verifyingPublicKey
|
|
9672
|
+
});
|
|
9673
|
+
if (!directFromCpfpRefundTx) {
|
|
9674
|
+
throw new Error("Could not create direct refund transactions");
|
|
9675
|
+
}
|
|
9676
|
+
signingJobs.push({
|
|
9677
|
+
signingPublicKey,
|
|
9678
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
9679
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
9680
|
+
type: "directFromCpfp",
|
|
9681
|
+
parentTxOut: newNodeTx.getOutput(0),
|
|
9682
|
+
leafId: node.id,
|
|
9683
|
+
keyDerivation,
|
|
9684
|
+
verifyingKey: node.verifyingPublicKey
|
|
9685
|
+
});
|
|
9686
|
+
return signingJobs;
|
|
9929
9687
|
}
|
|
9930
9688
|
};
|
|
9931
9689
|
|
|
@@ -9967,71 +9725,6 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
9967
9725
|
directFromCpfpSignaturesMap
|
|
9968
9726
|
};
|
|
9969
9727
|
}
|
|
9970
|
-
createConnectorRefundTransactions(sequence, directSequence, cpfpNodeOutPoint, directNodeOutPoint, connectorOutput, amountSats, receiverPubKey) {
|
|
9971
|
-
const cpfpRefundTx = new Transaction7();
|
|
9972
|
-
if (!cpfpNodeOutPoint.txid || cpfpNodeOutPoint.index === void 0) {
|
|
9973
|
-
throw new ValidationError("Invalid CPFP node outpoint", {
|
|
9974
|
-
field: "cpfpNodeOutPoint",
|
|
9975
|
-
value: { txid: cpfpNodeOutPoint.txid, index: cpfpNodeOutPoint.index },
|
|
9976
|
-
expected: "Both txid and index must be defined"
|
|
9977
|
-
});
|
|
9978
|
-
}
|
|
9979
|
-
cpfpRefundTx.addInput({
|
|
9980
|
-
txid: cpfpNodeOutPoint.txid,
|
|
9981
|
-
index: cpfpNodeOutPoint.index,
|
|
9982
|
-
sequence
|
|
9983
|
-
});
|
|
9984
|
-
cpfpRefundTx.addInput(connectorOutput);
|
|
9985
|
-
const receiverScript = getP2TRScriptFromPublicKey(
|
|
9986
|
-
receiverPubKey,
|
|
9987
|
-
this.config.getNetwork()
|
|
9988
|
-
);
|
|
9989
|
-
cpfpRefundTx.addOutput({
|
|
9990
|
-
script: receiverScript,
|
|
9991
|
-
amount: amountSats
|
|
9992
|
-
});
|
|
9993
|
-
let directRefundTx;
|
|
9994
|
-
let directFromCpfpRefundTx;
|
|
9995
|
-
if (directNodeOutPoint) {
|
|
9996
|
-
if (!directNodeOutPoint.txid || directNodeOutPoint.index === void 0) {
|
|
9997
|
-
throw new ValidationError("Invalid direct node outpoint", {
|
|
9998
|
-
field: "directNodeOutPoint",
|
|
9999
|
-
value: {
|
|
10000
|
-
txid: directNodeOutPoint.txid,
|
|
10001
|
-
index: directNodeOutPoint.index
|
|
10002
|
-
},
|
|
10003
|
-
expected: "Both txid and index must be defined"
|
|
10004
|
-
});
|
|
10005
|
-
}
|
|
10006
|
-
directRefundTx = new Transaction7();
|
|
10007
|
-
directRefundTx.addInput({
|
|
10008
|
-
txid: directNodeOutPoint.txid,
|
|
10009
|
-
index: directNodeOutPoint.index,
|
|
10010
|
-
sequence: directSequence
|
|
10011
|
-
});
|
|
10012
|
-
directRefundTx.addInput(connectorOutput);
|
|
10013
|
-
directRefundTx.addOutput({
|
|
10014
|
-
script: receiverScript,
|
|
10015
|
-
amount: maybeApplyFee(amountSats)
|
|
10016
|
-
});
|
|
10017
|
-
directFromCpfpRefundTx = new Transaction7();
|
|
10018
|
-
directFromCpfpRefundTx.addInput({
|
|
10019
|
-
txid: cpfpNodeOutPoint.txid,
|
|
10020
|
-
index: cpfpNodeOutPoint.index,
|
|
10021
|
-
sequence: directSequence
|
|
10022
|
-
});
|
|
10023
|
-
directFromCpfpRefundTx.addInput(connectorOutput);
|
|
10024
|
-
directFromCpfpRefundTx.addOutput({
|
|
10025
|
-
script: receiverScript,
|
|
10026
|
-
amount: maybeApplyFee(amountSats)
|
|
10027
|
-
});
|
|
10028
|
-
}
|
|
10029
|
-
return {
|
|
10030
|
-
cpfpRefundTx,
|
|
10031
|
-
directRefundTx,
|
|
10032
|
-
directFromCpfpRefundTx
|
|
10033
|
-
};
|
|
10034
|
-
}
|
|
10035
9728
|
async signCoopExitRefunds(leaves, exitTxId, connectorOutputs, receiverPubKey, transferId) {
|
|
10036
9729
|
if (leaves.length !== connectorOutputs.length) {
|
|
10037
9730
|
throw new ValidationError(
|
|
@@ -10065,29 +9758,39 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
10065
9758
|
expected: "Valid connector output"
|
|
10066
9759
|
});
|
|
10067
9760
|
}
|
|
9761
|
+
const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
9762
|
+
let directNodeTx;
|
|
9763
|
+
if (leaf.leaf.directTx.length > 0) {
|
|
9764
|
+
directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
|
|
9765
|
+
}
|
|
10068
9766
|
const currentRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
10069
|
-
|
|
10070
|
-
|
|
9767
|
+
if (!currentRefundTx) {
|
|
9768
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
9769
|
+
field: "currentRefundTx",
|
|
9770
|
+
value: currentRefundTx,
|
|
9771
|
+
expected: "Non-null refund transaction"
|
|
9772
|
+
});
|
|
9773
|
+
}
|
|
9774
|
+
const currentSequence = currentRefundTx.getInput(0).sequence;
|
|
9775
|
+
if (!currentSequence) {
|
|
10071
9776
|
throw new ValidationError("Invalid refund transaction", {
|
|
10072
9777
|
field: "sequence",
|
|
10073
9778
|
value: currentRefundTx.getInput(0),
|
|
10074
9779
|
expected: "Non-null sequence"
|
|
10075
9780
|
});
|
|
10076
9781
|
}
|
|
10077
|
-
const { nextSequence, nextDirectSequence } = getNextTransactionSequence(sequence);
|
|
10078
9782
|
let currentDirectRefundTx;
|
|
10079
9783
|
if (leaf.leaf.directRefundTx.length > 0) {
|
|
10080
9784
|
currentDirectRefundTx = getTxFromRawTxBytes(leaf.leaf.directRefundTx);
|
|
10081
9785
|
}
|
|
10082
|
-
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } =
|
|
10083
|
-
|
|
10084
|
-
|
|
10085
|
-
|
|
10086
|
-
currentDirectRefundTx?.getInput(0),
|
|
9786
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createConnectorRefundTxs({
|
|
9787
|
+
nodeTx,
|
|
9788
|
+
directNodeTx,
|
|
9789
|
+
sequence: currentSequence,
|
|
10087
9790
|
connectorOutput,
|
|
10088
|
-
|
|
10089
|
-
|
|
10090
|
-
);
|
|
9791
|
+
receivingPubkey: receiverPubKey,
|
|
9792
|
+
network: this.config.getNetwork()
|
|
9793
|
+
});
|
|
10091
9794
|
const signingNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
10092
9795
|
const directSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
10093
9796
|
const directFromCpfpSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
@@ -10568,12 +10271,9 @@ import {
|
|
|
10568
10271
|
import { EventEmitter } from "eventemitter3";
|
|
10569
10272
|
import { ClientError, Status } from "nice-grpc-common";
|
|
10570
10273
|
|
|
10571
|
-
// src/services/signing.ts
|
|
10572
|
-
import { hexToBytes as hexToBytes12 } from "@noble/curves/utils";
|
|
10573
|
-
|
|
10574
10274
|
// src/utils/htlc-transactions.ts
|
|
10575
10275
|
import {
|
|
10576
|
-
Transaction as
|
|
10276
|
+
Transaction as Transaction6,
|
|
10577
10277
|
Script,
|
|
10578
10278
|
taprootListToTree,
|
|
10579
10279
|
p2tr as p2tr3,
|
|
@@ -10661,7 +10361,7 @@ function createLightningHTLCTransaction({
|
|
|
10661
10361
|
txid: hexToBytes11(getTxId(nodeTx)),
|
|
10662
10362
|
index: 0
|
|
10663
10363
|
};
|
|
10664
|
-
const htlcTransaction = new
|
|
10364
|
+
const htlcTransaction = new Transaction6({
|
|
10665
10365
|
version: 3,
|
|
10666
10366
|
allowUnknownOutputs: true
|
|
10667
10367
|
});
|
|
@@ -10780,20 +10480,7 @@ var SigningService = class {
|
|
|
10780
10480
|
});
|
|
10781
10481
|
}
|
|
10782
10482
|
const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
10783
|
-
const cpfpNodeOutPoint = {
|
|
10784
|
-
txid: hexToBytes12(getTxId(nodeTx)),
|
|
10785
|
-
index: 0
|
|
10786
|
-
};
|
|
10787
10483
|
const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
10788
|
-
const sequence = currRefundTx.getInput(0).sequence;
|
|
10789
|
-
if (!sequence) {
|
|
10790
|
-
throw new ValidationError("Invalid refund transaction", {
|
|
10791
|
-
field: "sequence",
|
|
10792
|
-
value: currRefundTx.getInput(0),
|
|
10793
|
-
expected: "Non-null sequence"
|
|
10794
|
-
});
|
|
10795
|
-
}
|
|
10796
|
-
const { nextSequence, nextDirectSequence } = getNextTransactionSequence(sequence);
|
|
10797
10484
|
const amountSats = currRefundTx.getOutput(0).amount;
|
|
10798
10485
|
if (amountSats === void 0) {
|
|
10799
10486
|
throw new ValidationError("Invalid refund transaction", {
|
|
@@ -10803,20 +10490,21 @@ var SigningService = class {
|
|
|
10803
10490
|
});
|
|
10804
10491
|
}
|
|
10805
10492
|
let directNodeTx;
|
|
10806
|
-
let directNodeOutPoint;
|
|
10807
10493
|
if (leaf.leaf.directTx.length > 0) {
|
|
10808
10494
|
directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
|
|
10809
|
-
directNodeOutPoint = {
|
|
10810
|
-
txid: hexToBytes12(getTxId(directNodeTx)),
|
|
10811
|
-
index: 0
|
|
10812
|
-
};
|
|
10813
10495
|
}
|
|
10814
|
-
const
|
|
10815
|
-
|
|
10816
|
-
|
|
10817
|
-
|
|
10818
|
-
|
|
10819
|
-
|
|
10496
|
+
const currentSequence = currRefundTx.getInput(0).sequence;
|
|
10497
|
+
if (!currentSequence) {
|
|
10498
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
10499
|
+
field: "sequence",
|
|
10500
|
+
value: currRefundTx.getInput(0),
|
|
10501
|
+
expected: "Non-null sequence"
|
|
10502
|
+
});
|
|
10503
|
+
}
|
|
10504
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createDecrementedTimelockRefundTxs({
|
|
10505
|
+
nodeTx,
|
|
10506
|
+
directNodeTx,
|
|
10507
|
+
sequence: currentSequence,
|
|
10820
10508
|
receivingPubkey: receiverIdentityPubkey,
|
|
10821
10509
|
network: this.config.getNetwork()
|
|
10822
10510
|
});
|
|
@@ -10832,7 +10520,8 @@ var SigningService = class {
|
|
|
10832
10520
|
cpfpSigningCommitments[i]?.signingNonceCommitments
|
|
10833
10521
|
);
|
|
10834
10522
|
cpfpLeafSigningJobs.push(...signingJobs);
|
|
10835
|
-
|
|
10523
|
+
const isZeroNode = getCurrentTimelock(nodeTx.getInput(0).sequence);
|
|
10524
|
+
if (directRefundTx && !isZeroNode) {
|
|
10836
10525
|
if (!directNodeTx) {
|
|
10837
10526
|
throw new ValidationError(
|
|
10838
10527
|
"Direct node transaction undefined while direct refund transaction is defined",
|
|
@@ -10857,16 +10546,6 @@ var SigningService = class {
|
|
|
10857
10546
|
directLeafSigningJobs.push(...signingJobs2);
|
|
10858
10547
|
}
|
|
10859
10548
|
if (directFromCpfpRefundTx) {
|
|
10860
|
-
if (!directNodeTx) {
|
|
10861
|
-
throw new ValidationError(
|
|
10862
|
-
"Direct node transaction undefined while direct from CPFP refund transaction is defined",
|
|
10863
|
-
{
|
|
10864
|
-
field: "directNodeTx",
|
|
10865
|
-
value: directNodeTx,
|
|
10866
|
-
expected: "Non-null direct node transaction"
|
|
10867
|
-
}
|
|
10868
|
-
);
|
|
10869
|
-
}
|
|
10870
10549
|
const refundSighash2 = getSigHashFromTx(
|
|
10871
10550
|
directFromCpfpRefundTx,
|
|
10872
10551
|
0,
|
|
@@ -10993,6 +10672,35 @@ var SigningService = class {
|
|
|
10993
10672
|
directFromCpfpLeafSigningJobs
|
|
10994
10673
|
};
|
|
10995
10674
|
}
|
|
10675
|
+
async signSigningJobs(signingJobs) {
|
|
10676
|
+
const userSignedTxSigningJobs = /* @__PURE__ */ new Map();
|
|
10677
|
+
for (const signingJob of signingJobs) {
|
|
10678
|
+
const rawTx = getTxFromRawTxBytes(signingJob.rawTx);
|
|
10679
|
+
const txOut = signingJob.parentTxOut;
|
|
10680
|
+
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
10681
|
+
const userSignature = await this.config.signer.signFrost({
|
|
10682
|
+
message: rawTxSighash,
|
|
10683
|
+
keyDerivation: signingJob.keyDerivation,
|
|
10684
|
+
publicKey: signingJob.signingPublicKey,
|
|
10685
|
+
verifyingKey: signingJob.verifyingKey,
|
|
10686
|
+
selfCommitment: signingJob.signingNonceCommitment,
|
|
10687
|
+
statechainCommitments: signingJob.signingNonceCommitments,
|
|
10688
|
+
adaptorPubKey: new Uint8Array()
|
|
10689
|
+
});
|
|
10690
|
+
const userSignedTxSigningJob = {
|
|
10691
|
+
leafId: signingJob.leafId,
|
|
10692
|
+
signingPublicKey: signingJob.signingPublicKey,
|
|
10693
|
+
rawTx: rawTx.toBytes(),
|
|
10694
|
+
signingNonceCommitment: signingJob.signingNonceCommitment.commitment,
|
|
10695
|
+
signingCommitments: {
|
|
10696
|
+
signingCommitments: signingJob.signingNonceCommitments
|
|
10697
|
+
},
|
|
10698
|
+
userSignature
|
|
10699
|
+
};
|
|
10700
|
+
userSignedTxSigningJobs.set(signingJob.type, userSignedTxSigningJob);
|
|
10701
|
+
}
|
|
10702
|
+
return userSignedTxSigningJobs;
|
|
10703
|
+
}
|
|
10996
10704
|
};
|
|
10997
10705
|
|
|
10998
10706
|
// src/utils/chunkArray.ts
|
|
@@ -11249,10 +10957,8 @@ var SparkWallet = class extends EventEmitter {
|
|
|
11249
10957
|
}
|
|
11250
10958
|
} else if (isDepositStreamEvent(event)) {
|
|
11251
10959
|
const deposit = event.deposit.deposit;
|
|
11252
|
-
|
|
11253
|
-
|
|
11254
|
-
type: "leaf" /* LEAF */,
|
|
11255
|
-
path: deposit.id
|
|
10960
|
+
await this.withLeaves(async () => {
|
|
10961
|
+
this.leaves.push(deposit);
|
|
11256
10962
|
});
|
|
11257
10963
|
this.emit(
|
|
11258
10964
|
SparkWalletEvent.DepositConfirmed,
|
|
@@ -11428,19 +11134,6 @@ var SparkWallet = class extends EventEmitter {
|
|
|
11428
11134
|
}
|
|
11429
11135
|
return availableLeaves.filter(([_, node]) => !leavesToIgnore.has(node.id)).map(([_, node]) => node);
|
|
11430
11136
|
}
|
|
11431
|
-
async checkExtendLeaves(leaves) {
|
|
11432
|
-
await this.withLeaves(async () => {
|
|
11433
|
-
for (const leaf of leaves) {
|
|
11434
|
-
if (!leaf.parentNodeId && leaf.status === "AVAILABLE") {
|
|
11435
|
-
const res = await this.transferService.extendTimelock(leaf);
|
|
11436
|
-
await this.transferLeavesToSelf(res.nodes, {
|
|
11437
|
-
type: "leaf" /* LEAF */,
|
|
11438
|
-
path: leaf.id
|
|
11439
|
-
});
|
|
11440
|
-
}
|
|
11441
|
-
}
|
|
11442
|
-
});
|
|
11443
|
-
}
|
|
11444
11137
|
verifyKey(pubkey1, pubkey2, verifyingKey) {
|
|
11445
11138
|
return equalBytes6(addPublicKeys(pubkey1, pubkey2), verifyingKey);
|
|
11446
11139
|
}
|
|
@@ -11612,10 +11305,8 @@ var SparkWallet = class extends EventEmitter {
|
|
|
11612
11305
|
async syncWallet() {
|
|
11613
11306
|
await this.syncTokenOutputs();
|
|
11614
11307
|
let leaves = await this.getLeaves();
|
|
11615
|
-
leaves = await this.
|
|
11616
|
-
leaves = await this.checkExtendTimeLockNodes(leaves);
|
|
11308
|
+
leaves = await this.checkRenewLeaves(leaves);
|
|
11617
11309
|
this.leaves = leaves;
|
|
11618
|
-
this.checkExtendLeaves(leaves);
|
|
11619
11310
|
this.optimizeLeaves().catch((e) => {
|
|
11620
11311
|
console.error("Failed to optimize leaves", e);
|
|
11621
11312
|
});
|
|
@@ -11735,7 +11426,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
11735
11426
|
mnemonic = mnemonicOrSeed;
|
|
11736
11427
|
seed = await this.config.signer.mnemonicToSeed(mnemonicOrSeed);
|
|
11737
11428
|
} else {
|
|
11738
|
-
seed =
|
|
11429
|
+
seed = hexToBytes12(mnemonicOrSeed);
|
|
11739
11430
|
}
|
|
11740
11431
|
}
|
|
11741
11432
|
await this.initWalletFromSeed(seed, accountNumber);
|
|
@@ -11878,7 +11569,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
11878
11569
|
directFromCpfpSignatureMap
|
|
11879
11570
|
} = await this.transferService.startSwapSignRefund(
|
|
11880
11571
|
leafKeyTweaks,
|
|
11881
|
-
|
|
11572
|
+
hexToBytes12(this.config.getSspIdentityPublicKey()),
|
|
11882
11573
|
new Date(Date.now() + 2 * 60 * 1e3)
|
|
11883
11574
|
);
|
|
11884
11575
|
try {
|
|
@@ -12093,7 +11784,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
12093
11784
|
throw new Error(`Leaf not found for node ${nodeId}`);
|
|
12094
11785
|
}
|
|
12095
11786
|
const cpfpNodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
12096
|
-
const cpfpRefundTxBytes =
|
|
11787
|
+
const cpfpRefundTxBytes = hexToBytes12(leaf.rawUnsignedRefundTransaction);
|
|
12097
11788
|
const cpfpRefundTx = getTxFromRawTxBytes(cpfpRefundTxBytes);
|
|
12098
11789
|
const cpfpSighash = getSigHashFromTx(
|
|
12099
11790
|
cpfpRefundTx,
|
|
@@ -12102,7 +11793,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
12102
11793
|
);
|
|
12103
11794
|
const nodePublicKey = node.verifyingPublicKey;
|
|
12104
11795
|
const taprootKey = computeTaprootKeyNoScript(nodePublicKey.slice(1));
|
|
12105
|
-
const cpfpAdaptorSignatureBytes =
|
|
11796
|
+
const cpfpAdaptorSignatureBytes = hexToBytes12(
|
|
12106
11797
|
leaf.adaptorSignedSignature
|
|
12107
11798
|
);
|
|
12108
11799
|
applyAdaptorToSignature(
|
|
@@ -12113,7 +11804,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
12113
11804
|
);
|
|
12114
11805
|
if (leaf.directRawUnsignedRefundTransaction) {
|
|
12115
11806
|
const directNodeTx = getTxFromRawTxBytes(node.directTx);
|
|
12116
|
-
const directRefundTxBytes =
|
|
11807
|
+
const directRefundTxBytes = hexToBytes12(
|
|
12117
11808
|
leaf.directRawUnsignedRefundTransaction
|
|
12118
11809
|
);
|
|
12119
11810
|
const directRefundTx = getTxFromRawTxBytes(directRefundTxBytes);
|
|
@@ -12127,7 +11818,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
12127
11818
|
`Direct adaptor signed signature missing for node ${nodeId}`
|
|
12128
11819
|
);
|
|
12129
11820
|
}
|
|
12130
|
-
const directAdaptorSignatureBytes =
|
|
11821
|
+
const directAdaptorSignatureBytes = hexToBytes12(
|
|
12131
11822
|
leaf.directAdaptorSignedSignature
|
|
12132
11823
|
);
|
|
12133
11824
|
applyAdaptorToSignature(
|
|
@@ -12138,7 +11829,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
12138
11829
|
);
|
|
12139
11830
|
}
|
|
12140
11831
|
if (leaf.directFromCpfpRawUnsignedRefundTransaction) {
|
|
12141
|
-
const directFromCpfpRefundTxBytes =
|
|
11832
|
+
const directFromCpfpRefundTxBytes = hexToBytes12(
|
|
12142
11833
|
leaf.directFromCpfpRawUnsignedRefundTransaction
|
|
12143
11834
|
);
|
|
12144
11835
|
const directFromCpfpRefundTx = getTxFromRawTxBytes(
|
|
@@ -12154,7 +11845,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
12154
11845
|
`Direct adaptor signed signature missing for node ${nodeId}`
|
|
12155
11846
|
);
|
|
12156
11847
|
}
|
|
12157
|
-
const directFromCpfpAdaptorSignatureBytes =
|
|
11848
|
+
const directFromCpfpAdaptorSignatureBytes = hexToBytes12(
|
|
12158
11849
|
leaf.directFromCpfpAdaptorSignedSignature
|
|
12159
11850
|
);
|
|
12160
11851
|
applyAdaptorToSignature(
|
|
@@ -12596,7 +12287,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
12596
12287
|
}
|
|
12597
12288
|
);
|
|
12598
12289
|
}
|
|
12599
|
-
const tx = new
|
|
12290
|
+
const tx = new Transaction7();
|
|
12600
12291
|
tx.addInput({
|
|
12601
12292
|
txid: depositTransactionId,
|
|
12602
12293
|
index: outputIndex,
|
|
@@ -12636,7 +12327,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
12636
12327
|
);
|
|
12637
12328
|
const swapResponse = await sparkClient.initiate_static_deposit_utxo_refund({
|
|
12638
12329
|
onChainUtxo: {
|
|
12639
|
-
txid:
|
|
12330
|
+
txid: hexToBytes12(depositTransactionId),
|
|
12640
12331
|
vout: outputIndex,
|
|
12641
12332
|
network: networkType
|
|
12642
12333
|
},
|
|
@@ -12763,7 +12454,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
12763
12454
|
creditAmountView.setUint32(0, lowerHalf, true);
|
|
12764
12455
|
creditAmountView.setUint32(4, upperHalf, true);
|
|
12765
12456
|
parts.push(new Uint8Array(creditAmountBuffer));
|
|
12766
|
-
parts.push(
|
|
12457
|
+
parts.push(hexToBytes12(sspSignature));
|
|
12767
12458
|
const totalLength = parts.reduce((sum2, part) => sum2 + part.length, 0);
|
|
12768
12459
|
const payload = new Uint8Array(totalLength);
|
|
12769
12460
|
let offset = 0;
|
|
@@ -12867,26 +12558,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
12867
12558
|
depositTx,
|
|
12868
12559
|
vout
|
|
12869
12560
|
});
|
|
12870
|
-
|
|
12871
|
-
for (const node of res.nodes) {
|
|
12872
|
-
if (node.status === "AVAILABLE") {
|
|
12873
|
-
const { nodes } = await this.transferService.extendTimelock(node);
|
|
12874
|
-
for (const n of nodes) {
|
|
12875
|
-
if (n.status === "AVAILABLE") {
|
|
12876
|
-
const transfer = await this.transferLeavesToSelf([n], {
|
|
12877
|
-
type: "leaf" /* LEAF */,
|
|
12878
|
-
path: node.id
|
|
12879
|
-
});
|
|
12880
|
-
resultingNodes.push(...transfer);
|
|
12881
|
-
} else {
|
|
12882
|
-
resultingNodes.push(n);
|
|
12883
|
-
}
|
|
12884
|
-
}
|
|
12885
|
-
} else {
|
|
12886
|
-
resultingNodes.push(node);
|
|
12887
|
-
}
|
|
12888
|
-
}
|
|
12889
|
-
return resultingNodes;
|
|
12561
|
+
return res.nodes;
|
|
12890
12562
|
}
|
|
12891
12563
|
/**
|
|
12892
12564
|
* Gets all unused deposit addresses for the wallet.
|
|
@@ -13028,6 +12700,9 @@ var SparkWallet = class extends EventEmitter {
|
|
|
13028
12700
|
depositTx,
|
|
13029
12701
|
vout
|
|
13030
12702
|
});
|
|
12703
|
+
await this.withLeaves(async () => {
|
|
12704
|
+
this.leaves.push(...nodes2);
|
|
12705
|
+
});
|
|
13031
12706
|
return nodes2;
|
|
13032
12707
|
});
|
|
13033
12708
|
this.mutexes.delete(txid);
|
|
@@ -13157,7 +12832,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
13157
12832
|
const [outcome] = await this.transferWithInvoice([
|
|
13158
12833
|
{
|
|
13159
12834
|
amountSats,
|
|
13160
|
-
receiverIdentityPubkey:
|
|
12835
|
+
receiverIdentityPubkey: hexToBytes12(receiverAddress.identityPublicKey)
|
|
13161
12836
|
}
|
|
13162
12837
|
]);
|
|
13163
12838
|
if (!outcome) throw new Error("no transfer created");
|
|
@@ -13204,8 +12879,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
13204
12879
|
`TreeNode group at index ${groupIndex} not found for amount ${amount} after selection`
|
|
13205
12880
|
);
|
|
13206
12881
|
}
|
|
13207
|
-
|
|
13208
|
-
available = await this.checkExtendTimeLockNodes(available);
|
|
12882
|
+
const available = await this.checkRenewLeaves(group);
|
|
13209
12883
|
if (available.length < group.length) {
|
|
13210
12884
|
throw new Error(
|
|
13211
12885
|
`Not enough available nodes after refresh/extend. Expected ${group.length}, got ${available.length}`
|
|
@@ -13298,75 +12972,45 @@ var SparkWallet = class extends EventEmitter {
|
|
|
13298
12972
|
newKeyDerivation: { type: "random" /* RANDOM */ }
|
|
13299
12973
|
};
|
|
13300
12974
|
}
|
|
13301
|
-
async
|
|
13302
|
-
const
|
|
12975
|
+
async checkRenewLeaves(nodes) {
|
|
12976
|
+
const nodesToRenewNode = [];
|
|
12977
|
+
const nodesToRenewRefund = [];
|
|
12978
|
+
const nodesToRenewZeroTimelock = [];
|
|
13303
12979
|
const nodeIds = [];
|
|
13304
12980
|
const validNodes = [];
|
|
13305
12981
|
for (const node of nodes) {
|
|
13306
12982
|
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
13307
|
-
const
|
|
13308
|
-
|
|
12983
|
+
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
12984
|
+
const nodeSequence = nodeTx.getInput(0).sequence;
|
|
12985
|
+
const refundSequence = refundTx.getInput(0).sequence;
|
|
12986
|
+
if (nodeSequence === void 0) {
|
|
13309
12987
|
throw new ValidationError("Invalid node transaction", {
|
|
13310
12988
|
field: "sequence",
|
|
13311
12989
|
value: nodeTx.getInput(0),
|
|
13312
12990
|
expected: "Non-null sequence"
|
|
13313
12991
|
});
|
|
13314
12992
|
}
|
|
13315
|
-
|
|
13316
|
-
if (needsRefresh) {
|
|
13317
|
-
nodesToExtend.push(node);
|
|
13318
|
-
nodeIds.push(node.id);
|
|
13319
|
-
} else {
|
|
13320
|
-
validNodes.push(node);
|
|
13321
|
-
}
|
|
13322
|
-
}
|
|
13323
|
-
if (nodesToExtend.length === 0) {
|
|
13324
|
-
return validNodes;
|
|
13325
|
-
}
|
|
13326
|
-
const nodesToAdd = [];
|
|
13327
|
-
for (const node of nodesToExtend) {
|
|
13328
|
-
const { nodes: nodes2 } = await this.transferService.extendTimelock(node);
|
|
13329
|
-
this.leaves = this.leaves.filter((leaf) => leaf.id !== node.id);
|
|
13330
|
-
const newNodes = await this.transferLeavesToSelf(nodes2, {
|
|
13331
|
-
type: "leaf" /* LEAF */,
|
|
13332
|
-
path: node.id
|
|
13333
|
-
});
|
|
13334
|
-
nodesToAdd.push(...newNodes);
|
|
13335
|
-
}
|
|
13336
|
-
this.updateLeaves(nodeIds, nodesToAdd);
|
|
13337
|
-
validNodes.push(...nodesToAdd);
|
|
13338
|
-
return validNodes;
|
|
13339
|
-
}
|
|
13340
|
-
/**
|
|
13341
|
-
* Internal method to refresh timelock nodes.
|
|
13342
|
-
*
|
|
13343
|
-
* @param {string} nodeId - The optional ID of the node to refresh. If not provided, all nodes will be checked.
|
|
13344
|
-
* @returns {Promise<void>}
|
|
13345
|
-
* @private
|
|
13346
|
-
*/
|
|
13347
|
-
async checkRefreshTimelockNodes(nodes) {
|
|
13348
|
-
const nodesToRefresh = [];
|
|
13349
|
-
const nodeIds = [];
|
|
13350
|
-
const validNodes = [];
|
|
13351
|
-
for (const node of nodes) {
|
|
13352
|
-
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
13353
|
-
const sequence = refundTx.getInput(0).sequence;
|
|
13354
|
-
if (!sequence) {
|
|
12993
|
+
if (!refundSequence) {
|
|
13355
12994
|
throw new ValidationError("Invalid refund transaction", {
|
|
13356
12995
|
field: "sequence",
|
|
13357
12996
|
value: refundTx.getInput(0),
|
|
13358
12997
|
expected: "Non-null sequence"
|
|
13359
12998
|
});
|
|
13360
12999
|
}
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
|
|
13000
|
+
if (doesTxnNeedRenewed(refundSequence)) {
|
|
13001
|
+
if (isZeroTimelock(nodeSequence)) {
|
|
13002
|
+
nodesToRenewZeroTimelock.push(node);
|
|
13003
|
+
} else if (doesTxnNeedRenewed(nodeSequence)) {
|
|
13004
|
+
nodesToRenewNode.push(node);
|
|
13005
|
+
} else {
|
|
13006
|
+
nodesToRenewRefund.push(node);
|
|
13007
|
+
}
|
|
13364
13008
|
nodeIds.push(node.id);
|
|
13365
13009
|
} else {
|
|
13366
13010
|
validNodes.push(node);
|
|
13367
13011
|
}
|
|
13368
13012
|
}
|
|
13369
|
-
if (
|
|
13013
|
+
if (nodesToRenewNode.length === 0 && nodesToRenewRefund.length === 0 && nodesToRenewZeroTimelock.length === 0) {
|
|
13370
13014
|
return validNodes;
|
|
13371
13015
|
}
|
|
13372
13016
|
const nodesResp = await this.queryNodes({
|
|
@@ -13384,7 +13028,18 @@ var SparkWallet = class extends EventEmitter {
|
|
|
13384
13028
|
nodesMap.set(node.id, node);
|
|
13385
13029
|
}
|
|
13386
13030
|
const nodesToAdd = [];
|
|
13387
|
-
for (const node of
|
|
13031
|
+
for (const node of nodesToRenewNode) {
|
|
13032
|
+
if (!node.parentNodeId) {
|
|
13033
|
+
throw new Error(`node ${node.id} has no parent`);
|
|
13034
|
+
}
|
|
13035
|
+
const parentNode = nodesMap.get(node.parentNodeId);
|
|
13036
|
+
if (!parentNode) {
|
|
13037
|
+
throw new Error(`parent node ${node.parentNodeId} not found`);
|
|
13038
|
+
}
|
|
13039
|
+
const newNode = await this.transferService.renewNodeTxn(node, parentNode);
|
|
13040
|
+
nodesToAdd.push(newNode);
|
|
13041
|
+
}
|
|
13042
|
+
for (const node of nodesToRenewRefund) {
|
|
13388
13043
|
if (!node.parentNodeId) {
|
|
13389
13044
|
throw new Error(`node ${node.id} has no parent`);
|
|
13390
13045
|
}
|
|
@@ -13392,17 +13047,14 @@ var SparkWallet = class extends EventEmitter {
|
|
|
13392
13047
|
if (!parentNode) {
|
|
13393
13048
|
throw new Error(`parent node ${node.parentNodeId} not found`);
|
|
13394
13049
|
}
|
|
13395
|
-
const
|
|
13050
|
+
const newNode = await this.transferService.renewRefundTxn(
|
|
13396
13051
|
node,
|
|
13397
13052
|
parentNode
|
|
13398
13053
|
);
|
|
13399
|
-
|
|
13400
|
-
|
|
13401
|
-
|
|
13402
|
-
const newNode =
|
|
13403
|
-
if (!newNode) {
|
|
13404
|
-
throw new Error("Failed to refresh timelock node");
|
|
13405
|
-
}
|
|
13054
|
+
nodesToAdd.push(newNode);
|
|
13055
|
+
}
|
|
13056
|
+
for (const node of nodesToRenewZeroTimelock) {
|
|
13057
|
+
const newNode = await this.transferService.renewZeroTimelockNodeTxn(node);
|
|
13406
13058
|
nodesToAdd.push(newNode);
|
|
13407
13059
|
}
|
|
13408
13060
|
this.updateLeaves(nodeIds, nodesToAdd);
|
|
@@ -13444,8 +13096,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
13444
13096
|
});
|
|
13445
13097
|
}
|
|
13446
13098
|
async processClaimedTransferResults(result, transfer, emit, optimize) {
|
|
13447
|
-
result = await this.
|
|
13448
|
-
result = await this.checkExtendTimeLockNodes(result);
|
|
13099
|
+
result = await this.checkRenewLeaves(result);
|
|
13449
13100
|
const existingIds = new Set(this.leaves.map((leaf) => leaf.id));
|
|
13450
13101
|
const uniqueResults = result.filter((node) => !existingIds.has(node.id));
|
|
13451
13102
|
this.leaves.push(...uniqueResults);
|
|
@@ -13779,7 +13430,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
13779
13430
|
const sparkFallbackAddress = decodedInvoice.fallbackAddress;
|
|
13780
13431
|
const paymentHash = decodedInvoice.paymentHash;
|
|
13781
13432
|
if (preferSpark) {
|
|
13782
|
-
if (sparkFallbackAddress === void 0 || isValidSparkFallback(
|
|
13433
|
+
if (sparkFallbackAddress === void 0 || isValidSparkFallback(hexToBytes12(sparkFallbackAddress)) === false) {
|
|
13783
13434
|
console.warn(
|
|
13784
13435
|
"No valid spark address found in invoice. Defaulting to lightning."
|
|
13785
13436
|
);
|
|
@@ -13824,8 +13475,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
13824
13475
|
selectedLeaves,
|
|
13825
13476
|
`no leaves for ${totalAmount}`
|
|
13826
13477
|
);
|
|
13827
|
-
leaves = await this.
|
|
13828
|
-
leaves = await this.checkExtendTimeLockNodes(leaves);
|
|
13478
|
+
leaves = await this.checkRenewLeaves(leaves);
|
|
13829
13479
|
const leavesToSend = await Promise.all(
|
|
13830
13480
|
leaves.map(async (leaf) => ({
|
|
13831
13481
|
leaf,
|
|
@@ -13841,17 +13491,17 @@ var SparkWallet = class extends EventEmitter {
|
|
|
13841
13491
|
const transferID = uuidv74();
|
|
13842
13492
|
const startTransferRequest = await this.transferService.prepareTransferForLightning(
|
|
13843
13493
|
leavesToSend,
|
|
13844
|
-
|
|
13845
|
-
|
|
13494
|
+
hexToBytes12(this.config.getSspIdentityPublicKey()),
|
|
13495
|
+
hexToBytes12(paymentHash),
|
|
13846
13496
|
expiryTime,
|
|
13847
13497
|
transferID
|
|
13848
13498
|
);
|
|
13849
13499
|
const swapResponse = await this.lightningService.swapNodesForPreimage({
|
|
13850
13500
|
leaves: leavesToSend,
|
|
13851
|
-
receiverIdentityPubkey:
|
|
13501
|
+
receiverIdentityPubkey: hexToBytes12(
|
|
13852
13502
|
this.config.getSspIdentityPublicKey()
|
|
13853
13503
|
),
|
|
13854
|
-
paymentHash:
|
|
13504
|
+
paymentHash: hexToBytes12(paymentHash),
|
|
13855
13505
|
isInboundPayment: false,
|
|
13856
13506
|
invoiceString: invoice,
|
|
13857
13507
|
feeSats: feeEstimate,
|
|
@@ -13954,7 +13604,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
13954
13604
|
}
|
|
13955
13605
|
satsInvoices.push({
|
|
13956
13606
|
amountSats: encodedAmount ?? Number(amount),
|
|
13957
|
-
receiverIdentityPubkey:
|
|
13607
|
+
receiverIdentityPubkey: hexToBytes12(addressData.identityPublicKey),
|
|
13958
13608
|
sparkInvoice: invoice
|
|
13959
13609
|
});
|
|
13960
13610
|
} else if (fields.paymentType?.type === "tokens") {
|
|
@@ -14156,10 +13806,8 @@ var SparkWallet = class extends EventEmitter {
|
|
|
14156
13806
|
leavesToSendToSsp = leavesForTargetAmount;
|
|
14157
13807
|
leavesToSendToSE = leavesForFee;
|
|
14158
13808
|
}
|
|
14159
|
-
leavesToSendToSsp = await this.
|
|
14160
|
-
|
|
14161
|
-
leavesToSendToSE = await this.checkRefreshTimelockNodes(leavesToSendToSE);
|
|
14162
|
-
leavesToSendToSE = await this.checkExtendTimeLockNodes(leavesToSendToSE);
|
|
13809
|
+
leavesToSendToSsp = await this.checkRenewLeaves(leavesToSendToSsp);
|
|
13810
|
+
leavesToSendToSE = await this.checkRenewLeaves(leavesToSendToSE);
|
|
14163
13811
|
const leafKeyTweaks = await Promise.all(
|
|
14164
13812
|
[...leavesToSendToSE, ...leavesToSendToSsp].map(async (leaf) => ({
|
|
14165
13813
|
leaf,
|
|
@@ -14204,11 +13852,11 @@ var SparkWallet = class extends EventEmitter {
|
|
|
14204
13852
|
const connectorOutputs = [];
|
|
14205
13853
|
for (let i = 0; i < connectorTx.outputsLength - 1; i++) {
|
|
14206
13854
|
connectorOutputs.push({
|
|
14207
|
-
txid:
|
|
13855
|
+
txid: hexToBytes12(connectorTxId),
|
|
14208
13856
|
index: i
|
|
14209
13857
|
});
|
|
14210
13858
|
}
|
|
14211
|
-
const sspPubIdentityKey =
|
|
13859
|
+
const sspPubIdentityKey = hexToBytes12(this.config.getSspIdentityPublicKey());
|
|
14212
13860
|
const transfer = await this.coopExitService.getConnectorRefundSignatures({
|
|
14213
13861
|
leaves: leafKeyTweaks,
|
|
14214
13862
|
exitTxId: coopExitTxId,
|
|
@@ -14245,8 +13893,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
14245
13893
|
(await this.selectLeaves([amountSats])).get(amountSats),
|
|
14246
13894
|
`no leaves for ${amountSats}`
|
|
14247
13895
|
);
|
|
14248
|
-
leaves = await this.
|
|
14249
|
-
leaves = await this.checkExtendTimeLockNodes(leaves);
|
|
13896
|
+
leaves = await this.checkRenewLeaves(leaves);
|
|
14250
13897
|
const feeEstimate = await sspClient.getCoopExitFeeQuote({
|
|
14251
13898
|
leafExternalIds: leaves.map((leaf) => leaf.id),
|
|
14252
13899
|
withdrawalAddress
|
|
@@ -14521,7 +14168,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
14521
14168
|
async validateMessageWithIdentityKey(message, signature) {
|
|
14522
14169
|
const hash = sha25613(message);
|
|
14523
14170
|
if (typeof signature === "string") {
|
|
14524
|
-
signature =
|
|
14171
|
+
signature = hexToBytes12(signature);
|
|
14525
14172
|
}
|
|
14526
14173
|
return this.config.signer.validateMessageWithIdentityKey(hash, signature);
|
|
14527
14174
|
}
|
|
@@ -14534,7 +14181,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
14534
14181
|
*/
|
|
14535
14182
|
async signTransaction(txHex, keyType = "auto-detect") {
|
|
14536
14183
|
try {
|
|
14537
|
-
const tx =
|
|
14184
|
+
const tx = Transaction7.fromRaw(hexToBytes12(txHex));
|
|
14538
14185
|
let publicKey;
|
|
14539
14186
|
switch (keyType.toLowerCase()) {
|
|
14540
14187
|
case "identity":
|
|
@@ -14741,15 +14388,6 @@ var SparkWallet = class extends EventEmitter {
|
|
|
14741
14388
|
}
|
|
14742
14389
|
);
|
|
14743
14390
|
}
|
|
14744
|
-
if (!nodeInput.sequence) {
|
|
14745
|
-
throw new ValidationError(
|
|
14746
|
-
`Node transaction has no sequence for ${isRootNode ? "root" : "non-root"} node`,
|
|
14747
|
-
{
|
|
14748
|
-
field: "sequence",
|
|
14749
|
-
value: nodeInput.sequence
|
|
14750
|
-
}
|
|
14751
|
-
);
|
|
14752
|
-
}
|
|
14753
14391
|
const refundInput = refundTx.getInput(0);
|
|
14754
14392
|
if (!refundInput) {
|
|
14755
14393
|
throw new ValidationError(
|
|
@@ -14785,89 +14423,6 @@ var SparkWallet = class extends EventEmitter {
|
|
|
14785
14423
|
);
|
|
14786
14424
|
}
|
|
14787
14425
|
}
|
|
14788
|
-
/**
|
|
14789
|
-
* Refresh the timelock of a specific node.
|
|
14790
|
-
*
|
|
14791
|
-
* @param {string} nodeId - The ID of the node to refresh
|
|
14792
|
-
* @returns {Promise<void>} Promise that resolves when the timelock is refreshed
|
|
14793
|
-
*/
|
|
14794
|
-
async testOnly_expireTimelock(nodeId) {
|
|
14795
|
-
const sparkClient = await this.connectionManager.createSparkClient(
|
|
14796
|
-
this.config.getCoordinatorAddress()
|
|
14797
|
-
);
|
|
14798
|
-
try {
|
|
14799
|
-
const response = await sparkClient.query_nodes({
|
|
14800
|
-
source: {
|
|
14801
|
-
$case: "nodeIds",
|
|
14802
|
-
nodeIds: {
|
|
14803
|
-
nodeIds: [nodeId]
|
|
14804
|
-
}
|
|
14805
|
-
},
|
|
14806
|
-
includeParents: true
|
|
14807
|
-
});
|
|
14808
|
-
let leaf = response.nodes[nodeId];
|
|
14809
|
-
if (!leaf) {
|
|
14810
|
-
throw new ValidationError("Node not found", {
|
|
14811
|
-
field: "nodeId",
|
|
14812
|
-
value: nodeId
|
|
14813
|
-
});
|
|
14814
|
-
}
|
|
14815
|
-
let parentNode;
|
|
14816
|
-
let hasParentNode = false;
|
|
14817
|
-
if (!leaf.parentNodeId) {
|
|
14818
|
-
} else {
|
|
14819
|
-
hasParentNode = true;
|
|
14820
|
-
parentNode = response.nodes[leaf.parentNodeId];
|
|
14821
|
-
if (!parentNode) {
|
|
14822
|
-
throw new ValidationError("Parent node not found", {
|
|
14823
|
-
field: "parentNodeId",
|
|
14824
|
-
value: leaf.parentNodeId
|
|
14825
|
-
});
|
|
14826
|
-
}
|
|
14827
|
-
}
|
|
14828
|
-
const nodeTx = getTxFromRawTxBytes(leaf.nodeTx);
|
|
14829
|
-
const refundTx = getTxFromRawTxBytes(leaf.refundTx);
|
|
14830
|
-
if (hasParentNode) {
|
|
14831
|
-
const nodeTimelock = getCurrentTimelock(nodeTx.getInput(0).sequence);
|
|
14832
|
-
if (nodeTimelock > 100) {
|
|
14833
|
-
const expiredNodeTxLeaf = await this.transferService.testonly_expireTimeLockNodeTx(
|
|
14834
|
-
leaf,
|
|
14835
|
-
parentNode
|
|
14836
|
-
);
|
|
14837
|
-
if (!expiredNodeTxLeaf.nodes[0]) {
|
|
14838
|
-
throw new ValidationError("No expired node tx leaf", {
|
|
14839
|
-
field: "expiredNodeTxLeaf",
|
|
14840
|
-
value: expiredNodeTxLeaf
|
|
14841
|
-
});
|
|
14842
|
-
}
|
|
14843
|
-
leaf = expiredNodeTxLeaf.nodes[0];
|
|
14844
|
-
}
|
|
14845
|
-
}
|
|
14846
|
-
const refundTimelock = getCurrentTimelock(refundTx.getInput(0).sequence);
|
|
14847
|
-
if (refundTimelock > 100) {
|
|
14848
|
-
const expiredTxLeaf = await this.transferService.testonly_expireTimeLockRefundtx(leaf);
|
|
14849
|
-
if (!expiredTxLeaf.nodes[0]) {
|
|
14850
|
-
throw new ValidationError("No expired tx leaf", {
|
|
14851
|
-
field: "expiredTxLeaf",
|
|
14852
|
-
value: expiredTxLeaf
|
|
14853
|
-
});
|
|
14854
|
-
}
|
|
14855
|
-
leaf = expiredTxLeaf.nodes[0];
|
|
14856
|
-
}
|
|
14857
|
-
const leafIndex = this.leaves.findIndex((leaf2) => leaf2.id === leaf2.id);
|
|
14858
|
-
if (leafIndex !== -1) {
|
|
14859
|
-
this.leaves[leafIndex] = leaf;
|
|
14860
|
-
}
|
|
14861
|
-
} catch (error) {
|
|
14862
|
-
throw new NetworkError(
|
|
14863
|
-
"Failed to refresh timelock",
|
|
14864
|
-
{
|
|
14865
|
-
method: "refresh_timelock"
|
|
14866
|
-
},
|
|
14867
|
-
error
|
|
14868
|
-
);
|
|
14869
|
-
}
|
|
14870
|
-
}
|
|
14871
14426
|
cleanup() {
|
|
14872
14427
|
if (this.claimTransfersInterval) {
|
|
14873
14428
|
clearInterval(this.claimTransfersInterval);
|
|
@@ -15022,8 +14577,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
15022
14577
|
"getLightningReceiveRequest",
|
|
15023
14578
|
"getLightningSendRequest",
|
|
15024
14579
|
"getCoopExitRequest",
|
|
15025
|
-
"checkTimelock"
|
|
15026
|
-
"testOnly_expireTimelock"
|
|
14580
|
+
"checkTimelock"
|
|
15027
14581
|
];
|
|
15028
14582
|
methods.forEach((m) => this.wrapPublicSparkWalletMethodWithOtelSpan(m));
|
|
15029
14583
|
this.initWallet = this.wrapWithOtelSpan(
|
|
@@ -15074,23 +14628,26 @@ export {
|
|
|
15074
14628
|
HTLC_TIMELOCK_OFFSET,
|
|
15075
14629
|
DIRECT_HTLC_TIMELOCK_OFFSET,
|
|
15076
14630
|
INITIAL_SEQUENCE,
|
|
15077
|
-
INITIAL_DIRECT_SEQUENCE,
|
|
15078
14631
|
TEST_UNILATERAL_SEQUENCE,
|
|
15079
14632
|
TEST_UNILATERAL_DIRECT_SEQUENCE,
|
|
15080
14633
|
DEFAULT_FEE_SATS,
|
|
15081
14634
|
maybeApplyFee,
|
|
15082
|
-
|
|
15083
|
-
|
|
15084
|
-
|
|
15085
|
-
|
|
15086
|
-
|
|
15087
|
-
createRefundTx,
|
|
14635
|
+
createRootNodeTx,
|
|
14636
|
+
createZeroTimelockNodeTx,
|
|
14637
|
+
createInitialTimelockNodeTx,
|
|
14638
|
+
createDecrementedTimelockNodeTx,
|
|
14639
|
+
createTestUnilateralTimelockNodeTx,
|
|
15088
14640
|
getNextHTLCTransactionSequence,
|
|
15089
|
-
|
|
15090
|
-
|
|
14641
|
+
createInitialTimelockRefundTxs,
|
|
14642
|
+
createDecrementedTimelockRefundTxs,
|
|
14643
|
+
createCurrentTimelockRefundTxs,
|
|
14644
|
+
createTestUnilateralRefundTxs,
|
|
14645
|
+
createConnectorRefundTxs,
|
|
15091
14646
|
getCurrentTimelock,
|
|
15092
14647
|
getTransactionSequence,
|
|
15093
14648
|
checkIfValidSequence,
|
|
14649
|
+
isZeroTimelock,
|
|
14650
|
+
doesTxnNeedRenewed,
|
|
15094
14651
|
doesLeafNeedRefresh,
|
|
15095
14652
|
getNextTransactionSequence,
|
|
15096
14653
|
getEphemeralAnchorOutput,
|