@buildonspark/spark-sdk 0.3.8 → 0.4.0
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 +18 -0
- package/android/build.gradle +1 -1
- package/android/src/main/java/uniffi/uniffi/spark_frost/spark_frost.kt +1361 -1367
- package/android/src/main/jniLibs/arm64-v8a/libuniffi_spark_frost.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libuniffi_spark_frost.so +0 -0
- package/android/src/main/jniLibs/x86/libuniffi_spark_frost.so +0 -0
- package/android/src/main/jniLibs/x86_64/libuniffi_spark_frost.so +0 -0
- package/dist/bare/index.cjs +1342 -1346
- package/dist/bare/index.d.cts +114 -68
- package/dist/bare/index.d.ts +114 -68
- package/dist/bare/index.js +1266 -1279
- package/dist/{chunk-FXIESWE6.js → chunk-27ILUWDJ.js} +1 -1
- package/dist/{chunk-5ASXVNTM.js → chunk-4YFT7DAE.js} +1 -1
- package/dist/{chunk-FP2CRVQH.js → chunk-G3LHXHF3.js} +1045 -1308
- package/dist/{chunk-XI6FCNYG.js → chunk-JLF6WJ7K.js} +1 -1
- package/dist/{chunk-3LPEQGVJ.js → chunk-LOXWCMZL.js} +1 -1
- package/dist/{chunk-5HU5W56H.js → chunk-WICAF6BS.js} +2 -2
- 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 +1330 -1336
- package/dist/debug.d.cts +20 -16
- package/dist/debug.d.ts +20 -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 +1363 -1365
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +32 -24
- package/dist/index.node.cjs +1363 -1365
- package/dist/index.node.d.cts +7 -7
- package/dist/index.node.d.ts +7 -7
- package/dist/index.node.js +31 -23
- package/dist/{logging-DMFVY384.d.ts → logging-BNGm6dBp.d.ts} +42 -37
- package/dist/{logging-DxLp34Xm.d.cts → logging-D3IfXfHG.d.cts} +42 -37
- package/dist/native/index.react-native.cjs +1505 -1366
- package/dist/native/index.react-native.d.cts +112 -58
- package/dist/native/index.react-native.d.ts +112 -58
- package/dist/native/index.react-native.js +1415 -1289
- 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-C1dQknVj.d.ts → spark-wallet.browser-B2rGwjuM.d.ts} +2 -2
- package/dist/{spark-wallet.browser-CNMo3IvO.d.cts → spark-wallet.browser-Ck9No4Ks.d.cts} +2 -2
- package/dist/{spark-wallet.node-Og6__NMh.d.ts → spark-wallet.node-BqmKsGPs.d.ts} +2 -2
- package/dist/{spark-wallet.node-BZJhJZKq.d.cts → spark-wallet.node-C2TIkyt4.d.cts} +2 -2
- package/dist/tests/test-utils.cjs +1304 -1236
- package/dist/tests/test-utils.d.cts +18 -4
- package/dist/tests/test-utils.d.ts +18 -4
- package/dist/tests/test-utils.js +7 -7
- package/dist/{token-transactions-CLR3rnYi.d.cts → token-transactions-Db8mkjnU.d.cts} +2 -2
- package/dist/{token-transactions-C7yefB2S.d.ts → token-transactions-DoMcrxXQ.d.ts} +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-Bg3kWltL.d.ts} +42 -35
- package/dist/{wallet-config-xom-9UFF.d.cts → wallet-config-CuZKNo9S.d.cts} +42 -35
- package/ios/spark_frostFFI.xcframework/ios-arm64/SparkFrost +0 -0
- package/ios/spark_frostFFI.xcframework/ios-arm64/spark_frostFFI.framework/spark_frostFFI +0 -0
- package/ios/spark_frostFFI.xcframework/ios-arm64_x86_64-simulator/SparkFrost +0 -0
- package/ios/spark_frostFFI.xcframework/ios-arm64_x86_64-simulator/spark_frostFFI.framework/spark_frostFFI +0 -0
- package/ios/spark_frostFFI.xcframework/macos-arm64_x86_64/spark_frostFFI.framework/spark_frostFFI +0 -0
- package/package.json +1 -1
- package/src/index.react-native.ts +8 -2
- package/src/proto/spark.ts +348 -4
- package/src/services/config.ts +5 -0
- 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/services/wallet-config.ts +10 -0
- package/src/services/xhr-transport.ts +13 -3
- package/src/signer/signer.react-native.ts +73 -1
- package/src/spark-wallet/proto-descriptors.ts +1 -1
- package/src/spark-wallet/spark-wallet.ts +162 -315
- package/src/spark-wallet/types.ts +2 -2
- package/src/spark_descriptors.pb +0 -0
- package/src/tests/integration/lightning.test.ts +1 -27
- package/src/tests/integration/static_deposit.test.ts +6 -9
- package/src/tests/integration/unilateral-exit.test.ts +117 -0
- package/src/tests/optimize.test.ts +31 -1
- package/src/tests/utils/signing.ts +33 -0
- package/src/tests/utils/test-faucet.ts +61 -0
- package/src/utils/optimize.ts +42 -0
- package/src/utils/transaction.ts +250 -249
- package/src/utils/unilateral-exit.ts +1 -40
package/dist/index.cjs
CHANGED
|
@@ -1111,30 +1111,30 @@ function signFrost({
|
|
|
1111
1111
|
adaptorPubKey
|
|
1112
1112
|
}) {
|
|
1113
1113
|
const logMsg = JSON.stringify({
|
|
1114
|
-
message: (0,
|
|
1114
|
+
message: (0, import_utils13.bytesToHex)(message),
|
|
1115
1115
|
keyPackage: {
|
|
1116
|
-
secretKey: (0,
|
|
1117
|
-
publicKey: (0,
|
|
1118
|
-
verifyingKey: (0,
|
|
1116
|
+
secretKey: (0, import_utils13.bytesToHex)(keyPackage.secretKey),
|
|
1117
|
+
publicKey: (0, import_utils13.bytesToHex)(keyPackage.publicKey),
|
|
1118
|
+
verifyingKey: (0, import_utils13.bytesToHex)(keyPackage.verifyingKey)
|
|
1119
1119
|
},
|
|
1120
1120
|
nonce: {
|
|
1121
|
-
hiding: (0,
|
|
1122
|
-
binding: (0,
|
|
1121
|
+
hiding: (0, import_utils13.bytesToHex)(nonce.hiding),
|
|
1122
|
+
binding: (0, import_utils13.bytesToHex)(nonce.binding)
|
|
1123
1123
|
},
|
|
1124
1124
|
selfCommitment: {
|
|
1125
|
-
hiding: (0,
|
|
1126
|
-
binding: (0,
|
|
1125
|
+
hiding: (0, import_utils13.bytesToHex)(selfCommitment.hiding),
|
|
1126
|
+
binding: (0, import_utils13.bytesToHex)(selfCommitment.binding)
|
|
1127
1127
|
},
|
|
1128
1128
|
statechainCommitments: Object.fromEntries(
|
|
1129
1129
|
Object.entries(statechainCommitments ?? {}).map(([k, v]) => [
|
|
1130
1130
|
k,
|
|
1131
1131
|
{
|
|
1132
|
-
hiding: (0,
|
|
1133
|
-
binding: (0,
|
|
1132
|
+
hiding: (0, import_utils13.bytesToHex)(v.hiding),
|
|
1133
|
+
binding: (0, import_utils13.bytesToHex)(v.binding)
|
|
1134
1134
|
}
|
|
1135
1135
|
])
|
|
1136
1136
|
),
|
|
1137
|
-
adaptorPubKey: adaptorPubKey ? (0,
|
|
1137
|
+
adaptorPubKey: adaptorPubKey ? (0, import_utils13.bytesToHex)(adaptorPubKey) : void 0
|
|
1138
1138
|
});
|
|
1139
1139
|
SparkSdkLogger.get(LOGGER_NAMES.wasm).trace("signFrost", logMsg);
|
|
1140
1140
|
const result = wasm_sign_frost(
|
|
@@ -1147,7 +1147,7 @@ function signFrost({
|
|
|
1147
1147
|
);
|
|
1148
1148
|
SparkSdkLogger.get(LOGGER_NAMES.wasm).trace(
|
|
1149
1149
|
"signFrost result",
|
|
1150
|
-
(0,
|
|
1150
|
+
(0, import_utils13.bytesToHex)(result)
|
|
1151
1151
|
);
|
|
1152
1152
|
return result;
|
|
1153
1153
|
}
|
|
@@ -1163,36 +1163,36 @@ function aggregateFrost({
|
|
|
1163
1163
|
adaptorPubKey
|
|
1164
1164
|
}) {
|
|
1165
1165
|
const logMsg = JSON.stringify({
|
|
1166
|
-
message: (0,
|
|
1166
|
+
message: (0, import_utils13.bytesToHex)(message),
|
|
1167
1167
|
statechainCommitments: Object.fromEntries(
|
|
1168
1168
|
Object.entries(statechainCommitments ?? {}).map(([k, v]) => [
|
|
1169
1169
|
k,
|
|
1170
1170
|
{
|
|
1171
|
-
hiding: (0,
|
|
1172
|
-
binding: (0,
|
|
1171
|
+
hiding: (0, import_utils13.bytesToHex)(v.hiding),
|
|
1172
|
+
binding: (0, import_utils13.bytesToHex)(v.binding)
|
|
1173
1173
|
}
|
|
1174
1174
|
])
|
|
1175
1175
|
),
|
|
1176
1176
|
selfCommitment: {
|
|
1177
|
-
hiding: (0,
|
|
1178
|
-
binding: (0,
|
|
1177
|
+
hiding: (0, import_utils13.bytesToHex)(selfCommitment.hiding),
|
|
1178
|
+
binding: (0, import_utils13.bytesToHex)(selfCommitment.binding)
|
|
1179
1179
|
},
|
|
1180
1180
|
statechainSignatures: Object.fromEntries(
|
|
1181
1181
|
Object.entries(statechainSignatures ?? {}).map(([k, v]) => [
|
|
1182
1182
|
k,
|
|
1183
|
-
(0,
|
|
1183
|
+
(0, import_utils13.bytesToHex)(v)
|
|
1184
1184
|
])
|
|
1185
1185
|
),
|
|
1186
|
-
selfSignature: (0,
|
|
1186
|
+
selfSignature: (0, import_utils13.bytesToHex)(selfSignature),
|
|
1187
1187
|
statechainPublicKeys: Object.fromEntries(
|
|
1188
1188
|
Object.entries(statechainPublicKeys ?? {}).map(([k, v]) => [
|
|
1189
1189
|
k,
|
|
1190
|
-
(0,
|
|
1190
|
+
(0, import_utils13.bytesToHex)(v)
|
|
1191
1191
|
])
|
|
1192
1192
|
),
|
|
1193
|
-
selfPublicKey: (0,
|
|
1194
|
-
verifyingKey: (0,
|
|
1195
|
-
adaptorPubKey: adaptorPubKey ? (0,
|
|
1193
|
+
selfPublicKey: (0, import_utils13.bytesToHex)(selfPublicKey),
|
|
1194
|
+
verifyingKey: (0, import_utils13.bytesToHex)(verifyingKey),
|
|
1195
|
+
adaptorPubKey: adaptorPubKey ? (0, import_utils13.bytesToHex)(adaptorPubKey) : void 0
|
|
1196
1196
|
});
|
|
1197
1197
|
SparkSdkLogger.get(LOGGER_NAMES.wasm).trace("aggregateFrost", logMsg);
|
|
1198
1198
|
const result = wasm_aggregate_frost(
|
|
@@ -1208,7 +1208,7 @@ function aggregateFrost({
|
|
|
1208
1208
|
);
|
|
1209
1209
|
SparkSdkLogger.get(LOGGER_NAMES.wasm).trace(
|
|
1210
1210
|
"aggregateFrost result",
|
|
1211
|
-
(0,
|
|
1211
|
+
(0, import_utils13.bytesToHex)(result)
|
|
1212
1212
|
);
|
|
1213
1213
|
return result;
|
|
1214
1214
|
}
|
|
@@ -1230,12 +1230,12 @@ function decryptEcies({
|
|
|
1230
1230
|
}) {
|
|
1231
1231
|
return decrypt_ecies(encryptedMsg, privateKey);
|
|
1232
1232
|
}
|
|
1233
|
-
var
|
|
1233
|
+
var import_utils13;
|
|
1234
1234
|
var init_wasm = __esm({
|
|
1235
1235
|
"src/spark_bindings/wasm/index.ts"() {
|
|
1236
1236
|
"use strict";
|
|
1237
1237
|
init_buffer();
|
|
1238
|
-
|
|
1238
|
+
import_utils13 = require("@noble/curves/utils");
|
|
1239
1239
|
init_spark_bindings();
|
|
1240
1240
|
init_logging();
|
|
1241
1241
|
}
|
|
@@ -1252,7 +1252,6 @@ __export(index_exports, {
|
|
|
1252
1252
|
DIRECT_TIMELOCK_OFFSET: () => DIRECT_TIMELOCK_OFFSET,
|
|
1253
1253
|
DefaultSparkSigner: () => DefaultSparkSigner,
|
|
1254
1254
|
HTLC_TIMELOCK_OFFSET: () => HTLC_TIMELOCK_OFFSET,
|
|
1255
|
-
INITIAL_DIRECT_SEQUENCE: () => INITIAL_DIRECT_SEQUENCE,
|
|
1256
1255
|
INITIAL_SEQUENCE: () => INITIAL_SEQUENCE,
|
|
1257
1256
|
InternalValidationError: () => InternalValidationError,
|
|
1258
1257
|
KeyDerivationType: () => KeyDerivationType,
|
|
@@ -1289,21 +1288,24 @@ __export(index_exports, {
|
|
|
1289
1288
|
constructFeeBumpTx: () => constructFeeBumpTx,
|
|
1290
1289
|
constructUnilateralExitFeeBumpPackages: () => constructUnilateralExitFeeBumpPackages,
|
|
1291
1290
|
constructUnilateralExitTxs: () => constructUnilateralExitTxs,
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1291
|
+
createConnectorRefundTxs: () => createConnectorRefundTxs,
|
|
1292
|
+
createCurrentTimelockRefundTxs: () => createCurrentTimelockRefundTxs,
|
|
1293
|
+
createDecrementedTimelockNodeTx: () => createDecrementedTimelockNodeTx,
|
|
1294
|
+
createDecrementedTimelockRefundTxs: () => createDecrementedTimelockRefundTxs,
|
|
1295
|
+
createInitialTimelockNodeTx: () => createInitialTimelockNodeTx,
|
|
1296
|
+
createInitialTimelockRefundTxs: () => createInitialTimelockRefundTxs,
|
|
1297
|
+
createRootNodeTx: () => createRootNodeTx,
|
|
1299
1298
|
createSigningCommitment: () => createSigningCommitment,
|
|
1300
1299
|
createSigningNonce: () => createSigningNonce,
|
|
1301
|
-
|
|
1300
|
+
createTestUnilateralRefundTxs: () => createTestUnilateralRefundTxs,
|
|
1301
|
+
createTestUnilateralTimelockNodeTx: () => createTestUnilateralTimelockNodeTx,
|
|
1302
|
+
createZeroTimelockNodeTx: () => createZeroTimelockNodeTx,
|
|
1302
1303
|
decodeBech32mTokenIdentifier: () => decodeBech32mTokenIdentifier,
|
|
1303
1304
|
decodeBytesToSigningCommitment: () => decodeBytesToSigningCommitment,
|
|
1304
1305
|
decodeBytesToSigningNonce: () => decodeBytesToSigningNonce,
|
|
1305
1306
|
decodeSparkAddress: () => decodeSparkAddress,
|
|
1306
1307
|
doesLeafNeedRefresh: () => doesLeafNeedRefresh,
|
|
1308
|
+
doesTxnNeedRenewed: () => doesTxnNeedRenewed,
|
|
1307
1309
|
encodeBech32mTokenIdentifier: () => encodeBech32mTokenIdentifier,
|
|
1308
1310
|
encodeSigningCommitmentToBytes: () => encodeSigningCommitmentToBytes,
|
|
1309
1311
|
encodeSigningNonceToBytes: () => encodeSigningNonceToBytes,
|
|
@@ -1341,6 +1343,7 @@ __export(index_exports, {
|
|
|
1341
1343
|
getTxFromRawTxHex: () => getTxFromRawTxHex,
|
|
1342
1344
|
getTxId: () => getTxId,
|
|
1343
1345
|
getTxIdNoReverse: () => getTxIdNoReverse,
|
|
1346
|
+
hash160: () => hash160,
|
|
1344
1347
|
initializeTracerEnv: () => initializeTracerEnvBrowser,
|
|
1345
1348
|
isEphemeralAnchorOutput: () => isEphemeralAnchorOutput,
|
|
1346
1349
|
isLegacySparkAddress: () => isLegacySparkAddress,
|
|
@@ -1348,6 +1351,7 @@ __export(index_exports, {
|
|
|
1348
1351
|
isTxBroadcast: () => isTxBroadcast,
|
|
1349
1352
|
isValidPublicKey: () => isValidPublicKey,
|
|
1350
1353
|
isValidSparkAddress: () => isValidSparkAddress,
|
|
1354
|
+
isZeroTimelock: () => isZeroTimelock,
|
|
1351
1355
|
lastKeyWithTarget: () => lastKeyWithTarget,
|
|
1352
1356
|
maybeApplyFee: () => maybeApplyFee,
|
|
1353
1357
|
modInverse: () => modInverse,
|
|
@@ -3947,6 +3951,12 @@ var RenewLeafRequest = {
|
|
|
3947
3951
|
writer.uint32(26).fork()
|
|
3948
3952
|
).join();
|
|
3949
3953
|
break;
|
|
3954
|
+
case "renewNodeZeroTimelockSigningJob":
|
|
3955
|
+
RenewNodeZeroTimelockSigningJob.encode(
|
|
3956
|
+
message.signingJobs.renewNodeZeroTimelockSigningJob,
|
|
3957
|
+
writer.uint32(34).fork()
|
|
3958
|
+
).join();
|
|
3959
|
+
break;
|
|
3950
3960
|
}
|
|
3951
3961
|
return writer;
|
|
3952
3962
|
},
|
|
@@ -3984,6 +3994,16 @@ var RenewLeafRequest = {
|
|
|
3984
3994
|
};
|
|
3985
3995
|
continue;
|
|
3986
3996
|
}
|
|
3997
|
+
case 4: {
|
|
3998
|
+
if (tag !== 34) {
|
|
3999
|
+
break;
|
|
4000
|
+
}
|
|
4001
|
+
message.signingJobs = {
|
|
4002
|
+
$case: "renewNodeZeroTimelockSigningJob",
|
|
4003
|
+
renewNodeZeroTimelockSigningJob: RenewNodeZeroTimelockSigningJob.decode(reader, reader.uint32())
|
|
4004
|
+
};
|
|
4005
|
+
continue;
|
|
4006
|
+
}
|
|
3987
4007
|
}
|
|
3988
4008
|
if ((tag & 7) === 4 || tag === 0) {
|
|
3989
4009
|
break;
|
|
@@ -4001,6 +4021,11 @@ var RenewLeafRequest = {
|
|
|
4001
4021
|
} : isSet3(object.renewRefundTimelockSigningJob) ? {
|
|
4002
4022
|
$case: "renewRefundTimelockSigningJob",
|
|
4003
4023
|
renewRefundTimelockSigningJob: RenewRefundTimelockSigningJob.fromJSON(object.renewRefundTimelockSigningJob)
|
|
4024
|
+
} : isSet3(object.renewNodeZeroTimelockSigningJob) ? {
|
|
4025
|
+
$case: "renewNodeZeroTimelockSigningJob",
|
|
4026
|
+
renewNodeZeroTimelockSigningJob: RenewNodeZeroTimelockSigningJob.fromJSON(
|
|
4027
|
+
object.renewNodeZeroTimelockSigningJob
|
|
4028
|
+
)
|
|
4004
4029
|
} : void 0
|
|
4005
4030
|
};
|
|
4006
4031
|
},
|
|
@@ -4017,6 +4042,10 @@ var RenewLeafRequest = {
|
|
|
4017
4042
|
obj.renewRefundTimelockSigningJob = RenewRefundTimelockSigningJob.toJSON(
|
|
4018
4043
|
message.signingJobs.renewRefundTimelockSigningJob
|
|
4019
4044
|
);
|
|
4045
|
+
} else if (message.signingJobs?.$case === "renewNodeZeroTimelockSigningJob") {
|
|
4046
|
+
obj.renewNodeZeroTimelockSigningJob = RenewNodeZeroTimelockSigningJob.toJSON(
|
|
4047
|
+
message.signingJobs.renewNodeZeroTimelockSigningJob
|
|
4048
|
+
);
|
|
4020
4049
|
}
|
|
4021
4050
|
return obj;
|
|
4022
4051
|
},
|
|
@@ -4049,6 +4078,17 @@ var RenewLeafRequest = {
|
|
|
4049
4078
|
}
|
|
4050
4079
|
break;
|
|
4051
4080
|
}
|
|
4081
|
+
case "renewNodeZeroTimelockSigningJob": {
|
|
4082
|
+
if (object.signingJobs?.renewNodeZeroTimelockSigningJob !== void 0 && object.signingJobs?.renewNodeZeroTimelockSigningJob !== null) {
|
|
4083
|
+
message.signingJobs = {
|
|
4084
|
+
$case: "renewNodeZeroTimelockSigningJob",
|
|
4085
|
+
renewNodeZeroTimelockSigningJob: RenewNodeZeroTimelockSigningJob.fromPartial(
|
|
4086
|
+
object.signingJobs.renewNodeZeroTimelockSigningJob
|
|
4087
|
+
)
|
|
4088
|
+
};
|
|
4089
|
+
}
|
|
4090
|
+
break;
|
|
4091
|
+
}
|
|
4052
4092
|
}
|
|
4053
4093
|
return message;
|
|
4054
4094
|
}
|
|
@@ -4323,6 +4363,125 @@ var RenewRefundTimelockSigningJob = {
|
|
|
4323
4363
|
return message;
|
|
4324
4364
|
}
|
|
4325
4365
|
};
|
|
4366
|
+
function createBaseRenewNodeZeroTimelockSigningJob() {
|
|
4367
|
+
return {
|
|
4368
|
+
nodeTxSigningJob: void 0,
|
|
4369
|
+
refundTxSigningJob: void 0,
|
|
4370
|
+
directNodeTxSigningJob: void 0,
|
|
4371
|
+
directRefundTxSigningJob: void 0,
|
|
4372
|
+
directFromCpfpRefundTxSigningJob: void 0
|
|
4373
|
+
};
|
|
4374
|
+
}
|
|
4375
|
+
var RenewNodeZeroTimelockSigningJob = {
|
|
4376
|
+
encode(message, writer = new import_wire4.BinaryWriter()) {
|
|
4377
|
+
if (message.nodeTxSigningJob !== void 0) {
|
|
4378
|
+
UserSignedTxSigningJob.encode(message.nodeTxSigningJob, writer.uint32(10).fork()).join();
|
|
4379
|
+
}
|
|
4380
|
+
if (message.refundTxSigningJob !== void 0) {
|
|
4381
|
+
UserSignedTxSigningJob.encode(message.refundTxSigningJob, writer.uint32(18).fork()).join();
|
|
4382
|
+
}
|
|
4383
|
+
if (message.directNodeTxSigningJob !== void 0) {
|
|
4384
|
+
UserSignedTxSigningJob.encode(message.directNodeTxSigningJob, writer.uint32(26).fork()).join();
|
|
4385
|
+
}
|
|
4386
|
+
if (message.directRefundTxSigningJob !== void 0) {
|
|
4387
|
+
UserSignedTxSigningJob.encode(message.directRefundTxSigningJob, writer.uint32(34).fork()).join();
|
|
4388
|
+
}
|
|
4389
|
+
if (message.directFromCpfpRefundTxSigningJob !== void 0) {
|
|
4390
|
+
UserSignedTxSigningJob.encode(message.directFromCpfpRefundTxSigningJob, writer.uint32(42).fork()).join();
|
|
4391
|
+
}
|
|
4392
|
+
return writer;
|
|
4393
|
+
},
|
|
4394
|
+
decode(input, length) {
|
|
4395
|
+
const reader = input instanceof import_wire4.BinaryReader ? input : new import_wire4.BinaryReader(input);
|
|
4396
|
+
const end = length === void 0 ? reader.len : reader.pos + length;
|
|
4397
|
+
const message = createBaseRenewNodeZeroTimelockSigningJob();
|
|
4398
|
+
while (reader.pos < end) {
|
|
4399
|
+
const tag = reader.uint32();
|
|
4400
|
+
switch (tag >>> 3) {
|
|
4401
|
+
case 1: {
|
|
4402
|
+
if (tag !== 10) {
|
|
4403
|
+
break;
|
|
4404
|
+
}
|
|
4405
|
+
message.nodeTxSigningJob = UserSignedTxSigningJob.decode(reader, reader.uint32());
|
|
4406
|
+
continue;
|
|
4407
|
+
}
|
|
4408
|
+
case 2: {
|
|
4409
|
+
if (tag !== 18) {
|
|
4410
|
+
break;
|
|
4411
|
+
}
|
|
4412
|
+
message.refundTxSigningJob = UserSignedTxSigningJob.decode(reader, reader.uint32());
|
|
4413
|
+
continue;
|
|
4414
|
+
}
|
|
4415
|
+
case 3: {
|
|
4416
|
+
if (tag !== 26) {
|
|
4417
|
+
break;
|
|
4418
|
+
}
|
|
4419
|
+
message.directNodeTxSigningJob = UserSignedTxSigningJob.decode(reader, reader.uint32());
|
|
4420
|
+
continue;
|
|
4421
|
+
}
|
|
4422
|
+
case 4: {
|
|
4423
|
+
if (tag !== 34) {
|
|
4424
|
+
break;
|
|
4425
|
+
}
|
|
4426
|
+
message.directRefundTxSigningJob = UserSignedTxSigningJob.decode(reader, reader.uint32());
|
|
4427
|
+
continue;
|
|
4428
|
+
}
|
|
4429
|
+
case 5: {
|
|
4430
|
+
if (tag !== 42) {
|
|
4431
|
+
break;
|
|
4432
|
+
}
|
|
4433
|
+
message.directFromCpfpRefundTxSigningJob = UserSignedTxSigningJob.decode(reader, reader.uint32());
|
|
4434
|
+
continue;
|
|
4435
|
+
}
|
|
4436
|
+
}
|
|
4437
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
4438
|
+
break;
|
|
4439
|
+
}
|
|
4440
|
+
reader.skip(tag & 7);
|
|
4441
|
+
}
|
|
4442
|
+
return message;
|
|
4443
|
+
},
|
|
4444
|
+
fromJSON(object) {
|
|
4445
|
+
return {
|
|
4446
|
+
nodeTxSigningJob: isSet3(object.nodeTxSigningJob) ? UserSignedTxSigningJob.fromJSON(object.nodeTxSigningJob) : void 0,
|
|
4447
|
+
refundTxSigningJob: isSet3(object.refundTxSigningJob) ? UserSignedTxSigningJob.fromJSON(object.refundTxSigningJob) : void 0,
|
|
4448
|
+
directNodeTxSigningJob: isSet3(object.directNodeTxSigningJob) ? UserSignedTxSigningJob.fromJSON(object.directNodeTxSigningJob) : void 0,
|
|
4449
|
+
directRefundTxSigningJob: isSet3(object.directRefundTxSigningJob) ? UserSignedTxSigningJob.fromJSON(object.directRefundTxSigningJob) : void 0,
|
|
4450
|
+
directFromCpfpRefundTxSigningJob: isSet3(object.directFromCpfpRefundTxSigningJob) ? UserSignedTxSigningJob.fromJSON(object.directFromCpfpRefundTxSigningJob) : void 0
|
|
4451
|
+
};
|
|
4452
|
+
},
|
|
4453
|
+
toJSON(message) {
|
|
4454
|
+
const obj = {};
|
|
4455
|
+
if (message.nodeTxSigningJob !== void 0) {
|
|
4456
|
+
obj.nodeTxSigningJob = UserSignedTxSigningJob.toJSON(message.nodeTxSigningJob);
|
|
4457
|
+
}
|
|
4458
|
+
if (message.refundTxSigningJob !== void 0) {
|
|
4459
|
+
obj.refundTxSigningJob = UserSignedTxSigningJob.toJSON(message.refundTxSigningJob);
|
|
4460
|
+
}
|
|
4461
|
+
if (message.directNodeTxSigningJob !== void 0) {
|
|
4462
|
+
obj.directNodeTxSigningJob = UserSignedTxSigningJob.toJSON(message.directNodeTxSigningJob);
|
|
4463
|
+
}
|
|
4464
|
+
if (message.directRefundTxSigningJob !== void 0) {
|
|
4465
|
+
obj.directRefundTxSigningJob = UserSignedTxSigningJob.toJSON(message.directRefundTxSigningJob);
|
|
4466
|
+
}
|
|
4467
|
+
if (message.directFromCpfpRefundTxSigningJob !== void 0) {
|
|
4468
|
+
obj.directFromCpfpRefundTxSigningJob = UserSignedTxSigningJob.toJSON(message.directFromCpfpRefundTxSigningJob);
|
|
4469
|
+
}
|
|
4470
|
+
return obj;
|
|
4471
|
+
},
|
|
4472
|
+
create(base) {
|
|
4473
|
+
return RenewNodeZeroTimelockSigningJob.fromPartial(base ?? {});
|
|
4474
|
+
},
|
|
4475
|
+
fromPartial(object) {
|
|
4476
|
+
const message = createBaseRenewNodeZeroTimelockSigningJob();
|
|
4477
|
+
message.nodeTxSigningJob = object.nodeTxSigningJob !== void 0 && object.nodeTxSigningJob !== null ? UserSignedTxSigningJob.fromPartial(object.nodeTxSigningJob) : void 0;
|
|
4478
|
+
message.refundTxSigningJob = object.refundTxSigningJob !== void 0 && object.refundTxSigningJob !== null ? UserSignedTxSigningJob.fromPartial(object.refundTxSigningJob) : void 0;
|
|
4479
|
+
message.directNodeTxSigningJob = object.directNodeTxSigningJob !== void 0 && object.directNodeTxSigningJob !== null ? UserSignedTxSigningJob.fromPartial(object.directNodeTxSigningJob) : void 0;
|
|
4480
|
+
message.directRefundTxSigningJob = object.directRefundTxSigningJob !== void 0 && object.directRefundTxSigningJob !== null ? UserSignedTxSigningJob.fromPartial(object.directRefundTxSigningJob) : void 0;
|
|
4481
|
+
message.directFromCpfpRefundTxSigningJob = object.directFromCpfpRefundTxSigningJob !== void 0 && object.directFromCpfpRefundTxSigningJob !== null ? UserSignedTxSigningJob.fromPartial(object.directFromCpfpRefundTxSigningJob) : void 0;
|
|
4482
|
+
return message;
|
|
4483
|
+
}
|
|
4484
|
+
};
|
|
4326
4485
|
function createBaseRenewLeafResponse() {
|
|
4327
4486
|
return { renewResult: void 0 };
|
|
4328
4487
|
}
|
|
@@ -4335,6 +4494,9 @@ var RenewLeafResponse = {
|
|
|
4335
4494
|
case "renewRefundTimelockResult":
|
|
4336
4495
|
RenewRefundTimelockResult.encode(message.renewResult.renewRefundTimelockResult, writer.uint32(18).fork()).join();
|
|
4337
4496
|
break;
|
|
4497
|
+
case "renewNodeZeroTimelockResult":
|
|
4498
|
+
RenewNodeZeroTimelockResult.encode(message.renewResult.renewNodeZeroTimelockResult, writer.uint32(26).fork()).join();
|
|
4499
|
+
break;
|
|
4338
4500
|
}
|
|
4339
4501
|
return writer;
|
|
4340
4502
|
},
|
|
@@ -4365,6 +4527,16 @@ var RenewLeafResponse = {
|
|
|
4365
4527
|
};
|
|
4366
4528
|
continue;
|
|
4367
4529
|
}
|
|
4530
|
+
case 3: {
|
|
4531
|
+
if (tag !== 26) {
|
|
4532
|
+
break;
|
|
4533
|
+
}
|
|
4534
|
+
message.renewResult = {
|
|
4535
|
+
$case: "renewNodeZeroTimelockResult",
|
|
4536
|
+
renewNodeZeroTimelockResult: RenewNodeZeroTimelockResult.decode(reader, reader.uint32())
|
|
4537
|
+
};
|
|
4538
|
+
continue;
|
|
4539
|
+
}
|
|
4368
4540
|
}
|
|
4369
4541
|
if ((tag & 7) === 4 || tag === 0) {
|
|
4370
4542
|
break;
|
|
@@ -4381,6 +4553,9 @@ var RenewLeafResponse = {
|
|
|
4381
4553
|
} : isSet3(object.renewRefundTimelockResult) ? {
|
|
4382
4554
|
$case: "renewRefundTimelockResult",
|
|
4383
4555
|
renewRefundTimelockResult: RenewRefundTimelockResult.fromJSON(object.renewRefundTimelockResult)
|
|
4556
|
+
} : isSet3(object.renewNodeZeroTimelockResult) ? {
|
|
4557
|
+
$case: "renewNodeZeroTimelockResult",
|
|
4558
|
+
renewNodeZeroTimelockResult: RenewNodeZeroTimelockResult.fromJSON(object.renewNodeZeroTimelockResult)
|
|
4384
4559
|
} : void 0
|
|
4385
4560
|
};
|
|
4386
4561
|
},
|
|
@@ -4390,6 +4565,10 @@ var RenewLeafResponse = {
|
|
|
4390
4565
|
obj.renewNodeTimelockResult = RenewNodeTimelockResult.toJSON(message.renewResult.renewNodeTimelockResult);
|
|
4391
4566
|
} else if (message.renewResult?.$case === "renewRefundTimelockResult") {
|
|
4392
4567
|
obj.renewRefundTimelockResult = RenewRefundTimelockResult.toJSON(message.renewResult.renewRefundTimelockResult);
|
|
4568
|
+
} else if (message.renewResult?.$case === "renewNodeZeroTimelockResult") {
|
|
4569
|
+
obj.renewNodeZeroTimelockResult = RenewNodeZeroTimelockResult.toJSON(
|
|
4570
|
+
message.renewResult.renewNodeZeroTimelockResult
|
|
4571
|
+
);
|
|
4393
4572
|
}
|
|
4394
4573
|
return obj;
|
|
4395
4574
|
},
|
|
@@ -4419,6 +4598,17 @@ var RenewLeafResponse = {
|
|
|
4419
4598
|
}
|
|
4420
4599
|
break;
|
|
4421
4600
|
}
|
|
4601
|
+
case "renewNodeZeroTimelockResult": {
|
|
4602
|
+
if (object.renewResult?.renewNodeZeroTimelockResult !== void 0 && object.renewResult?.renewNodeZeroTimelockResult !== null) {
|
|
4603
|
+
message.renewResult = {
|
|
4604
|
+
$case: "renewNodeZeroTimelockResult",
|
|
4605
|
+
renewNodeZeroTimelockResult: RenewNodeZeroTimelockResult.fromPartial(
|
|
4606
|
+
object.renewResult.renewNodeZeroTimelockResult
|
|
4607
|
+
)
|
|
4608
|
+
};
|
|
4609
|
+
}
|
|
4610
|
+
break;
|
|
4611
|
+
}
|
|
4422
4612
|
}
|
|
4423
4613
|
return message;
|
|
4424
4614
|
}
|
|
@@ -4542,6 +4732,74 @@ var RenewRefundTimelockResult = {
|
|
|
4542
4732
|
return message;
|
|
4543
4733
|
}
|
|
4544
4734
|
};
|
|
4735
|
+
function createBaseRenewNodeZeroTimelockResult() {
|
|
4736
|
+
return { splitNode: void 0, node: void 0 };
|
|
4737
|
+
}
|
|
4738
|
+
var RenewNodeZeroTimelockResult = {
|
|
4739
|
+
encode(message, writer = new import_wire4.BinaryWriter()) {
|
|
4740
|
+
if (message.splitNode !== void 0) {
|
|
4741
|
+
TreeNode.encode(message.splitNode, writer.uint32(10).fork()).join();
|
|
4742
|
+
}
|
|
4743
|
+
if (message.node !== void 0) {
|
|
4744
|
+
TreeNode.encode(message.node, writer.uint32(18).fork()).join();
|
|
4745
|
+
}
|
|
4746
|
+
return writer;
|
|
4747
|
+
},
|
|
4748
|
+
decode(input, length) {
|
|
4749
|
+
const reader = input instanceof import_wire4.BinaryReader ? input : new import_wire4.BinaryReader(input);
|
|
4750
|
+
const end = length === void 0 ? reader.len : reader.pos + length;
|
|
4751
|
+
const message = createBaseRenewNodeZeroTimelockResult();
|
|
4752
|
+
while (reader.pos < end) {
|
|
4753
|
+
const tag = reader.uint32();
|
|
4754
|
+
switch (tag >>> 3) {
|
|
4755
|
+
case 1: {
|
|
4756
|
+
if (tag !== 10) {
|
|
4757
|
+
break;
|
|
4758
|
+
}
|
|
4759
|
+
message.splitNode = TreeNode.decode(reader, reader.uint32());
|
|
4760
|
+
continue;
|
|
4761
|
+
}
|
|
4762
|
+
case 2: {
|
|
4763
|
+
if (tag !== 18) {
|
|
4764
|
+
break;
|
|
4765
|
+
}
|
|
4766
|
+
message.node = TreeNode.decode(reader, reader.uint32());
|
|
4767
|
+
continue;
|
|
4768
|
+
}
|
|
4769
|
+
}
|
|
4770
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
4771
|
+
break;
|
|
4772
|
+
}
|
|
4773
|
+
reader.skip(tag & 7);
|
|
4774
|
+
}
|
|
4775
|
+
return message;
|
|
4776
|
+
},
|
|
4777
|
+
fromJSON(object) {
|
|
4778
|
+
return {
|
|
4779
|
+
splitNode: isSet3(object.splitNode) ? TreeNode.fromJSON(object.splitNode) : void 0,
|
|
4780
|
+
node: isSet3(object.node) ? TreeNode.fromJSON(object.node) : void 0
|
|
4781
|
+
};
|
|
4782
|
+
},
|
|
4783
|
+
toJSON(message) {
|
|
4784
|
+
const obj = {};
|
|
4785
|
+
if (message.splitNode !== void 0) {
|
|
4786
|
+
obj.splitNode = TreeNode.toJSON(message.splitNode);
|
|
4787
|
+
}
|
|
4788
|
+
if (message.node !== void 0) {
|
|
4789
|
+
obj.node = TreeNode.toJSON(message.node);
|
|
4790
|
+
}
|
|
4791
|
+
return obj;
|
|
4792
|
+
},
|
|
4793
|
+
create(base) {
|
|
4794
|
+
return RenewNodeZeroTimelockResult.fromPartial(base ?? {});
|
|
4795
|
+
},
|
|
4796
|
+
fromPartial(object) {
|
|
4797
|
+
const message = createBaseRenewNodeZeroTimelockResult();
|
|
4798
|
+
message.splitNode = object.splitNode !== void 0 && object.splitNode !== null ? TreeNode.fromPartial(object.splitNode) : void 0;
|
|
4799
|
+
message.node = object.node !== void 0 && object.node !== null ? TreeNode.fromPartial(object.node) : void 0;
|
|
4800
|
+
return message;
|
|
4801
|
+
}
|
|
4802
|
+
};
|
|
4545
4803
|
function createBaseNodeSignatureShares() {
|
|
4546
4804
|
return {
|
|
4547
4805
|
nodeId: "",
|
|
@@ -18244,7 +18502,11 @@ var BASE_CONFIG = {
|
|
|
18244
18502
|
console: {
|
|
18245
18503
|
otel: false
|
|
18246
18504
|
},
|
|
18247
|
-
events: {}
|
|
18505
|
+
events: {},
|
|
18506
|
+
optimizationOptions: {
|
|
18507
|
+
auto: true,
|
|
18508
|
+
multiplicity: 0
|
|
18509
|
+
}
|
|
18248
18510
|
};
|
|
18249
18511
|
var LOCAL_WALLET_CONFIG = {
|
|
18250
18512
|
...BASE_CONFIG,
|
|
@@ -19901,6 +20163,7 @@ function getTransferPackageSigningPayload(transferID, transferPackage) {
|
|
|
19901
20163
|
|
|
19902
20164
|
// src/utils/transaction.ts
|
|
19903
20165
|
init_buffer();
|
|
20166
|
+
var import_utils11 = require("@noble/hashes/utils");
|
|
19904
20167
|
var import_btc_signer = require("@scure/btc-signer");
|
|
19905
20168
|
var INITIAL_TIMELOCK = 2e3;
|
|
19906
20169
|
var TEST_UNILATERAL_TIMELOCK = 100;
|
|
@@ -19909,9 +20172,9 @@ var DIRECT_TIMELOCK_OFFSET = 50;
|
|
|
19909
20172
|
var HTLC_TIMELOCK_OFFSET = 70;
|
|
19910
20173
|
var DIRECT_HTLC_TIMELOCK_OFFSET = 85;
|
|
19911
20174
|
var INITIAL_SEQUENCE = 1 << 30 | INITIAL_TIMELOCK;
|
|
19912
|
-
var INITIAL_DIRECT_SEQUENCE = 1 << 30 | INITIAL_TIMELOCK + DIRECT_TIMELOCK_OFFSET;
|
|
19913
20175
|
var TEST_UNILATERAL_SEQUENCE = 1 << 30 | TEST_UNILATERAL_TIMELOCK;
|
|
19914
20176
|
var TEST_UNILATERAL_DIRECT_SEQUENCE = 1 << 30 | TEST_UNILATERAL_TIMELOCK + DIRECT_TIMELOCK_OFFSET;
|
|
20177
|
+
var INITIAL_ROOT_NODE_SEQUENCE = 1 << 30 | 0;
|
|
19915
20178
|
var ESTIMATED_TX_SIZE = 191;
|
|
19916
20179
|
var DEFAULT_SATS_PER_VBYTE = 5;
|
|
19917
20180
|
var DEFAULT_FEE_SATS = ESTIMATED_TX_SIZE * DEFAULT_SATS_PER_VBYTE;
|
|
@@ -19921,63 +20184,8 @@ function maybeApplyFee(amount) {
|
|
|
19921
20184
|
}
|
|
19922
20185
|
return amount;
|
|
19923
20186
|
}
|
|
19924
|
-
function createRootTx(depositOutPoint, depositTxOut) {
|
|
19925
|
-
const cpfpRootTx = new import_btc_signer.Transaction({
|
|
19926
|
-
version: 3,
|
|
19927
|
-
allowUnknownOutputs: true
|
|
19928
|
-
});
|
|
19929
|
-
cpfpRootTx.addInput(depositOutPoint);
|
|
19930
|
-
cpfpRootTx.addOutput(depositTxOut);
|
|
19931
|
-
cpfpRootTx.addOutput(getEphemeralAnchorOutput());
|
|
19932
|
-
const directRootTx = new import_btc_signer.Transaction({
|
|
19933
|
-
version: 3,
|
|
19934
|
-
allowUnknownOutputs: true
|
|
19935
|
-
});
|
|
19936
|
-
directRootTx.addInput(depositOutPoint);
|
|
19937
|
-
directRootTx.addOutput({
|
|
19938
|
-
script: depositTxOut.script,
|
|
19939
|
-
amount: maybeApplyFee(depositTxOut.amount ?? 0n)
|
|
19940
|
-
});
|
|
19941
|
-
return [cpfpRootTx, directRootTx];
|
|
19942
|
-
}
|
|
19943
|
-
function createSplitTx(parentOutPoint, childTxOuts) {
|
|
19944
|
-
const cpfpSplitTx = new import_btc_signer.Transaction({
|
|
19945
|
-
version: 3,
|
|
19946
|
-
allowUnknownOutputs: true
|
|
19947
|
-
});
|
|
19948
|
-
cpfpSplitTx.addInput(parentOutPoint);
|
|
19949
|
-
for (const txOut of childTxOuts) {
|
|
19950
|
-
cpfpSplitTx.addOutput(txOut);
|
|
19951
|
-
}
|
|
19952
|
-
cpfpSplitTx.addOutput(getEphemeralAnchorOutput());
|
|
19953
|
-
const directSplitTx = new import_btc_signer.Transaction({
|
|
19954
|
-
version: 3,
|
|
19955
|
-
allowUnknownOutputs: true
|
|
19956
|
-
});
|
|
19957
|
-
directSplitTx.addInput(parentOutPoint);
|
|
19958
|
-
let totalOutputAmount = 0n;
|
|
19959
|
-
for (const txOut of childTxOuts) {
|
|
19960
|
-
totalOutputAmount += txOut.amount ?? 0n;
|
|
19961
|
-
}
|
|
19962
|
-
if (totalOutputAmount > BigInt(DEFAULT_FEE_SATS)) {
|
|
19963
|
-
const feeRatio = Number(DEFAULT_FEE_SATS) / Number(totalOutputAmount);
|
|
19964
|
-
for (const txOut of childTxOuts) {
|
|
19965
|
-
const adjustedAmount = BigInt(
|
|
19966
|
-
Math.floor(Number(txOut.amount ?? 0n) * (1 - feeRatio))
|
|
19967
|
-
);
|
|
19968
|
-
directSplitTx.addOutput({
|
|
19969
|
-
script: txOut.script,
|
|
19970
|
-
amount: adjustedAmount
|
|
19971
|
-
});
|
|
19972
|
-
}
|
|
19973
|
-
} else {
|
|
19974
|
-
for (const txOut of childTxOuts) {
|
|
19975
|
-
directSplitTx.addOutput(txOut);
|
|
19976
|
-
}
|
|
19977
|
-
}
|
|
19978
|
-
return [cpfpSplitTx, directSplitTx];
|
|
19979
|
-
}
|
|
19980
20187
|
function createNodeTx({
|
|
20188
|
+
sequence,
|
|
19981
20189
|
txOut,
|
|
19982
20190
|
parentOutPoint,
|
|
19983
20191
|
applyFee,
|
|
@@ -19987,7 +20195,10 @@ function createNodeTx({
|
|
|
19987
20195
|
version: 3,
|
|
19988
20196
|
allowUnknownOutputs: true
|
|
19989
20197
|
});
|
|
19990
|
-
nodeTx.addInput(
|
|
20198
|
+
nodeTx.addInput({
|
|
20199
|
+
...parentOutPoint,
|
|
20200
|
+
sequence
|
|
20201
|
+
});
|
|
19991
20202
|
if (applyFee) {
|
|
19992
20203
|
nodeTx.addOutput({
|
|
19993
20204
|
script: txOut.script,
|
|
@@ -20001,52 +20212,92 @@ function createNodeTx({
|
|
|
20001
20212
|
}
|
|
20002
20213
|
return nodeTx;
|
|
20003
20214
|
}
|
|
20004
|
-
function createNodeTxs(
|
|
20005
|
-
|
|
20006
|
-
|
|
20007
|
-
|
|
20008
|
-
|
|
20009
|
-
|
|
20010
|
-
|
|
20011
|
-
if (
|
|
20012
|
-
|
|
20013
|
-
|
|
20014
|
-
|
|
20015
|
-
includeAnchor: false,
|
|
20016
|
-
applyFee: true
|
|
20215
|
+
function createNodeTxs({
|
|
20216
|
+
parentTx,
|
|
20217
|
+
sequence,
|
|
20218
|
+
directSequence,
|
|
20219
|
+
vout
|
|
20220
|
+
}) {
|
|
20221
|
+
const parentOutput = parentTx.getOutput(vout);
|
|
20222
|
+
if (!parentOutput.amount || !parentOutput.script) {
|
|
20223
|
+
throw new ValidationError("Parent output amount or script not found", {
|
|
20224
|
+
field: "parentOutput",
|
|
20225
|
+
value: parentOutput
|
|
20017
20226
|
});
|
|
20018
20227
|
}
|
|
20019
|
-
|
|
20228
|
+
const output = {
|
|
20229
|
+
script: parentOutput.script,
|
|
20230
|
+
amount: parentOutput.amount
|
|
20231
|
+
};
|
|
20232
|
+
const input = {
|
|
20233
|
+
txid: (0, import_utils11.hexToBytes)(getTxId(parentTx)),
|
|
20234
|
+
index: vout
|
|
20235
|
+
};
|
|
20236
|
+
const nodeTx = createNodeTx({
|
|
20237
|
+
sequence,
|
|
20238
|
+
txOut: output,
|
|
20239
|
+
parentOutPoint: input,
|
|
20240
|
+
includeAnchor: true
|
|
20241
|
+
});
|
|
20242
|
+
const directNodeTx = createNodeTx({
|
|
20243
|
+
sequence: directSequence ?? sequence + DIRECT_TIMELOCK_OFFSET,
|
|
20244
|
+
txOut: output,
|
|
20245
|
+
parentOutPoint: input,
|
|
20246
|
+
includeAnchor: false,
|
|
20247
|
+
applyFee: true
|
|
20248
|
+
});
|
|
20249
|
+
return { nodeTx, directNodeTx };
|
|
20020
20250
|
}
|
|
20021
|
-
function
|
|
20022
|
-
|
|
20023
|
-
|
|
20024
|
-
|
|
20251
|
+
function createRootNodeTx(parentTx, vout) {
|
|
20252
|
+
return createNodeTxs({
|
|
20253
|
+
parentTx,
|
|
20254
|
+
sequence: INITIAL_ROOT_NODE_SEQUENCE,
|
|
20255
|
+
vout
|
|
20025
20256
|
});
|
|
20026
|
-
|
|
20027
|
-
|
|
20028
|
-
|
|
20257
|
+
}
|
|
20258
|
+
function createZeroTimelockNodeTx(parentTx) {
|
|
20259
|
+
return createNodeTxs({
|
|
20260
|
+
parentTx,
|
|
20261
|
+
sequence: INITIAL_ROOT_NODE_SEQUENCE,
|
|
20262
|
+
directSequence: DIRECT_TIMELOCK_OFFSET,
|
|
20263
|
+
vout: 0
|
|
20029
20264
|
});
|
|
20030
|
-
|
|
20031
|
-
|
|
20032
|
-
|
|
20033
|
-
|
|
20034
|
-
|
|
20265
|
+
}
|
|
20266
|
+
function createInitialTimelockNodeTx(parentTx) {
|
|
20267
|
+
return createNodeTxs({
|
|
20268
|
+
parentTx,
|
|
20269
|
+
sequence: INITIAL_SEQUENCE,
|
|
20270
|
+
vout: 0
|
|
20035
20271
|
});
|
|
20036
|
-
|
|
20037
|
-
|
|
20038
|
-
|
|
20272
|
+
}
|
|
20273
|
+
function createDecrementedTimelockNodeTx(parentTx, currentTx) {
|
|
20274
|
+
const currentSequence = currentTx.getInput(0).sequence;
|
|
20275
|
+
if (!currentSequence) {
|
|
20276
|
+
throw new ValidationError("Current sequence not found", {
|
|
20277
|
+
field: "currentSequence",
|
|
20278
|
+
value: currentSequence
|
|
20279
|
+
});
|
|
20280
|
+
}
|
|
20281
|
+
return createNodeTxs({
|
|
20282
|
+
parentTx,
|
|
20283
|
+
sequence: getNextTransactionSequence(currentSequence).nextSequence,
|
|
20284
|
+
vout: 0
|
|
20039
20285
|
});
|
|
20040
|
-
|
|
20041
|
-
|
|
20042
|
-
|
|
20043
|
-
|
|
20286
|
+
}
|
|
20287
|
+
function createTestUnilateralTimelockNodeTx(parentTx, nodeTx) {
|
|
20288
|
+
const sequence = nodeTx.getInput(0).sequence;
|
|
20289
|
+
if (!sequence) {
|
|
20290
|
+
throw new ValidationError("Sequence not found", {
|
|
20291
|
+
field: "sequence",
|
|
20292
|
+
value: sequence
|
|
20293
|
+
});
|
|
20044
20294
|
}
|
|
20045
|
-
|
|
20046
|
-
|
|
20047
|
-
|
|
20295
|
+
const isBit30Defined = (sequence || 0) & 1 << 30;
|
|
20296
|
+
return createNodeTxs({
|
|
20297
|
+
parentTx,
|
|
20298
|
+
sequence: isBit30Defined | TEST_UNILATERAL_TIMELOCK,
|
|
20299
|
+
vout: 0
|
|
20048
20300
|
});
|
|
20049
|
-
return [cpfpLeafTx, directLeafTx];
|
|
20050
20301
|
}
|
|
20051
20302
|
function createRefundTx({
|
|
20052
20303
|
sequence,
|
|
@@ -20102,110 +20353,109 @@ function getNextHTLCTransactionSequence(currSequence, isNodeTx) {
|
|
|
20102
20353
|
};
|
|
20103
20354
|
}
|
|
20104
20355
|
function createRefundTxs({
|
|
20105
|
-
|
|
20106
|
-
|
|
20107
|
-
input,
|
|
20108
|
-
directInput,
|
|
20109
|
-
amountSats,
|
|
20356
|
+
nodeTx,
|
|
20357
|
+
directNodeTx,
|
|
20110
20358
|
receivingPubkey,
|
|
20111
|
-
network
|
|
20359
|
+
network,
|
|
20360
|
+
sequence
|
|
20112
20361
|
}) {
|
|
20113
|
-
const
|
|
20114
|
-
|
|
20115
|
-
|
|
20116
|
-
|
|
20117
|
-
|
|
20118
|
-
|
|
20119
|
-
|
|
20120
|
-
|
|
20121
|
-
|
|
20362
|
+
const refundInput = {
|
|
20363
|
+
txid: (0, import_utils11.hexToBytes)(getTxId(nodeTx)),
|
|
20364
|
+
index: 0
|
|
20365
|
+
};
|
|
20366
|
+
const nodeAmountSats = nodeTx.getOutput(0).amount;
|
|
20367
|
+
if (nodeAmountSats === void 0) {
|
|
20368
|
+
throw new ValidationError("Node amount not found", {
|
|
20369
|
+
field: "nodeAmountSats",
|
|
20370
|
+
value: nodeAmountSats
|
|
20371
|
+
});
|
|
20372
|
+
}
|
|
20122
20373
|
let directRefundTx;
|
|
20123
|
-
|
|
20124
|
-
|
|
20374
|
+
if (directNodeTx) {
|
|
20375
|
+
const directRefundInput = {
|
|
20376
|
+
txid: (0, import_utils11.hexToBytes)(getTxId(directNodeTx)),
|
|
20377
|
+
index: 0
|
|
20378
|
+
};
|
|
20379
|
+
const directAmountSats = directNodeTx.getOutput(0).amount;
|
|
20380
|
+
if (directAmountSats === void 0) {
|
|
20381
|
+
throw new ValidationError("Direct amount not found", {
|
|
20382
|
+
field: "directAmountSats",
|
|
20383
|
+
value: directAmountSats
|
|
20384
|
+
});
|
|
20385
|
+
}
|
|
20125
20386
|
directRefundTx = createRefundTx({
|
|
20126
|
-
sequence:
|
|
20127
|
-
input:
|
|
20128
|
-
amountSats,
|
|
20129
|
-
receivingPubkey,
|
|
20130
|
-
network,
|
|
20131
|
-
shouldCalculateFee: true,
|
|
20132
|
-
includeAnchor: false
|
|
20133
|
-
});
|
|
20134
|
-
directFromCpfpRefundTx = createRefundTx({
|
|
20135
|
-
sequence: directSequence,
|
|
20136
|
-
input,
|
|
20137
|
-
amountSats,
|
|
20387
|
+
sequence: sequence + DIRECT_TIMELOCK_OFFSET,
|
|
20388
|
+
input: directRefundInput,
|
|
20389
|
+
amountSats: directAmountSats,
|
|
20138
20390
|
receivingPubkey,
|
|
20139
20391
|
network,
|
|
20140
20392
|
shouldCalculateFee: true,
|
|
20141
20393
|
includeAnchor: false
|
|
20142
20394
|
});
|
|
20143
|
-
} else if (directInput && !directSequence) {
|
|
20144
|
-
throw new ValidationError(
|
|
20145
|
-
"directSequence must be provided if directInput is",
|
|
20146
|
-
{
|
|
20147
|
-
field: "directSequence",
|
|
20148
|
-
value: directSequence
|
|
20149
|
-
}
|
|
20150
|
-
);
|
|
20151
20395
|
}
|
|
20152
|
-
|
|
20153
|
-
|
|
20154
|
-
|
|
20155
|
-
|
|
20156
|
-
|
|
20157
|
-
|
|
20396
|
+
const cpfpRefundTx = createRefundTx({
|
|
20397
|
+
sequence,
|
|
20398
|
+
input: refundInput,
|
|
20399
|
+
amountSats: nodeAmountSats,
|
|
20400
|
+
receivingPubkey,
|
|
20401
|
+
network,
|
|
20402
|
+
shouldCalculateFee: false,
|
|
20403
|
+
includeAnchor: true
|
|
20158
20404
|
});
|
|
20159
|
-
|
|
20160
|
-
|
|
20161
|
-
|
|
20405
|
+
const directFromCpfpRefundTx = createRefundTx({
|
|
20406
|
+
sequence: sequence + DIRECT_TIMELOCK_OFFSET,
|
|
20407
|
+
input: refundInput,
|
|
20408
|
+
amountSats: nodeAmountSats,
|
|
20409
|
+
receivingPubkey,
|
|
20410
|
+
network,
|
|
20411
|
+
shouldCalculateFee: true,
|
|
20412
|
+
includeAnchor: false
|
|
20162
20413
|
});
|
|
20163
|
-
cpfpRefundTx
|
|
20164
|
-
|
|
20165
|
-
|
|
20166
|
-
|
|
20167
|
-
|
|
20414
|
+
return { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx };
|
|
20415
|
+
}
|
|
20416
|
+
function createInitialTimelockRefundTxs(params) {
|
|
20417
|
+
return createRefundTxs({
|
|
20418
|
+
...params,
|
|
20419
|
+
sequence: INITIAL_SEQUENCE
|
|
20168
20420
|
});
|
|
20169
|
-
|
|
20170
|
-
|
|
20171
|
-
|
|
20421
|
+
}
|
|
20422
|
+
function createDecrementedTimelockRefundTxs(params) {
|
|
20423
|
+
const nextSequence = getNextTransactionSequence(params.sequence).nextSequence;
|
|
20424
|
+
return createRefundTxs({
|
|
20425
|
+
...params,
|
|
20426
|
+
sequence: nextSequence
|
|
20172
20427
|
});
|
|
20173
|
-
|
|
20174
|
-
|
|
20175
|
-
|
|
20428
|
+
}
|
|
20429
|
+
function createCurrentTimelockRefundTxs(params) {
|
|
20430
|
+
return createRefundTxs(params);
|
|
20431
|
+
}
|
|
20432
|
+
function createTestUnilateralRefundTxs(params) {
|
|
20433
|
+
return createRefundTxs({
|
|
20434
|
+
...params,
|
|
20435
|
+
sequence: TEST_UNILATERAL_SEQUENCE
|
|
20176
20436
|
});
|
|
20177
|
-
|
|
20178
|
-
|
|
20179
|
-
|
|
20180
|
-
|
|
20437
|
+
}
|
|
20438
|
+
function createConnectorRefundTxs(params) {
|
|
20439
|
+
const { connectorOutput, ...baseParams } = params;
|
|
20440
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createDecrementedTimelockRefundTxs(baseParams);
|
|
20441
|
+
cpfpRefundTx.addInput(connectorOutput);
|
|
20442
|
+
if (directRefundTx) {
|
|
20443
|
+
directRefundTx.addInput(connectorOutput);
|
|
20181
20444
|
}
|
|
20182
|
-
|
|
20183
|
-
|
|
20184
|
-
|
|
20185
|
-
}
|
|
20186
|
-
const directFromCpfpTx = new import_btc_signer.Transaction({
|
|
20187
|
-
version: 3,
|
|
20188
|
-
allowUnknownOutputs: true
|
|
20189
|
-
});
|
|
20190
|
-
directFromCpfpTx.addInput({
|
|
20191
|
-
...cpfpNodeOutPoint,
|
|
20192
|
-
sequence
|
|
20193
|
-
});
|
|
20194
|
-
directFromCpfpTx.addInput(connectorOutput);
|
|
20195
|
-
directFromCpfpTx.addOutput({
|
|
20196
|
-
script: receiverScript,
|
|
20197
|
-
amount: outputAmount
|
|
20198
|
-
});
|
|
20199
|
-
return [cpfpRefundTx, directRefundTx, directFromCpfpTx];
|
|
20445
|
+
if (directFromCpfpRefundTx) {
|
|
20446
|
+
directFromCpfpRefundTx.addInput(connectorOutput);
|
|
20447
|
+
}
|
|
20448
|
+
return { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx };
|
|
20200
20449
|
}
|
|
20201
20450
|
function getCurrentTimelock(currSequence) {
|
|
20202
20451
|
return (currSequence || 0) & 65535;
|
|
20203
20452
|
}
|
|
20204
20453
|
function getTransactionSequence(currSequence) {
|
|
20205
20454
|
const timelock = getCurrentTimelock(currSequence);
|
|
20455
|
+
const isBit30Defined = (currSequence || 0) & 1 << 30;
|
|
20206
20456
|
return {
|
|
20207
|
-
nextSequence:
|
|
20208
|
-
nextDirectSequence:
|
|
20457
|
+
nextSequence: isBit30Defined | timelock,
|
|
20458
|
+
nextDirectSequence: isBit30Defined | timelock + DIRECT_TIMELOCK_OFFSET
|
|
20209
20459
|
};
|
|
20210
20460
|
}
|
|
20211
20461
|
function checkIfValidSequence(currSequence) {
|
|
@@ -20224,6 +20474,13 @@ function checkIfValidSequence(currSequence) {
|
|
|
20224
20474
|
});
|
|
20225
20475
|
}
|
|
20226
20476
|
}
|
|
20477
|
+
function isZeroTimelock(currSequence) {
|
|
20478
|
+
return getCurrentTimelock(currSequence) === 0;
|
|
20479
|
+
}
|
|
20480
|
+
function doesTxnNeedRenewed(currSequence) {
|
|
20481
|
+
const currentTimelock = getCurrentTimelock(currSequence);
|
|
20482
|
+
return currentTimelock <= 100;
|
|
20483
|
+
}
|
|
20227
20484
|
function doesLeafNeedRefresh(currSequence, isNodeTx) {
|
|
20228
20485
|
const currentTimelock = getCurrentTimelock(currSequence);
|
|
20229
20486
|
if (isNodeTx) {
|
|
@@ -20234,6 +20491,7 @@ function doesLeafNeedRefresh(currSequence, isNodeTx) {
|
|
|
20234
20491
|
function getNextTransactionSequence(currSequence, isNodeTx) {
|
|
20235
20492
|
const currentTimelock = getCurrentTimelock(currSequence);
|
|
20236
20493
|
const nextTimelock = currentTimelock - TIME_LOCK_INTERVAL;
|
|
20494
|
+
const isBit30Defined = (currSequence || 0) & 1 << 30;
|
|
20237
20495
|
if (isNodeTx && nextTimelock < 0) {
|
|
20238
20496
|
throw new ValidationError("timelock interval is less than 0", {
|
|
20239
20497
|
field: "nextTimelock",
|
|
@@ -20248,8 +20506,8 @@ function getNextTransactionSequence(currSequence, isNodeTx) {
|
|
|
20248
20506
|
});
|
|
20249
20507
|
}
|
|
20250
20508
|
return {
|
|
20251
|
-
nextSequence:
|
|
20252
|
-
nextDirectSequence:
|
|
20509
|
+
nextSequence: isBit30Defined | nextTimelock,
|
|
20510
|
+
nextDirectSequence: isBit30Defined | nextTimelock + DIRECT_TIMELOCK_OFFSET
|
|
20253
20511
|
};
|
|
20254
20512
|
}
|
|
20255
20513
|
function getEphemeralAnchorOutput() {
|
|
@@ -20262,7 +20520,7 @@ function getEphemeralAnchorOutput() {
|
|
|
20262
20520
|
|
|
20263
20521
|
// src/utils/unilateral-exit.ts
|
|
20264
20522
|
init_buffer();
|
|
20265
|
-
var
|
|
20523
|
+
var import_utils12 = require("@noble/curves/utils");
|
|
20266
20524
|
var import_legacy = require("@noble/hashes/legacy");
|
|
20267
20525
|
var import_sha25 = require("@noble/hashes/sha2");
|
|
20268
20526
|
var btc3 = __toESM(require("@scure/btc-signer"), 1);
|
|
@@ -20277,7 +20535,7 @@ function isEphemeralAnchorOutput(script, amount) {
|
|
|
20277
20535
|
}
|
|
20278
20536
|
async function constructUnilateralExitTxs(nodeHexStrings, sparkClient, network) {
|
|
20279
20537
|
const result = [];
|
|
20280
|
-
const nodes = nodeHexStrings.map((hex) => TreeNode.decode((0,
|
|
20538
|
+
const nodes = nodeHexStrings.map((hex) => TreeNode.decode((0, import_utils12.hexToBytes)(hex)));
|
|
20281
20539
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
20282
20540
|
for (const node of nodes) {
|
|
20283
20541
|
nodeMap.set(node.id, node);
|
|
@@ -20333,10 +20591,10 @@ async function constructUnilateralExitTxs(nodeHexStrings, sparkClient, network)
|
|
|
20333
20591
|
}
|
|
20334
20592
|
}
|
|
20335
20593
|
for (const chainNode of chain) {
|
|
20336
|
-
const nodeTx = (0,
|
|
20594
|
+
const nodeTx = (0, import_utils12.bytesToHex)(chainNode.nodeTx);
|
|
20337
20595
|
transactions.push(nodeTx);
|
|
20338
20596
|
if (chainNode.id === node.id) {
|
|
20339
|
-
const refundTx = (0,
|
|
20597
|
+
const refundTx = (0, import_utils12.bytesToHex)(chainNode.refundTx);
|
|
20340
20598
|
transactions.push(refundTx);
|
|
20341
20599
|
}
|
|
20342
20600
|
}
|
|
@@ -20366,7 +20624,7 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
20366
20624
|
`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.`
|
|
20367
20625
|
);
|
|
20368
20626
|
}
|
|
20369
|
-
const nodeBytes = (0,
|
|
20627
|
+
const nodeBytes = (0, import_utils12.hexToBytes)(hex);
|
|
20370
20628
|
const node = TreeNode.decode(nodeBytes);
|
|
20371
20629
|
if (!node.id) {
|
|
20372
20630
|
throw new Error(
|
|
@@ -20442,7 +20700,7 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
20442
20700
|
}
|
|
20443
20701
|
}
|
|
20444
20702
|
for (const chainNode of chain) {
|
|
20445
|
-
let nodeTxHex = (0,
|
|
20703
|
+
let nodeTxHex = (0, import_utils12.bytesToHex)(chainNode.nodeTx);
|
|
20446
20704
|
try {
|
|
20447
20705
|
const txObj = getTxFromRawTxHex(nodeTxHex);
|
|
20448
20706
|
const txid = getTxId(txObj);
|
|
@@ -20459,7 +20717,7 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
20459
20717
|
for (let i = txObj.outputsLength - 1; i >= 0; i--) {
|
|
20460
20718
|
const output = txObj.getOutput(i);
|
|
20461
20719
|
if (output?.amount === 0n && output.script) {
|
|
20462
|
-
anchorOutputScriptHex = (0,
|
|
20720
|
+
anchorOutputScriptHex = (0, import_utils12.bytesToHex)(output.script);
|
|
20463
20721
|
break;
|
|
20464
20722
|
}
|
|
20465
20723
|
}
|
|
@@ -20480,11 +20738,11 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
20480
20738
|
usedUtxos,
|
|
20481
20739
|
correctedParentTx
|
|
20482
20740
|
} = constructFeeBumpTx(nodeTxHex, availableUtxos, feeRate, void 0);
|
|
20483
|
-
const feeBumpTx = btc3.Transaction.fromPSBT((0,
|
|
20741
|
+
const feeBumpTx = btc3.Transaction.fromPSBT((0, import_utils12.hexToBytes)(nodeFeeBumpPsbt));
|
|
20484
20742
|
var feeBumpOut = feeBumpTx.outputsLength === 1 ? feeBumpTx.getOutput(0) : null;
|
|
20485
20743
|
var feeBumpOutPubKey = null;
|
|
20486
20744
|
for (const usedUtxo of usedUtxos) {
|
|
20487
|
-
if (feeBumpOut && (0,
|
|
20745
|
+
if (feeBumpOut && (0, import_utils12.bytesToHex)(feeBumpOut.script) == usedUtxo.script) {
|
|
20488
20746
|
feeBumpOutPubKey = usedUtxo.publicKey;
|
|
20489
20747
|
}
|
|
20490
20748
|
const index = availableUtxos.findIndex(
|
|
@@ -20499,20 +20757,20 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
20499
20757
|
txid: getTxId(feeBumpTx),
|
|
20500
20758
|
vout: 0,
|
|
20501
20759
|
value: feeBumpOut.amount,
|
|
20502
|
-
script: (0,
|
|
20760
|
+
script: (0, import_utils12.bytesToHex)(feeBumpOut.script),
|
|
20503
20761
|
publicKey: feeBumpOutPubKey
|
|
20504
20762
|
});
|
|
20505
20763
|
const finalNodeTx = correctedParentTx || nodeTxHex;
|
|
20506
20764
|
txPackages.push({ tx: finalNodeTx, feeBumpPsbt: nodeFeeBumpPsbt });
|
|
20507
20765
|
if (chainNode.id === node.id) {
|
|
20508
|
-
let refundTxHex = (0,
|
|
20766
|
+
let refundTxHex = (0, import_utils12.bytesToHex)(chainNode.refundTx);
|
|
20509
20767
|
try {
|
|
20510
20768
|
const txObj = getTxFromRawTxHex(refundTxHex);
|
|
20511
20769
|
let anchorOutputScriptHex;
|
|
20512
20770
|
for (let i = txObj.outputsLength - 1; i >= 0; i--) {
|
|
20513
20771
|
const output = txObj.getOutput(i);
|
|
20514
20772
|
if (output?.amount === 0n && output.script) {
|
|
20515
|
-
anchorOutputScriptHex = (0,
|
|
20773
|
+
anchorOutputScriptHex = (0, import_utils12.bytesToHex)(output.script);
|
|
20516
20774
|
break;
|
|
20517
20775
|
}
|
|
20518
20776
|
}
|
|
@@ -20535,12 +20793,12 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
20535
20793
|
void 0
|
|
20536
20794
|
);
|
|
20537
20795
|
const feeBumpTx2 = btc3.Transaction.fromPSBT(
|
|
20538
|
-
(0,
|
|
20796
|
+
(0, import_utils12.hexToBytes)(refundFeeBump.feeBumpPsbt)
|
|
20539
20797
|
);
|
|
20540
20798
|
var feeBumpOut = feeBumpTx2.outputsLength === 1 ? feeBumpTx2.getOutput(0) : null;
|
|
20541
20799
|
var feeBumpOutPubKey = null;
|
|
20542
20800
|
for (const usedUtxo of usedUtxos) {
|
|
20543
|
-
if (feeBumpOut && (0,
|
|
20801
|
+
if (feeBumpOut && (0, import_utils12.bytesToHex)(feeBumpOut.script) == usedUtxo.script) {
|
|
20544
20802
|
feeBumpOutPubKey = usedUtxo.publicKey;
|
|
20545
20803
|
}
|
|
20546
20804
|
const index = availableUtxos.findIndex(
|
|
@@ -20555,7 +20813,7 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
20555
20813
|
txid: getTxId(feeBumpTx2),
|
|
20556
20814
|
vout: 0,
|
|
20557
20815
|
value: feeBumpOut.amount,
|
|
20558
|
-
script: (0,
|
|
20816
|
+
script: (0, import_utils12.bytesToHex)(feeBumpOut.script),
|
|
20559
20817
|
publicKey: feeBumpOutPubKey
|
|
20560
20818
|
});
|
|
20561
20819
|
txPackages.push({
|
|
@@ -20650,10 +20908,10 @@ function constructFeeBumpTx(txHex, utxos, feeRate, previousFeeBumpTx) {
|
|
|
20650
20908
|
if (!fundingUtxo) {
|
|
20651
20909
|
throw new Error(`UTXO at index ${i} is undefined`);
|
|
20652
20910
|
}
|
|
20653
|
-
const pubKeyHash = hash160((0,
|
|
20911
|
+
const pubKeyHash = hash160((0, import_utils12.hexToBytes)(fundingUtxo.publicKey));
|
|
20654
20912
|
const scriptToUse = new Uint8Array([0, 20, ...pubKeyHash]);
|
|
20655
|
-
const providedScript = (0,
|
|
20656
|
-
if ((0,
|
|
20913
|
+
const providedScript = (0, import_utils12.hexToBytes)(fundingUtxo.script);
|
|
20914
|
+
if ((0, import_utils12.bytesToHex)(scriptToUse) !== (0, import_utils12.bytesToHex)(providedScript)) {
|
|
20657
20915
|
throw new Error(
|
|
20658
20916
|
`\u274C Derived script doesn't match provided script for UTXO ${i + 1}.`
|
|
20659
20917
|
);
|
|
@@ -20718,7 +20976,7 @@ function constructFeeBumpTx(txHex, utxos, feeRate, previousFeeBumpTx) {
|
|
|
20718
20976
|
}
|
|
20719
20977
|
let psbtHex;
|
|
20720
20978
|
try {
|
|
20721
|
-
psbtHex = (0,
|
|
20979
|
+
psbtHex = (0, import_utils12.bytesToHex)(builder.toPSBT());
|
|
20722
20980
|
} catch (error) {
|
|
20723
20981
|
throw new Error(`Failed to extract transaction: ${error}`);
|
|
20724
20982
|
}
|
|
@@ -20767,12 +21025,12 @@ init_logging();
|
|
|
20767
21025
|
init_buffer();
|
|
20768
21026
|
var import_secp256k17 = require("@bitcoinerlab/secp256k1");
|
|
20769
21027
|
var import_secp256k18 = require("@noble/curves/secp256k1");
|
|
20770
|
-
var
|
|
21028
|
+
var import_utils14 = require("@noble/curves/utils");
|
|
20771
21029
|
var import_sha26 = require("@noble/hashes/sha2");
|
|
20772
21030
|
var import_bip32 = require("@scure/bip32");
|
|
20773
21031
|
var import_bip39 = require("@scure/bip39");
|
|
20774
21032
|
var import_english = require("@scure/bip39/wordlists/english");
|
|
20775
|
-
var
|
|
21033
|
+
var import_utils15 = require("@scure/btc-signer/utils");
|
|
20776
21034
|
var ecies = __toESM(require("eciesjs"), 1);
|
|
20777
21035
|
|
|
20778
21036
|
// src/constants.ts
|
|
@@ -20785,7 +21043,7 @@ var isWebExtension = (
|
|
|
20785
21043
|
"chrome" in globalThis && globalThis.chrome.runtime?.id
|
|
20786
21044
|
);
|
|
20787
21045
|
var userAgent = "navigator" in globalThis ? globalThis.navigator.userAgent || "unknown-user-agent" : void 0;
|
|
20788
|
-
var packageVersion = true ? "0.
|
|
21046
|
+
var packageVersion = true ? "0.4.0" : "unknown";
|
|
20789
21047
|
var baseEnvStr = "unknown";
|
|
20790
21048
|
if (isBun) {
|
|
20791
21049
|
const bunVersion = "version" in globalThis.Bun ? globalThis.Bun.version : "unknown-version";
|
|
@@ -20886,7 +21144,7 @@ var TaprootOutputKeysGenerator = class {
|
|
|
20886
21144
|
}
|
|
20887
21145
|
const derivationPath = this.useAddressIndex ? `m/86'/0'/0'/0/${accountNumber}` : `m/86'/0'/${accountNumber}'/0/0`;
|
|
20888
21146
|
const taprootInternalKey = hdkey.derive(derivationPath);
|
|
20889
|
-
let tweakedPrivateKey = (0,
|
|
21147
|
+
let tweakedPrivateKey = (0, import_utils15.taprootTweakPrivKey)(taprootInternalKey.privateKey);
|
|
20890
21148
|
let tweakedPublicKey = import_secp256k18.secp256k1.getPublicKey(tweakedPrivateKey);
|
|
20891
21149
|
if (tweakedPublicKey[0] === 3) {
|
|
20892
21150
|
tweakedPrivateKey = (0, import_secp256k17.privateNegate)(tweakedPrivateKey);
|
|
@@ -20964,7 +21222,7 @@ var DefaultSparkSigner = class {
|
|
|
20964
21222
|
});
|
|
20965
21223
|
}
|
|
20966
21224
|
const receiverEciesPrivKey = ecies.PrivateKey.fromHex(
|
|
20967
|
-
(0,
|
|
21225
|
+
(0, import_utils14.bytesToHex)(this.identityKey.privateKey)
|
|
20968
21226
|
);
|
|
20969
21227
|
const privateKey = ecies.decrypt(receiverEciesPrivKey.toHex(), ciphertext);
|
|
20970
21228
|
return privateKey;
|
|
@@ -21098,7 +21356,7 @@ var DefaultSparkSigner = class {
|
|
|
21098
21356
|
threshold,
|
|
21099
21357
|
numShares
|
|
21100
21358
|
}) {
|
|
21101
|
-
const secretAsInt = (0,
|
|
21359
|
+
const secretAsInt = (0, import_utils14.bytesToNumberBE)(secret);
|
|
21102
21360
|
return splitSecretWithProofs(secretAsInt, curveOrder, threshold, numShares);
|
|
21103
21361
|
}
|
|
21104
21362
|
async signFrost({
|
|
@@ -21134,7 +21392,7 @@ var DefaultSparkSigner = class {
|
|
|
21134
21392
|
publicKey,
|
|
21135
21393
|
verifyingKey
|
|
21136
21394
|
};
|
|
21137
|
-
const logMessage = (0,
|
|
21395
|
+
const logMessage = (0, import_utils14.bytesToHex)(message);
|
|
21138
21396
|
const result = await SparkFrost.signFrost({
|
|
21139
21397
|
message,
|
|
21140
21398
|
keyPackage,
|
|
@@ -21176,7 +21434,7 @@ var DefaultSparkSigner = class {
|
|
|
21176
21434
|
}
|
|
21177
21435
|
async createSparkWalletFromSeed(seed, accountNumber) {
|
|
21178
21436
|
if (typeof seed === "string") {
|
|
21179
|
-
seed = (0,
|
|
21437
|
+
seed = (0, import_utils14.hexToBytes)(seed);
|
|
21180
21438
|
}
|
|
21181
21439
|
const {
|
|
21182
21440
|
identityKey,
|
|
@@ -21188,7 +21446,7 @@ var DefaultSparkSigner = class {
|
|
|
21188
21446
|
this.depositKey = depositKey;
|
|
21189
21447
|
this.signingKey = signingKey.hdKey;
|
|
21190
21448
|
this.staticDepositKey = staticDepositKey.hdKey;
|
|
21191
|
-
return (0,
|
|
21449
|
+
return (0, import_utils14.bytesToHex)(identityKey.publicKey);
|
|
21192
21450
|
}
|
|
21193
21451
|
async signMessageWithIdentityKey(message, compact) {
|
|
21194
21452
|
if (!this.identityKey?.privateKey) {
|
|
@@ -21209,7 +21467,7 @@ var DefaultSparkSigner = class {
|
|
|
21209
21467
|
});
|
|
21210
21468
|
}
|
|
21211
21469
|
const receiverEciesPrivKey = ecies.PrivateKey.fromHex(
|
|
21212
|
-
(0,
|
|
21470
|
+
(0, import_utils14.bytesToHex)(this.identityKey.privateKey)
|
|
21213
21471
|
);
|
|
21214
21472
|
const privateKey = ecies.decrypt(receiverEciesPrivKey.toHex(), ciphertext);
|
|
21215
21473
|
const publicKey = import_secp256k18.secp256k1.getPublicKey(privateKey);
|
|
@@ -21233,15 +21491,15 @@ var DefaultSparkSigner = class {
|
|
|
21233
21491
|
}
|
|
21234
21492
|
signTransactionIndex(tx, index, publicKey) {
|
|
21235
21493
|
let privateKey;
|
|
21236
|
-
if ((0,
|
|
21494
|
+
if ((0, import_utils14.equalBytes)(publicKey, this.identityKey?.publicKey ?? new Uint8Array())) {
|
|
21237
21495
|
privateKey = this.identityKey?.privateKey;
|
|
21238
|
-
} else if ((0,
|
|
21496
|
+
} else if ((0, import_utils14.equalBytes)(publicKey, this.depositKey?.publicKey ?? new Uint8Array())) {
|
|
21239
21497
|
privateKey = this.depositKey?.privateKey;
|
|
21240
21498
|
}
|
|
21241
21499
|
if (!privateKey) {
|
|
21242
21500
|
throw new ValidationError("Private key not found for public key", {
|
|
21243
21501
|
field: "privateKey",
|
|
21244
|
-
value: (0,
|
|
21502
|
+
value: (0, import_utils14.bytesToHex)(publicKey)
|
|
21245
21503
|
});
|
|
21246
21504
|
}
|
|
21247
21505
|
tx.signIdx(privateKey, index);
|
|
@@ -21323,7 +21581,7 @@ var import_secp256k114 = require("@noble/curves/secp256k1");
|
|
|
21323
21581
|
var import_utils25 = require("@noble/curves/utils");
|
|
21324
21582
|
var import_bip392 = require("@scure/bip39");
|
|
21325
21583
|
var import_english2 = require("@scure/bip39/wordlists/english");
|
|
21326
|
-
var
|
|
21584
|
+
var import_btc_signer5 = require("@scure/btc-signer");
|
|
21327
21585
|
var import_async_mutex = require("async-mutex");
|
|
21328
21586
|
var import_uuidv75 = require("uuidv7");
|
|
21329
21587
|
|
|
@@ -22570,28 +22828,22 @@ var WalletConfigService = class {
|
|
|
22570
22828
|
getEvents() {
|
|
22571
22829
|
return this.config.events;
|
|
22572
22830
|
}
|
|
22831
|
+
getOptimizationOptions() {
|
|
22832
|
+
return this.config.optimizationOptions;
|
|
22833
|
+
}
|
|
22573
22834
|
};
|
|
22574
22835
|
|
|
22575
22836
|
// src/services/coop-exit.ts
|
|
22576
22837
|
init_buffer();
|
|
22577
|
-
var import_btc_signer3 = require("@scure/btc-signer");
|
|
22578
22838
|
var import_uuidv73 = require("uuidv7");
|
|
22579
22839
|
|
|
22580
22840
|
// src/services/transfer.ts
|
|
22581
22841
|
init_buffer();
|
|
22582
22842
|
var import_secp256k19 = require("@noble/curves/secp256k1");
|
|
22583
|
-
var
|
|
22843
|
+
var import_utils16 = require("@noble/curves/utils");
|
|
22584
22844
|
var import_sha28 = require("@noble/hashes/sha2");
|
|
22585
|
-
var import_btc_signer2 = require("@scure/btc-signer");
|
|
22586
22845
|
var ecies2 = __toESM(require("eciesjs"), 1);
|
|
22587
22846
|
var import_uuidv72 = require("uuidv7");
|
|
22588
|
-
function getSigningJobProto(signingJob) {
|
|
22589
|
-
return {
|
|
22590
|
-
signingPublicKey: signingJob.signingPublicKey,
|
|
22591
|
-
rawTx: signingJob.rawTx,
|
|
22592
|
-
signingNonceCommitment: signingJob.signingNonceCommitment.commitment
|
|
22593
|
-
};
|
|
22594
|
-
}
|
|
22595
22847
|
var BaseTransferService = class {
|
|
22596
22848
|
config;
|
|
22597
22849
|
connectionManager;
|
|
@@ -22938,7 +23190,7 @@ var BaseTransferService = class {
|
|
|
22938
23190
|
}
|
|
22939
23191
|
async prepareSendTransferKeyTweaks(transferID, receiverIdentityPubkey, leaves, cpfpRefundSignatureMap, directRefundSignatureMap, directFromCpfpRefundSignatureMap) {
|
|
22940
23192
|
const receiverEciesPubKey = ecies2.PublicKey.fromHex(
|
|
22941
|
-
(0,
|
|
23193
|
+
(0, import_utils16.bytesToHex)(receiverIdentityPubkey)
|
|
22942
23194
|
);
|
|
22943
23195
|
const leavesTweaksMap = /* @__PURE__ */ new Map();
|
|
22944
23196
|
for (const leaf of leaves) {
|
|
@@ -22979,7 +23231,7 @@ var BaseTransferService = class {
|
|
|
22979
23231
|
throw new Error(`Share not found for operator ${operator.id}`);
|
|
22980
23232
|
}
|
|
22981
23233
|
const pubkeyTweak = import_secp256k19.secp256k1.getPublicKey(
|
|
22982
|
-
(0,
|
|
23234
|
+
(0, import_utils16.numberToBytesBE)(share.share, 32),
|
|
22983
23235
|
true
|
|
22984
23236
|
);
|
|
22985
23237
|
pubkeySharesTweak.set(identifier, pubkeyTweak);
|
|
@@ -23004,7 +23256,7 @@ var BaseTransferService = class {
|
|
|
23004
23256
|
leafTweaksMap.set(identifier, {
|
|
23005
23257
|
leafId: leaf.leaf.id,
|
|
23006
23258
|
secretShareTweak: {
|
|
23007
|
-
secretShare: (0,
|
|
23259
|
+
secretShare: (0, import_utils16.numberToBytesBE)(share.share, 32),
|
|
23008
23260
|
proofs: share.proofs
|
|
23009
23261
|
},
|
|
23010
23262
|
pubkeySharesTweak: Object.fromEntries(pubkeySharesTweak),
|
|
@@ -23027,7 +23279,7 @@ var BaseTransferService = class {
|
|
|
23027
23279
|
return void 0;
|
|
23028
23280
|
}
|
|
23029
23281
|
compareTransfers(transfer1, transfer2) {
|
|
23030
|
-
return transfer1.id === transfer2.id && (0,
|
|
23282
|
+
return transfer1.id === transfer2.id && (0, import_utils16.equalBytes)(
|
|
23031
23283
|
transfer1.senderIdentityPublicKey,
|
|
23032
23284
|
transfer2.senderIdentityPublicKey
|
|
23033
23285
|
) && transfer1.status === transfer2.status && transfer1.totalValue === transfer2.totalValue && transfer1.expiryTime?.getTime() === transfer2.expiryTime?.getTime() && transfer1.leaves.length === transfer2.leaves.length;
|
|
@@ -23273,42 +23525,27 @@ var TransferService = class extends BaseTransferService {
|
|
|
23273
23525
|
throw new Error(`Leaf data not found for leaf ${leaf.leaf.id}`);
|
|
23274
23526
|
}
|
|
23275
23527
|
const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
23276
|
-
const cpfpNodeOutPoint = {
|
|
23277
|
-
txid: (0, import_utils15.hexToBytes)(getTxId(nodeTx)),
|
|
23278
|
-
index: 0
|
|
23279
|
-
};
|
|
23280
23528
|
let directNodeTx;
|
|
23281
|
-
let directNodeOutPoint;
|
|
23282
23529
|
if (leaf.leaf.directTx.length > 0) {
|
|
23283
23530
|
directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
|
|
23284
|
-
directNodeOutPoint = {
|
|
23285
|
-
txid: (0, import_utils15.hexToBytes)(getTxId(directNodeTx)),
|
|
23286
|
-
index: 0
|
|
23287
|
-
};
|
|
23288
23531
|
}
|
|
23289
23532
|
const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
23290
|
-
const
|
|
23291
|
-
if (!
|
|
23533
|
+
const currentSequence = currRefundTx.getInput(0).sequence;
|
|
23534
|
+
if (!currentSequence) {
|
|
23292
23535
|
throw new ValidationError("Invalid refund transaction", {
|
|
23293
23536
|
field: "sequence",
|
|
23294
23537
|
value: currRefundTx.getInput(0),
|
|
23295
23538
|
expected: "Non-null sequence"
|
|
23296
23539
|
});
|
|
23297
23540
|
}
|
|
23298
|
-
const
|
|
23299
|
-
|
|
23300
|
-
|
|
23301
|
-
|
|
23302
|
-
}
|
|
23303
|
-
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
23304
|
-
sequence: nextSequence,
|
|
23305
|
-
directSequence: nextDirectSequence,
|
|
23306
|
-
input: cpfpNodeOutPoint,
|
|
23307
|
-
directInput: directNodeOutPoint,
|
|
23308
|
-
amountSats,
|
|
23541
|
+
const refundTxsParams = {
|
|
23542
|
+
nodeTx,
|
|
23543
|
+
directNodeTx,
|
|
23544
|
+
sequence: currentSequence,
|
|
23309
23545
|
receivingPubkey: refundSigningData.receivingPubkey,
|
|
23310
23546
|
network: this.config.getNetwork()
|
|
23311
|
-
}
|
|
23547
|
+
};
|
|
23548
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = isForClaim ? createCurrentTimelockRefundTxs(refundTxsParams) : createDecrementedTimelockRefundTxs(refundTxsParams);
|
|
23312
23549
|
refundSigningData.refundTx = cpfpRefundTx;
|
|
23313
23550
|
refundSigningData.directRefundTx = directRefundTx;
|
|
23314
23551
|
refundSigningData.directFromCpfpRefundTx = directFromCpfpRefundTx;
|
|
@@ -23416,7 +23653,7 @@ var TransferService = class extends BaseTransferService {
|
|
|
23416
23653
|
throw new Error(`Share not found for operator ${operator.id}`);
|
|
23417
23654
|
}
|
|
23418
23655
|
const pubkeyTweak = import_secp256k19.secp256k1.getPublicKey(
|
|
23419
|
-
(0,
|
|
23656
|
+
(0, import_utils16.numberToBytesBE)(share.share, 32)
|
|
23420
23657
|
);
|
|
23421
23658
|
pubkeySharesTweak.set(identifier, pubkeyTweak);
|
|
23422
23659
|
}
|
|
@@ -23429,7 +23666,7 @@ var TransferService = class extends BaseTransferService {
|
|
|
23429
23666
|
leafTweaksMap.set(identifier, {
|
|
23430
23667
|
leafId: leaf.leaf.id,
|
|
23431
23668
|
secretShareTweak: {
|
|
23432
|
-
secretShare: (0,
|
|
23669
|
+
secretShare: (0, import_utils16.numberToBytesBE)(share.share, 32),
|
|
23433
23670
|
proofs: share.proofs
|
|
23434
23671
|
},
|
|
23435
23672
|
pubkeySharesTweak: Object.fromEntries(pubkeySharesTweak)
|
|
@@ -23521,71 +23758,127 @@ var TransferService = class extends BaseTransferService {
|
|
|
23521
23758
|
throw new Error(`Error querying pending transfers by sender: ${error}`);
|
|
23522
23759
|
}
|
|
23523
23760
|
}
|
|
23524
|
-
async
|
|
23525
|
-
const
|
|
23526
|
-
|
|
23527
|
-
|
|
23528
|
-
|
|
23529
|
-
|
|
23761
|
+
async renewRefundTxn(node, parentNode) {
|
|
23762
|
+
const sparkClient = await this.connectionManager.createSparkClient(
|
|
23763
|
+
this.config.getCoordinatorAddress()
|
|
23764
|
+
);
|
|
23765
|
+
const signingJobs = await this.createRenewRefundSigningJobs(
|
|
23766
|
+
node,
|
|
23767
|
+
parentNode
|
|
23768
|
+
);
|
|
23769
|
+
const statechainCommitments = await sparkClient.get_signing_commitments({
|
|
23770
|
+
nodeIds: [node.id],
|
|
23771
|
+
count: signingJobs.length
|
|
23772
|
+
});
|
|
23773
|
+
const mappedSigningJobs = signingJobs.map((signingJob, index) => {
|
|
23774
|
+
const signingNonceCommitments = statechainCommitments.signingCommitments[index]?.signingNonceCommitments;
|
|
23775
|
+
if (!signingNonceCommitments) {
|
|
23776
|
+
throw new Error("Signing nonce commitments not found");
|
|
23777
|
+
}
|
|
23778
|
+
return {
|
|
23779
|
+
...signingJob,
|
|
23780
|
+
signingNonceCommitments
|
|
23781
|
+
};
|
|
23782
|
+
});
|
|
23783
|
+
const userSignedTxSigningJobs = await this.signingService.signSigningJobs(mappedSigningJobs);
|
|
23784
|
+
const renewRefundTimelockSigningJob = {
|
|
23785
|
+
nodeTxSigningJob: userSignedTxSigningJobs.get("node"),
|
|
23786
|
+
refundTxSigningJob: userSignedTxSigningJobs.get("cpfp"),
|
|
23787
|
+
directNodeTxSigningJob: userSignedTxSigningJobs.get("directNode"),
|
|
23788
|
+
directRefundTxSigningJob: userSignedTxSigningJobs.get("direct"),
|
|
23789
|
+
directFromCpfpRefundTxSigningJob: userSignedTxSigningJobs.get("directFromCpfp")
|
|
23790
|
+
};
|
|
23791
|
+
const response = await sparkClient.renew_leaf({
|
|
23792
|
+
leafId: node.id,
|
|
23793
|
+
signingJobs: {
|
|
23794
|
+
$case: "renewRefundTimelockSigningJob",
|
|
23795
|
+
renewRefundTimelockSigningJob
|
|
23796
|
+
}
|
|
23797
|
+
});
|
|
23798
|
+
if (response.renewResult?.$case !== "renewRefundTimelockResult" || !response.renewResult?.renewRefundTimelockResult.node) {
|
|
23799
|
+
throw new ValidationError("Unexpected renew result", {
|
|
23800
|
+
field: "renewResult",
|
|
23801
|
+
value: response.renewResult
|
|
23802
|
+
});
|
|
23530
23803
|
}
|
|
23531
|
-
|
|
23532
|
-
|
|
23533
|
-
|
|
23534
|
-
|
|
23535
|
-
|
|
23536
|
-
|
|
23537
|
-
|
|
23538
|
-
|
|
23539
|
-
|
|
23540
|
-
|
|
23541
|
-
|
|
23542
|
-
|
|
23543
|
-
|
|
23544
|
-
|
|
23545
|
-
|
|
23546
|
-
|
|
23547
|
-
|
|
23548
|
-
|
|
23804
|
+
return response.renewResult?.renewRefundTimelockResult.node;
|
|
23805
|
+
}
|
|
23806
|
+
async renewNodeTxn(node, parentNode) {
|
|
23807
|
+
const sparkClient = await this.connectionManager.createSparkClient(
|
|
23808
|
+
this.config.getCoordinatorAddress()
|
|
23809
|
+
);
|
|
23810
|
+
const signingJobs = await this.createRenewNodeSigningJobs(node, parentNode);
|
|
23811
|
+
const statechainCommitments = await sparkClient.get_signing_commitments({
|
|
23812
|
+
nodeIds: [node.id],
|
|
23813
|
+
count: signingJobs.length
|
|
23814
|
+
});
|
|
23815
|
+
const mappedSigningJobs = signingJobs.map((signingJob, index) => {
|
|
23816
|
+
const signingNonceCommitments = statechainCommitments.signingCommitments[index]?.signingNonceCommitments;
|
|
23817
|
+
if (!signingNonceCommitments) {
|
|
23818
|
+
throw new Error("Signing nonce commitments not found");
|
|
23819
|
+
}
|
|
23820
|
+
return {
|
|
23821
|
+
...signingJob,
|
|
23822
|
+
signingNonceCommitments
|
|
23823
|
+
};
|
|
23824
|
+
});
|
|
23825
|
+
const userSignedTxSigningJobs = await this.signingService.signSigningJobs(mappedSigningJobs);
|
|
23826
|
+
const response = await sparkClient.renew_leaf({
|
|
23827
|
+
leafId: node.id,
|
|
23828
|
+
signingJobs: {
|
|
23829
|
+
$case: "renewNodeTimelockSigningJob",
|
|
23830
|
+
renewNodeTimelockSigningJob: {
|
|
23831
|
+
splitNodeTxSigningJob: userSignedTxSigningJobs.get("split"),
|
|
23832
|
+
splitNodeDirectTxSigningJob: userSignedTxSigningJobs.get("directSplit"),
|
|
23833
|
+
nodeTxSigningJob: userSignedTxSigningJobs.get("node"),
|
|
23834
|
+
directNodeTxSigningJob: userSignedTxSigningJobs.get("directNode"),
|
|
23835
|
+
refundTxSigningJob: userSignedTxSigningJobs.get("cpfp"),
|
|
23836
|
+
directRefundTxSigningJob: userSignedTxSigningJobs.get("direct"),
|
|
23837
|
+
directFromCpfpRefundTxSigningJob: userSignedTxSigningJobs.get("directFromCpfp")
|
|
23838
|
+
}
|
|
23839
|
+
}
|
|
23840
|
+
});
|
|
23841
|
+
if (response.renewResult?.$case !== "renewNodeTimelockResult" || !response.renewResult?.renewNodeTimelockResult.node) {
|
|
23842
|
+
throw new ValidationError("Unexpected renew result", {
|
|
23843
|
+
field: "renewResult",
|
|
23844
|
+
value: response.renewResult
|
|
23549
23845
|
});
|
|
23550
23846
|
}
|
|
23551
|
-
|
|
23552
|
-
|
|
23553
|
-
|
|
23847
|
+
return response.renewResult.renewNodeTimelockResult.node;
|
|
23848
|
+
}
|
|
23849
|
+
async createRenewRefundSigningJobs(node, parentNode) {
|
|
23850
|
+
const signingJobs = [];
|
|
23851
|
+
const parentTx = getTxFromRawTxBytes(parentNode.nodeTx);
|
|
23852
|
+
const parentNodeOutput = getTxFromRawTxBytes(parentNode.nodeTx).getOutput(
|
|
23853
|
+
0
|
|
23554
23854
|
);
|
|
23555
|
-
|
|
23855
|
+
if (!parentNodeOutput) {
|
|
23856
|
+
throw new Error("Parent node output not found");
|
|
23857
|
+
}
|
|
23858
|
+
const unsignedParentNodeOutput = {
|
|
23556
23859
|
script: parentNodeOutput.script,
|
|
23557
23860
|
amount: parentNodeOutput.amount
|
|
23558
23861
|
};
|
|
23559
|
-
const
|
|
23560
|
-
txid: nodeInput.txid,
|
|
23561
|
-
index: nodeInput.index,
|
|
23562
|
-
sequence: useTestUnilateralSequence ? TEST_UNILATERAL_SEQUENCE : nextSequence
|
|
23563
|
-
};
|
|
23564
|
-
const newDirectInput = directNodeTx && directNodeInput ? {
|
|
23565
|
-
txid: directNodeInput.txid,
|
|
23566
|
-
index: directNodeInput.index,
|
|
23567
|
-
sequence: useTestUnilateralSequence ? TEST_UNILATERAL_DIRECT_SEQUENCE : nextDirectSequence
|
|
23568
|
-
} : void 0;
|
|
23569
|
-
const { cpfpNodeTx, directNodeTx: newDirectNodeTx } = createNodeTxs(
|
|
23570
|
-
output,
|
|
23571
|
-
newNodeInput,
|
|
23572
|
-
newDirectInput
|
|
23573
|
-
);
|
|
23574
|
-
const newCpfpNodeOutput = cpfpNodeTx.getOutput(0);
|
|
23575
|
-
if (!newCpfpNodeOutput) {
|
|
23576
|
-
throw Error("Could not get new cpfp node output");
|
|
23577
|
-
}
|
|
23578
|
-
const newDirectNodeOutput = newDirectNodeTx?.getOutput(0);
|
|
23579
|
-
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation({
|
|
23862
|
+
const keyDerivation = {
|
|
23580
23863
|
type: "leaf" /* LEAF */,
|
|
23581
23864
|
path: node.id
|
|
23582
|
-
}
|
|
23865
|
+
};
|
|
23866
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
23867
|
+
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
23868
|
+
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
23869
|
+
const { nodeTx: newNodeTx, directNodeTx: newDirectNodeTx } = createDecrementedTimelockNodeTx(parentTx, nodeTx);
|
|
23583
23870
|
signingJobs.push({
|
|
23584
23871
|
signingPublicKey,
|
|
23585
|
-
rawTx:
|
|
23872
|
+
rawTx: newNodeTx.toBytes(),
|
|
23586
23873
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
23587
23874
|
type: "node",
|
|
23588
|
-
parentTxOut:
|
|
23875
|
+
parentTxOut: unsignedParentNodeOutput,
|
|
23876
|
+
leafId: node.id,
|
|
23877
|
+
keyDerivation: {
|
|
23878
|
+
type: "leaf" /* LEAF */,
|
|
23879
|
+
path: node.id
|
|
23880
|
+
},
|
|
23881
|
+
verifyingKey: node.verifyingPublicKey
|
|
23589
23882
|
});
|
|
23590
23883
|
if (newDirectNodeTx) {
|
|
23591
23884
|
signingJobs.push({
|
|
@@ -23593,537 +23886,299 @@ var TransferService = class extends BaseTransferService {
|
|
|
23593
23886
|
rawTx: newDirectNodeTx.toBytes(),
|
|
23594
23887
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
23595
23888
|
type: "directNode",
|
|
23596
|
-
parentTxOut:
|
|
23889
|
+
parentTxOut: unsignedParentNodeOutput,
|
|
23890
|
+
leafId: node.id,
|
|
23891
|
+
keyDerivation: {
|
|
23892
|
+
type: "leaf" /* LEAF */,
|
|
23893
|
+
path: node.id
|
|
23894
|
+
},
|
|
23895
|
+
verifyingKey: node.verifyingPublicKey
|
|
23597
23896
|
});
|
|
23598
23897
|
}
|
|
23599
|
-
const
|
|
23600
|
-
|
|
23601
|
-
|
|
23602
|
-
};
|
|
23603
|
-
let newDirectRefundOutPoint;
|
|
23604
|
-
if (newDirectNodeTx) {
|
|
23605
|
-
newDirectRefundOutPoint = {
|
|
23606
|
-
txid: (0, import_utils15.hexToBytes)(getTxId(newDirectNodeTx)),
|
|
23607
|
-
index: 0
|
|
23608
|
-
};
|
|
23898
|
+
const newCpfpNodeOutput = newNodeTx.getOutput(0);
|
|
23899
|
+
if (!newCpfpNodeOutput) {
|
|
23900
|
+
throw Error("Could not get new cpfp node output");
|
|
23609
23901
|
}
|
|
23610
|
-
const
|
|
23611
|
-
|
|
23612
|
-
|
|
23613
|
-
|
|
23614
|
-
|
|
23615
|
-
|
|
23616
|
-
|
|
23617
|
-
|
|
23618
|
-
|
|
23619
|
-
|
|
23902
|
+
const newDirectNodeOutput = newDirectNodeTx?.getOutput(0);
|
|
23903
|
+
const amountSats = refundTx.getOutput(0).amount;
|
|
23904
|
+
if (amountSats === void 0) {
|
|
23905
|
+
throw new Error("Amount not found in extendTimelock");
|
|
23906
|
+
}
|
|
23907
|
+
const directAmountSats = newDirectNodeOutput?.amount;
|
|
23908
|
+
if (directAmountSats === void 0) {
|
|
23909
|
+
throw new Error("Amount not found in extendTimelock");
|
|
23910
|
+
}
|
|
23911
|
+
const {
|
|
23912
|
+
cpfpRefundTx: newRefundTx,
|
|
23913
|
+
directRefundTx: newDirectRefundTx,
|
|
23914
|
+
directFromCpfpRefundTx: newDirectFromCpfpRefundTx
|
|
23915
|
+
} = createInitialTimelockRefundTxs({
|
|
23916
|
+
nodeTx: newNodeTx,
|
|
23917
|
+
directNodeTx: newDirectNodeTx,
|
|
23918
|
+
receivingPubkey: signingPublicKey,
|
|
23620
23919
|
network: this.config.getNetwork()
|
|
23621
23920
|
});
|
|
23622
23921
|
signingJobs.push({
|
|
23623
23922
|
signingPublicKey,
|
|
23624
|
-
rawTx:
|
|
23923
|
+
rawTx: newRefundTx.toBytes(),
|
|
23625
23924
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
23626
23925
|
type: "cpfp",
|
|
23627
|
-
parentTxOut: newCpfpNodeOutput
|
|
23926
|
+
parentTxOut: newCpfpNodeOutput,
|
|
23927
|
+
leafId: node.id,
|
|
23928
|
+
keyDerivation,
|
|
23929
|
+
verifyingKey: node.verifyingPublicKey
|
|
23628
23930
|
});
|
|
23629
|
-
if (
|
|
23931
|
+
if (newDirectRefundTx && newDirectNodeOutput) {
|
|
23630
23932
|
signingJobs.push({
|
|
23631
23933
|
signingPublicKey,
|
|
23632
|
-
rawTx:
|
|
23934
|
+
rawTx: newDirectRefundTx.toBytes(),
|
|
23633
23935
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
23634
23936
|
type: "direct",
|
|
23635
|
-
parentTxOut: newDirectNodeOutput
|
|
23937
|
+
parentTxOut: newDirectNodeOutput,
|
|
23938
|
+
leafId: node.id,
|
|
23939
|
+
keyDerivation,
|
|
23940
|
+
verifyingKey: node.verifyingPublicKey
|
|
23636
23941
|
});
|
|
23637
23942
|
}
|
|
23638
|
-
if (
|
|
23943
|
+
if (newDirectFromCpfpRefundTx && newDirectNodeOutput) {
|
|
23639
23944
|
signingJobs.push({
|
|
23640
23945
|
signingPublicKey,
|
|
23641
|
-
rawTx:
|
|
23946
|
+
rawTx: newDirectFromCpfpRefundTx.toBytes(),
|
|
23642
23947
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
23643
23948
|
type: "directFromCpfp",
|
|
23644
|
-
parentTxOut: newCpfpNodeOutput
|
|
23949
|
+
parentTxOut: newCpfpNodeOutput,
|
|
23950
|
+
leafId: node.id,
|
|
23951
|
+
keyDerivation,
|
|
23952
|
+
verifyingKey: node.verifyingPublicKey
|
|
23645
23953
|
});
|
|
23646
23954
|
}
|
|
23647
|
-
|
|
23648
|
-
this.config.getCoordinatorAddress()
|
|
23649
|
-
);
|
|
23650
|
-
const response = await sparkClient.refresh_timelock_v2({
|
|
23651
|
-
leafId: node.id,
|
|
23652
|
-
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
23653
|
-
signingJobs: signingJobs.map(getSigningJobProto)
|
|
23654
|
-
});
|
|
23655
|
-
if (signingJobs.length !== response.signingResults.length) {
|
|
23656
|
-
throw Error(
|
|
23657
|
-
`number of signing jobs and signing results do not match: ${signingJobs.length} !== ${response.signingResults.length}`
|
|
23658
|
-
);
|
|
23659
|
-
}
|
|
23660
|
-
let nodeSignatures = [];
|
|
23661
|
-
let leafCpfpSignature;
|
|
23662
|
-
let leafDirectSignature;
|
|
23663
|
-
let cpfpRefundSignature;
|
|
23664
|
-
let directRefundSignature;
|
|
23665
|
-
let directFromCpfpRefundSignature;
|
|
23666
|
-
for (const [i, signingResult] of response.signingResults.entries()) {
|
|
23667
|
-
const signingJob = signingJobs[i];
|
|
23668
|
-
if (!signingJob || !signingResult) {
|
|
23669
|
-
throw Error("Signing job does not exist");
|
|
23670
|
-
}
|
|
23671
|
-
const rawTx = getTxFromRawTxBytes(signingJob.rawTx);
|
|
23672
|
-
const txOut = signingJob.parentTxOut;
|
|
23673
|
-
if (!txOut) {
|
|
23674
|
-
throw Error("Could not get tx out");
|
|
23675
|
-
}
|
|
23676
|
-
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
23677
|
-
const userSignature = await this.config.signer.signFrost({
|
|
23678
|
-
message: rawTxSighash,
|
|
23679
|
-
keyDerivation: {
|
|
23680
|
-
type: "leaf" /* LEAF */,
|
|
23681
|
-
path: node.id
|
|
23682
|
-
},
|
|
23683
|
-
publicKey: signingJob.signingPublicKey,
|
|
23684
|
-
verifyingKey: signingResult.verifyingKey,
|
|
23685
|
-
selfCommitment: signingJob.signingNonceCommitment,
|
|
23686
|
-
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
23687
|
-
adaptorPubKey: new Uint8Array()
|
|
23688
|
-
});
|
|
23689
|
-
const signature = await this.config.signer.aggregateFrost({
|
|
23690
|
-
message: rawTxSighash,
|
|
23691
|
-
statechainSignatures: signingResult.signingResult?.signatureShares,
|
|
23692
|
-
statechainPublicKeys: signingResult.signingResult?.publicKeys,
|
|
23693
|
-
verifyingKey: signingResult.verifyingKey,
|
|
23694
|
-
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
23695
|
-
selfCommitment: signingJob.signingNonceCommitment,
|
|
23696
|
-
publicKey: signingJob.signingPublicKey,
|
|
23697
|
-
selfSignature: userSignature,
|
|
23698
|
-
adaptorPubKey: new Uint8Array()
|
|
23699
|
-
});
|
|
23700
|
-
if (signingJob.type === "node") {
|
|
23701
|
-
leafCpfpSignature = signature;
|
|
23702
|
-
} else if (signingJob.type === "directNode") {
|
|
23703
|
-
leafDirectSignature = signature;
|
|
23704
|
-
} else if (signingJob.type === "cpfp") {
|
|
23705
|
-
cpfpRefundSignature = signature;
|
|
23706
|
-
} else if (signingJob.type === "direct") {
|
|
23707
|
-
directRefundSignature = signature;
|
|
23708
|
-
} else if (signingJob.type === "directFromCpfp") {
|
|
23709
|
-
directFromCpfpRefundSignature = signature;
|
|
23710
|
-
}
|
|
23711
|
-
}
|
|
23712
|
-
nodeSignatures.push({
|
|
23713
|
-
nodeId: node.id,
|
|
23714
|
-
nodeTxSignature: leafCpfpSignature || new Uint8Array(),
|
|
23715
|
-
directNodeTxSignature: leafDirectSignature || new Uint8Array(),
|
|
23716
|
-
refundTxSignature: cpfpRefundSignature || new Uint8Array(),
|
|
23717
|
-
directRefundTxSignature: directRefundSignature || new Uint8Array(),
|
|
23718
|
-
directFromCpfpRefundTxSignature: directFromCpfpRefundSignature || new Uint8Array()
|
|
23719
|
-
});
|
|
23720
|
-
const result = await sparkClient.finalize_node_signatures_v2({
|
|
23721
|
-
intent: 3 /* REFRESH */,
|
|
23722
|
-
nodeSignatures
|
|
23723
|
-
});
|
|
23724
|
-
return result;
|
|
23725
|
-
}
|
|
23726
|
-
async refreshTimelockNodes(node, parentNode) {
|
|
23727
|
-
return await this.refreshTimelockNodesInternal(node, parentNode);
|
|
23955
|
+
return signingJobs;
|
|
23728
23956
|
}
|
|
23729
|
-
async
|
|
23730
|
-
const
|
|
23731
|
-
const
|
|
23732
|
-
const
|
|
23733
|
-
|
|
23734
|
-
txid: (0, import_utils15.hexToBytes)(getTxId(nodeTx)),
|
|
23735
|
-
index: 0
|
|
23736
|
-
};
|
|
23737
|
-
const {
|
|
23738
|
-
nextSequence: newNodeSequence,
|
|
23739
|
-
nextDirectSequence: newDirectNodeSequence
|
|
23740
|
-
} = getNextTransactionSequence(refundSequence);
|
|
23741
|
-
const newNodeTx = new import_btc_signer2.Transaction({
|
|
23742
|
-
version: 3,
|
|
23743
|
-
allowUnknownOutputs: true
|
|
23744
|
-
});
|
|
23745
|
-
newNodeTx.addInput({ ...newNodeOutPoint, sequence: newNodeSequence });
|
|
23746
|
-
const originalOutput = nodeTx.getOutput(0);
|
|
23747
|
-
if (!originalOutput) {
|
|
23748
|
-
throw Error("Could not get original node output");
|
|
23749
|
-
}
|
|
23750
|
-
newNodeTx.addOutput({
|
|
23751
|
-
script: originalOutput.script,
|
|
23752
|
-
amount: originalOutput.amount
|
|
23753
|
-
});
|
|
23754
|
-
newNodeTx.addOutput(getEphemeralAnchorOutput());
|
|
23755
|
-
let newDirectNodeTx;
|
|
23756
|
-
if (node.directTx.length > 0) {
|
|
23757
|
-
newDirectNodeTx = new import_btc_signer2.Transaction({
|
|
23758
|
-
version: 3,
|
|
23759
|
-
allowUnknownOutputs: true
|
|
23760
|
-
});
|
|
23761
|
-
newDirectNodeTx.addInput({
|
|
23762
|
-
...newNodeOutPoint,
|
|
23763
|
-
sequence: newDirectNodeSequence
|
|
23764
|
-
});
|
|
23765
|
-
newDirectNodeTx.addOutput({
|
|
23766
|
-
script: originalOutput.script,
|
|
23767
|
-
amount: maybeApplyFee(originalOutput.amount)
|
|
23768
|
-
});
|
|
23769
|
-
}
|
|
23770
|
-
const newCpfpRefundOutPoint = {
|
|
23771
|
-
txid: (0, import_utils15.hexToBytes)(getTxId(newNodeTx)),
|
|
23772
|
-
index: 0
|
|
23773
|
-
};
|
|
23774
|
-
let newDirectRefundOutPoint;
|
|
23775
|
-
if (newDirectNodeTx) {
|
|
23776
|
-
newDirectRefundOutPoint = {
|
|
23777
|
-
txid: (0, import_utils15.hexToBytes)(getTxId(newDirectNodeTx)),
|
|
23778
|
-
index: 0
|
|
23779
|
-
};
|
|
23780
|
-
}
|
|
23781
|
-
const amountSats = refundTx.getOutput(0).amount;
|
|
23782
|
-
if (amountSats === void 0) {
|
|
23783
|
-
throw new Error("Amount not found in extendTimelock");
|
|
23784
|
-
}
|
|
23785
|
-
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation({
|
|
23786
|
-
type: "leaf" /* LEAF */,
|
|
23787
|
-
path: node.id
|
|
23788
|
-
});
|
|
23789
|
-
const {
|
|
23790
|
-
cpfpRefundTx: newCpfpRefundTx,
|
|
23791
|
-
directRefundTx: newDirectRefundTx,
|
|
23792
|
-
directFromCpfpRefundTx: newDirectFromCpfpRefundTx
|
|
23793
|
-
} = createRefundTxs({
|
|
23794
|
-
sequence: INITIAL_SEQUENCE,
|
|
23795
|
-
directSequence: INITIAL_DIRECT_SEQUENCE,
|
|
23796
|
-
input: newCpfpRefundOutPoint,
|
|
23797
|
-
directInput: newDirectRefundOutPoint,
|
|
23798
|
-
amountSats,
|
|
23799
|
-
receivingPubkey: signingPublicKey,
|
|
23800
|
-
network: this.config.getNetwork()
|
|
23801
|
-
});
|
|
23802
|
-
if (!newCpfpRefundTx) {
|
|
23803
|
-
throw new ValidationError(
|
|
23804
|
-
"Failed to create refund transactions in extendTimelock"
|
|
23805
|
-
);
|
|
23806
|
-
}
|
|
23807
|
-
const nodeSighash = getSigHashFromTx(newNodeTx, 0, nodeTx.getOutput(0));
|
|
23808
|
-
const directNodeSighash = newDirectNodeTx ? getSigHashFromTx(newDirectNodeTx, 0, nodeTx.getOutput(0)) : void 0;
|
|
23809
|
-
const cpfpRefundSighash = getSigHashFromTx(
|
|
23810
|
-
newCpfpRefundTx,
|
|
23811
|
-
0,
|
|
23812
|
-
newNodeTx.getOutput(0)
|
|
23957
|
+
async createRenewNodeSigningJobs(node, parentNode) {
|
|
23958
|
+
const signingJobs = [];
|
|
23959
|
+
const parentTx = getTxFromRawTxBytes(parentNode.nodeTx);
|
|
23960
|
+
const parentNodeOutput = getTxFromRawTxBytes(parentNode.nodeTx).getOutput(
|
|
23961
|
+
0
|
|
23813
23962
|
);
|
|
23814
|
-
const
|
|
23815
|
-
|
|
23816
|
-
|
|
23817
|
-
signingPublicKey,
|
|
23818
|
-
rawTx: newNodeTx.toBytes(),
|
|
23819
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
23820
|
-
};
|
|
23821
|
-
const newDirectNodeSigningJob = newDirectNodeTx ? {
|
|
23822
|
-
signingPublicKey,
|
|
23823
|
-
rawTx: newDirectNodeTx.toBytes(),
|
|
23824
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
23825
|
-
} : void 0;
|
|
23826
|
-
const newCpfpRefundSigningJob = {
|
|
23827
|
-
signingPublicKey,
|
|
23828
|
-
rawTx: newCpfpRefundTx.toBytes(),
|
|
23829
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
23963
|
+
const unsignedParentNodeOutput = {
|
|
23964
|
+
script: parentNodeOutput.script,
|
|
23965
|
+
amount: parentNodeOutput.amount
|
|
23830
23966
|
};
|
|
23831
|
-
const newDirectRefundSigningJob = newDirectRefundTx ? {
|
|
23832
|
-
signingPublicKey,
|
|
23833
|
-
rawTx: newDirectRefundTx.toBytes(),
|
|
23834
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
23835
|
-
} : void 0;
|
|
23836
|
-
const newDirectFromCpfpRefundSigningJob = newDirectFromCpfpRefundTx ? {
|
|
23837
|
-
signingPublicKey,
|
|
23838
|
-
rawTx: newDirectFromCpfpRefundTx.toBytes(),
|
|
23839
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
23840
|
-
} : void 0;
|
|
23841
|
-
const sparkClient = await this.connectionManager.createSparkClient(
|
|
23842
|
-
this.config.getCoordinatorAddress()
|
|
23843
|
-
);
|
|
23844
|
-
const response = await sparkClient.extend_leaf_v2({
|
|
23845
|
-
leafId: node.id,
|
|
23846
|
-
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
23847
|
-
nodeTxSigningJob: getSigningJobProto(newNodeSigningJob),
|
|
23848
|
-
directNodeTxSigningJob: newDirectNodeSigningJob ? getSigningJobProto(newDirectNodeSigningJob) : void 0,
|
|
23849
|
-
refundTxSigningJob: getSigningJobProto(newCpfpRefundSigningJob),
|
|
23850
|
-
directRefundTxSigningJob: newDirectRefundSigningJob ? getSigningJobProto(newDirectRefundSigningJob) : void 0,
|
|
23851
|
-
directFromCpfpRefundTxSigningJob: newDirectFromCpfpRefundSigningJob ? getSigningJobProto(newDirectFromCpfpRefundSigningJob) : void 0
|
|
23852
|
-
});
|
|
23853
|
-
if (!response.nodeTxSigningResult || !response.refundTxSigningResult) {
|
|
23854
|
-
throw new Error("Signing result does not exist");
|
|
23855
|
-
}
|
|
23856
23967
|
const keyDerivation = {
|
|
23857
23968
|
type: "leaf" /* LEAF */,
|
|
23858
23969
|
path: node.id
|
|
23859
23970
|
};
|
|
23860
|
-
const
|
|
23861
|
-
|
|
23971
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
23972
|
+
const { nodeTx: splitNodeTx, directNodeTx: splitNodeDirectTx } = createZeroTimelockNodeTx(parentTx);
|
|
23973
|
+
signingJobs.push({
|
|
23974
|
+
signingPublicKey,
|
|
23975
|
+
rawTx: splitNodeTx.toBytes(),
|
|
23976
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
23977
|
+
type: "split",
|
|
23978
|
+
parentTxOut: unsignedParentNodeOutput,
|
|
23979
|
+
leafId: node.id,
|
|
23862
23980
|
keyDerivation,
|
|
23863
|
-
|
|
23864
|
-
verifyingKey: response.nodeTxSigningResult.verifyingKey,
|
|
23865
|
-
selfCommitment: newNodeSigningJob.signingNonceCommitment,
|
|
23866
|
-
statechainCommitments: response.nodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
23867
|
-
adaptorPubKey: new Uint8Array()
|
|
23981
|
+
verifyingKey: node.verifyingPublicKey
|
|
23868
23982
|
});
|
|
23869
|
-
|
|
23870
|
-
|
|
23871
|
-
|
|
23872
|
-
|
|
23873
|
-
|
|
23874
|
-
|
|
23875
|
-
|
|
23876
|
-
|
|
23877
|
-
selfSignature: nodeUserSig,
|
|
23878
|
-
adaptorPubKey: new Uint8Array()
|
|
23879
|
-
});
|
|
23880
|
-
let directNodeSig;
|
|
23881
|
-
if (directNodeSighash && newDirectNodeSigningJob && response.directNodeTxSigningResult) {
|
|
23882
|
-
const directNodeUserSig = await this.config.signer.signFrost({
|
|
23883
|
-
message: directNodeSighash,
|
|
23983
|
+
if (splitNodeDirectTx) {
|
|
23984
|
+
signingJobs.push({
|
|
23985
|
+
signingPublicKey,
|
|
23986
|
+
rawTx: splitNodeDirectTx.toBytes(),
|
|
23987
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
23988
|
+
type: "directSplit",
|
|
23989
|
+
parentTxOut: unsignedParentNodeOutput,
|
|
23990
|
+
leafId: node.id,
|
|
23884
23991
|
keyDerivation,
|
|
23885
|
-
|
|
23886
|
-
verifyingKey: response.directNodeTxSigningResult.verifyingKey,
|
|
23887
|
-
selfCommitment: newDirectNodeSigningJob.signingNonceCommitment,
|
|
23888
|
-
statechainCommitments: response.directNodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
23889
|
-
adaptorPubKey: new Uint8Array()
|
|
23890
|
-
});
|
|
23891
|
-
directNodeSig = await this.config.signer.aggregateFrost({
|
|
23892
|
-
message: directNodeSighash,
|
|
23893
|
-
statechainSignatures: response.directNodeTxSigningResult.signingResult?.signatureShares,
|
|
23894
|
-
statechainPublicKeys: response.directNodeTxSigningResult.signingResult?.publicKeys,
|
|
23895
|
-
verifyingKey: response.directNodeTxSigningResult.verifyingKey,
|
|
23896
|
-
statechainCommitments: response.directNodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
23897
|
-
selfCommitment: newDirectNodeSigningJob.signingNonceCommitment,
|
|
23898
|
-
publicKey: signingPublicKey,
|
|
23899
|
-
selfSignature: directNodeUserSig,
|
|
23900
|
-
adaptorPubKey: new Uint8Array()
|
|
23992
|
+
verifyingKey: node.verifyingPublicKey
|
|
23901
23993
|
});
|
|
23902
23994
|
}
|
|
23903
|
-
const
|
|
23904
|
-
|
|
23995
|
+
const splitNodeOutput = splitNodeTx.getOutput(0);
|
|
23996
|
+
const splitNodeDirectOutput = splitNodeDirectTx.getOutput(0);
|
|
23997
|
+
if (!splitNodeDirectOutput.amount || !splitNodeDirectOutput.script) {
|
|
23998
|
+
throw new Error("Could not get split node output");
|
|
23999
|
+
}
|
|
24000
|
+
const unsignedSplitNodeOutput = {
|
|
24001
|
+
script: splitNodeDirectOutput.script,
|
|
24002
|
+
amount: splitNodeDirectOutput.amount
|
|
24003
|
+
};
|
|
24004
|
+
const { nodeTx: newNodeTx, directNodeTx: newDirectNodeTx } = createInitialTimelockNodeTx(splitNodeTx);
|
|
24005
|
+
signingJobs.push({
|
|
24006
|
+
signingPublicKey,
|
|
24007
|
+
rawTx: newNodeTx.toBytes(),
|
|
24008
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24009
|
+
type: "node",
|
|
24010
|
+
parentTxOut: splitNodeOutput,
|
|
24011
|
+
leafId: node.id,
|
|
23905
24012
|
keyDerivation,
|
|
23906
|
-
|
|
23907
|
-
verifyingKey: response.refundTxSigningResult.verifyingKey,
|
|
23908
|
-
selfCommitment: newCpfpRefundSigningJob.signingNonceCommitment,
|
|
23909
|
-
statechainCommitments: response.refundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
23910
|
-
adaptorPubKey: new Uint8Array()
|
|
24013
|
+
verifyingKey: node.verifyingPublicKey
|
|
23911
24014
|
});
|
|
23912
|
-
|
|
23913
|
-
|
|
23914
|
-
|
|
23915
|
-
|
|
23916
|
-
|
|
23917
|
-
|
|
23918
|
-
|
|
23919
|
-
|
|
23920
|
-
selfSignature: cpfpRefundUserSig,
|
|
23921
|
-
adaptorPubKey: new Uint8Array()
|
|
23922
|
-
});
|
|
23923
|
-
let directRefundSig;
|
|
23924
|
-
if (directRefundSighash && newDirectRefundSigningJob && response.directRefundTxSigningResult) {
|
|
23925
|
-
const directRefundUserSig = await this.config.signer.signFrost({
|
|
23926
|
-
message: directRefundSighash,
|
|
23927
|
-
keyDerivation,
|
|
23928
|
-
publicKey: signingPublicKey,
|
|
23929
|
-
verifyingKey: response.directRefundTxSigningResult.verifyingKey,
|
|
23930
|
-
selfCommitment: newDirectRefundSigningJob.signingNonceCommitment,
|
|
23931
|
-
statechainCommitments: response.directRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
23932
|
-
adaptorPubKey: new Uint8Array()
|
|
23933
|
-
});
|
|
23934
|
-
directRefundSig = await this.config.signer.aggregateFrost({
|
|
23935
|
-
message: directRefundSighash,
|
|
23936
|
-
statechainSignatures: response.directRefundTxSigningResult.signingResult?.signatureShares,
|
|
23937
|
-
statechainPublicKeys: response.directRefundTxSigningResult.signingResult?.publicKeys,
|
|
23938
|
-
verifyingKey: response.directRefundTxSigningResult.verifyingKey,
|
|
23939
|
-
statechainCommitments: response.directRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
23940
|
-
selfCommitment: newDirectRefundSigningJob.signingNonceCommitment,
|
|
23941
|
-
publicKey: signingPublicKey,
|
|
23942
|
-
selfSignature: directRefundUserSig,
|
|
23943
|
-
adaptorPubKey: new Uint8Array()
|
|
23944
|
-
});
|
|
23945
|
-
}
|
|
23946
|
-
let directFromCpfpRefundSig;
|
|
23947
|
-
if (directFromCpfpRefundSighash && newDirectFromCpfpRefundSigningJob && response.directFromCpfpRefundTxSigningResult) {
|
|
23948
|
-
const directFromCpfpRefundUserSig = await this.config.signer.signFrost({
|
|
23949
|
-
message: directFromCpfpRefundSighash,
|
|
24015
|
+
if (newDirectNodeTx) {
|
|
24016
|
+
signingJobs.push({
|
|
24017
|
+
signingPublicKey,
|
|
24018
|
+
rawTx: newDirectNodeTx.toBytes(),
|
|
24019
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24020
|
+
type: "directNode",
|
|
24021
|
+
parentTxOut: splitNodeOutput,
|
|
24022
|
+
leafId: node.id,
|
|
23950
24023
|
keyDerivation,
|
|
23951
|
-
|
|
23952
|
-
verifyingKey: response.directFromCpfpRefundTxSigningResult.verifyingKey,
|
|
23953
|
-
selfCommitment: newDirectFromCpfpRefundSigningJob.signingNonceCommitment,
|
|
23954
|
-
statechainCommitments: response.directFromCpfpRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
23955
|
-
adaptorPubKey: new Uint8Array()
|
|
23956
|
-
});
|
|
23957
|
-
directFromCpfpRefundSig = await this.config.signer.aggregateFrost({
|
|
23958
|
-
message: directFromCpfpRefundSighash,
|
|
23959
|
-
statechainSignatures: response.directFromCpfpRefundTxSigningResult.signingResult?.signatureShares,
|
|
23960
|
-
statechainPublicKeys: response.directFromCpfpRefundTxSigningResult.signingResult?.publicKeys,
|
|
23961
|
-
verifyingKey: response.directFromCpfpRefundTxSigningResult.verifyingKey,
|
|
23962
|
-
statechainCommitments: response.directFromCpfpRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
23963
|
-
selfCommitment: newDirectFromCpfpRefundSigningJob.signingNonceCommitment,
|
|
23964
|
-
publicKey: signingPublicKey,
|
|
23965
|
-
selfSignature: directFromCpfpRefundUserSig,
|
|
23966
|
-
adaptorPubKey: new Uint8Array()
|
|
24024
|
+
verifyingKey: node.verifyingPublicKey
|
|
23967
24025
|
});
|
|
23968
24026
|
}
|
|
23969
|
-
|
|
23970
|
-
|
|
23971
|
-
|
|
23972
|
-
{
|
|
23973
|
-
nodeId: response.leafId,
|
|
23974
|
-
nodeTxSignature: nodeSig,
|
|
23975
|
-
directNodeTxSignature: directNodeSig,
|
|
23976
|
-
refundTxSignature: cpfpRefundSig,
|
|
23977
|
-
directRefundTxSignature: directRefundSig,
|
|
23978
|
-
directFromCpfpRefundTxSignature: directFromCpfpRefundSig
|
|
23979
|
-
}
|
|
23980
|
-
]
|
|
23981
|
-
});
|
|
23982
|
-
}
|
|
23983
|
-
async testonly_expireTimeLockNodeTx(node, parentNode) {
|
|
23984
|
-
return await this.refreshTimelockNodesInternal(node, parentNode, true);
|
|
23985
|
-
}
|
|
23986
|
-
async testonly_expireTimeLockRefundtx(node) {
|
|
23987
|
-
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
23988
|
-
const directNodeTx = node.directTx.length > 0 ? getTxFromRawTxBytes(node.directTx) : void 0;
|
|
23989
|
-
const cpfpRefundTx = getTxFromRawTxBytes(node.refundTx);
|
|
23990
|
-
const currSequence = cpfpRefundTx.getInput(0).sequence || 0;
|
|
23991
|
-
const currTimelock = getCurrentTimelock(currSequence);
|
|
23992
|
-
if (currTimelock <= 100) {
|
|
23993
|
-
throw new ValidationError("Cannot expire timelock below 100", {
|
|
23994
|
-
field: "currTimelock",
|
|
23995
|
-
value: currTimelock,
|
|
23996
|
-
expected: "Timelock greater than 100"
|
|
23997
|
-
});
|
|
23998
|
-
}
|
|
23999
|
-
const nextSequence = TEST_UNILATERAL_SEQUENCE;
|
|
24000
|
-
const nextDirectSequence = TEST_UNILATERAL_SEQUENCE + DIRECT_TIMELOCK_OFFSET;
|
|
24001
|
-
const nodeOutput = nodeTx.getOutput(0);
|
|
24002
|
-
if (!nodeOutput) {
|
|
24003
|
-
throw Error("Could not get node output");
|
|
24004
|
-
}
|
|
24005
|
-
const keyDerivation = {
|
|
24006
|
-
type: "leaf" /* LEAF */,
|
|
24007
|
-
path: node.id
|
|
24008
|
-
};
|
|
24009
|
-
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
24010
|
-
const cpfpRefundOutPoint = {
|
|
24011
|
-
txid: (0, import_utils15.hexToBytes)(getTxId(nodeTx)),
|
|
24012
|
-
index: 0
|
|
24013
|
-
};
|
|
24014
|
-
let directRefundOutPoint;
|
|
24015
|
-
if (directNodeTx) {
|
|
24016
|
-
directRefundOutPoint = {
|
|
24017
|
-
txid: (0, import_utils15.hexToBytes)(getTxId(directNodeTx)),
|
|
24018
|
-
index: 0
|
|
24019
|
-
};
|
|
24027
|
+
const newCpfpNodeOutput = newNodeTx.getOutput(0);
|
|
24028
|
+
if (!newCpfpNodeOutput) {
|
|
24029
|
+
throw Error("Could not get new cpfp node output");
|
|
24020
24030
|
}
|
|
24031
|
+
const newDirectNodeOutput = newDirectNodeTx?.getOutput(0);
|
|
24021
24032
|
const {
|
|
24022
|
-
cpfpRefundTx:
|
|
24033
|
+
cpfpRefundTx: newRefundTx,
|
|
24023
24034
|
directRefundTx: newDirectRefundTx,
|
|
24024
24035
|
directFromCpfpRefundTx: newDirectFromCpfpRefundTx
|
|
24025
|
-
} =
|
|
24026
|
-
|
|
24027
|
-
|
|
24028
|
-
input: cpfpRefundOutPoint,
|
|
24029
|
-
directInput: directRefundOutPoint,
|
|
24030
|
-
amountSats: nodeOutput.amount,
|
|
24036
|
+
} = createInitialTimelockRefundTxs({
|
|
24037
|
+
nodeTx: newNodeTx,
|
|
24038
|
+
directNodeTx: newDirectNodeTx,
|
|
24031
24039
|
receivingPubkey: signingPublicKey,
|
|
24032
24040
|
network: this.config.getNetwork()
|
|
24033
24041
|
});
|
|
24034
|
-
const signingJobs = [];
|
|
24035
24042
|
signingJobs.push({
|
|
24036
24043
|
signingPublicKey,
|
|
24037
|
-
rawTx:
|
|
24044
|
+
rawTx: newRefundTx.toBytes(),
|
|
24038
24045
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24039
24046
|
type: "cpfp",
|
|
24040
|
-
parentTxOut:
|
|
24047
|
+
parentTxOut: newCpfpNodeOutput,
|
|
24048
|
+
leafId: node.id,
|
|
24049
|
+
keyDerivation,
|
|
24050
|
+
verifyingKey: node.verifyingPublicKey
|
|
24041
24051
|
});
|
|
24042
|
-
|
|
24043
|
-
if (newDirectRefundTx && directNodeTxOut) {
|
|
24052
|
+
if (newDirectRefundTx && newDirectNodeOutput) {
|
|
24044
24053
|
signingJobs.push({
|
|
24045
24054
|
signingPublicKey,
|
|
24046
24055
|
rawTx: newDirectRefundTx.toBytes(),
|
|
24047
24056
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24048
24057
|
type: "direct",
|
|
24049
|
-
parentTxOut:
|
|
24058
|
+
parentTxOut: newDirectNodeOutput,
|
|
24059
|
+
leafId: node.id,
|
|
24060
|
+
keyDerivation,
|
|
24061
|
+
verifyingKey: node.verifyingPublicKey
|
|
24050
24062
|
});
|
|
24051
24063
|
}
|
|
24052
|
-
if (newDirectFromCpfpRefundTx) {
|
|
24064
|
+
if (newDirectFromCpfpRefundTx && newDirectNodeOutput) {
|
|
24053
24065
|
signingJobs.push({
|
|
24054
24066
|
signingPublicKey,
|
|
24055
24067
|
rawTx: newDirectFromCpfpRefundTx.toBytes(),
|
|
24056
24068
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24057
24069
|
type: "directFromCpfp",
|
|
24058
|
-
parentTxOut:
|
|
24070
|
+
parentTxOut: newCpfpNodeOutput,
|
|
24071
|
+
leafId: node.id,
|
|
24072
|
+
keyDerivation,
|
|
24073
|
+
verifyingKey: node.verifyingPublicKey
|
|
24059
24074
|
});
|
|
24060
24075
|
}
|
|
24076
|
+
return signingJobs;
|
|
24077
|
+
}
|
|
24078
|
+
async renewZeroTimelockNodeTxn(node) {
|
|
24061
24079
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
24062
24080
|
this.config.getCoordinatorAddress()
|
|
24063
24081
|
);
|
|
24064
|
-
const
|
|
24065
|
-
|
|
24066
|
-
|
|
24067
|
-
|
|
24082
|
+
const signingJobs = await this.createRenewZeroTimelockNodeSigningJobs(node);
|
|
24083
|
+
const statechainCommitments = await sparkClient.get_signing_commitments({
|
|
24084
|
+
nodeIds: [node.id],
|
|
24085
|
+
count: signingJobs.length
|
|
24068
24086
|
});
|
|
24069
|
-
|
|
24070
|
-
|
|
24071
|
-
|
|
24072
|
-
|
|
24073
|
-
|
|
24074
|
-
|
|
24075
|
-
|
|
24076
|
-
let directFromCpfpRefundSignature;
|
|
24077
|
-
for (const [i, signingJob] of signingJobs.entries()) {
|
|
24078
|
-
const signingResult = response.signingResults[i];
|
|
24079
|
-
if (!signingResult) {
|
|
24080
|
-
throw Error("Signing result does not exist");
|
|
24087
|
+
const mappedSigningJobs = signingJobs.map((signingJob, index) => {
|
|
24088
|
+
const signingNonceCommitments = statechainCommitments.signingCommitments[index]?.signingNonceCommitments;
|
|
24089
|
+
if (!signingNonceCommitments) {
|
|
24090
|
+
throw new ValidationError("Signing nonce commitments not found", {
|
|
24091
|
+
field: "signingNonceCommitments",
|
|
24092
|
+
value: signingNonceCommitments
|
|
24093
|
+
});
|
|
24081
24094
|
}
|
|
24082
|
-
|
|
24083
|
-
|
|
24084
|
-
|
|
24085
|
-
|
|
24086
|
-
|
|
24087
|
-
|
|
24088
|
-
|
|
24089
|
-
|
|
24090
|
-
|
|
24091
|
-
|
|
24092
|
-
|
|
24093
|
-
|
|
24094
|
-
|
|
24095
|
-
|
|
24096
|
-
|
|
24097
|
-
|
|
24098
|
-
|
|
24099
|
-
|
|
24100
|
-
selfCommitment: signingJob.signingNonceCommitment,
|
|
24101
|
-
publicKey: signingPublicKey,
|
|
24102
|
-
selfSignature: userSignature,
|
|
24103
|
-
adaptorPubKey: new Uint8Array()
|
|
24104
|
-
});
|
|
24105
|
-
if (signingJob.type === "cpfp") {
|
|
24106
|
-
cpfpRefundSignature = signature;
|
|
24107
|
-
} else if (signingJob.type === "direct") {
|
|
24108
|
-
directRefundSignature = signature;
|
|
24109
|
-
} else if (signingJob.type === "directFromCpfp") {
|
|
24110
|
-
directFromCpfpRefundSignature = signature;
|
|
24095
|
+
return {
|
|
24096
|
+
...signingJob,
|
|
24097
|
+
signingNonceCommitments
|
|
24098
|
+
};
|
|
24099
|
+
});
|
|
24100
|
+
const userSignedTxSigningJobs = await this.signingService.signSigningJobs(mappedSigningJobs);
|
|
24101
|
+
const renewZeroTimelockNodeSigningJob = {
|
|
24102
|
+
nodeTxSigningJob: userSignedTxSigningJobs.get("node"),
|
|
24103
|
+
refundTxSigningJob: userSignedTxSigningJobs.get("cpfp"),
|
|
24104
|
+
directNodeTxSigningJob: userSignedTxSigningJobs.get("directNode"),
|
|
24105
|
+
directRefundTxSigningJob: void 0,
|
|
24106
|
+
directFromCpfpRefundTxSigningJob: userSignedTxSigningJobs.get("directFromCpfp")
|
|
24107
|
+
};
|
|
24108
|
+
const response = await sparkClient.renew_leaf({
|
|
24109
|
+
leafId: node.id,
|
|
24110
|
+
signingJobs: {
|
|
24111
|
+
$case: "renewNodeZeroTimelockSigningJob",
|
|
24112
|
+
renewNodeZeroTimelockSigningJob: renewZeroTimelockNodeSigningJob
|
|
24111
24113
|
}
|
|
24114
|
+
});
|
|
24115
|
+
if (response.renewResult?.$case !== "renewNodeZeroTimelockResult" || !response.renewResult?.renewNodeZeroTimelockResult.node) {
|
|
24116
|
+
throw new ValidationError("Unexpected renew result", {
|
|
24117
|
+
field: "renewResult",
|
|
24118
|
+
value: response.renewResult
|
|
24119
|
+
});
|
|
24112
24120
|
}
|
|
24113
|
-
|
|
24114
|
-
|
|
24115
|
-
|
|
24116
|
-
|
|
24117
|
-
|
|
24118
|
-
|
|
24119
|
-
|
|
24120
|
-
|
|
24121
|
-
|
|
24122
|
-
|
|
24123
|
-
|
|
24124
|
-
|
|
24121
|
+
return response.renewResult.renewNodeZeroTimelockResult.node;
|
|
24122
|
+
}
|
|
24123
|
+
async createRenewZeroTimelockNodeSigningJobs(node) {
|
|
24124
|
+
const signingJobs = [];
|
|
24125
|
+
const keyDerivation = {
|
|
24126
|
+
type: "leaf" /* LEAF */,
|
|
24127
|
+
path: node.id
|
|
24128
|
+
};
|
|
24129
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
24130
|
+
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
24131
|
+
const { nodeTx: newNodeTx, directNodeTx: newDirectNodeTx } = createZeroTimelockNodeTx(nodeTx);
|
|
24132
|
+
signingJobs.push({
|
|
24133
|
+
signingPublicKey,
|
|
24134
|
+
rawTx: newNodeTx.toBytes(),
|
|
24135
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24136
|
+
type: "node",
|
|
24137
|
+
parentTxOut: nodeTx.getOutput(0),
|
|
24138
|
+
leafId: node.id,
|
|
24139
|
+
keyDerivation,
|
|
24140
|
+
verifyingKey: node.verifyingPublicKey
|
|
24125
24141
|
});
|
|
24126
|
-
|
|
24142
|
+
signingJobs.push({
|
|
24143
|
+
signingPublicKey,
|
|
24144
|
+
rawTx: newDirectNodeTx.toBytes(),
|
|
24145
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24146
|
+
type: "directNode",
|
|
24147
|
+
parentTxOut: nodeTx.getOutput(0),
|
|
24148
|
+
leafId: node.id,
|
|
24149
|
+
keyDerivation,
|
|
24150
|
+
verifyingKey: node.verifyingPublicKey
|
|
24151
|
+
});
|
|
24152
|
+
const { cpfpRefundTx, directFromCpfpRefundTx } = createInitialTimelockRefundTxs({
|
|
24153
|
+
nodeTx: newNodeTx,
|
|
24154
|
+
directNodeTx: newDirectNodeTx,
|
|
24155
|
+
receivingPubkey: signingPublicKey,
|
|
24156
|
+
network: this.config.getNetwork()
|
|
24157
|
+
});
|
|
24158
|
+
signingJobs.push({
|
|
24159
|
+
signingPublicKey,
|
|
24160
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
24161
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24162
|
+
type: "cpfp",
|
|
24163
|
+
parentTxOut: newNodeTx.getOutput(0),
|
|
24164
|
+
leafId: node.id,
|
|
24165
|
+
keyDerivation,
|
|
24166
|
+
verifyingKey: node.verifyingPublicKey
|
|
24167
|
+
});
|
|
24168
|
+
if (!directFromCpfpRefundTx) {
|
|
24169
|
+
throw new Error("Could not create direct refund transactions");
|
|
24170
|
+
}
|
|
24171
|
+
signingJobs.push({
|
|
24172
|
+
signingPublicKey,
|
|
24173
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
24174
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24175
|
+
type: "directFromCpfp",
|
|
24176
|
+
parentTxOut: newNodeTx.getOutput(0),
|
|
24177
|
+
leafId: node.id,
|
|
24178
|
+
keyDerivation,
|
|
24179
|
+
verifyingKey: node.verifyingPublicKey
|
|
24180
|
+
});
|
|
24181
|
+
return signingJobs;
|
|
24127
24182
|
}
|
|
24128
24183
|
};
|
|
24129
24184
|
|
|
@@ -24165,71 +24220,6 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
24165
24220
|
directFromCpfpSignaturesMap
|
|
24166
24221
|
};
|
|
24167
24222
|
}
|
|
24168
|
-
createConnectorRefundTransactions(sequence, directSequence, cpfpNodeOutPoint, directNodeOutPoint, connectorOutput, amountSats, receiverPubKey) {
|
|
24169
|
-
const cpfpRefundTx = new import_btc_signer3.Transaction();
|
|
24170
|
-
if (!cpfpNodeOutPoint.txid || cpfpNodeOutPoint.index === void 0) {
|
|
24171
|
-
throw new ValidationError("Invalid CPFP node outpoint", {
|
|
24172
|
-
field: "cpfpNodeOutPoint",
|
|
24173
|
-
value: { txid: cpfpNodeOutPoint.txid, index: cpfpNodeOutPoint.index },
|
|
24174
|
-
expected: "Both txid and index must be defined"
|
|
24175
|
-
});
|
|
24176
|
-
}
|
|
24177
|
-
cpfpRefundTx.addInput({
|
|
24178
|
-
txid: cpfpNodeOutPoint.txid,
|
|
24179
|
-
index: cpfpNodeOutPoint.index,
|
|
24180
|
-
sequence
|
|
24181
|
-
});
|
|
24182
|
-
cpfpRefundTx.addInput(connectorOutput);
|
|
24183
|
-
const receiverScript = getP2TRScriptFromPublicKey(
|
|
24184
|
-
receiverPubKey,
|
|
24185
|
-
this.config.getNetwork()
|
|
24186
|
-
);
|
|
24187
|
-
cpfpRefundTx.addOutput({
|
|
24188
|
-
script: receiverScript,
|
|
24189
|
-
amount: amountSats
|
|
24190
|
-
});
|
|
24191
|
-
let directRefundTx;
|
|
24192
|
-
let directFromCpfpRefundTx;
|
|
24193
|
-
if (directNodeOutPoint) {
|
|
24194
|
-
if (!directNodeOutPoint.txid || directNodeOutPoint.index === void 0) {
|
|
24195
|
-
throw new ValidationError("Invalid direct node outpoint", {
|
|
24196
|
-
field: "directNodeOutPoint",
|
|
24197
|
-
value: {
|
|
24198
|
-
txid: directNodeOutPoint.txid,
|
|
24199
|
-
index: directNodeOutPoint.index
|
|
24200
|
-
},
|
|
24201
|
-
expected: "Both txid and index must be defined"
|
|
24202
|
-
});
|
|
24203
|
-
}
|
|
24204
|
-
directRefundTx = new import_btc_signer3.Transaction();
|
|
24205
|
-
directRefundTx.addInput({
|
|
24206
|
-
txid: directNodeOutPoint.txid,
|
|
24207
|
-
index: directNodeOutPoint.index,
|
|
24208
|
-
sequence: directSequence
|
|
24209
|
-
});
|
|
24210
|
-
directRefundTx.addInput(connectorOutput);
|
|
24211
|
-
directRefundTx.addOutput({
|
|
24212
|
-
script: receiverScript,
|
|
24213
|
-
amount: maybeApplyFee(amountSats)
|
|
24214
|
-
});
|
|
24215
|
-
directFromCpfpRefundTx = new import_btc_signer3.Transaction();
|
|
24216
|
-
directFromCpfpRefundTx.addInput({
|
|
24217
|
-
txid: cpfpNodeOutPoint.txid,
|
|
24218
|
-
index: cpfpNodeOutPoint.index,
|
|
24219
|
-
sequence: directSequence
|
|
24220
|
-
});
|
|
24221
|
-
directFromCpfpRefundTx.addInput(connectorOutput);
|
|
24222
|
-
directFromCpfpRefundTx.addOutput({
|
|
24223
|
-
script: receiverScript,
|
|
24224
|
-
amount: maybeApplyFee(amountSats)
|
|
24225
|
-
});
|
|
24226
|
-
}
|
|
24227
|
-
return {
|
|
24228
|
-
cpfpRefundTx,
|
|
24229
|
-
directRefundTx,
|
|
24230
|
-
directFromCpfpRefundTx
|
|
24231
|
-
};
|
|
24232
|
-
}
|
|
24233
24223
|
async signCoopExitRefunds(leaves, exitTxId, connectorOutputs, receiverPubKey, transferId) {
|
|
24234
24224
|
if (leaves.length !== connectorOutputs.length) {
|
|
24235
24225
|
throw new ValidationError(
|
|
@@ -24263,29 +24253,39 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
24263
24253
|
expected: "Valid connector output"
|
|
24264
24254
|
});
|
|
24265
24255
|
}
|
|
24256
|
+
const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
24257
|
+
let directNodeTx;
|
|
24258
|
+
if (leaf.leaf.directTx.length > 0) {
|
|
24259
|
+
directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
|
|
24260
|
+
}
|
|
24266
24261
|
const currentRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
24267
|
-
|
|
24268
|
-
|
|
24262
|
+
if (!currentRefundTx) {
|
|
24263
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
24264
|
+
field: "currentRefundTx",
|
|
24265
|
+
value: currentRefundTx,
|
|
24266
|
+
expected: "Non-null refund transaction"
|
|
24267
|
+
});
|
|
24268
|
+
}
|
|
24269
|
+
const currentSequence = currentRefundTx.getInput(0).sequence;
|
|
24270
|
+
if (!currentSequence) {
|
|
24269
24271
|
throw new ValidationError("Invalid refund transaction", {
|
|
24270
24272
|
field: "sequence",
|
|
24271
24273
|
value: currentRefundTx.getInput(0),
|
|
24272
24274
|
expected: "Non-null sequence"
|
|
24273
24275
|
});
|
|
24274
24276
|
}
|
|
24275
|
-
const { nextSequence, nextDirectSequence } = getNextTransactionSequence(sequence);
|
|
24276
24277
|
let currentDirectRefundTx;
|
|
24277
24278
|
if (leaf.leaf.directRefundTx.length > 0) {
|
|
24278
24279
|
currentDirectRefundTx = getTxFromRawTxBytes(leaf.leaf.directRefundTx);
|
|
24279
24280
|
}
|
|
24280
|
-
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } =
|
|
24281
|
-
|
|
24282
|
-
|
|
24283
|
-
|
|
24284
|
-
currentDirectRefundTx?.getInput(0),
|
|
24281
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createConnectorRefundTxs({
|
|
24282
|
+
nodeTx,
|
|
24283
|
+
directNodeTx,
|
|
24284
|
+
sequence: currentSequence,
|
|
24285
24285
|
connectorOutput,
|
|
24286
|
-
|
|
24287
|
-
|
|
24288
|
-
);
|
|
24286
|
+
receivingPubkey: receiverPubKey,
|
|
24287
|
+
network: this.config.getNetwork()
|
|
24288
|
+
});
|
|
24289
24289
|
const signingNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
24290
24290
|
const directSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
24291
24291
|
const directFromCpfpSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
@@ -24392,9 +24392,9 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
24392
24392
|
init_buffer();
|
|
24393
24393
|
var import_secp256k110 = require("@noble/curves/secp256k1");
|
|
24394
24394
|
var import_sha29 = require("@noble/hashes/sha2");
|
|
24395
|
-
var
|
|
24396
|
-
var
|
|
24397
|
-
var
|
|
24395
|
+
var import_utils17 = require("@noble/hashes/utils");
|
|
24396
|
+
var import_btc_signer2 = require("@scure/btc-signer");
|
|
24397
|
+
var import_utils18 = require("@scure/btc-signer/utils");
|
|
24398
24398
|
var DepositService = class {
|
|
24399
24399
|
config;
|
|
24400
24400
|
connectionManager;
|
|
@@ -24422,7 +24422,7 @@ var DepositService = class {
|
|
|
24422
24422
|
operatorPubkey,
|
|
24423
24423
|
address.address
|
|
24424
24424
|
);
|
|
24425
|
-
const taprootKey = (0,
|
|
24425
|
+
const taprootKey = (0, import_btc_signer2.p2tr)(
|
|
24426
24426
|
operatorPubkey.slice(1, 33),
|
|
24427
24427
|
void 0,
|
|
24428
24428
|
getNetwork(this.config.getNetwork())
|
|
@@ -24446,7 +24446,7 @@ var DepositService = class {
|
|
|
24446
24446
|
if (operator.identifier === this.config.getCoordinatorIdentifier() && !verifyCoordinatorProof) {
|
|
24447
24447
|
continue;
|
|
24448
24448
|
}
|
|
24449
|
-
const operatorPubkey2 = (0,
|
|
24449
|
+
const operatorPubkey2 = (0, import_utils17.hexToBytes)(operator.identityPublicKey);
|
|
24450
24450
|
const operatorSig = address.depositAddressProof.addressSignatures[operator.identifier];
|
|
24451
24451
|
if (!operatorSig) {
|
|
24452
24452
|
throw new ValidationError("Operator signature not found", {
|
|
@@ -24565,38 +24565,18 @@ var DepositService = class {
|
|
|
24565
24565
|
expected: "Valid output index"
|
|
24566
24566
|
});
|
|
24567
24567
|
}
|
|
24568
|
-
const
|
|
24569
|
-
|
|
24570
|
-
|
|
24571
|
-
throw new ValidationError("No script or amount found in deposit tx", {
|
|
24572
|
-
field: "output",
|
|
24573
|
-
value: output,
|
|
24574
|
-
expected: "Output with script and amount"
|
|
24575
|
-
});
|
|
24576
|
-
}
|
|
24577
|
-
const depositOutPoint = {
|
|
24578
|
-
txid: (0, import_utils16.hexToBytes)(getTxId(depositTx)),
|
|
24579
|
-
index: vout
|
|
24580
|
-
};
|
|
24581
|
-
const depositTxOut = {
|
|
24582
|
-
script,
|
|
24583
|
-
amount
|
|
24584
|
-
};
|
|
24585
|
-
const [cpfpRootTx, directRootTx] = createRootTx(
|
|
24586
|
-
depositOutPoint,
|
|
24587
|
-
depositTxOut
|
|
24568
|
+
const { nodeTx: cpfpRootTx, directNodeTx: directRootTx } = createRootNodeTx(
|
|
24569
|
+
depositTx,
|
|
24570
|
+
vout
|
|
24588
24571
|
);
|
|
24589
24572
|
const cpfpRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
24590
24573
|
const directRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
24591
24574
|
const cpfpRootTxSighash = getSigHashFromTx(cpfpRootTx, 0, output);
|
|
24592
24575
|
const directRootTxSighash = getSigHashFromTx(directRootTx, 0, output);
|
|
24593
24576
|
const signingPubKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
24594
|
-
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } =
|
|
24595
|
-
|
|
24596
|
-
|
|
24597
|
-
input: { txid: (0, import_utils16.hexToBytes)(getTxId(cpfpRootTx)), index: 0 },
|
|
24598
|
-
directInput: { txid: (0, import_utils16.hexToBytes)(getTxId(directRootTx)), index: 0 },
|
|
24599
|
-
amountSats: amount,
|
|
24577
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createInitialTimelockRefundTxs({
|
|
24578
|
+
nodeTx: cpfpRootTx,
|
|
24579
|
+
directNodeTx: directRootTx,
|
|
24600
24580
|
receivingPubkey: signingPubKey,
|
|
24601
24581
|
network: this.config.getNetwork()
|
|
24602
24582
|
});
|
|
@@ -24725,7 +24705,7 @@ var DepositService = class {
|
|
|
24725
24705
|
}
|
|
24726
24706
|
);
|
|
24727
24707
|
}
|
|
24728
|
-
if (!(0,
|
|
24708
|
+
if (!(0, import_utils18.equalBytes)(treeResp.rootNodeSignatureShares.verifyingKey, verifyingKey)) {
|
|
24729
24709
|
throw new ValidationError("Verifying key mismatch", {
|
|
24730
24710
|
field: "verifyingKey",
|
|
24731
24711
|
value: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
@@ -24888,22 +24868,12 @@ var DepositService = class {
|
|
|
24888
24868
|
expected: "Output with script and amount"
|
|
24889
24869
|
});
|
|
24890
24870
|
}
|
|
24891
|
-
const
|
|
24892
|
-
txid: (0, import_utils16.hexToBytes)(getTxId(depositTx)),
|
|
24893
|
-
index: vout
|
|
24894
|
-
};
|
|
24895
|
-
const depositTxOut = {
|
|
24896
|
-
script,
|
|
24897
|
-
amount
|
|
24898
|
-
};
|
|
24899
|
-
const [cpfpRootTx, _] = createRootTx(depositOutPoint, depositTxOut);
|
|
24871
|
+
const { nodeTx: cpfpRootTx } = createRootNodeTx(depositTx, vout);
|
|
24900
24872
|
const cpfpRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
24901
24873
|
const cpfpRootTxSighash = getSigHashFromTx(cpfpRootTx, 0, output);
|
|
24902
24874
|
const signingPubKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
24903
|
-
const { cpfpRefundTx } =
|
|
24904
|
-
|
|
24905
|
-
input: { txid: (0, import_utils16.hexToBytes)(getTxId(cpfpRootTx)), index: 0 },
|
|
24906
|
-
amountSats: amount,
|
|
24875
|
+
const { cpfpRefundTx } = createInitialTimelockRefundTxs({
|
|
24876
|
+
nodeTx: cpfpRootTx,
|
|
24907
24877
|
receivingPubkey: signingPubKey,
|
|
24908
24878
|
network: this.config.getNetwork()
|
|
24909
24879
|
});
|
|
@@ -24972,7 +24942,7 @@ var DepositService = class {
|
|
|
24972
24942
|
}
|
|
24973
24943
|
);
|
|
24974
24944
|
}
|
|
24975
|
-
if (!(0,
|
|
24945
|
+
if (!(0, import_utils18.equalBytes)(treeResp.rootNodeSignatureShares.verifyingKey, verifyingKey)) {
|
|
24976
24946
|
throw new ValidationError("Verifying key mismatch", {
|
|
24977
24947
|
field: "verifyingKey",
|
|
24978
24948
|
value: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
@@ -25049,7 +25019,7 @@ var DepositService = class {
|
|
|
25049
25019
|
// src/services/lightning.ts
|
|
25050
25020
|
init_buffer();
|
|
25051
25021
|
var import_secp256k111 = require("@noble/curves/secp256k1");
|
|
25052
|
-
var
|
|
25022
|
+
var import_utils19 = require("@noble/curves/utils");
|
|
25053
25023
|
var import_sha210 = require("@noble/hashes/sha2");
|
|
25054
25024
|
var import_uuidv74 = require("uuidv7");
|
|
25055
25025
|
|
|
@@ -25135,8 +25105,8 @@ var LightningService = class {
|
|
|
25135
25105
|
}) {
|
|
25136
25106
|
const crypto = getCrypto();
|
|
25137
25107
|
const randBytes = crypto.getRandomValues(new Uint8Array(32));
|
|
25138
|
-
const preimage = (0,
|
|
25139
|
-
(0,
|
|
25108
|
+
const preimage = (0, import_utils19.numberToBytesBE)(
|
|
25109
|
+
(0, import_utils19.bytesToNumberBE)(randBytes) % import_secp256k111.secp256k1.CURVE.n,
|
|
25140
25110
|
32
|
|
25141
25111
|
);
|
|
25142
25112
|
return await this.createLightningInvoiceWithPreImage({
|
|
@@ -25191,12 +25161,12 @@ var LightningService = class {
|
|
|
25191
25161
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
25192
25162
|
operator.address
|
|
25193
25163
|
);
|
|
25194
|
-
const userIdentityPublicKey = receiverIdentityPubkey ? (0,
|
|
25164
|
+
const userIdentityPublicKey = receiverIdentityPubkey ? (0, import_utils19.hexToBytes)(receiverIdentityPubkey) : await this.config.signer.getIdentityPublicKey();
|
|
25195
25165
|
try {
|
|
25196
25166
|
await sparkClient.store_preimage_share({
|
|
25197
25167
|
paymentHash,
|
|
25198
25168
|
preimageShare: {
|
|
25199
|
-
secretShare: (0,
|
|
25169
|
+
secretShare: (0, import_utils19.numberToBytesBE)(share.share, 32),
|
|
25200
25170
|
proofs: share.proofs
|
|
25201
25171
|
},
|
|
25202
25172
|
threshold: this.config.getThreshold(),
|
|
@@ -25414,8 +25384,8 @@ var LightningService = class {
|
|
|
25414
25384
|
|
|
25415
25385
|
// src/services/token-transactions.ts
|
|
25416
25386
|
init_buffer();
|
|
25417
|
-
var
|
|
25418
|
-
var
|
|
25387
|
+
var import_utils20 = require("@noble/curves/utils");
|
|
25388
|
+
var import_utils21 = require("@noble/hashes/utils");
|
|
25419
25389
|
|
|
25420
25390
|
// src/utils/token-hashing.ts
|
|
25421
25391
|
init_buffer();
|
|
@@ -29560,14 +29530,14 @@ var TokenTransactionService = class {
|
|
|
29560
29530
|
}
|
|
29561
29531
|
if (receiverAddress.sparkInvoiceFields) {
|
|
29562
29532
|
return {
|
|
29563
|
-
receiverPublicKey: (0,
|
|
29533
|
+
receiverPublicKey: (0, import_utils21.hexToBytes)(receiverAddress.identityPublicKey),
|
|
29564
29534
|
rawTokenIdentifier,
|
|
29565
29535
|
tokenAmount: transfer.tokenAmount,
|
|
29566
29536
|
sparkInvoice: transfer.receiverSparkAddress
|
|
29567
29537
|
};
|
|
29568
29538
|
}
|
|
29569
29539
|
return {
|
|
29570
|
-
receiverPublicKey: (0,
|
|
29540
|
+
receiverPublicKey: (0, import_utils21.hexToBytes)(receiverAddress.identityPublicKey),
|
|
29571
29541
|
rawTokenIdentifier,
|
|
29572
29542
|
tokenAmount: transfer.tokenAmount
|
|
29573
29543
|
};
|
|
@@ -29597,7 +29567,7 @@ var TokenTransactionService = class {
|
|
|
29597
29567
|
(output) => ({
|
|
29598
29568
|
ownerPublicKey: output.receiverPublicKey,
|
|
29599
29569
|
tokenIdentifier: output.rawTokenIdentifier,
|
|
29600
|
-
tokenAmount: (0,
|
|
29570
|
+
tokenAmount: (0, import_utils20.numberToBytesBE)(output.tokenAmount, 16)
|
|
29601
29571
|
})
|
|
29602
29572
|
);
|
|
29603
29573
|
if (availableTokenAmount > totalRequestedAmount) {
|
|
@@ -29606,7 +29576,7 @@ var TokenTransactionService = class {
|
|
|
29606
29576
|
tokenOutputs.push({
|
|
29607
29577
|
ownerPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
29608
29578
|
tokenIdentifier: firstTokenIdentifierBytes,
|
|
29609
|
-
tokenAmount: (0,
|
|
29579
|
+
tokenAmount: (0, import_utils20.numberToBytesBE)(changeAmount, 16)
|
|
29610
29580
|
});
|
|
29611
29581
|
}
|
|
29612
29582
|
return {
|
|
@@ -29633,7 +29603,7 @@ var TokenTransactionService = class {
|
|
|
29633
29603
|
for (const [_, operator] of Object.entries(
|
|
29634
29604
|
this.config.getSigningOperators()
|
|
29635
29605
|
)) {
|
|
29636
|
-
operatorKeys.push((0,
|
|
29606
|
+
operatorKeys.push((0, import_utils21.hexToBytes)(operator.identityPublicKey));
|
|
29637
29607
|
}
|
|
29638
29608
|
return operatorKeys;
|
|
29639
29609
|
}
|
|
@@ -29650,7 +29620,7 @@ var TokenTransactionService = class {
|
|
|
29650
29620
|
finalTokenTransactionHash,
|
|
29651
29621
|
signingOperators
|
|
29652
29622
|
);
|
|
29653
|
-
return (0,
|
|
29623
|
+
return (0, import_utils20.bytesToHex)(finalTokenTransactionHash);
|
|
29654
29624
|
}
|
|
29655
29625
|
async startTokenTransaction(tokenTransaction, signingOperators, outputsToSpendSigningPublicKeys, outputsToSpendCommitments) {
|
|
29656
29626
|
const sparkClient = await this.connectionManager.createSparkTokenClient(
|
|
@@ -29825,10 +29795,10 @@ var TokenTransactionService = class {
|
|
|
29825
29795
|
});
|
|
29826
29796
|
}
|
|
29827
29797
|
for (const ownerPublicKey of ownerPublicKeys) {
|
|
29828
|
-
isValidPublicKey((0,
|
|
29798
|
+
isValidPublicKey((0, import_utils20.bytesToHex)(ownerPublicKey));
|
|
29829
29799
|
}
|
|
29830
29800
|
for (const issuerPublicKey of issuerPublicKeys) {
|
|
29831
|
-
isValidPublicKey((0,
|
|
29801
|
+
isValidPublicKey((0, import_utils20.bytesToHex)(issuerPublicKey));
|
|
29832
29802
|
}
|
|
29833
29803
|
for (const tokenIdentifier of tokenIdentifiers) {
|
|
29834
29804
|
if (tokenIdentifier.length !== 32) {
|
|
@@ -29896,8 +29866,8 @@ var TokenTransactionService = class {
|
|
|
29896
29866
|
this.config.getCoordinatorAddress()
|
|
29897
29867
|
);
|
|
29898
29868
|
let queryParams = {
|
|
29899
|
-
issuerPublicKeys: issuerPublicKeys?.map(
|
|
29900
|
-
ownerPublicKeys: ownerPublicKeys?.map(
|
|
29869
|
+
issuerPublicKeys: issuerPublicKeys?.map(import_utils21.hexToBytes),
|
|
29870
|
+
ownerPublicKeys: ownerPublicKeys?.map(import_utils21.hexToBytes),
|
|
29901
29871
|
tokenIdentifiers: tokenIdentifiers?.map((identifier) => {
|
|
29902
29872
|
const { tokenIdentifier } = decodeBech32mTokenIdentifier(
|
|
29903
29873
|
identifier,
|
|
@@ -29905,7 +29875,7 @@ var TokenTransactionService = class {
|
|
|
29905
29875
|
);
|
|
29906
29876
|
return tokenIdentifier;
|
|
29907
29877
|
}),
|
|
29908
|
-
tokenTransactionHashes: tokenTransactionHashes?.map(
|
|
29878
|
+
tokenTransactionHashes: tokenTransactionHashes?.map(import_utils21.hexToBytes),
|
|
29909
29879
|
outputIds: outputIds || [],
|
|
29910
29880
|
limit: pageSize,
|
|
29911
29881
|
offset
|
|
@@ -29940,7 +29910,7 @@ var TokenTransactionService = class {
|
|
|
29940
29910
|
});
|
|
29941
29911
|
}
|
|
29942
29912
|
const exactMatch = tokenOutputs.find(
|
|
29943
|
-
(item) => (0,
|
|
29913
|
+
(item) => (0, import_utils20.bytesToNumberBE)(item.output.tokenAmount) === tokenAmount
|
|
29944
29914
|
);
|
|
29945
29915
|
if (exactMatch) {
|
|
29946
29916
|
return [exactMatch];
|
|
@@ -29951,7 +29921,7 @@ var TokenTransactionService = class {
|
|
|
29951
29921
|
for (const outputWithPreviousTransactionData of tokenOutputs) {
|
|
29952
29922
|
if (remainingAmount <= 0n) break;
|
|
29953
29923
|
selectedOutputs.push(outputWithPreviousTransactionData);
|
|
29954
|
-
remainingAmount -= (0,
|
|
29924
|
+
remainingAmount -= (0, import_utils20.bytesToNumberBE)(
|
|
29955
29925
|
outputWithPreviousTransactionData.output.tokenAmount
|
|
29956
29926
|
);
|
|
29957
29927
|
}
|
|
@@ -29966,14 +29936,14 @@ var TokenTransactionService = class {
|
|
|
29966
29936
|
sortTokenOutputsByStrategy(tokenOutputs, strategy) {
|
|
29967
29937
|
if (strategy === "SMALL_FIRST") {
|
|
29968
29938
|
tokenOutputs.sort((a, b) => {
|
|
29969
|
-
const amountA = (0,
|
|
29970
|
-
const amountB = (0,
|
|
29939
|
+
const amountA = (0, import_utils20.bytesToNumberBE)(a.output.tokenAmount);
|
|
29940
|
+
const amountB = (0, import_utils20.bytesToNumberBE)(b.output.tokenAmount);
|
|
29971
29941
|
return amountA < amountB ? -1 : amountA > amountB ? 1 : 0;
|
|
29972
29942
|
});
|
|
29973
29943
|
} else {
|
|
29974
29944
|
tokenOutputs.sort((a, b) => {
|
|
29975
|
-
const amountA = (0,
|
|
29976
|
-
const amountB = (0,
|
|
29945
|
+
const amountA = (0, import_utils20.bytesToNumberBE)(a.output.tokenAmount);
|
|
29946
|
+
const amountB = (0, import_utils20.bytesToNumberBE)(b.output.tokenAmount);
|
|
29977
29947
|
return amountB < amountA ? -1 : amountB > amountA ? 1 : 0;
|
|
29978
29948
|
});
|
|
29979
29949
|
}
|
|
@@ -29981,7 +29951,7 @@ var TokenTransactionService = class {
|
|
|
29981
29951
|
// Helper function for deciding if the signer public key is the identity public key
|
|
29982
29952
|
async signMessageWithKey(message, publicKey) {
|
|
29983
29953
|
const tokenSignatures = this.config.getTokenSignatures();
|
|
29984
|
-
if ((0,
|
|
29954
|
+
if ((0, import_utils20.bytesToHex)(publicKey) === (0, import_utils20.bytesToHex)(await this.config.signer.getIdentityPublicKey())) {
|
|
29985
29955
|
if (tokenSignatures === "SCHNORR") {
|
|
29986
29956
|
return await this.config.signer.signSchnorrWithIdentityKey(message);
|
|
29987
29957
|
} else {
|
|
@@ -29990,8 +29960,8 @@ var TokenTransactionService = class {
|
|
|
29990
29960
|
} else {
|
|
29991
29961
|
throw new ValidationError("Invalid public key", {
|
|
29992
29962
|
field: "publicKey",
|
|
29993
|
-
value: (0,
|
|
29994
|
-
expected: (0,
|
|
29963
|
+
value: (0, import_utils20.bytesToHex)(publicKey),
|
|
29964
|
+
expected: (0, import_utils20.bytesToHex)(await this.config.signer.getIdentityPublicKey())
|
|
29995
29965
|
});
|
|
29996
29966
|
}
|
|
29997
29967
|
}
|
|
@@ -30010,7 +29980,7 @@ var TokenTransactionService = class {
|
|
|
30010
29980
|
}
|
|
30011
29981
|
const payload = {
|
|
30012
29982
|
finalTokenTransactionHash,
|
|
30013
|
-
operatorIdentityPublicKey: (0,
|
|
29983
|
+
operatorIdentityPublicKey: (0, import_utils21.hexToBytes)(operator.identityPublicKey)
|
|
30014
29984
|
};
|
|
30015
29985
|
const payloadHash = await hashOperatorSpecificTokenTransactionSignablePayload(payload);
|
|
30016
29986
|
const ownerSignature = await this.signMessageWithKey(
|
|
@@ -30032,7 +30002,7 @@ var TokenTransactionService = class {
|
|
|
30032
30002
|
}
|
|
30033
30003
|
const payload = {
|
|
30034
30004
|
finalTokenTransactionHash,
|
|
30035
|
-
operatorIdentityPublicKey: (0,
|
|
30005
|
+
operatorIdentityPublicKey: (0, import_utils21.hexToBytes)(operator.identityPublicKey)
|
|
30036
30006
|
};
|
|
30037
30007
|
const payloadHash = await hashOperatorSpecificTokenTransactionSignablePayload(payload);
|
|
30038
30008
|
const ownerSignature = await this.signMessageWithKey(
|
|
@@ -30048,7 +30018,7 @@ var TokenTransactionService = class {
|
|
|
30048
30018
|
for (let i = 0; i < transferInput.outputsToSpend.length; i++) {
|
|
30049
30019
|
const payload = {
|
|
30050
30020
|
finalTokenTransactionHash,
|
|
30051
|
-
operatorIdentityPublicKey: (0,
|
|
30021
|
+
operatorIdentityPublicKey: (0, import_utils21.hexToBytes)(operator.identityPublicKey)
|
|
30052
30022
|
};
|
|
30053
30023
|
const payloadHash = await hashOperatorSpecificTokenTransactionSignablePayload(payload);
|
|
30054
30024
|
let ownerSignature;
|
|
@@ -30065,7 +30035,7 @@ var TokenTransactionService = class {
|
|
|
30065
30035
|
}
|
|
30066
30036
|
inputTtxoSignaturesPerOperator.push({
|
|
30067
30037
|
ttxoSignatures,
|
|
30068
|
-
operatorIdentityPublicKey: (0,
|
|
30038
|
+
operatorIdentityPublicKey: (0, import_utils21.hexToBytes)(operator.identityPublicKey)
|
|
30069
30039
|
});
|
|
30070
30040
|
}
|
|
30071
30041
|
return inputTtxoSignaturesPerOperator;
|
|
@@ -30081,13 +30051,12 @@ var import_nice_grpc_common = require("nice-grpc-common");
|
|
|
30081
30051
|
|
|
30082
30052
|
// src/services/signing.ts
|
|
30083
30053
|
init_buffer();
|
|
30084
|
-
var import_utils22 = require("@noble/curves/utils");
|
|
30085
30054
|
|
|
30086
30055
|
// src/utils/htlc-transactions.ts
|
|
30087
30056
|
init_buffer();
|
|
30088
|
-
var
|
|
30057
|
+
var import_btc_signer3 = require("@scure/btc-signer");
|
|
30089
30058
|
var import_secp256k112 = require("@noble/curves/secp256k1");
|
|
30090
|
-
var
|
|
30059
|
+
var import_utils22 = require("@noble/curves/utils");
|
|
30091
30060
|
var PUB_KEY_BYTES = "0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0";
|
|
30092
30061
|
function numsPoint() {
|
|
30093
30062
|
const withdrawalPubKeyPoint = import_secp256k112.secp256k1.Point.fromHex(PUB_KEY_BYTES);
|
|
@@ -30165,10 +30134,10 @@ function createLightningHTLCTransaction({
|
|
|
30165
30134
|
outAmount = maybeApplyFee(outAmount);
|
|
30166
30135
|
}
|
|
30167
30136
|
const input = {
|
|
30168
|
-
txid: (0,
|
|
30137
|
+
txid: (0, import_utils22.hexToBytes)(getTxId(nodeTx)),
|
|
30169
30138
|
index: 0
|
|
30170
30139
|
};
|
|
30171
|
-
const htlcTransaction = new
|
|
30140
|
+
const htlcTransaction = new import_btc_signer3.Transaction({
|
|
30172
30141
|
version: 3,
|
|
30173
30142
|
allowUnknownOutputs: true
|
|
30174
30143
|
});
|
|
@@ -30207,12 +30176,12 @@ function createHTLCTaprootAddress({
|
|
|
30207
30176
|
);
|
|
30208
30177
|
const hashLockLeaf = { leafVersion: 192, script: hashLockScript };
|
|
30209
30178
|
const sequenceLockLeaf = { leafVersion: 192, script: sequenceLockScript };
|
|
30210
|
-
const scriptTree = (0,
|
|
30211
|
-
const p2trScript = (0,
|
|
30179
|
+
const scriptTree = (0, import_btc_signer3.taprootListToTree)([hashLockLeaf, sequenceLockLeaf]);
|
|
30180
|
+
const p2trScript = (0, import_btc_signer3.p2tr)(numsKey, scriptTree, network, true).script;
|
|
30212
30181
|
return p2trScript;
|
|
30213
30182
|
}
|
|
30214
30183
|
function createHashLockScript(hash, pubkey) {
|
|
30215
|
-
const result =
|
|
30184
|
+
const result = import_btc_signer3.Script.encode([
|
|
30216
30185
|
"SHA256",
|
|
30217
30186
|
hash,
|
|
30218
30187
|
"EQUALVERIFY",
|
|
@@ -30222,8 +30191,8 @@ function createHashLockScript(hash, pubkey) {
|
|
|
30222
30191
|
return result;
|
|
30223
30192
|
}
|
|
30224
30193
|
function createSequenceLockScript(sequence, sequenceLockDestinationPubkey) {
|
|
30225
|
-
const result =
|
|
30226
|
-
(0,
|
|
30194
|
+
const result = import_btc_signer3.Script.encode([
|
|
30195
|
+
(0, import_btc_signer3.ScriptNum)().encode(BigInt(sequence)),
|
|
30227
30196
|
"CHECKSEQUENCEVERIFY",
|
|
30228
30197
|
"DROP",
|
|
30229
30198
|
sequenceLockDestinationPubkey.slice(1, 33),
|
|
@@ -30287,20 +30256,7 @@ var SigningService = class {
|
|
|
30287
30256
|
});
|
|
30288
30257
|
}
|
|
30289
30258
|
const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
30290
|
-
const cpfpNodeOutPoint = {
|
|
30291
|
-
txid: (0, import_utils22.hexToBytes)(getTxId(nodeTx)),
|
|
30292
|
-
index: 0
|
|
30293
|
-
};
|
|
30294
30259
|
const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
30295
|
-
const sequence = currRefundTx.getInput(0).sequence;
|
|
30296
|
-
if (!sequence) {
|
|
30297
|
-
throw new ValidationError("Invalid refund transaction", {
|
|
30298
|
-
field: "sequence",
|
|
30299
|
-
value: currRefundTx.getInput(0),
|
|
30300
|
-
expected: "Non-null sequence"
|
|
30301
|
-
});
|
|
30302
|
-
}
|
|
30303
|
-
const { nextSequence, nextDirectSequence } = getNextTransactionSequence(sequence);
|
|
30304
30260
|
const amountSats = currRefundTx.getOutput(0).amount;
|
|
30305
30261
|
if (amountSats === void 0) {
|
|
30306
30262
|
throw new ValidationError("Invalid refund transaction", {
|
|
@@ -30310,20 +30266,21 @@ var SigningService = class {
|
|
|
30310
30266
|
});
|
|
30311
30267
|
}
|
|
30312
30268
|
let directNodeTx;
|
|
30313
|
-
let directNodeOutPoint;
|
|
30314
30269
|
if (leaf.leaf.directTx.length > 0) {
|
|
30315
30270
|
directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
|
|
30316
|
-
directNodeOutPoint = {
|
|
30317
|
-
txid: (0, import_utils22.hexToBytes)(getTxId(directNodeTx)),
|
|
30318
|
-
index: 0
|
|
30319
|
-
};
|
|
30320
30271
|
}
|
|
30321
|
-
const
|
|
30322
|
-
|
|
30323
|
-
|
|
30324
|
-
|
|
30325
|
-
|
|
30326
|
-
|
|
30272
|
+
const currentSequence = currRefundTx.getInput(0).sequence;
|
|
30273
|
+
if (!currentSequence) {
|
|
30274
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
30275
|
+
field: "sequence",
|
|
30276
|
+
value: currRefundTx.getInput(0),
|
|
30277
|
+
expected: "Non-null sequence"
|
|
30278
|
+
});
|
|
30279
|
+
}
|
|
30280
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createDecrementedTimelockRefundTxs({
|
|
30281
|
+
nodeTx,
|
|
30282
|
+
directNodeTx,
|
|
30283
|
+
sequence: currentSequence,
|
|
30327
30284
|
receivingPubkey: receiverIdentityPubkey,
|
|
30328
30285
|
network: this.config.getNetwork()
|
|
30329
30286
|
});
|
|
@@ -30339,7 +30296,8 @@ var SigningService = class {
|
|
|
30339
30296
|
cpfpSigningCommitments[i]?.signingNonceCommitments
|
|
30340
30297
|
);
|
|
30341
30298
|
cpfpLeafSigningJobs.push(...signingJobs);
|
|
30342
|
-
|
|
30299
|
+
const isZeroNode = getCurrentTimelock(nodeTx.getInput(0).sequence);
|
|
30300
|
+
if (directRefundTx && !isZeroNode) {
|
|
30343
30301
|
if (!directNodeTx) {
|
|
30344
30302
|
throw new ValidationError(
|
|
30345
30303
|
"Direct node transaction undefined while direct refund transaction is defined",
|
|
@@ -30364,16 +30322,6 @@ var SigningService = class {
|
|
|
30364
30322
|
directLeafSigningJobs.push(...signingJobs2);
|
|
30365
30323
|
}
|
|
30366
30324
|
if (directFromCpfpRefundTx) {
|
|
30367
|
-
if (!directNodeTx) {
|
|
30368
|
-
throw new ValidationError(
|
|
30369
|
-
"Direct node transaction undefined while direct from CPFP refund transaction is defined",
|
|
30370
|
-
{
|
|
30371
|
-
field: "directNodeTx",
|
|
30372
|
-
value: directNodeTx,
|
|
30373
|
-
expected: "Non-null direct node transaction"
|
|
30374
|
-
}
|
|
30375
|
-
);
|
|
30376
|
-
}
|
|
30377
30325
|
const refundSighash2 = getSigHashFromTx(
|
|
30378
30326
|
directFromCpfpRefundTx,
|
|
30379
30327
|
0,
|
|
@@ -30500,6 +30448,35 @@ var SigningService = class {
|
|
|
30500
30448
|
directFromCpfpLeafSigningJobs
|
|
30501
30449
|
};
|
|
30502
30450
|
}
|
|
30451
|
+
async signSigningJobs(signingJobs) {
|
|
30452
|
+
const userSignedTxSigningJobs = /* @__PURE__ */ new Map();
|
|
30453
|
+
for (const signingJob of signingJobs) {
|
|
30454
|
+
const rawTx = getTxFromRawTxBytes(signingJob.rawTx);
|
|
30455
|
+
const txOut = signingJob.parentTxOut;
|
|
30456
|
+
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
30457
|
+
const userSignature = await this.config.signer.signFrost({
|
|
30458
|
+
message: rawTxSighash,
|
|
30459
|
+
keyDerivation: signingJob.keyDerivation,
|
|
30460
|
+
publicKey: signingJob.signingPublicKey,
|
|
30461
|
+
verifyingKey: signingJob.verifyingKey,
|
|
30462
|
+
selfCommitment: signingJob.signingNonceCommitment,
|
|
30463
|
+
statechainCommitments: signingJob.signingNonceCommitments,
|
|
30464
|
+
adaptorPubKey: new Uint8Array()
|
|
30465
|
+
});
|
|
30466
|
+
const userSignedTxSigningJob = {
|
|
30467
|
+
leafId: signingJob.leafId,
|
|
30468
|
+
signingPublicKey: signingJob.signingPublicKey,
|
|
30469
|
+
rawTx: rawTx.toBytes(),
|
|
30470
|
+
signingNonceCommitment: signingJob.signingNonceCommitment.commitment,
|
|
30471
|
+
signingCommitments: {
|
|
30472
|
+
signingCommitments: signingJob.signingNonceCommitments
|
|
30473
|
+
},
|
|
30474
|
+
userSignature
|
|
30475
|
+
};
|
|
30476
|
+
userSignedTxSigningJobs.set(signingJob.type, userSignedTxSigningJob);
|
|
30477
|
+
}
|
|
30478
|
+
return userSignedTxSigningJobs;
|
|
30479
|
+
}
|
|
30503
30480
|
};
|
|
30504
30481
|
|
|
30505
30482
|
// src/tests/utils/test-faucet.ts
|
|
@@ -30507,7 +30484,7 @@ init_buffer();
|
|
|
30507
30484
|
var import_secp256k113 = require("@noble/curves/secp256k1");
|
|
30508
30485
|
var import_utils23 = require("@noble/curves/utils");
|
|
30509
30486
|
var btc5 = __toESM(require("@scure/btc-signer"), 1);
|
|
30510
|
-
var
|
|
30487
|
+
var import_btc_signer4 = require("@scure/btc-signer");
|
|
30511
30488
|
var import_utils24 = require("@scure/btc-signer/utils");
|
|
30512
30489
|
var STATIC_FAUCET_KEY = (0, import_utils23.hexToBytes)(
|
|
30513
30490
|
"deadbeef1337cafe4242424242424242deadbeef1337cafe4242424242424242"
|
|
@@ -30595,7 +30572,7 @@ var BitcoinFaucet = class _BitcoinFaucet {
|
|
|
30595
30572
|
);
|
|
30596
30573
|
await this.generateToAddress(1, address);
|
|
30597
30574
|
const fundingTxRaw = await this.getRawTransaction(fundingTxid);
|
|
30598
|
-
const fundingTx =
|
|
30575
|
+
const fundingTx = import_btc_signer4.Transaction.fromRaw((0, import_utils23.hexToBytes)(fundingTxRaw.hex));
|
|
30599
30576
|
for (let i = 0; i < fundingTx.outputsLength; i++) {
|
|
30600
30577
|
const output = fundingTx.getOutput(i);
|
|
30601
30578
|
if (!output.script || !output.amount) continue;
|
|
@@ -30626,7 +30603,7 @@ var BitcoinFaucet = class _BitcoinFaucet {
|
|
|
30626
30603
|
`Selected UTXO (${selectedUtxoAmountSats} sats) is too small to create even one faucet coin of ${COIN_AMOUNT} sats`
|
|
30627
30604
|
);
|
|
30628
30605
|
}
|
|
30629
|
-
const splitTx = new
|
|
30606
|
+
const splitTx = new import_btc_signer4.Transaction();
|
|
30630
30607
|
splitTx.addInput({
|
|
30631
30608
|
txid: selectedUtxo.txid,
|
|
30632
30609
|
index: selectedUtxo.vout
|
|
@@ -30669,7 +30646,7 @@ var BitcoinFaucet = class _BitcoinFaucet {
|
|
|
30669
30646
|
}
|
|
30670
30647
|
}
|
|
30671
30648
|
async sendFaucetCoinToP2WPKHAddress(pubKey) {
|
|
30672
|
-
const sendToPubKeyTx = new
|
|
30649
|
+
const sendToPubKeyTx = new import_btc_signer4.Transaction();
|
|
30673
30650
|
const p2wpkhAddress = btc5.p2wpkh(pubKey, getNetwork(4 /* LOCAL */)).address;
|
|
30674
30651
|
if (!p2wpkhAddress) {
|
|
30675
30652
|
throw new Error("Invalid P2WPKH address");
|
|
@@ -30705,7 +30682,7 @@ var BitcoinFaucet = class _BitcoinFaucet {
|
|
|
30705
30682
|
const sighash = unsignedTx.preimageWitnessV1(
|
|
30706
30683
|
0,
|
|
30707
30684
|
new Array(unsignedTx.inputsLength).fill(script),
|
|
30708
|
-
|
|
30685
|
+
import_btc_signer4.SigHash.DEFAULT,
|
|
30709
30686
|
new Array(unsignedTx.inputsLength).fill(fundingTxOut.amount)
|
|
30710
30687
|
);
|
|
30711
30688
|
const merkleRoot = new Uint8Array();
|
|
@@ -30724,6 +30701,14 @@ var BitcoinFaucet = class _BitcoinFaucet {
|
|
|
30724
30701
|
async mineBlocks(numBlocks) {
|
|
30725
30702
|
return await this.generateToAddress(numBlocks, this.miningAddress);
|
|
30726
30703
|
}
|
|
30704
|
+
async mineBlocksAndWaitForMiningToComplete(numBlocks) {
|
|
30705
|
+
const startBlock = await this.getBlockCount();
|
|
30706
|
+
await this.mineBlocks(numBlocks);
|
|
30707
|
+
await this.waitForBlocksMined({
|
|
30708
|
+
startBlock,
|
|
30709
|
+
expectedIncrease: numBlocks
|
|
30710
|
+
});
|
|
30711
|
+
}
|
|
30727
30712
|
async call(method, params) {
|
|
30728
30713
|
try {
|
|
30729
30714
|
const { fetch, Headers: Headers2 } = getFetch();
|
|
@@ -30776,27 +30761,62 @@ var BitcoinFaucet = class _BitcoinFaucet {
|
|
|
30776
30761
|
async getBlock(blockHash) {
|
|
30777
30762
|
return await this.call("getblock", [blockHash, 2]);
|
|
30778
30763
|
}
|
|
30764
|
+
async getBlockCount() {
|
|
30765
|
+
return await this.call("getblockcount", []);
|
|
30766
|
+
}
|
|
30767
|
+
async waitForBlocksMined({
|
|
30768
|
+
startBlock,
|
|
30769
|
+
expectedIncrease,
|
|
30770
|
+
timeoutMs = 3e4,
|
|
30771
|
+
intervalMs = 5e3
|
|
30772
|
+
}) {
|
|
30773
|
+
const deadline = Date.now() + timeoutMs;
|
|
30774
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
30775
|
+
const start = startBlock;
|
|
30776
|
+
const target = start + expectedIncrease;
|
|
30777
|
+
while (Date.now() < deadline) {
|
|
30778
|
+
const currentBlock = await this.getBlockCount();
|
|
30779
|
+
if (currentBlock >= target) return currentBlock;
|
|
30780
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
30781
|
+
}
|
|
30782
|
+
throw new Error(
|
|
30783
|
+
`Timed out waiting for ${expectedIncrease} blocks (target height ${target})`
|
|
30784
|
+
);
|
|
30785
|
+
}
|
|
30779
30786
|
async broadcastTx(txHex) {
|
|
30780
30787
|
let response = await this.call("sendrawtransaction", [txHex, 0]);
|
|
30781
30788
|
return response;
|
|
30782
30789
|
}
|
|
30790
|
+
async submitPackage(txHexs) {
|
|
30791
|
+
let response = await this.call("submitpackage", [txHexs]);
|
|
30792
|
+
return response;
|
|
30793
|
+
}
|
|
30783
30794
|
async getNewAddress() {
|
|
30784
30795
|
const key = import_secp256k113.secp256k1.utils.randomPrivateKey();
|
|
30785
30796
|
const pubKey = import_secp256k113.secp256k1.getPublicKey(key);
|
|
30786
30797
|
return getP2TRAddressFromPublicKey(pubKey, 4 /* LOCAL */);
|
|
30787
30798
|
}
|
|
30799
|
+
async getNewExternalWallet() {
|
|
30800
|
+
const key = import_secp256k113.secp256k1.utils.randomPrivateKey();
|
|
30801
|
+
const pubKey = import_secp256k113.secp256k1.getPublicKey(key);
|
|
30802
|
+
return {
|
|
30803
|
+
address: getP2TRAddressFromPublicKey(pubKey, 4 /* LOCAL */),
|
|
30804
|
+
key,
|
|
30805
|
+
pubKey
|
|
30806
|
+
};
|
|
30807
|
+
}
|
|
30788
30808
|
async sendToAddress(address, amount, blocksToGenerate = 1) {
|
|
30789
30809
|
const coin = await this.fund();
|
|
30790
30810
|
if (!coin) {
|
|
30791
30811
|
throw new Error("No coins available");
|
|
30792
30812
|
}
|
|
30793
|
-
const tx = new
|
|
30813
|
+
const tx = new import_btc_signer4.Transaction();
|
|
30794
30814
|
tx.addInput(coin.outpoint);
|
|
30795
30815
|
const availableAmount = COIN_AMOUNT - FEE_AMOUNT;
|
|
30796
|
-
const destinationAddress = (0,
|
|
30816
|
+
const destinationAddress = (0, import_btc_signer4.Address)(getNetwork(4 /* LOCAL */)).decode(
|
|
30797
30817
|
address
|
|
30798
30818
|
);
|
|
30799
|
-
const destinationScript =
|
|
30819
|
+
const destinationScript = import_btc_signer4.OutScript.encode(destinationAddress);
|
|
30800
30820
|
tx.addOutput({
|
|
30801
30821
|
script: destinationScript,
|
|
30802
30822
|
amount
|
|
@@ -30841,76 +30861,6 @@ function chunkArray(arr, size) {
|
|
|
30841
30861
|
return chunks;
|
|
30842
30862
|
}
|
|
30843
30863
|
|
|
30844
|
-
// src/utils/optimize.ts
|
|
30845
|
-
init_buffer();
|
|
30846
|
-
var DENOMINATIONS = Array.from({ length: 28 }, (_, i) => 2 ** i);
|
|
30847
|
-
function assert(condition, message) {
|
|
30848
|
-
if (!condition) {
|
|
30849
|
-
throw new InternalValidationError(message || "Assertion failed");
|
|
30850
|
-
}
|
|
30851
|
-
}
|
|
30852
|
-
function sum(arr) {
|
|
30853
|
-
return arr.reduce((a, b) => a + b, 0);
|
|
30854
|
-
}
|
|
30855
|
-
function sorted(arr) {
|
|
30856
|
-
return [...arr].sort((a, b) => a - b);
|
|
30857
|
-
}
|
|
30858
|
-
function equals(a, b) {
|
|
30859
|
-
return a.length === b.length && a.every((val, index) => val === b[index]);
|
|
30860
|
-
}
|
|
30861
|
-
function greedyLeaves(amount) {
|
|
30862
|
-
const leaves = [];
|
|
30863
|
-
let remaining = amount;
|
|
30864
|
-
for (let i = DENOMINATIONS.length - 1; i >= 0; i--) {
|
|
30865
|
-
const leaf = DENOMINATIONS[i];
|
|
30866
|
-
if (typeof leaf === "number" && leaf > 0) {
|
|
30867
|
-
while (remaining >= leaf) {
|
|
30868
|
-
remaining -= leaf;
|
|
30869
|
-
leaves.push(leaf);
|
|
30870
|
-
}
|
|
30871
|
-
}
|
|
30872
|
-
}
|
|
30873
|
-
assert(sum(leaves) === amount, "greedy_leaves: sum mismatch");
|
|
30874
|
-
return sorted(leaves);
|
|
30875
|
-
}
|
|
30876
|
-
var Swap = class {
|
|
30877
|
-
inLeaves;
|
|
30878
|
-
outLeaves;
|
|
30879
|
-
constructor(inLeaves, outLeaves) {
|
|
30880
|
-
this.inLeaves = [...inLeaves];
|
|
30881
|
-
this.outLeaves = [...outLeaves];
|
|
30882
|
-
assert(
|
|
30883
|
-
sum(this.inLeaves) === sum(this.outLeaves),
|
|
30884
|
-
"Swap in/out leaves must sum to same value for swap: " + this.toString()
|
|
30885
|
-
);
|
|
30886
|
-
}
|
|
30887
|
-
toString() {
|
|
30888
|
-
return `Swap(in=${JSON.stringify(this.inLeaves)}, out=${JSON.stringify(this.outLeaves)})`;
|
|
30889
|
-
}
|
|
30890
|
-
};
|
|
30891
|
-
function maximizeUnilateralExit(inputLeaves, maxLeavesPerSwap = 64) {
|
|
30892
|
-
const swaps = [];
|
|
30893
|
-
let batch = [];
|
|
30894
|
-
let leaves = sorted(inputLeaves);
|
|
30895
|
-
while (leaves.length > 0) {
|
|
30896
|
-
batch.push(leaves.shift());
|
|
30897
|
-
const target = greedyLeaves(sum(batch));
|
|
30898
|
-
if (batch.length >= maxLeavesPerSwap || target.length >= maxLeavesPerSwap) {
|
|
30899
|
-
if (!equals(target, batch)) {
|
|
30900
|
-
swaps.push(new Swap([...batch], target));
|
|
30901
|
-
}
|
|
30902
|
-
batch = [];
|
|
30903
|
-
}
|
|
30904
|
-
}
|
|
30905
|
-
if (batch.length > 0) {
|
|
30906
|
-
const target = greedyLeaves(sum(batch));
|
|
30907
|
-
if (!equals(target, batch)) {
|
|
30908
|
-
swaps.push(new Swap([...batch], target));
|
|
30909
|
-
}
|
|
30910
|
-
}
|
|
30911
|
-
return swaps;
|
|
30912
|
-
}
|
|
30913
|
-
|
|
30914
30864
|
// src/utils/retry.ts
|
|
30915
30865
|
init_buffer();
|
|
30916
30866
|
var DEFAULT_RETRY_CONFIG = {
|
|
@@ -30989,6 +30939,200 @@ var SparkWalletEvent = {
|
|
|
30989
30939
|
StreamReconnecting: "stream:reconnecting"
|
|
30990
30940
|
};
|
|
30991
30941
|
|
|
30942
|
+
// src/utils/optimize.ts
|
|
30943
|
+
init_buffer();
|
|
30944
|
+
var DENOMINATIONS = Array.from({ length: 28 }, (_, i) => 2 ** i);
|
|
30945
|
+
function assert(condition, message) {
|
|
30946
|
+
if (!condition) {
|
|
30947
|
+
throw new InternalValidationError(message || "Assertion failed");
|
|
30948
|
+
}
|
|
30949
|
+
}
|
|
30950
|
+
function sum(arr) {
|
|
30951
|
+
return arr.reduce((a, b) => a + b, 0);
|
|
30952
|
+
}
|
|
30953
|
+
function sorted(arr) {
|
|
30954
|
+
return [...arr].sort((a, b) => a - b);
|
|
30955
|
+
}
|
|
30956
|
+
function equals(a, b) {
|
|
30957
|
+
return a.length === b.length && a.every((val, index) => val === b[index]);
|
|
30958
|
+
}
|
|
30959
|
+
function countOccurrences(arr) {
|
|
30960
|
+
const map = /* @__PURE__ */ new Map();
|
|
30961
|
+
for (const x of arr) {
|
|
30962
|
+
map.set(x, (map.get(x) ?? 0) + 1);
|
|
30963
|
+
}
|
|
30964
|
+
return map;
|
|
30965
|
+
}
|
|
30966
|
+
function subtractCounters(a, b) {
|
|
30967
|
+
const result = /* @__PURE__ */ new Map();
|
|
30968
|
+
for (const [key, value] of a.entries()) {
|
|
30969
|
+
const diff = value - (b.get(key) ?? 0);
|
|
30970
|
+
if (diff > 0) {
|
|
30971
|
+
result.set(key, diff);
|
|
30972
|
+
}
|
|
30973
|
+
}
|
|
30974
|
+
return result;
|
|
30975
|
+
}
|
|
30976
|
+
function counterToFlatArray(counter) {
|
|
30977
|
+
const arr = [];
|
|
30978
|
+
for (const [k, v] of Array.from(counter.entries()).sort(
|
|
30979
|
+
(a, b) => a[0] - b[0]
|
|
30980
|
+
)) {
|
|
30981
|
+
for (let i = 0; i < v; i++) {
|
|
30982
|
+
arr.push(k);
|
|
30983
|
+
}
|
|
30984
|
+
}
|
|
30985
|
+
return arr;
|
|
30986
|
+
}
|
|
30987
|
+
function greedyLeaves(amount) {
|
|
30988
|
+
const leaves = [];
|
|
30989
|
+
let remaining = amount;
|
|
30990
|
+
for (let i = DENOMINATIONS.length - 1; i >= 0; i--) {
|
|
30991
|
+
const leaf = DENOMINATIONS[i];
|
|
30992
|
+
if (typeof leaf === "number" && leaf > 0) {
|
|
30993
|
+
while (remaining >= leaf) {
|
|
30994
|
+
remaining -= leaf;
|
|
30995
|
+
leaves.push(leaf);
|
|
30996
|
+
}
|
|
30997
|
+
}
|
|
30998
|
+
}
|
|
30999
|
+
assert(sum(leaves) === amount, "greedy_leaves: sum mismatch");
|
|
31000
|
+
return sorted(leaves);
|
|
31001
|
+
}
|
|
31002
|
+
function swapMinimizingLeaves(amount, multiplicity = 1) {
|
|
31003
|
+
const leaves = [];
|
|
31004
|
+
let remaining = amount;
|
|
31005
|
+
assert(multiplicity > 0, "multiplicity must be > 0");
|
|
31006
|
+
for (const leaf of DENOMINATIONS) {
|
|
31007
|
+
if (typeof leaf === "number" && leaf > 0) {
|
|
31008
|
+
for (let i = 0; i < multiplicity; i++) {
|
|
31009
|
+
if (remaining >= leaf) {
|
|
31010
|
+
remaining -= leaf;
|
|
31011
|
+
leaves.push(leaf);
|
|
31012
|
+
}
|
|
31013
|
+
}
|
|
31014
|
+
}
|
|
31015
|
+
}
|
|
31016
|
+
leaves.push(...greedyLeaves(remaining));
|
|
31017
|
+
assert(sum(leaves) === amount, "swap_minimizing_leaves: sum mismatch");
|
|
31018
|
+
return sorted(leaves);
|
|
31019
|
+
}
|
|
31020
|
+
var Swap = class {
|
|
31021
|
+
inLeaves;
|
|
31022
|
+
outLeaves;
|
|
31023
|
+
constructor(inLeaves, outLeaves) {
|
|
31024
|
+
this.inLeaves = [...inLeaves];
|
|
31025
|
+
this.outLeaves = [...outLeaves];
|
|
31026
|
+
assert(
|
|
31027
|
+
sum(this.inLeaves) === sum(this.outLeaves),
|
|
31028
|
+
"Swap in/out leaves must sum to same value for swap: " + this.toString()
|
|
31029
|
+
);
|
|
31030
|
+
}
|
|
31031
|
+
toString() {
|
|
31032
|
+
return `Swap(in=${JSON.stringify(this.inLeaves)}, out=${JSON.stringify(this.outLeaves)})`;
|
|
31033
|
+
}
|
|
31034
|
+
};
|
|
31035
|
+
function maximizeUnilateralExit(inputLeaves, maxLeavesPerSwap = 64) {
|
|
31036
|
+
const swaps = [];
|
|
31037
|
+
let batch = [];
|
|
31038
|
+
let leaves = sorted(inputLeaves);
|
|
31039
|
+
while (leaves.length > 0) {
|
|
31040
|
+
batch.push(leaves.shift());
|
|
31041
|
+
const target = greedyLeaves(sum(batch));
|
|
31042
|
+
if (batch.length >= maxLeavesPerSwap || target.length >= maxLeavesPerSwap) {
|
|
31043
|
+
if (!equals(target, batch)) {
|
|
31044
|
+
swaps.push(new Swap([...batch], target));
|
|
31045
|
+
}
|
|
31046
|
+
batch = [];
|
|
31047
|
+
}
|
|
31048
|
+
}
|
|
31049
|
+
if (batch.length > 0) {
|
|
31050
|
+
const target = greedyLeaves(sum(batch));
|
|
31051
|
+
if (!equals(target, batch)) {
|
|
31052
|
+
swaps.push(new Swap([...batch], target));
|
|
31053
|
+
}
|
|
31054
|
+
}
|
|
31055
|
+
return swaps;
|
|
31056
|
+
}
|
|
31057
|
+
function minimizeTransferSwap(inputLeaves, multiplicity = 1, maxLeavesPerSwap = 64) {
|
|
31058
|
+
const balance = sum(inputLeaves);
|
|
31059
|
+
const optimalLeaves = swapMinimizingLeaves(balance, multiplicity);
|
|
31060
|
+
const walletCounter = countOccurrences(inputLeaves);
|
|
31061
|
+
const optimalCounter = countOccurrences(optimalLeaves);
|
|
31062
|
+
const leavesToGive = subtractCounters(walletCounter, optimalCounter);
|
|
31063
|
+
const leavesToReceive = subtractCounters(optimalCounter, walletCounter);
|
|
31064
|
+
const leavesToGiveFlat = counterToFlatArray(leavesToGive);
|
|
31065
|
+
const leavesToReceiveFlat = counterToFlatArray(leavesToReceive);
|
|
31066
|
+
const swaps = [];
|
|
31067
|
+
let toGiveBatch = [];
|
|
31068
|
+
let toReceiveBatch = [];
|
|
31069
|
+
let give = [...leavesToGiveFlat];
|
|
31070
|
+
let receive = [...leavesToReceiveFlat];
|
|
31071
|
+
while (give.length > 0 || receive.length > 0) {
|
|
31072
|
+
if (sum(toGiveBatch) > sum(toReceiveBatch)) {
|
|
31073
|
+
if (receive.length === 0) break;
|
|
31074
|
+
toReceiveBatch.push(receive.shift());
|
|
31075
|
+
} else {
|
|
31076
|
+
if (give.length === 0) break;
|
|
31077
|
+
toGiveBatch.push(give.shift());
|
|
31078
|
+
}
|
|
31079
|
+
if (toGiveBatch.length > 0 && toReceiveBatch.length > 0 && sum(toGiveBatch) === sum(toReceiveBatch)) {
|
|
31080
|
+
if (toGiveBatch.length > maxLeavesPerSwap) {
|
|
31081
|
+
for (let i = 0; i < toGiveBatch.length; i += maxLeavesPerSwap) {
|
|
31082
|
+
const subset = toGiveBatch.slice(i, i + maxLeavesPerSwap);
|
|
31083
|
+
swaps.push(new Swap(subset, greedyLeaves(sum(subset))));
|
|
31084
|
+
}
|
|
31085
|
+
} else if (toReceiveBatch.length > maxLeavesPerSwap) {
|
|
31086
|
+
for (let cutoff = maxLeavesPerSwap; cutoff > 0; cutoff--) {
|
|
31087
|
+
const sumCut = sum(toReceiveBatch.slice(0, cutoff));
|
|
31088
|
+
const remainder = sum(toGiveBatch) - sumCut;
|
|
31089
|
+
const alternateBatch = [
|
|
31090
|
+
...toReceiveBatch.slice(0, cutoff),
|
|
31091
|
+
...greedyLeaves(remainder)
|
|
31092
|
+
];
|
|
31093
|
+
if (alternateBatch.length <= maxLeavesPerSwap) {
|
|
31094
|
+
swaps.push(new Swap([...toGiveBatch], alternateBatch));
|
|
31095
|
+
break;
|
|
31096
|
+
}
|
|
31097
|
+
}
|
|
31098
|
+
} else {
|
|
31099
|
+
swaps.push(new Swap([...toGiveBatch], [...toReceiveBatch]));
|
|
31100
|
+
}
|
|
31101
|
+
toGiveBatch = [];
|
|
31102
|
+
toReceiveBatch = [];
|
|
31103
|
+
}
|
|
31104
|
+
}
|
|
31105
|
+
return swaps;
|
|
31106
|
+
}
|
|
31107
|
+
function shouldOptimize(inputLeaves, multiplicity = 1, maxLeavesPerSwap = 64) {
|
|
31108
|
+
if (multiplicity == 0) {
|
|
31109
|
+
const swaps = maximizeUnilateralExit(inputLeaves, maxLeavesPerSwap);
|
|
31110
|
+
const numInputs = sum(swaps.map((swap) => swap.inLeaves.length));
|
|
31111
|
+
const numOutputs = sum(swaps.map((swap) => swap.outLeaves.length));
|
|
31112
|
+
return numOutputs * 5 < numInputs;
|
|
31113
|
+
} else {
|
|
31114
|
+
const swaps = minimizeTransferSwap(
|
|
31115
|
+
inputLeaves,
|
|
31116
|
+
multiplicity,
|
|
31117
|
+
maxLeavesPerSwap
|
|
31118
|
+
);
|
|
31119
|
+
const inputCounter = countOccurrences(
|
|
31120
|
+
swaps.flatMap((swap) => swap.inLeaves)
|
|
31121
|
+
);
|
|
31122
|
+
const outputCounter = countOccurrences(
|
|
31123
|
+
swaps.flatMap((swap) => swap.outLeaves)
|
|
31124
|
+
);
|
|
31125
|
+
return Math.abs(inputCounter.size - outputCounter.size) > 1;
|
|
31126
|
+
}
|
|
31127
|
+
}
|
|
31128
|
+
function optimize(inputLeaves, multiplicity = 1, maxLeavesPerSwap = 64) {
|
|
31129
|
+
if (multiplicity == 0) {
|
|
31130
|
+
return maximizeUnilateralExit(inputLeaves, maxLeavesPerSwap);
|
|
31131
|
+
} else {
|
|
31132
|
+
return minimizeTransferSwap(inputLeaves, multiplicity, maxLeavesPerSwap);
|
|
31133
|
+
}
|
|
31134
|
+
}
|
|
31135
|
+
|
|
30992
31136
|
// src/spark-wallet/spark-wallet.ts
|
|
30993
31137
|
var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
30994
31138
|
config;
|
|
@@ -31093,16 +31237,13 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
31093
31237
|
if (event.transfer.transfer && !(0, import_utils25.equalBytes)(senderIdentityPublicKey, receiverIdentityPublicKey)) {
|
|
31094
31238
|
await this.claimTransfer({
|
|
31095
31239
|
transfer: event.transfer.transfer,
|
|
31096
|
-
emit: true
|
|
31097
|
-
optimize: true
|
|
31240
|
+
emit: true
|
|
31098
31241
|
});
|
|
31099
31242
|
}
|
|
31100
31243
|
} else if (isDepositStreamEvent(event)) {
|
|
31101
31244
|
const deposit = event.deposit.deposit;
|
|
31102
|
-
|
|
31103
|
-
|
|
31104
|
-
type: "leaf" /* LEAF */,
|
|
31105
|
-
path: deposit.id
|
|
31245
|
+
await this.withLeaves(async () => {
|
|
31246
|
+
this.leaves.push(deposit);
|
|
31106
31247
|
});
|
|
31107
31248
|
this.emit(
|
|
31108
31249
|
SparkWalletEvent.DepositConfirmed,
|
|
@@ -31278,19 +31419,6 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
31278
31419
|
}
|
|
31279
31420
|
return availableLeaves.filter(([_, node]) => !leavesToIgnore.has(node.id)).map(([_, node]) => node);
|
|
31280
31421
|
}
|
|
31281
|
-
async checkExtendLeaves(leaves) {
|
|
31282
|
-
await this.withLeaves(async () => {
|
|
31283
|
-
for (const leaf of leaves) {
|
|
31284
|
-
if (!leaf.parentNodeId && leaf.status === "AVAILABLE") {
|
|
31285
|
-
const res = await this.transferService.extendTimelock(leaf);
|
|
31286
|
-
await this.transferLeavesToSelf(res.nodes, {
|
|
31287
|
-
type: "leaf" /* LEAF */,
|
|
31288
|
-
path: leaf.id
|
|
31289
|
-
});
|
|
31290
|
-
}
|
|
31291
|
-
}
|
|
31292
|
-
});
|
|
31293
|
-
}
|
|
31294
31422
|
verifyKey(pubkey1, pubkey2, verifyingKey) {
|
|
31295
31423
|
return (0, import_utils25.equalBytes)(addPublicKeys(pubkey1, pubkey2), verifyingKey);
|
|
31296
31424
|
}
|
|
@@ -31400,75 +31528,84 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
31400
31528
|
}
|
|
31401
31529
|
return nodes;
|
|
31402
31530
|
}
|
|
31403
|
-
|
|
31404
|
-
const
|
|
31405
|
-
if (
|
|
31406
|
-
|
|
31407
|
-
}
|
|
31408
|
-
|
|
31409
|
-
let remainingAmount = totalAmount;
|
|
31410
|
-
let optimalLeavesLength = 0;
|
|
31411
|
-
for (let i = nextLowerPowerOfTwo; i >= 0; i--) {
|
|
31412
|
-
const denomination = 2 ** i;
|
|
31413
|
-
while (remainingAmount >= denomination) {
|
|
31414
|
-
remainingAmount -= denomination;
|
|
31415
|
-
optimalLeavesLength++;
|
|
31416
|
-
}
|
|
31531
|
+
async *optimizeLeaves(multiplicity = void 0) {
|
|
31532
|
+
const multiplicityValue = multiplicity ?? this.config.getOptimizationOptions().multiplicity ?? 0;
|
|
31533
|
+
if (multiplicityValue < 0) {
|
|
31534
|
+
throw new ValidationError("Multiplicity cannot be negative");
|
|
31535
|
+
} else if (multiplicityValue > 5) {
|
|
31536
|
+
throw new ValidationError("Multiplicity cannot be greater than 5");
|
|
31417
31537
|
}
|
|
31418
|
-
|
|
31419
|
-
|
|
31420
|
-
|
|
31421
|
-
|
|
31538
|
+
if (this.optimizationInProgress || !shouldOptimize(
|
|
31539
|
+
this.leaves.map((leaf) => leaf.value),
|
|
31540
|
+
multiplicityValue
|
|
31541
|
+
)) {
|
|
31422
31542
|
return;
|
|
31423
31543
|
}
|
|
31424
|
-
|
|
31544
|
+
const controller = new AbortController();
|
|
31545
|
+
const release = await this.leavesMutex.acquire();
|
|
31546
|
+
try {
|
|
31425
31547
|
this.optimizationInProgress = true;
|
|
31426
|
-
|
|
31427
|
-
|
|
31428
|
-
|
|
31429
|
-
|
|
31430
|
-
|
|
31431
|
-
|
|
31432
|
-
|
|
31433
|
-
|
|
31434
|
-
|
|
31435
|
-
|
|
31436
|
-
|
|
31437
|
-
|
|
31438
|
-
|
|
31439
|
-
|
|
31440
|
-
|
|
31441
|
-
|
|
31442
|
-
|
|
31443
|
-
|
|
31444
|
-
|
|
31445
|
-
|
|
31446
|
-
|
|
31447
|
-
|
|
31448
|
-
|
|
31449
|
-
|
|
31548
|
+
this.leaves = await this.getLeaves();
|
|
31549
|
+
const swaps = optimize(
|
|
31550
|
+
this.leaves.map((leaf) => leaf.value),
|
|
31551
|
+
multiplicityValue
|
|
31552
|
+
);
|
|
31553
|
+
if (swaps.length === 0) {
|
|
31554
|
+
return;
|
|
31555
|
+
}
|
|
31556
|
+
yield {
|
|
31557
|
+
step: 0,
|
|
31558
|
+
total: swaps.length,
|
|
31559
|
+
controller
|
|
31560
|
+
};
|
|
31561
|
+
const valueToNodes = /* @__PURE__ */ new Map();
|
|
31562
|
+
this.leaves.forEach((leaf) => {
|
|
31563
|
+
if (!valueToNodes.has(leaf.value)) {
|
|
31564
|
+
valueToNodes.set(leaf.value, []);
|
|
31565
|
+
}
|
|
31566
|
+
valueToNodes.get(leaf.value).push(leaf);
|
|
31567
|
+
});
|
|
31568
|
+
for (const swap of swaps) {
|
|
31569
|
+
if (controller.signal.aborted) {
|
|
31570
|
+
break;
|
|
31571
|
+
}
|
|
31572
|
+
const leavesToSend = [];
|
|
31573
|
+
for (const leafValue of swap.inLeaves) {
|
|
31574
|
+
const nodes = valueToNodes.get(leafValue);
|
|
31575
|
+
if (nodes && nodes.length > 0) {
|
|
31576
|
+
const node = nodes.shift();
|
|
31577
|
+
leavesToSend.push(node);
|
|
31578
|
+
} else {
|
|
31579
|
+
throw new InternalValidationError(
|
|
31580
|
+
`No unused leaf with value ${leafValue} found in leaves`
|
|
31581
|
+
);
|
|
31450
31582
|
}
|
|
31451
|
-
await this.requestLeavesSwap({
|
|
31452
|
-
leaves: leavesToSend,
|
|
31453
|
-
targetAmounts: swap.outLeaves
|
|
31454
|
-
});
|
|
31455
31583
|
}
|
|
31456
|
-
|
|
31457
|
-
|
|
31458
|
-
|
|
31584
|
+
await this.requestLeavesSwap({
|
|
31585
|
+
leaves: leavesToSend,
|
|
31586
|
+
targetAmounts: swap.outLeaves
|
|
31587
|
+
});
|
|
31588
|
+
yield {
|
|
31589
|
+
step: swaps.indexOf(swap) + 1,
|
|
31590
|
+
total: swaps.length,
|
|
31591
|
+
controller
|
|
31592
|
+
};
|
|
31459
31593
|
}
|
|
31460
|
-
|
|
31594
|
+
this.leaves = await this.getLeaves();
|
|
31595
|
+
} finally {
|
|
31596
|
+
this.optimizationInProgress = false;
|
|
31597
|
+
release();
|
|
31598
|
+
}
|
|
31461
31599
|
}
|
|
31462
31600
|
async syncWallet() {
|
|
31463
31601
|
await this.syncTokenOutputs();
|
|
31464
31602
|
let leaves = await this.getLeaves();
|
|
31465
|
-
leaves = await this.
|
|
31466
|
-
leaves = await this.checkExtendTimeLockNodes(leaves);
|
|
31603
|
+
leaves = await this.checkRenewLeaves(leaves);
|
|
31467
31604
|
this.leaves = leaves;
|
|
31468
|
-
this.
|
|
31469
|
-
|
|
31470
|
-
|
|
31471
|
-
}
|
|
31605
|
+
if (this.config.getOptimizationOptions().auto) {
|
|
31606
|
+
for await (const _ of this.optimizeLeaves()) {
|
|
31607
|
+
}
|
|
31608
|
+
}
|
|
31472
31609
|
}
|
|
31473
31610
|
async withLeaves(operation) {
|
|
31474
31611
|
const release = await this.leavesMutex.acquire();
|
|
@@ -32051,8 +32188,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
32051
32188
|
}
|
|
32052
32189
|
return await this.claimTransfer({
|
|
32053
32190
|
transfer: incomingTransfer,
|
|
32054
|
-
emit: false
|
|
32055
|
-
optimize: false
|
|
32191
|
+
emit: false
|
|
32056
32192
|
});
|
|
32057
32193
|
} catch (e) {
|
|
32058
32194
|
console.error("[processSwapBatch] Error details:", {
|
|
@@ -32446,16 +32582,16 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
32446
32582
|
}
|
|
32447
32583
|
);
|
|
32448
32584
|
}
|
|
32449
|
-
const tx = new
|
|
32585
|
+
const tx = new import_btc_signer5.Transaction();
|
|
32450
32586
|
tx.addInput({
|
|
32451
32587
|
txid: depositTransactionId,
|
|
32452
32588
|
index: outputIndex,
|
|
32453
32589
|
witnessScript: new Uint8Array()
|
|
32454
32590
|
});
|
|
32455
|
-
const addressDecoded = (0,
|
|
32591
|
+
const addressDecoded = (0, import_btc_signer5.Address)(getNetwork(network)).decode(
|
|
32456
32592
|
destinationAddress
|
|
32457
32593
|
);
|
|
32458
|
-
const outputScript =
|
|
32594
|
+
const outputScript = import_btc_signer5.OutScript.encode(addressDecoded);
|
|
32459
32595
|
tx.addOutput({
|
|
32460
32596
|
script: outputScript,
|
|
32461
32597
|
amount: BigInt(creditAmountSats)
|
|
@@ -32639,8 +32775,8 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
32639
32775
|
if (!output) {
|
|
32640
32776
|
continue;
|
|
32641
32777
|
}
|
|
32642
|
-
const parsedScript =
|
|
32643
|
-
const address = (0,
|
|
32778
|
+
const parsedScript = import_btc_signer5.OutScript.decode(output.script);
|
|
32779
|
+
const address = (0, import_btc_signer5.Address)(getNetwork(this.config.getNetwork())).encode(
|
|
32644
32780
|
parsedScript
|
|
32645
32781
|
);
|
|
32646
32782
|
if (staticDepositAddresses.has(address)) {
|
|
@@ -32717,26 +32853,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
32717
32853
|
depositTx,
|
|
32718
32854
|
vout
|
|
32719
32855
|
});
|
|
32720
|
-
|
|
32721
|
-
for (const node of res.nodes) {
|
|
32722
|
-
if (node.status === "AVAILABLE") {
|
|
32723
|
-
const { nodes } = await this.transferService.extendTimelock(node);
|
|
32724
|
-
for (const n of nodes) {
|
|
32725
|
-
if (n.status === "AVAILABLE") {
|
|
32726
|
-
const transfer = await this.transferLeavesToSelf([n], {
|
|
32727
|
-
type: "leaf" /* LEAF */,
|
|
32728
|
-
path: node.id
|
|
32729
|
-
});
|
|
32730
|
-
resultingNodes.push(...transfer);
|
|
32731
|
-
} else {
|
|
32732
|
-
resultingNodes.push(n);
|
|
32733
|
-
}
|
|
32734
|
-
}
|
|
32735
|
-
} else {
|
|
32736
|
-
resultingNodes.push(node);
|
|
32737
|
-
}
|
|
32738
|
-
}
|
|
32739
|
-
return resultingNodes;
|
|
32856
|
+
return res.nodes;
|
|
32740
32857
|
}
|
|
32741
32858
|
/**
|
|
32742
32859
|
* Gets all unused deposit addresses for the wallet.
|
|
@@ -32845,8 +32962,8 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
32845
32962
|
if (!output) {
|
|
32846
32963
|
continue;
|
|
32847
32964
|
}
|
|
32848
|
-
const parsedScript =
|
|
32849
|
-
const address = (0,
|
|
32965
|
+
const parsedScript = import_btc_signer5.OutScript.decode(output.script);
|
|
32966
|
+
const address = (0, import_btc_signer5.Address)(getNetwork(this.config.getNetwork())).encode(
|
|
32850
32967
|
parsedScript
|
|
32851
32968
|
);
|
|
32852
32969
|
if (unusedDepositAddresses.has(address)) {
|
|
@@ -32878,6 +32995,9 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
32878
32995
|
depositTx,
|
|
32879
32996
|
vout
|
|
32880
32997
|
});
|
|
32998
|
+
await this.withLeaves(async () => {
|
|
32999
|
+
this.leaves.push(...nodes2);
|
|
33000
|
+
});
|
|
32881
33001
|
return nodes2;
|
|
32882
33002
|
});
|
|
32883
33003
|
this.mutexes.delete(txid);
|
|
@@ -32906,8 +33026,8 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
32906
33026
|
if (!output) {
|
|
32907
33027
|
continue;
|
|
32908
33028
|
}
|
|
32909
|
-
const parsedScript =
|
|
32910
|
-
const address = (0,
|
|
33029
|
+
const parsedScript = import_btc_signer5.OutScript.decode(output.script);
|
|
33030
|
+
const address = (0, import_btc_signer5.Address)(getNetwork(this.config.getNetwork())).encode(
|
|
32911
33031
|
parsedScript
|
|
32912
33032
|
);
|
|
32913
33033
|
const unusedDepositAddress = unusedDepositAddresses.get(address);
|
|
@@ -33054,8 +33174,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33054
33174
|
`TreeNode group at index ${groupIndex} not found for amount ${amount} after selection`
|
|
33055
33175
|
);
|
|
33056
33176
|
}
|
|
33057
|
-
|
|
33058
|
-
available = await this.checkExtendTimeLockNodes(available);
|
|
33177
|
+
const available = await this.checkRenewLeaves(group);
|
|
33059
33178
|
if (available.length < group.length) {
|
|
33060
33179
|
throw new Error(
|
|
33061
33180
|
`Not enough available nodes after refresh/extend. Expected ${group.length}, got ${available.length}`
|
|
@@ -33098,7 +33217,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33098
33217
|
transfer.id
|
|
33099
33218
|
);
|
|
33100
33219
|
if (pending) {
|
|
33101
|
-
await this.claimTransfer({ transfer: pending
|
|
33220
|
+
await this.claimTransfer({ transfer: pending });
|
|
33102
33221
|
}
|
|
33103
33222
|
}
|
|
33104
33223
|
return {
|
|
@@ -33148,75 +33267,45 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33148
33267
|
newKeyDerivation: { type: "random" /* RANDOM */ }
|
|
33149
33268
|
};
|
|
33150
33269
|
}
|
|
33151
|
-
async
|
|
33152
|
-
const
|
|
33270
|
+
async checkRenewLeaves(nodes) {
|
|
33271
|
+
const nodesToRenewNode = [];
|
|
33272
|
+
const nodesToRenewRefund = [];
|
|
33273
|
+
const nodesToRenewZeroTimelock = [];
|
|
33153
33274
|
const nodeIds = [];
|
|
33154
33275
|
const validNodes = [];
|
|
33155
33276
|
for (const node of nodes) {
|
|
33156
33277
|
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
33157
|
-
const
|
|
33158
|
-
|
|
33278
|
+
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
33279
|
+
const nodeSequence = nodeTx.getInput(0).sequence;
|
|
33280
|
+
const refundSequence = refundTx.getInput(0).sequence;
|
|
33281
|
+
if (nodeSequence === void 0) {
|
|
33159
33282
|
throw new ValidationError("Invalid node transaction", {
|
|
33160
33283
|
field: "sequence",
|
|
33161
33284
|
value: nodeTx.getInput(0),
|
|
33162
33285
|
expected: "Non-null sequence"
|
|
33163
33286
|
});
|
|
33164
33287
|
}
|
|
33165
|
-
|
|
33166
|
-
if (needsRefresh) {
|
|
33167
|
-
nodesToExtend.push(node);
|
|
33168
|
-
nodeIds.push(node.id);
|
|
33169
|
-
} else {
|
|
33170
|
-
validNodes.push(node);
|
|
33171
|
-
}
|
|
33172
|
-
}
|
|
33173
|
-
if (nodesToExtend.length === 0) {
|
|
33174
|
-
return validNodes;
|
|
33175
|
-
}
|
|
33176
|
-
const nodesToAdd = [];
|
|
33177
|
-
for (const node of nodesToExtend) {
|
|
33178
|
-
const { nodes: nodes2 } = await this.transferService.extendTimelock(node);
|
|
33179
|
-
this.leaves = this.leaves.filter((leaf) => leaf.id !== node.id);
|
|
33180
|
-
const newNodes = await this.transferLeavesToSelf(nodes2, {
|
|
33181
|
-
type: "leaf" /* LEAF */,
|
|
33182
|
-
path: node.id
|
|
33183
|
-
});
|
|
33184
|
-
nodesToAdd.push(...newNodes);
|
|
33185
|
-
}
|
|
33186
|
-
this.updateLeaves(nodeIds, nodesToAdd);
|
|
33187
|
-
validNodes.push(...nodesToAdd);
|
|
33188
|
-
return validNodes;
|
|
33189
|
-
}
|
|
33190
|
-
/**
|
|
33191
|
-
* Internal method to refresh timelock nodes.
|
|
33192
|
-
*
|
|
33193
|
-
* @param {string} nodeId - The optional ID of the node to refresh. If not provided, all nodes will be checked.
|
|
33194
|
-
* @returns {Promise<void>}
|
|
33195
|
-
* @private
|
|
33196
|
-
*/
|
|
33197
|
-
async checkRefreshTimelockNodes(nodes) {
|
|
33198
|
-
const nodesToRefresh = [];
|
|
33199
|
-
const nodeIds = [];
|
|
33200
|
-
const validNodes = [];
|
|
33201
|
-
for (const node of nodes) {
|
|
33202
|
-
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
33203
|
-
const sequence = refundTx.getInput(0).sequence;
|
|
33204
|
-
if (!sequence) {
|
|
33288
|
+
if (!refundSequence) {
|
|
33205
33289
|
throw new ValidationError("Invalid refund transaction", {
|
|
33206
33290
|
field: "sequence",
|
|
33207
33291
|
value: refundTx.getInput(0),
|
|
33208
33292
|
expected: "Non-null sequence"
|
|
33209
33293
|
});
|
|
33210
33294
|
}
|
|
33211
|
-
|
|
33212
|
-
|
|
33213
|
-
|
|
33295
|
+
if (doesTxnNeedRenewed(refundSequence)) {
|
|
33296
|
+
if (isZeroTimelock(nodeSequence)) {
|
|
33297
|
+
nodesToRenewZeroTimelock.push(node);
|
|
33298
|
+
} else if (doesTxnNeedRenewed(nodeSequence)) {
|
|
33299
|
+
nodesToRenewNode.push(node);
|
|
33300
|
+
} else {
|
|
33301
|
+
nodesToRenewRefund.push(node);
|
|
33302
|
+
}
|
|
33214
33303
|
nodeIds.push(node.id);
|
|
33215
33304
|
} else {
|
|
33216
33305
|
validNodes.push(node);
|
|
33217
33306
|
}
|
|
33218
33307
|
}
|
|
33219
|
-
if (
|
|
33308
|
+
if (nodesToRenewNode.length === 0 && nodesToRenewRefund.length === 0 && nodesToRenewZeroTimelock.length === 0) {
|
|
33220
33309
|
return validNodes;
|
|
33221
33310
|
}
|
|
33222
33311
|
const nodesResp = await this.queryNodes({
|
|
@@ -33234,7 +33323,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33234
33323
|
nodesMap.set(node.id, node);
|
|
33235
33324
|
}
|
|
33236
33325
|
const nodesToAdd = [];
|
|
33237
|
-
for (const node of
|
|
33326
|
+
for (const node of nodesToRenewNode) {
|
|
33238
33327
|
if (!node.parentNodeId) {
|
|
33239
33328
|
throw new Error(`node ${node.id} has no parent`);
|
|
33240
33329
|
}
|
|
@@ -33242,17 +33331,25 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33242
33331
|
if (!parentNode) {
|
|
33243
33332
|
throw new Error(`parent node ${node.parentNodeId} not found`);
|
|
33244
33333
|
}
|
|
33245
|
-
const
|
|
33334
|
+
const newNode = await this.transferService.renewNodeTxn(node, parentNode);
|
|
33335
|
+
nodesToAdd.push(newNode);
|
|
33336
|
+
}
|
|
33337
|
+
for (const node of nodesToRenewRefund) {
|
|
33338
|
+
if (!node.parentNodeId) {
|
|
33339
|
+
throw new Error(`node ${node.id} has no parent`);
|
|
33340
|
+
}
|
|
33341
|
+
const parentNode = nodesMap.get(node.parentNodeId);
|
|
33342
|
+
if (!parentNode) {
|
|
33343
|
+
throw new Error(`parent node ${node.parentNodeId} not found`);
|
|
33344
|
+
}
|
|
33345
|
+
const newNode = await this.transferService.renewRefundTxn(
|
|
33246
33346
|
node,
|
|
33247
33347
|
parentNode
|
|
33248
33348
|
);
|
|
33249
|
-
|
|
33250
|
-
|
|
33251
|
-
|
|
33252
|
-
const newNode =
|
|
33253
|
-
if (!newNode) {
|
|
33254
|
-
throw new Error("Failed to refresh timelock node");
|
|
33255
|
-
}
|
|
33349
|
+
nodesToAdd.push(newNode);
|
|
33350
|
+
}
|
|
33351
|
+
for (const node of nodesToRenewZeroTimelock) {
|
|
33352
|
+
const newNode = await this.transferService.renewZeroTimelockNodeTxn(node);
|
|
33256
33353
|
nodesToAdd.push(newNode);
|
|
33257
33354
|
}
|
|
33258
33355
|
this.updateLeaves(nodeIds, nodesToAdd);
|
|
@@ -33293,14 +33390,14 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33293
33390
|
return response.nodes;
|
|
33294
33391
|
});
|
|
33295
33392
|
}
|
|
33296
|
-
async processClaimedTransferResults(result, transfer, emit
|
|
33297
|
-
result = await this.
|
|
33298
|
-
result = await this.checkExtendTimeLockNodes(result);
|
|
33393
|
+
async processClaimedTransferResults(result, transfer, emit) {
|
|
33394
|
+
result = await this.checkRenewLeaves(result);
|
|
33299
33395
|
const existingIds = new Set(this.leaves.map((leaf) => leaf.id));
|
|
33300
33396
|
const uniqueResults = result.filter((node) => !existingIds.has(node.id));
|
|
33301
33397
|
this.leaves.push(...uniqueResults);
|
|
33302
|
-
if (
|
|
33303
|
-
await this.optimizeLeaves()
|
|
33398
|
+
if (this.config.getOptimizationOptions().auto && transfer.type !== 40 /* COUNTER_SWAP */) {
|
|
33399
|
+
for await (const _ of this.optimizeLeaves()) {
|
|
33400
|
+
}
|
|
33304
33401
|
}
|
|
33305
33402
|
if (emit) {
|
|
33306
33403
|
this.emit(
|
|
@@ -33319,8 +33416,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33319
33416
|
*/
|
|
33320
33417
|
async claimTransfer({
|
|
33321
33418
|
transfer,
|
|
33322
|
-
emit
|
|
33323
|
-
optimize
|
|
33419
|
+
emit
|
|
33324
33420
|
}) {
|
|
33325
33421
|
const onError = async (context) => {
|
|
33326
33422
|
const error = context.error;
|
|
@@ -33365,12 +33461,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33365
33461
|
if (result.length === 0) {
|
|
33366
33462
|
return [];
|
|
33367
33463
|
}
|
|
33368
|
-
return await this.processClaimedTransferResults(
|
|
33369
|
-
result,
|
|
33370
|
-
transfer,
|
|
33371
|
-
emit,
|
|
33372
|
-
optimize
|
|
33373
|
-
);
|
|
33464
|
+
return await this.processClaimedTransferResults(result, transfer, emit);
|
|
33374
33465
|
} catch (error) {
|
|
33375
33466
|
console.warn(
|
|
33376
33467
|
`Failed to claim transfer after all retries. Please try reinitializing your wallet in a few minutes. Transfer ID: ${transfer.id}`,
|
|
@@ -33403,7 +33494,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33403
33494
|
continue;
|
|
33404
33495
|
}
|
|
33405
33496
|
promises.push(
|
|
33406
|
-
this.claimTransfer({ transfer, emit
|
|
33497
|
+
this.claimTransfer({ transfer, emit }).then(() => transfer.id).catch((error) => {
|
|
33407
33498
|
console.warn(`Failed to claim transfer ${transfer.id}:`, error);
|
|
33408
33499
|
return null;
|
|
33409
33500
|
})
|
|
@@ -33674,8 +33765,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33674
33765
|
selectedLeaves,
|
|
33675
33766
|
`no leaves for ${totalAmount}`
|
|
33676
33767
|
);
|
|
33677
|
-
leaves = await this.
|
|
33678
|
-
leaves = await this.checkExtendTimeLockNodes(leaves);
|
|
33768
|
+
leaves = await this.checkRenewLeaves(leaves);
|
|
33679
33769
|
const leavesToSend = await Promise.all(
|
|
33680
33770
|
leaves.map(async (leaf) => ({
|
|
33681
33771
|
leaf,
|
|
@@ -34006,10 +34096,8 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
34006
34096
|
leavesToSendToSsp = leavesForTargetAmount;
|
|
34007
34097
|
leavesToSendToSE = leavesForFee;
|
|
34008
34098
|
}
|
|
34009
|
-
leavesToSendToSsp = await this.
|
|
34010
|
-
|
|
34011
|
-
leavesToSendToSE = await this.checkRefreshTimelockNodes(leavesToSendToSE);
|
|
34012
|
-
leavesToSendToSE = await this.checkExtendTimeLockNodes(leavesToSendToSE);
|
|
34099
|
+
leavesToSendToSsp = await this.checkRenewLeaves(leavesToSendToSsp);
|
|
34100
|
+
leavesToSendToSE = await this.checkRenewLeaves(leavesToSendToSE);
|
|
34013
34101
|
const leafKeyTweaks = await Promise.all(
|
|
34014
34102
|
[...leavesToSendToSE, ...leavesToSendToSsp].map(async (leaf) => ({
|
|
34015
34103
|
leaf,
|
|
@@ -34095,8 +34183,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
34095
34183
|
(await this.selectLeaves([amountSats])).get(amountSats),
|
|
34096
34184
|
`no leaves for ${amountSats}`
|
|
34097
34185
|
);
|
|
34098
|
-
leaves = await this.
|
|
34099
|
-
leaves = await this.checkExtendTimeLockNodes(leaves);
|
|
34186
|
+
leaves = await this.checkRenewLeaves(leaves);
|
|
34100
34187
|
const feeEstimate = await sspClient.getCoopExitFeeQuote({
|
|
34101
34188
|
leafExternalIds: leaves.map((leaf) => leaf.id),
|
|
34102
34189
|
withdrawalAddress
|
|
@@ -34384,7 +34471,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
34384
34471
|
*/
|
|
34385
34472
|
async signTransaction(txHex, keyType = "auto-detect") {
|
|
34386
34473
|
try {
|
|
34387
|
-
const tx =
|
|
34474
|
+
const tx = import_btc_signer5.Transaction.fromRaw((0, import_utils25.hexToBytes)(txHex));
|
|
34388
34475
|
let publicKey;
|
|
34389
34476
|
switch (keyType.toLowerCase()) {
|
|
34390
34477
|
case "identity":
|
|
@@ -34591,15 +34678,6 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
34591
34678
|
}
|
|
34592
34679
|
);
|
|
34593
34680
|
}
|
|
34594
|
-
if (!nodeInput.sequence) {
|
|
34595
|
-
throw new ValidationError(
|
|
34596
|
-
`Node transaction has no sequence for ${isRootNode ? "root" : "non-root"} node`,
|
|
34597
|
-
{
|
|
34598
|
-
field: "sequence",
|
|
34599
|
-
value: nodeInput.sequence
|
|
34600
|
-
}
|
|
34601
|
-
);
|
|
34602
|
-
}
|
|
34603
34681
|
const refundInput = refundTx.getInput(0);
|
|
34604
34682
|
if (!refundInput) {
|
|
34605
34683
|
throw new ValidationError(
|
|
@@ -34635,89 +34713,6 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
34635
34713
|
);
|
|
34636
34714
|
}
|
|
34637
34715
|
}
|
|
34638
|
-
/**
|
|
34639
|
-
* Refresh the timelock of a specific node.
|
|
34640
|
-
*
|
|
34641
|
-
* @param {string} nodeId - The ID of the node to refresh
|
|
34642
|
-
* @returns {Promise<void>} Promise that resolves when the timelock is refreshed
|
|
34643
|
-
*/
|
|
34644
|
-
async testOnly_expireTimelock(nodeId) {
|
|
34645
|
-
const sparkClient = await this.connectionManager.createSparkClient(
|
|
34646
|
-
this.config.getCoordinatorAddress()
|
|
34647
|
-
);
|
|
34648
|
-
try {
|
|
34649
|
-
const response = await sparkClient.query_nodes({
|
|
34650
|
-
source: {
|
|
34651
|
-
$case: "nodeIds",
|
|
34652
|
-
nodeIds: {
|
|
34653
|
-
nodeIds: [nodeId]
|
|
34654
|
-
}
|
|
34655
|
-
},
|
|
34656
|
-
includeParents: true
|
|
34657
|
-
});
|
|
34658
|
-
let leaf = response.nodes[nodeId];
|
|
34659
|
-
if (!leaf) {
|
|
34660
|
-
throw new ValidationError("Node not found", {
|
|
34661
|
-
field: "nodeId",
|
|
34662
|
-
value: nodeId
|
|
34663
|
-
});
|
|
34664
|
-
}
|
|
34665
|
-
let parentNode;
|
|
34666
|
-
let hasParentNode = false;
|
|
34667
|
-
if (!leaf.parentNodeId) {
|
|
34668
|
-
} else {
|
|
34669
|
-
hasParentNode = true;
|
|
34670
|
-
parentNode = response.nodes[leaf.parentNodeId];
|
|
34671
|
-
if (!parentNode) {
|
|
34672
|
-
throw new ValidationError("Parent node not found", {
|
|
34673
|
-
field: "parentNodeId",
|
|
34674
|
-
value: leaf.parentNodeId
|
|
34675
|
-
});
|
|
34676
|
-
}
|
|
34677
|
-
}
|
|
34678
|
-
const nodeTx = getTxFromRawTxBytes(leaf.nodeTx);
|
|
34679
|
-
const refundTx = getTxFromRawTxBytes(leaf.refundTx);
|
|
34680
|
-
if (hasParentNode) {
|
|
34681
|
-
const nodeTimelock = getCurrentTimelock(nodeTx.getInput(0).sequence);
|
|
34682
|
-
if (nodeTimelock > 100) {
|
|
34683
|
-
const expiredNodeTxLeaf = await this.transferService.testonly_expireTimeLockNodeTx(
|
|
34684
|
-
leaf,
|
|
34685
|
-
parentNode
|
|
34686
|
-
);
|
|
34687
|
-
if (!expiredNodeTxLeaf.nodes[0]) {
|
|
34688
|
-
throw new ValidationError("No expired node tx leaf", {
|
|
34689
|
-
field: "expiredNodeTxLeaf",
|
|
34690
|
-
value: expiredNodeTxLeaf
|
|
34691
|
-
});
|
|
34692
|
-
}
|
|
34693
|
-
leaf = expiredNodeTxLeaf.nodes[0];
|
|
34694
|
-
}
|
|
34695
|
-
}
|
|
34696
|
-
const refundTimelock = getCurrentTimelock(refundTx.getInput(0).sequence);
|
|
34697
|
-
if (refundTimelock > 100) {
|
|
34698
|
-
const expiredTxLeaf = await this.transferService.testonly_expireTimeLockRefundtx(leaf);
|
|
34699
|
-
if (!expiredTxLeaf.nodes[0]) {
|
|
34700
|
-
throw new ValidationError("No expired tx leaf", {
|
|
34701
|
-
field: "expiredTxLeaf",
|
|
34702
|
-
value: expiredTxLeaf
|
|
34703
|
-
});
|
|
34704
|
-
}
|
|
34705
|
-
leaf = expiredTxLeaf.nodes[0];
|
|
34706
|
-
}
|
|
34707
|
-
const leafIndex = this.leaves.findIndex((leaf2) => leaf2.id === leaf2.id);
|
|
34708
|
-
if (leafIndex !== -1) {
|
|
34709
|
-
this.leaves[leafIndex] = leaf;
|
|
34710
|
-
}
|
|
34711
|
-
} catch (error) {
|
|
34712
|
-
throw new NetworkError(
|
|
34713
|
-
"Failed to refresh timelock",
|
|
34714
|
-
{
|
|
34715
|
-
method: "refresh_timelock"
|
|
34716
|
-
},
|
|
34717
|
-
error
|
|
34718
|
-
);
|
|
34719
|
-
}
|
|
34720
|
-
}
|
|
34721
34716
|
cleanup() {
|
|
34722
34717
|
if (this.claimTransfersInterval) {
|
|
34723
34718
|
clearInterval(this.claimTransfersInterval);
|
|
@@ -34872,8 +34867,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
34872
34867
|
"getLightningReceiveRequest",
|
|
34873
34868
|
"getLightningSendRequest",
|
|
34874
34869
|
"getCoopExitRequest",
|
|
34875
|
-
"checkTimelock"
|
|
34876
|
-
"testOnly_expireTimelock"
|
|
34870
|
+
"checkTimelock"
|
|
34877
34871
|
];
|
|
34878
34872
|
methods.forEach((m) => this.wrapPublicSparkWalletMethodWithOtelSpan(m));
|
|
34879
34873
|
this.initWallet = this.wrapWithOtelSpan(
|
|
@@ -35873,7 +35867,6 @@ setCrypto(cryptoImpl2);
|
|
|
35873
35867
|
DIRECT_TIMELOCK_OFFSET,
|
|
35874
35868
|
DefaultSparkSigner,
|
|
35875
35869
|
HTLC_TIMELOCK_OFFSET,
|
|
35876
|
-
INITIAL_DIRECT_SEQUENCE,
|
|
35877
35870
|
INITIAL_SEQUENCE,
|
|
35878
35871
|
InternalValidationError,
|
|
35879
35872
|
KeyDerivationType,
|
|
@@ -35910,21 +35903,24 @@ setCrypto(cryptoImpl2);
|
|
|
35910
35903
|
constructFeeBumpTx,
|
|
35911
35904
|
constructUnilateralExitFeeBumpPackages,
|
|
35912
35905
|
constructUnilateralExitTxs,
|
|
35913
|
-
|
|
35914
|
-
|
|
35915
|
-
|
|
35916
|
-
|
|
35917
|
-
|
|
35918
|
-
|
|
35919
|
-
|
|
35906
|
+
createConnectorRefundTxs,
|
|
35907
|
+
createCurrentTimelockRefundTxs,
|
|
35908
|
+
createDecrementedTimelockNodeTx,
|
|
35909
|
+
createDecrementedTimelockRefundTxs,
|
|
35910
|
+
createInitialTimelockNodeTx,
|
|
35911
|
+
createInitialTimelockRefundTxs,
|
|
35912
|
+
createRootNodeTx,
|
|
35920
35913
|
createSigningCommitment,
|
|
35921
35914
|
createSigningNonce,
|
|
35922
|
-
|
|
35915
|
+
createTestUnilateralRefundTxs,
|
|
35916
|
+
createTestUnilateralTimelockNodeTx,
|
|
35917
|
+
createZeroTimelockNodeTx,
|
|
35923
35918
|
decodeBech32mTokenIdentifier,
|
|
35924
35919
|
decodeBytesToSigningCommitment,
|
|
35925
35920
|
decodeBytesToSigningNonce,
|
|
35926
35921
|
decodeSparkAddress,
|
|
35927
35922
|
doesLeafNeedRefresh,
|
|
35923
|
+
doesTxnNeedRenewed,
|
|
35928
35924
|
encodeBech32mTokenIdentifier,
|
|
35929
35925
|
encodeSigningCommitmentToBytes,
|
|
35930
35926
|
encodeSigningNonceToBytes,
|
|
@@ -35962,6 +35958,7 @@ setCrypto(cryptoImpl2);
|
|
|
35962
35958
|
getTxFromRawTxHex,
|
|
35963
35959
|
getTxId,
|
|
35964
35960
|
getTxIdNoReverse,
|
|
35961
|
+
hash160,
|
|
35965
35962
|
initializeTracerEnv,
|
|
35966
35963
|
isEphemeralAnchorOutput,
|
|
35967
35964
|
isLegacySparkAddress,
|
|
@@ -35969,6 +35966,7 @@ setCrypto(cryptoImpl2);
|
|
|
35969
35966
|
isTxBroadcast,
|
|
35970
35967
|
isValidPublicKey,
|
|
35971
35968
|
isValidSparkAddress,
|
|
35969
|
+
isZeroTimelock,
|
|
35972
35970
|
lastKeyWithTarget,
|
|
35973
35971
|
maybeApplyFee,
|
|
35974
35972
|
modInverse,
|