@buildonspark/spark-sdk 0.1.38 → 0.1.40
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 +12 -0
- package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +1 -1
- package/android/build/intermediates/library_jni/debug/copyDebugJniLibsProjectOnly/jni/arm64-v8a/libspark_frost.so +0 -0
- package/android/build/intermediates/library_jni/debug/copyDebugJniLibsProjectOnly/jni/arm64-v8a/libuniffi_spark_frost.so +0 -0
- package/android/build/intermediates/library_jni/debug/copyDebugJniLibsProjectOnly/jni/armeabi-v7a/libspark_frost.so +0 -0
- package/android/build/intermediates/library_jni/debug/copyDebugJniLibsProjectOnly/jni/armeabi-v7a/libuniffi_spark_frost.so +0 -0
- package/android/build/intermediates/library_jni/debug/copyDebugJniLibsProjectOnly/jni/x86/libspark_frost.so +0 -0
- package/android/build/intermediates/library_jni/debug/copyDebugJniLibsProjectOnly/jni/x86/libuniffi_spark_frost.so +0 -0
- package/android/build/intermediates/library_jni/debug/copyDebugJniLibsProjectOnly/jni/x86_64/libspark_frost.so +0 -0
- package/android/build/intermediates/library_jni/debug/copyDebugJniLibsProjectOnly/jni/x86_64/libuniffi_spark_frost.so +0 -0
- package/android/build/intermediates/merged_jni_libs/debug/mergeDebugJniLibFolders/out/arm64-v8a/libspark_frost.so +0 -0
- package/android/build/intermediates/merged_jni_libs/debug/mergeDebugJniLibFolders/out/arm64-v8a/libuniffi_spark_frost.so +0 -0
- package/android/build/intermediates/merged_jni_libs/debug/mergeDebugJniLibFolders/out/armeabi-v7a/libspark_frost.so +0 -0
- package/android/build/intermediates/merged_jni_libs/debug/mergeDebugJniLibFolders/out/armeabi-v7a/libuniffi_spark_frost.so +0 -0
- package/android/build/intermediates/merged_jni_libs/debug/mergeDebugJniLibFolders/out/x86/libspark_frost.so +0 -0
- package/android/build/intermediates/merged_jni_libs/debug/mergeDebugJniLibFolders/out/x86/libuniffi_spark_frost.so +0 -0
- package/android/build/intermediates/merged_jni_libs/debug/mergeDebugJniLibFolders/out/x86_64/libspark_frost.so +0 -0
- package/android/build/intermediates/merged_jni_libs/debug/mergeDebugJniLibFolders/out/x86_64/libuniffi_spark_frost.so +0 -0
- package/android/build/intermediates/merged_native_libs/debug/mergeDebugNativeLibs/out/lib/arm64-v8a/libspark_frost.so +0 -0
- package/android/build/intermediates/merged_native_libs/debug/mergeDebugNativeLibs/out/lib/arm64-v8a/libuniffi_spark_frost.so +0 -0
- package/android/build/intermediates/merged_native_libs/debug/mergeDebugNativeLibs/out/lib/armeabi-v7a/libspark_frost.so +0 -0
- package/android/build/intermediates/merged_native_libs/debug/mergeDebugNativeLibs/out/lib/armeabi-v7a/libuniffi_spark_frost.so +0 -0
- package/android/build/intermediates/merged_native_libs/debug/mergeDebugNativeLibs/out/lib/x86/libspark_frost.so +0 -0
- package/android/build/intermediates/merged_native_libs/debug/mergeDebugNativeLibs/out/lib/x86/libuniffi_spark_frost.so +0 -0
- package/android/build/intermediates/merged_native_libs/debug/mergeDebugNativeLibs/out/lib/x86_64/libspark_frost.so +0 -0
- package/android/build/intermediates/merged_native_libs/debug/mergeDebugNativeLibs/out/lib/x86_64/libuniffi_spark_frost.so +0 -0
- package/dist/{RequestLightningSendInput-B4JdzclX.d.ts → RequestLightningSendInput-CJtcHOnu.d.ts} +1 -1
- package/dist/{RequestLightningSendInput-39_zGri6.d.cts → RequestLightningSendInput-DfmfqzZo.d.cts} +1 -1
- package/dist/address/index.d.cts +1 -1
- package/dist/address/index.d.ts +1 -1
- package/dist/address/index.js +2 -2
- package/dist/{chunk-W3EC5XSA.js → chunk-5MNQB2T4.js} +2 -2
- package/dist/chunk-ED3ZAFDI.js +784 -0
- package/dist/{chunk-VJTDG4BQ.js → chunk-HK6LPV6Z.js} +10 -1
- package/dist/{chunk-7WRK6WNJ.js → chunk-LHT4QTFK.js} +556 -41
- package/dist/{chunk-RAPBVYJY.js → chunk-RFCXPGDM.js} +26 -4
- package/dist/{chunk-DI7QXUQJ.js → chunk-W2VXS35Y.js} +4 -4
- package/dist/graphql/objects/index.d.cts +5 -4
- package/dist/graphql/objects/index.d.ts +5 -4
- package/dist/{index-CxAi2L8y.d.ts → index-BDEYgYxP.d.ts} +42 -4
- package/dist/{index-Dm17Ggfe.d.cts → index-CLdtdMU4.d.cts} +42 -4
- package/dist/index.cjs +1069 -40
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +33 -17
- package/dist/index.node.cjs +1069 -40
- package/dist/index.node.d.cts +6 -6
- package/dist/index.node.d.ts +6 -6
- package/dist/index.node.js +33 -17
- package/dist/native/index.cjs +1069 -40
- package/dist/native/index.d.cts +108 -5
- package/dist/native/index.d.ts +108 -5
- package/dist/native/index.js +1065 -40
- package/dist/{network-GFGEHkS4.d.cts → network-B10hBoHp.d.cts} +8 -1
- package/dist/{network-DobHpaV6.d.ts → network-CCgyIsGl.d.ts} +8 -1
- package/dist/services/config.cjs +29 -12
- package/dist/services/config.d.cts +4 -4
- package/dist/services/config.d.ts +4 -4
- package/dist/services/config.js +5 -5
- package/dist/services/connection.d.cts +4 -4
- package/dist/services/connection.d.ts +4 -4
- package/dist/services/connection.js +2 -2
- package/dist/services/index.cjs +30 -13
- package/dist/services/index.d.cts +4 -4
- package/dist/services/index.d.ts +4 -4
- package/dist/services/index.js +8 -8
- package/dist/services/lrc-connection.d.cts +4 -4
- package/dist/services/lrc-connection.d.ts +4 -4
- package/dist/services/lrc-connection.js +1 -1
- package/dist/services/token-transactions.cjs +1 -1
- package/dist/services/token-transactions.d.cts +4 -4
- package/dist/services/token-transactions.d.ts +4 -4
- package/dist/services/token-transactions.js +3 -3
- package/dist/services/wallet-config.d.cts +4 -4
- package/dist/services/wallet-config.d.ts +4 -4
- package/dist/signer/signer.cjs +23 -6
- package/dist/signer/signer.d.cts +3 -2
- package/dist/signer/signer.d.ts +3 -2
- package/dist/signer/signer.js +1 -1
- package/dist/{signer-DFGw9RRp.d.ts → signer-C5h1DpjF.d.ts} +4 -1
- package/dist/{signer-C1t40Wus.d.cts → signer-CYwn7h9U.d.cts} +4 -1
- package/dist/types/index.d.cts +4 -3
- package/dist/types/index.d.ts +4 -3
- package/dist/utils/index.cjs +891 -2
- package/dist/utils/index.d.cts +62 -6
- package/dist/utils/index.d.ts +62 -6
- package/dist/utils/index.js +23 -7
- package/package.json +1 -1
- package/src/services/deposit.ts +23 -5
- package/src/services/token-transactions.ts +1 -1
- package/src/services/transfer.ts +218 -11
- package/src/services/tree-creation.ts +29 -14
- package/src/signer/signer.ts +47 -5
- package/src/spark-wallet/spark-wallet.ts +430 -4
- package/src/tests/integration/swap.test.ts +225 -0
- package/src/tests/integration/tree-creation.test.ts +5 -1
- package/src/utils/index.ts +1 -0
- package/src/utils/mempool.ts +26 -1
- package/src/utils/network.ts +15 -0
- package/src/utils/transaction.ts +22 -2
- package/src/utils/unilateral-exit.ts +729 -0
- package/dist/chunk-E5SL7XTO.js +0 -301
- package/dist/{chunk-LIP2K6KR.js → chunk-2CDJZQN4.js} +3 -3
- package/dist/{chunk-RGWBSZIO.js → chunk-I4JI6TYN.js} +4 -4
|
@@ -2,9 +2,7 @@ import {
|
|
|
2
2
|
Lrc20ConnectionManager
|
|
3
3
|
} from "./chunk-FWQPAPXK.js";
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
} from "./chunk-W3EC5XSA.js";
|
|
7
|
-
import {
|
|
5
|
+
DEFAULT_FEE_SATS,
|
|
8
6
|
computeTaprootKeyNoScript,
|
|
9
7
|
createRefundTx,
|
|
10
8
|
getEphemeralAnchorOutput,
|
|
@@ -19,10 +17,7 @@ import {
|
|
|
19
17
|
getTxFromRawTxHex,
|
|
20
18
|
getTxId,
|
|
21
19
|
proofOfPossessionMessageHashForDepositAddress
|
|
22
|
-
} from "./chunk-
|
|
23
|
-
import {
|
|
24
|
-
calculateAvailableTokenAmount
|
|
25
|
-
} from "./chunk-57XLH3ZR.js";
|
|
20
|
+
} from "./chunk-ED3ZAFDI.js";
|
|
26
21
|
import {
|
|
27
22
|
mapTransferToWalletTransfer,
|
|
28
23
|
mapTreeNodeToWalletLeaf
|
|
@@ -41,26 +36,29 @@ import {
|
|
|
41
36
|
LightningReceiveRequestFromJson,
|
|
42
37
|
LightningSendRequestFromJson
|
|
43
38
|
} from "./chunk-S7KD6DDL.js";
|
|
39
|
+
import {
|
|
40
|
+
TokenTransactionService
|
|
41
|
+
} from "./chunk-5MNQB2T4.js";
|
|
42
|
+
import {
|
|
43
|
+
calculateAvailableTokenAmount
|
|
44
|
+
} from "./chunk-57XLH3ZR.js";
|
|
44
45
|
import {
|
|
45
46
|
decodeSparkAddress,
|
|
46
47
|
encodeSparkAddress
|
|
47
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-2CDJZQN4.js";
|
|
48
49
|
import {
|
|
49
50
|
WalletConfigService
|
|
50
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-W2VXS35Y.js";
|
|
51
52
|
import {
|
|
52
53
|
LRC_WALLET_NETWORK,
|
|
53
54
|
LRC_WALLET_NETWORK_TYPE,
|
|
54
55
|
Network,
|
|
55
56
|
NetworkToProto,
|
|
56
57
|
getNetwork
|
|
57
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-HK6LPV6Z.js";
|
|
58
59
|
import {
|
|
59
60
|
ELECTRS_CREDENTIALS
|
|
60
61
|
} from "./chunk-ZUVYYR5T.js";
|
|
61
|
-
import {
|
|
62
|
-
BitcoinNetwork_default
|
|
63
|
-
} from "./chunk-HMLOC6TE.js";
|
|
64
62
|
import {
|
|
65
63
|
addPublicKeys,
|
|
66
64
|
applyAdaptorToSignature,
|
|
@@ -72,12 +70,11 @@ import {
|
|
|
72
70
|
getCrypto
|
|
73
71
|
} from "./chunk-MGPRLH6Q.js";
|
|
74
72
|
import {
|
|
75
|
-
|
|
76
|
-
} from "./chunk-
|
|
73
|
+
BitcoinNetwork_default
|
|
74
|
+
} from "./chunk-HMLOC6TE.js";
|
|
77
75
|
import {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
} from "./chunk-C5LTJBI7.js";
|
|
76
|
+
ConnectionManager
|
|
77
|
+
} from "./chunk-I4JI6TYN.js";
|
|
81
78
|
import {
|
|
82
79
|
isReactNative
|
|
83
80
|
} from "./chunk-HKAKEKCE.js";
|
|
@@ -88,6 +85,10 @@ import {
|
|
|
88
85
|
RPCError,
|
|
89
86
|
ValidationError
|
|
90
87
|
} from "./chunk-TWF35O6M.js";
|
|
88
|
+
import {
|
|
89
|
+
SendLeafKeyTweaks,
|
|
90
|
+
networkToJSON
|
|
91
|
+
} from "./chunk-C5LTJBI7.js";
|
|
91
92
|
import {
|
|
92
93
|
Buffer
|
|
93
94
|
} from "./chunk-MVRQ5US7.js";
|
|
@@ -1058,6 +1059,32 @@ var BaseTransferService = class {
|
|
|
1058
1059
|
}
|
|
1059
1060
|
return updatedTransfer;
|
|
1060
1061
|
}
|
|
1062
|
+
async deliverTransferPackage(transfer, leaves, refundSignatureMap) {
|
|
1063
|
+
const keyTweakInputMap = await this.prepareSendTransferKeyTweaks(
|
|
1064
|
+
transfer.id,
|
|
1065
|
+
transfer.receiverIdentityPublicKey,
|
|
1066
|
+
leaves,
|
|
1067
|
+
refundSignatureMap
|
|
1068
|
+
);
|
|
1069
|
+
const transferPackage = await this.prepareTransferPackage(
|
|
1070
|
+
transfer.id,
|
|
1071
|
+
keyTweakInputMap,
|
|
1072
|
+
leaves,
|
|
1073
|
+
transfer.receiverIdentityPublicKey
|
|
1074
|
+
);
|
|
1075
|
+
const sparkClient = await this.connectionManager.createSparkClient(
|
|
1076
|
+
this.config.getCoordinatorAddress()
|
|
1077
|
+
);
|
|
1078
|
+
const response = await sparkClient.finalize_transfer_with_transfer_package({
|
|
1079
|
+
transferId: transfer.id,
|
|
1080
|
+
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
1081
|
+
transferPackage
|
|
1082
|
+
});
|
|
1083
|
+
if (!response.transfer) {
|
|
1084
|
+
throw new ValidationError("No transfer response from operator");
|
|
1085
|
+
}
|
|
1086
|
+
return response.transfer;
|
|
1087
|
+
}
|
|
1061
1088
|
async sendTransferWithKeyTweaks(leaves, receiverIdentityPubkey) {
|
|
1062
1089
|
const transferID = uuidv7();
|
|
1063
1090
|
const keyTweakInputMap = await this.prepareSendTransferKeyTweaks(
|
|
@@ -1815,9 +1842,20 @@ var TransferService = class extends BaseTransferService {
|
|
|
1815
1842
|
if (!input) {
|
|
1816
1843
|
throw Error("Could not fetch tx input");
|
|
1817
1844
|
}
|
|
1818
|
-
const newTx = new Transaction({ allowUnknownOutputs: true });
|
|
1819
|
-
|
|
1820
|
-
|
|
1845
|
+
const newTx = new Transaction({ version: 3, allowUnknownOutputs: true });
|
|
1846
|
+
const originalOutput = nodeTx.getOutput(0);
|
|
1847
|
+
if (!originalOutput) {
|
|
1848
|
+
throw Error("Could not get original output");
|
|
1849
|
+
}
|
|
1850
|
+
newTx.addOutput({
|
|
1851
|
+
script: originalOutput.script,
|
|
1852
|
+
amount: originalOutput.amount
|
|
1853
|
+
});
|
|
1854
|
+
for (let j = 1; j < nodeTx.outputsLength; j++) {
|
|
1855
|
+
const additionalOutput = nodeTx.getOutput(j);
|
|
1856
|
+
if (additionalOutput) {
|
|
1857
|
+
newTx.addOutput(additionalOutput);
|
|
1858
|
+
}
|
|
1821
1859
|
}
|
|
1822
1860
|
if (i === 0) {
|
|
1823
1861
|
const currSequence = input.sequence;
|
|
@@ -1844,9 +1882,23 @@ var TransferService = class extends BaseTransferService {
|
|
|
1844
1882
|
throw Error("leaf does not have refund tx");
|
|
1845
1883
|
}
|
|
1846
1884
|
const refundTx = getTxFromRawTxBytes(leaf?.refundTx);
|
|
1847
|
-
const newRefundTx = new Transaction({
|
|
1848
|
-
|
|
1849
|
-
|
|
1885
|
+
const newRefundTx = new Transaction({
|
|
1886
|
+
version: 3,
|
|
1887
|
+
allowUnknownOutputs: true
|
|
1888
|
+
});
|
|
1889
|
+
const originalRefundOutput = refundTx.getOutput(0);
|
|
1890
|
+
if (!originalRefundOutput) {
|
|
1891
|
+
throw Error("Could not get original refund output");
|
|
1892
|
+
}
|
|
1893
|
+
newRefundTx.addOutput({
|
|
1894
|
+
script: originalRefundOutput.script,
|
|
1895
|
+
amount: originalRefundOutput.amount
|
|
1896
|
+
});
|
|
1897
|
+
for (let j = 1; j < refundTx.outputsLength; j++) {
|
|
1898
|
+
const additionalOutput = refundTx.getOutput(j);
|
|
1899
|
+
if (additionalOutput) {
|
|
1900
|
+
newRefundTx.addOutput(additionalOutput);
|
|
1901
|
+
}
|
|
1850
1902
|
}
|
|
1851
1903
|
const refundTxInput = refundTx.getInput(0);
|
|
1852
1904
|
if (!refundTxInput) {
|
|
@@ -1955,10 +2007,11 @@ var TransferService = class extends BaseTransferService {
|
|
|
1955
2007
|
nodeTxSignature: leafSignature,
|
|
1956
2008
|
refundTxSignature: refundSignature
|
|
1957
2009
|
});
|
|
1958
|
-
|
|
2010
|
+
const result = await sparkClient.finalize_node_signatures({
|
|
1959
2011
|
intent: 3 /* REFRESH */,
|
|
1960
2012
|
nodeSignatures
|
|
1961
2013
|
});
|
|
2014
|
+
return result;
|
|
1962
2015
|
}
|
|
1963
2016
|
async extendTimelock(node, signingPubKey) {
|
|
1964
2017
|
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
@@ -1969,9 +2022,20 @@ var TransferService = class extends BaseTransferService {
|
|
|
1969
2022
|
index: 0
|
|
1970
2023
|
};
|
|
1971
2024
|
const { nextSequence: newNodeSequence } = getNextTransactionSequence(refundSequence);
|
|
1972
|
-
const newNodeTx = new Transaction({
|
|
2025
|
+
const newNodeTx = new Transaction({
|
|
2026
|
+
version: 3,
|
|
2027
|
+
allowUnknownOutputs: true
|
|
2028
|
+
});
|
|
1973
2029
|
newNodeTx.addInput({ ...newNodeOutPoint, sequence: newNodeSequence });
|
|
1974
|
-
|
|
2030
|
+
const originalOutput = nodeTx.getOutput(0);
|
|
2031
|
+
if (!originalOutput) {
|
|
2032
|
+
throw Error("Could not get original node output");
|
|
2033
|
+
}
|
|
2034
|
+
newNodeTx.addOutput({
|
|
2035
|
+
script: originalOutput.script,
|
|
2036
|
+
amount: originalOutput.amount
|
|
2037
|
+
// feeReducedAmount,
|
|
2038
|
+
});
|
|
1975
2039
|
newNodeTx.addOutput(getEphemeralAnchorOutput());
|
|
1976
2040
|
const newRefundOutPoint = {
|
|
1977
2041
|
txid: hexToBytes(getTxId(newNodeTx)),
|
|
@@ -1985,11 +2049,16 @@ var TransferService = class extends BaseTransferService {
|
|
|
1985
2049
|
initialSequence(),
|
|
1986
2050
|
newRefundOutPoint,
|
|
1987
2051
|
amountSats,
|
|
2052
|
+
// feeReducedRefundAmount,
|
|
1988
2053
|
signingPubKey,
|
|
1989
2054
|
this.config.getNetwork()
|
|
1990
2055
|
);
|
|
1991
2056
|
const nodeSighash = getSigHashFromTx(newNodeTx, 0, nodeTx.getOutput(0));
|
|
1992
|
-
const refundSighash = getSigHashFromTx(
|
|
2057
|
+
const refundSighash = getSigHashFromTx(
|
|
2058
|
+
newRefundTx,
|
|
2059
|
+
0,
|
|
2060
|
+
newNodeTx.getOutput(0)
|
|
2061
|
+
);
|
|
1993
2062
|
const newNodeSigningJob = {
|
|
1994
2063
|
signingPublicKey: signingPubKey,
|
|
1995
2064
|
rawTx: newNodeTx.toBytes(),
|
|
@@ -2063,6 +2132,94 @@ var TransferService = class extends BaseTransferService {
|
|
|
2063
2132
|
]
|
|
2064
2133
|
});
|
|
2065
2134
|
}
|
|
2135
|
+
async refreshTimelockRefundTx(node, signingPubKey) {
|
|
2136
|
+
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
2137
|
+
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
2138
|
+
const currSequence = refundTx.getInput(0).sequence || 0;
|
|
2139
|
+
const { nextSequence } = getNextTransactionSequence(currSequence);
|
|
2140
|
+
const newRefundTx = new Transaction({
|
|
2141
|
+
version: 3,
|
|
2142
|
+
allowUnknownOutputs: true
|
|
2143
|
+
});
|
|
2144
|
+
const originalRefundOutput = refundTx.getOutput(0);
|
|
2145
|
+
if (!originalRefundOutput) {
|
|
2146
|
+
throw Error("Could not get original refund output");
|
|
2147
|
+
}
|
|
2148
|
+
newRefundTx.addOutput({
|
|
2149
|
+
script: originalRefundOutput.script,
|
|
2150
|
+
amount: originalRefundOutput.amount
|
|
2151
|
+
});
|
|
2152
|
+
for (let j = 1; j < refundTx.outputsLength; j++) {
|
|
2153
|
+
const additionalOutput = refundTx.getOutput(j);
|
|
2154
|
+
if (additionalOutput) {
|
|
2155
|
+
newRefundTx.addOutput(additionalOutput);
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
const refundTxInput = refundTx.getInput(0);
|
|
2159
|
+
if (!refundTxInput) {
|
|
2160
|
+
throw Error("refund tx doesn't have input");
|
|
2161
|
+
}
|
|
2162
|
+
newRefundTx.addInput({
|
|
2163
|
+
...refundTxInput,
|
|
2164
|
+
sequence: nextSequence
|
|
2165
|
+
});
|
|
2166
|
+
const refundSigningJob = {
|
|
2167
|
+
signingPublicKey: signingPubKey,
|
|
2168
|
+
rawTx: newRefundTx.toBytes(),
|
|
2169
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
2170
|
+
};
|
|
2171
|
+
const sparkClient = await this.connectionManager.createSparkClient(
|
|
2172
|
+
this.config.getCoordinatorAddress()
|
|
2173
|
+
);
|
|
2174
|
+
const response = await sparkClient.refresh_timelock({
|
|
2175
|
+
leafId: node.id,
|
|
2176
|
+
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
2177
|
+
signingJobs: [refundSigningJob]
|
|
2178
|
+
});
|
|
2179
|
+
if (response.signingResults.length !== 1) {
|
|
2180
|
+
throw Error(
|
|
2181
|
+
`Expected 1 signing result, got ${response.signingResults.length}`
|
|
2182
|
+
);
|
|
2183
|
+
}
|
|
2184
|
+
const signingResult = response.signingResults[0];
|
|
2185
|
+
if (!signingResult || !refundSigningJob.signingNonceCommitment) {
|
|
2186
|
+
throw Error("Signing result or nonce commitment does not exist");
|
|
2187
|
+
}
|
|
2188
|
+
const rawTx = getTxFromRawTxBytes(refundSigningJob.rawTx);
|
|
2189
|
+
const txOut = nodeTx.getOutput(0);
|
|
2190
|
+
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
2191
|
+
const userSignature = await this.config.signer.signFrost({
|
|
2192
|
+
message: rawTxSighash,
|
|
2193
|
+
privateAsPubKey: signingPubKey,
|
|
2194
|
+
publicKey: signingPubKey,
|
|
2195
|
+
verifyingKey: signingResult.verifyingKey,
|
|
2196
|
+
selfCommitment: refundSigningJob.signingNonceCommitment,
|
|
2197
|
+
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
2198
|
+
adaptorPubKey: new Uint8Array()
|
|
2199
|
+
});
|
|
2200
|
+
const signature = await this.config.signer.aggregateFrost({
|
|
2201
|
+
message: rawTxSighash,
|
|
2202
|
+
statechainSignatures: signingResult.signingResult?.signatureShares,
|
|
2203
|
+
statechainPublicKeys: signingResult.signingResult?.publicKeys,
|
|
2204
|
+
verifyingKey: signingResult.verifyingKey,
|
|
2205
|
+
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
2206
|
+
selfCommitment: refundSigningJob.signingNonceCommitment,
|
|
2207
|
+
publicKey: signingPubKey,
|
|
2208
|
+
selfSignature: userSignature,
|
|
2209
|
+
adaptorPubKey: new Uint8Array()
|
|
2210
|
+
});
|
|
2211
|
+
const result = await sparkClient.finalize_node_signatures({
|
|
2212
|
+
intent: 3 /* REFRESH */,
|
|
2213
|
+
nodeSignatures: [
|
|
2214
|
+
{
|
|
2215
|
+
nodeId: node.id,
|
|
2216
|
+
nodeTxSignature: new Uint8Array(),
|
|
2217
|
+
refundTxSignature: signature
|
|
2218
|
+
}
|
|
2219
|
+
]
|
|
2220
|
+
});
|
|
2221
|
+
return result;
|
|
2222
|
+
}
|
|
2066
2223
|
};
|
|
2067
2224
|
|
|
2068
2225
|
// src/services/coop-exit.ts
|
|
@@ -2349,7 +2506,7 @@ var DepositService = class {
|
|
|
2349
2506
|
depositTx,
|
|
2350
2507
|
vout
|
|
2351
2508
|
}) {
|
|
2352
|
-
const rootTx = new Transaction3();
|
|
2509
|
+
const rootTx = new Transaction3({ version: 3 });
|
|
2353
2510
|
const output = depositTx.getOutput(vout);
|
|
2354
2511
|
if (!output) {
|
|
2355
2512
|
throw new ValidationError("Invalid deposit transaction output", {
|
|
@@ -2367,17 +2524,19 @@ var DepositService = class {
|
|
|
2367
2524
|
expected: "Output with script and amount"
|
|
2368
2525
|
});
|
|
2369
2526
|
}
|
|
2527
|
+
let outputAmount = amount;
|
|
2370
2528
|
rootTx.addInput({
|
|
2371
2529
|
txid: getTxId(depositTx),
|
|
2372
2530
|
index: vout
|
|
2373
2531
|
});
|
|
2374
2532
|
rootTx.addOutput({
|
|
2375
2533
|
script,
|
|
2376
|
-
amount
|
|
2534
|
+
amount: outputAmount
|
|
2377
2535
|
});
|
|
2536
|
+
rootTx.addOutput(getEphemeralAnchorOutput());
|
|
2378
2537
|
const rootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
2379
2538
|
const rootTxSighash = getSigHashFromTx(rootTx, 0, output);
|
|
2380
|
-
const refundTx = new Transaction3();
|
|
2539
|
+
const refundTx = new Transaction3({ version: 3 });
|
|
2381
2540
|
const sequence = 1 << 30 | INITIAL_TIME_LOCK2;
|
|
2382
2541
|
refundTx.addInput({
|
|
2383
2542
|
txid: getTxId(rootTx),
|
|
@@ -2392,10 +2551,11 @@ var DepositService = class {
|
|
|
2392
2551
|
const refundPkScript = btc.OutScript.encode(refundAddress);
|
|
2393
2552
|
refundTx.addOutput({
|
|
2394
2553
|
script: refundPkScript,
|
|
2395
|
-
amount
|
|
2554
|
+
amount: outputAmount
|
|
2396
2555
|
});
|
|
2556
|
+
refundTx.addOutput(getEphemeralAnchorOutput());
|
|
2397
2557
|
const refundNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
2398
|
-
const refundTxSighash = getSigHashFromTx(refundTx, 0,
|
|
2558
|
+
const refundTxSighash = getSigHashFromTx(refundTx, 0, rootTx.getOutput(0));
|
|
2399
2559
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
2400
2560
|
this.config.getCoordinatorAddress()
|
|
2401
2561
|
);
|
|
@@ -2968,6 +3128,12 @@ import { hexToBytes as hexToBytes4 } from "@noble/curves/abstract/utils";
|
|
|
2968
3128
|
import { sha256 as sha2566 } from "@noble/hashes/sha2";
|
|
2969
3129
|
import { Address as Address2, OutScript as OutScript2, Transaction as Transaction4 } from "@scure/btc-signer";
|
|
2970
3130
|
var INITIAL_TIME_LOCK3 = 2e3;
|
|
3131
|
+
function maybeApplyFee2(amount) {
|
|
3132
|
+
if (amount > BigInt(DEFAULT_FEE_SATS)) {
|
|
3133
|
+
return amount - BigInt(DEFAULT_FEE_SATS);
|
|
3134
|
+
}
|
|
3135
|
+
return amount;
|
|
3136
|
+
}
|
|
2971
3137
|
var TreeCreationService = class {
|
|
2972
3138
|
config;
|
|
2973
3139
|
connectionManager;
|
|
@@ -3166,7 +3332,7 @@ var TreeCreationService = class {
|
|
|
3166
3332
|
refundTxSigningJob: void 0,
|
|
3167
3333
|
children: []
|
|
3168
3334
|
};
|
|
3169
|
-
const tx = new Transaction4();
|
|
3335
|
+
const tx = new Transaction4({ version: 3 });
|
|
3170
3336
|
tx.addInput({
|
|
3171
3337
|
txid: getTxId(parentTx),
|
|
3172
3338
|
index: vout
|
|
@@ -3178,6 +3344,7 @@ var TreeCreationService = class {
|
|
|
3178
3344
|
tx.addOutput({
|
|
3179
3345
|
script: parentTxOut.script,
|
|
3180
3346
|
amount: parentTxOut.amount
|
|
3347
|
+
// maybeApplyFee(parentTxOut.amount),
|
|
3181
3348
|
});
|
|
3182
3349
|
tx.addOutput(getEphemeralAnchorOutput());
|
|
3183
3350
|
const signingNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
@@ -3194,7 +3361,7 @@ var TreeCreationService = class {
|
|
|
3194
3361
|
refundTxSigningJob: void 0,
|
|
3195
3362
|
children: []
|
|
3196
3363
|
};
|
|
3197
|
-
const childTx = new Transaction4();
|
|
3364
|
+
const childTx = new Transaction4({ version: 3 });
|
|
3198
3365
|
childTx.addInput({
|
|
3199
3366
|
txid: getTxId(tx),
|
|
3200
3367
|
index: 0,
|
|
@@ -3203,6 +3370,7 @@ var TreeCreationService = class {
|
|
|
3203
3370
|
childTx.addOutput({
|
|
3204
3371
|
script: parentTxOut.script,
|
|
3205
3372
|
amount: parentTxOut.amount
|
|
3373
|
+
// maybeApplyFee(parentTxOut.amount),
|
|
3206
3374
|
});
|
|
3207
3375
|
childTx.addOutput(getEphemeralAnchorOutput());
|
|
3208
3376
|
const childSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
@@ -3213,7 +3381,7 @@ var TreeCreationService = class {
|
|
|
3213
3381
|
};
|
|
3214
3382
|
childCreationNode.nodeTxSigningCommitment = childSigningNonceCommitment;
|
|
3215
3383
|
childCreationNode.nodeTxSigningJob = childSigningJob;
|
|
3216
|
-
const refundTx = new Transaction4();
|
|
3384
|
+
const refundTx = new Transaction4({ version: 3 });
|
|
3217
3385
|
refundTx.addInput({
|
|
3218
3386
|
txid: getTxId(childTx),
|
|
3219
3387
|
index: 0,
|
|
@@ -3229,8 +3397,9 @@ var TreeCreationService = class {
|
|
|
3229
3397
|
const refundPkScript = OutScript2.encode(refundAddress);
|
|
3230
3398
|
refundTx.addOutput({
|
|
3231
3399
|
script: refundPkScript,
|
|
3232
|
-
amount: parentTxOut.amount
|
|
3400
|
+
amount: maybeApplyFee2(parentTxOut.amount)
|
|
3233
3401
|
});
|
|
3402
|
+
refundTx.addOutput(getEphemeralAnchorOutput());
|
|
3234
3403
|
const refundSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
3235
3404
|
const refundSigningJob = {
|
|
3236
3405
|
signingPublicKey: node.signingPublicKey,
|
|
@@ -3247,7 +3416,7 @@ var TreeCreationService = class {
|
|
|
3247
3416
|
if (!parentTxOutput?.script || !parentTxOutput?.amount) {
|
|
3248
3417
|
throw new Error("parentTxOutput is undefined");
|
|
3249
3418
|
}
|
|
3250
|
-
const rootNodeTx = new Transaction4();
|
|
3419
|
+
const rootNodeTx = new Transaction4({ version: 3 });
|
|
3251
3420
|
rootNodeTx.addInput({
|
|
3252
3421
|
txid: getTxId(parentTx),
|
|
3253
3422
|
index: vout
|
|
@@ -3262,10 +3431,10 @@ var TreeCreationService = class {
|
|
|
3262
3431
|
rootNodeTx.addOutput({
|
|
3263
3432
|
script: childPkScript,
|
|
3264
3433
|
amount: parentTxOutput.amount / 2n
|
|
3434
|
+
// feeAdjustedAmount / 2n,
|
|
3265
3435
|
});
|
|
3266
3436
|
}
|
|
3267
|
-
|
|
3268
|
-
rootNodeTx.addOutput(anchor);
|
|
3437
|
+
rootNodeTx.addOutput(getEphemeralAnchorOutput());
|
|
3269
3438
|
const rootNodeSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
3270
3439
|
const rootNodeSigningJob = {
|
|
3271
3440
|
signingPublicKey: root.signingPublicKey,
|
|
@@ -4476,7 +4645,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
4476
4645
|
adaptorPrivateKey
|
|
4477
4646
|
);
|
|
4478
4647
|
}
|
|
4479
|
-
await this.transferService.
|
|
4648
|
+
await this.transferService.deliverTransferPackage(
|
|
4480
4649
|
transfer,
|
|
4481
4650
|
leafKeyTweaks,
|
|
4482
4651
|
signatureMap
|
|
@@ -6161,6 +6330,112 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
6161
6330
|
}
|
|
6162
6331
|
return this.config.signer.validateMessageWithIdentityKey(hash, signature);
|
|
6163
6332
|
}
|
|
6333
|
+
/**
|
|
6334
|
+
* Signs a transaction with wallet keys.
|
|
6335
|
+
*
|
|
6336
|
+
* @param {string} txHex - The transaction hex to sign
|
|
6337
|
+
* @param {string} keyType - The type of key to use for signing ("identity", "deposit", or "auto-detect")
|
|
6338
|
+
* @returns {Promise<string>} The signed transaction hex
|
|
6339
|
+
*/
|
|
6340
|
+
async signTransaction(txHex, keyType = "auto-detect") {
|
|
6341
|
+
try {
|
|
6342
|
+
const tx = Transaction6.fromRaw(hexToBytes7(txHex));
|
|
6343
|
+
let publicKey;
|
|
6344
|
+
switch (keyType.toLowerCase()) {
|
|
6345
|
+
case "identity":
|
|
6346
|
+
publicKey = await this.config.signer.getIdentityPublicKey();
|
|
6347
|
+
break;
|
|
6348
|
+
case "deposit":
|
|
6349
|
+
publicKey = await this.config.signer.getDepositSigningKey();
|
|
6350
|
+
break;
|
|
6351
|
+
case "auto-detect":
|
|
6352
|
+
default:
|
|
6353
|
+
const detectedKey = await this.detectKeyForTransaction(tx);
|
|
6354
|
+
if (detectedKey) {
|
|
6355
|
+
publicKey = detectedKey.publicKey;
|
|
6356
|
+
} else {
|
|
6357
|
+
publicKey = await this.config.signer.getIdentityPublicKey();
|
|
6358
|
+
}
|
|
6359
|
+
break;
|
|
6360
|
+
}
|
|
6361
|
+
let inputsSigned = 0;
|
|
6362
|
+
for (let i = 0; i < tx.inputsLength; i++) {
|
|
6363
|
+
const input = tx.getInput(i);
|
|
6364
|
+
if (!input?.witnessUtxo?.script) {
|
|
6365
|
+
continue;
|
|
6366
|
+
}
|
|
6367
|
+
const script = input.witnessUtxo.script;
|
|
6368
|
+
if (script.length === 1 && script[0] === 81) {
|
|
6369
|
+
continue;
|
|
6370
|
+
}
|
|
6371
|
+
const identityScript = getP2TRScriptFromPublicKey(
|
|
6372
|
+
publicKey,
|
|
6373
|
+
this.config.getNetwork()
|
|
6374
|
+
);
|
|
6375
|
+
if (bytesToHex4(script) === bytesToHex4(identityScript)) {
|
|
6376
|
+
try {
|
|
6377
|
+
this.config.signer.signTransactionIndex(tx, i, publicKey);
|
|
6378
|
+
inputsSigned++;
|
|
6379
|
+
} catch (error) {
|
|
6380
|
+
throw new ValidationError(`Failed to sign input ${i}: ${error}`, {
|
|
6381
|
+
field: "input",
|
|
6382
|
+
value: i
|
|
6383
|
+
});
|
|
6384
|
+
}
|
|
6385
|
+
}
|
|
6386
|
+
}
|
|
6387
|
+
if (inputsSigned === 0) {
|
|
6388
|
+
throw new Error(
|
|
6389
|
+
"No inputs were signed. Check that the transaction contains inputs controlled by this wallet."
|
|
6390
|
+
);
|
|
6391
|
+
}
|
|
6392
|
+
tx.finalize();
|
|
6393
|
+
const signedTxHex = tx.hex;
|
|
6394
|
+
return signedTxHex;
|
|
6395
|
+
} catch (error) {
|
|
6396
|
+
console.error("\u274C Error signing transaction:", error);
|
|
6397
|
+
throw error;
|
|
6398
|
+
}
|
|
6399
|
+
}
|
|
6400
|
+
/**
|
|
6401
|
+
* Helper method to auto-detect which key should be used for signing a transaction.
|
|
6402
|
+
*/
|
|
6403
|
+
async detectKeyForTransaction(tx) {
|
|
6404
|
+
try {
|
|
6405
|
+
const identityPubKey = await this.config.signer.getIdentityPublicKey();
|
|
6406
|
+
const depositPubKey = await this.config.signer.getDepositSigningKey();
|
|
6407
|
+
for (let i = 0; i < tx.inputsLength; i++) {
|
|
6408
|
+
const input = tx.getInput(i);
|
|
6409
|
+
if (input?.witnessUtxo?.script) {
|
|
6410
|
+
const script = input.witnessUtxo.script;
|
|
6411
|
+
const identityScript = getP2TRScriptFromPublicKey(
|
|
6412
|
+
identityPubKey,
|
|
6413
|
+
this.config.getNetwork()
|
|
6414
|
+
);
|
|
6415
|
+
const depositScript = getP2TRScriptFromPublicKey(
|
|
6416
|
+
depositPubKey,
|
|
6417
|
+
this.config.getNetwork()
|
|
6418
|
+
);
|
|
6419
|
+
if (bytesToHex4(script) === bytesToHex4(identityScript)) {
|
|
6420
|
+
return {
|
|
6421
|
+
publicKey: identityPubKey,
|
|
6422
|
+
keyType: "identity"
|
|
6423
|
+
};
|
|
6424
|
+
}
|
|
6425
|
+
if (bytesToHex4(script) === bytesToHex4(depositScript)) {
|
|
6426
|
+
return {
|
|
6427
|
+
publicKey: depositPubKey,
|
|
6428
|
+
keyType: "deposit"
|
|
6429
|
+
};
|
|
6430
|
+
}
|
|
6431
|
+
}
|
|
6432
|
+
}
|
|
6433
|
+
return null;
|
|
6434
|
+
} catch (error) {
|
|
6435
|
+
console.warn("Error during key auto-detection:", error);
|
|
6436
|
+
return null;
|
|
6437
|
+
}
|
|
6438
|
+
}
|
|
6164
6439
|
/**
|
|
6165
6440
|
* Get a Lightning receive request by ID.
|
|
6166
6441
|
*
|
|
@@ -6191,6 +6466,246 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
6191
6466
|
const sspClient = this.getSspClient();
|
|
6192
6467
|
return await sspClient.getCoopExitRequest(id);
|
|
6193
6468
|
}
|
|
6469
|
+
/**
|
|
6470
|
+
* Check the remaining timelock on a given node.
|
|
6471
|
+
*
|
|
6472
|
+
* @param {string} nodeId - The ID of the node to check
|
|
6473
|
+
* @returns {Promise<{nodeTimelock: number, refundTimelock: number}>} The remaining timelocks in blocks for both node and refund transactions
|
|
6474
|
+
*/
|
|
6475
|
+
async checkTimelock(nodeId) {
|
|
6476
|
+
const sparkClient = await this.connectionManager.createSparkClient(
|
|
6477
|
+
this.config.getCoordinatorAddress()
|
|
6478
|
+
);
|
|
6479
|
+
try {
|
|
6480
|
+
const response = await sparkClient.query_nodes({
|
|
6481
|
+
source: {
|
|
6482
|
+
$case: "nodeIds",
|
|
6483
|
+
nodeIds: {
|
|
6484
|
+
nodeIds: [nodeId]
|
|
6485
|
+
}
|
|
6486
|
+
},
|
|
6487
|
+
includeParents: false,
|
|
6488
|
+
network: NetworkToProto[this.config.getNetwork()]
|
|
6489
|
+
});
|
|
6490
|
+
const node = response.nodes[nodeId];
|
|
6491
|
+
if (!node) {
|
|
6492
|
+
throw new ValidationError("Node not found", {
|
|
6493
|
+
field: "nodeId",
|
|
6494
|
+
value: nodeId
|
|
6495
|
+
});
|
|
6496
|
+
}
|
|
6497
|
+
const isRootNode = !node.parentNodeId;
|
|
6498
|
+
if (!node.nodeTx || node.nodeTx.length === 0) {
|
|
6499
|
+
throw new ValidationError(
|
|
6500
|
+
`Node transaction data is missing or empty for ${isRootNode ? "root" : "non-root"} node`,
|
|
6501
|
+
{
|
|
6502
|
+
field: "nodeTx",
|
|
6503
|
+
value: node.nodeTx?.length || 0
|
|
6504
|
+
}
|
|
6505
|
+
);
|
|
6506
|
+
}
|
|
6507
|
+
if (!node.refundTx || node.refundTx.length === 0) {
|
|
6508
|
+
throw new ValidationError(
|
|
6509
|
+
`Refund transaction data is missing or empty for ${isRootNode ? "root" : "non-root"} node`,
|
|
6510
|
+
{
|
|
6511
|
+
field: "refundTx",
|
|
6512
|
+
value: node.refundTx?.length || 0
|
|
6513
|
+
}
|
|
6514
|
+
);
|
|
6515
|
+
}
|
|
6516
|
+
let nodeTx, refundTx;
|
|
6517
|
+
try {
|
|
6518
|
+
nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
6519
|
+
} catch (error) {
|
|
6520
|
+
throw new ValidationError(
|
|
6521
|
+
`Failed to parse node transaction for ${isRootNode ? "root" : "non-root"} node: ${error instanceof Error ? error.message : String(error)}`,
|
|
6522
|
+
{
|
|
6523
|
+
field: "nodeTx",
|
|
6524
|
+
value: node.nodeTx.length
|
|
6525
|
+
}
|
|
6526
|
+
);
|
|
6527
|
+
}
|
|
6528
|
+
try {
|
|
6529
|
+
refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
6530
|
+
} catch (error) {
|
|
6531
|
+
throw new ValidationError(
|
|
6532
|
+
`Failed to parse refund transaction for ${isRootNode ? "root" : "non-root"} node: ${error instanceof Error ? error.message : String(error)}`,
|
|
6533
|
+
{
|
|
6534
|
+
field: "refundTx",
|
|
6535
|
+
value: node.refundTx.length
|
|
6536
|
+
}
|
|
6537
|
+
);
|
|
6538
|
+
}
|
|
6539
|
+
const nodeInput = nodeTx.getInput(0);
|
|
6540
|
+
if (!nodeInput) {
|
|
6541
|
+
throw new ValidationError(
|
|
6542
|
+
`Node transaction has no inputs for ${isRootNode ? "root" : "non-root"} node`,
|
|
6543
|
+
{
|
|
6544
|
+
field: "nodeInput",
|
|
6545
|
+
value: nodeTx.inputsLength
|
|
6546
|
+
}
|
|
6547
|
+
);
|
|
6548
|
+
}
|
|
6549
|
+
if (!nodeInput.sequence) {
|
|
6550
|
+
throw new ValidationError(
|
|
6551
|
+
`Node transaction has no sequence for ${isRootNode ? "root" : "non-root"} node`,
|
|
6552
|
+
{
|
|
6553
|
+
field: "sequence",
|
|
6554
|
+
value: nodeInput.sequence
|
|
6555
|
+
}
|
|
6556
|
+
);
|
|
6557
|
+
}
|
|
6558
|
+
const refundInput = refundTx.getInput(0);
|
|
6559
|
+
if (!refundInput) {
|
|
6560
|
+
throw new ValidationError(
|
|
6561
|
+
`Refund transaction has no inputs for ${isRootNode ? "root" : "non-root"} node`,
|
|
6562
|
+
{
|
|
6563
|
+
field: "refundInput",
|
|
6564
|
+
value: refundTx.inputsLength
|
|
6565
|
+
}
|
|
6566
|
+
);
|
|
6567
|
+
}
|
|
6568
|
+
if (!refundInput.sequence) {
|
|
6569
|
+
throw new ValidationError(
|
|
6570
|
+
`Refund transaction has no sequence for ${isRootNode ? "root" : "non-root"} node`,
|
|
6571
|
+
{
|
|
6572
|
+
field: "sequence",
|
|
6573
|
+
value: refundInput.sequence
|
|
6574
|
+
}
|
|
6575
|
+
);
|
|
6576
|
+
}
|
|
6577
|
+
const nodeTimelock = nodeInput.sequence & 65535;
|
|
6578
|
+
const refundTimelock = refundInput.sequence & 65535;
|
|
6579
|
+
return {
|
|
6580
|
+
nodeTimelock,
|
|
6581
|
+
refundTimelock
|
|
6582
|
+
};
|
|
6583
|
+
} catch (error) {
|
|
6584
|
+
throw new NetworkError(
|
|
6585
|
+
`Failed to check timelock for node ${nodeId}`,
|
|
6586
|
+
{
|
|
6587
|
+
method: "query_nodes"
|
|
6588
|
+
},
|
|
6589
|
+
error
|
|
6590
|
+
);
|
|
6591
|
+
}
|
|
6592
|
+
}
|
|
6593
|
+
/**
|
|
6594
|
+
* Refresh the timelock of a specific node.
|
|
6595
|
+
*
|
|
6596
|
+
* @param {string} nodeId - The ID of the node to refresh
|
|
6597
|
+
* @returns {Promise<void>} Promise that resolves when the timelock is refreshed
|
|
6598
|
+
*/
|
|
6599
|
+
async testOnly_expireTimelock(nodeId) {
|
|
6600
|
+
const sparkClient = await this.connectionManager.createSparkClient(
|
|
6601
|
+
this.config.getCoordinatorAddress()
|
|
6602
|
+
);
|
|
6603
|
+
try {
|
|
6604
|
+
const response = await sparkClient.query_nodes({
|
|
6605
|
+
source: {
|
|
6606
|
+
$case: "nodeIds",
|
|
6607
|
+
nodeIds: {
|
|
6608
|
+
nodeIds: [nodeId]
|
|
6609
|
+
}
|
|
6610
|
+
},
|
|
6611
|
+
includeParents: true
|
|
6612
|
+
});
|
|
6613
|
+
const node = response.nodes[nodeId];
|
|
6614
|
+
if (!node) {
|
|
6615
|
+
throw new ValidationError("Node not found", {
|
|
6616
|
+
field: "nodeId",
|
|
6617
|
+
value: nodeId
|
|
6618
|
+
});
|
|
6619
|
+
}
|
|
6620
|
+
if (!node.parentNodeId) {
|
|
6621
|
+
throw new ValidationError("Node has no parent", {
|
|
6622
|
+
field: "parentNodeId",
|
|
6623
|
+
value: node.parentNodeId
|
|
6624
|
+
});
|
|
6625
|
+
}
|
|
6626
|
+
const parentNode = response.nodes[node.parentNodeId];
|
|
6627
|
+
if (!parentNode) {
|
|
6628
|
+
throw new ValidationError("Parent node not found", {
|
|
6629
|
+
field: "parentNodeId",
|
|
6630
|
+
value: node.parentNodeId
|
|
6631
|
+
});
|
|
6632
|
+
}
|
|
6633
|
+
const signingPubKey = await this.config.signer.generatePublicKey(
|
|
6634
|
+
sha2567(node.id)
|
|
6635
|
+
);
|
|
6636
|
+
const result = await this.transferService.refreshTimelockNodes(
|
|
6637
|
+
[node],
|
|
6638
|
+
parentNode,
|
|
6639
|
+
signingPubKey
|
|
6640
|
+
);
|
|
6641
|
+
const leafIndex = this.leaves.findIndex((leaf) => leaf.id === node.id);
|
|
6642
|
+
if (leafIndex !== -1 && result.nodes.length > 0) {
|
|
6643
|
+
const newNode = result.nodes[0];
|
|
6644
|
+
if (newNode) {
|
|
6645
|
+
this.leaves[leafIndex] = newNode;
|
|
6646
|
+
}
|
|
6647
|
+
}
|
|
6648
|
+
} catch (error) {
|
|
6649
|
+
throw new NetworkError(
|
|
6650
|
+
"Failed to refresh timelock",
|
|
6651
|
+
{
|
|
6652
|
+
method: "refresh_timelock"
|
|
6653
|
+
},
|
|
6654
|
+
error
|
|
6655
|
+
);
|
|
6656
|
+
}
|
|
6657
|
+
}
|
|
6658
|
+
/**
|
|
6659
|
+
* Refresh the timelock of a specific node's refund transaction only.
|
|
6660
|
+
*
|
|
6661
|
+
* @param {string} nodeId - The ID of the node whose refund transaction to refresh
|
|
6662
|
+
* @returns {Promise<void>} Promise that resolves when the refund timelock is refreshed
|
|
6663
|
+
*/
|
|
6664
|
+
async testOnly_expireTimelockRefundTx(nodeId) {
|
|
6665
|
+
const sparkClient = await this.connectionManager.createSparkClient(
|
|
6666
|
+
this.config.getCoordinatorAddress()
|
|
6667
|
+
);
|
|
6668
|
+
try {
|
|
6669
|
+
const response = await sparkClient.query_nodes({
|
|
6670
|
+
source: {
|
|
6671
|
+
$case: "nodeIds",
|
|
6672
|
+
nodeIds: {
|
|
6673
|
+
nodeIds: [nodeId]
|
|
6674
|
+
}
|
|
6675
|
+
},
|
|
6676
|
+
includeParents: false
|
|
6677
|
+
});
|
|
6678
|
+
const node = response.nodes[nodeId];
|
|
6679
|
+
if (!node) {
|
|
6680
|
+
throw new ValidationError("Node not found", {
|
|
6681
|
+
field: "nodeId",
|
|
6682
|
+
value: nodeId
|
|
6683
|
+
});
|
|
6684
|
+
}
|
|
6685
|
+
const signingPubKey = await this.config.signer.generatePublicKey(
|
|
6686
|
+
sha2567(node.id)
|
|
6687
|
+
);
|
|
6688
|
+
const result = await this.transferService.refreshTimelockRefundTx(
|
|
6689
|
+
node,
|
|
6690
|
+
signingPubKey
|
|
6691
|
+
);
|
|
6692
|
+
const leafIndex = this.leaves.findIndex((leaf) => leaf.id === node.id);
|
|
6693
|
+
if (leafIndex !== -1 && result.nodes.length > 0) {
|
|
6694
|
+
const newNode = result.nodes[0];
|
|
6695
|
+
if (newNode) {
|
|
6696
|
+
this.leaves[leafIndex] = newNode;
|
|
6697
|
+
}
|
|
6698
|
+
}
|
|
6699
|
+
} catch (error) {
|
|
6700
|
+
throw new NetworkError(
|
|
6701
|
+
"Failed to refresh refund timelock",
|
|
6702
|
+
{
|
|
6703
|
+
method: "refresh_timelock_refund_tx"
|
|
6704
|
+
},
|
|
6705
|
+
error
|
|
6706
|
+
);
|
|
6707
|
+
}
|
|
6708
|
+
}
|
|
6194
6709
|
cleanup() {
|
|
6195
6710
|
if (this.claimTransfersInterval) {
|
|
6196
6711
|
clearInterval(this.claimTransfersInterval);
|