@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
|
@@ -1113,30 +1113,30 @@ function signFrost({
|
|
|
1113
1113
|
adaptorPubKey
|
|
1114
1114
|
}) {
|
|
1115
1115
|
const logMsg = JSON.stringify({
|
|
1116
|
-
message: (0,
|
|
1116
|
+
message: (0, import_utils13.bytesToHex)(message),
|
|
1117
1117
|
keyPackage: {
|
|
1118
|
-
secretKey: (0,
|
|
1119
|
-
publicKey: (0,
|
|
1120
|
-
verifyingKey: (0,
|
|
1118
|
+
secretKey: (0, import_utils13.bytesToHex)(keyPackage.secretKey),
|
|
1119
|
+
publicKey: (0, import_utils13.bytesToHex)(keyPackage.publicKey),
|
|
1120
|
+
verifyingKey: (0, import_utils13.bytesToHex)(keyPackage.verifyingKey)
|
|
1121
1121
|
},
|
|
1122
1122
|
nonce: {
|
|
1123
|
-
hiding: (0,
|
|
1124
|
-
binding: (0,
|
|
1123
|
+
hiding: (0, import_utils13.bytesToHex)(nonce.hiding),
|
|
1124
|
+
binding: (0, import_utils13.bytesToHex)(nonce.binding)
|
|
1125
1125
|
},
|
|
1126
1126
|
selfCommitment: {
|
|
1127
|
-
hiding: (0,
|
|
1128
|
-
binding: (0,
|
|
1127
|
+
hiding: (0, import_utils13.bytesToHex)(selfCommitment.hiding),
|
|
1128
|
+
binding: (0, import_utils13.bytesToHex)(selfCommitment.binding)
|
|
1129
1129
|
},
|
|
1130
1130
|
statechainCommitments: Object.fromEntries(
|
|
1131
1131
|
Object.entries(statechainCommitments ?? {}).map(([k, v]) => [
|
|
1132
1132
|
k,
|
|
1133
1133
|
{
|
|
1134
|
-
hiding: (0,
|
|
1135
|
-
binding: (0,
|
|
1134
|
+
hiding: (0, import_utils13.bytesToHex)(v.hiding),
|
|
1135
|
+
binding: (0, import_utils13.bytesToHex)(v.binding)
|
|
1136
1136
|
}
|
|
1137
1137
|
])
|
|
1138
1138
|
),
|
|
1139
|
-
adaptorPubKey: adaptorPubKey ? (0,
|
|
1139
|
+
adaptorPubKey: adaptorPubKey ? (0, import_utils13.bytesToHex)(adaptorPubKey) : void 0
|
|
1140
1140
|
});
|
|
1141
1141
|
SparkSdkLogger.get(LOGGER_NAMES.wasm).trace("signFrost", logMsg);
|
|
1142
1142
|
const result = wasm_sign_frost(
|
|
@@ -1149,7 +1149,7 @@ function signFrost({
|
|
|
1149
1149
|
);
|
|
1150
1150
|
SparkSdkLogger.get(LOGGER_NAMES.wasm).trace(
|
|
1151
1151
|
"signFrost result",
|
|
1152
|
-
(0,
|
|
1152
|
+
(0, import_utils13.bytesToHex)(result)
|
|
1153
1153
|
);
|
|
1154
1154
|
return result;
|
|
1155
1155
|
}
|
|
@@ -1165,36 +1165,36 @@ function aggregateFrost({
|
|
|
1165
1165
|
adaptorPubKey
|
|
1166
1166
|
}) {
|
|
1167
1167
|
const logMsg = JSON.stringify({
|
|
1168
|
-
message: (0,
|
|
1168
|
+
message: (0, import_utils13.bytesToHex)(message),
|
|
1169
1169
|
statechainCommitments: Object.fromEntries(
|
|
1170
1170
|
Object.entries(statechainCommitments ?? {}).map(([k, v]) => [
|
|
1171
1171
|
k,
|
|
1172
1172
|
{
|
|
1173
|
-
hiding: (0,
|
|
1174
|
-
binding: (0,
|
|
1173
|
+
hiding: (0, import_utils13.bytesToHex)(v.hiding),
|
|
1174
|
+
binding: (0, import_utils13.bytesToHex)(v.binding)
|
|
1175
1175
|
}
|
|
1176
1176
|
])
|
|
1177
1177
|
),
|
|
1178
1178
|
selfCommitment: {
|
|
1179
|
-
hiding: (0,
|
|
1180
|
-
binding: (0,
|
|
1179
|
+
hiding: (0, import_utils13.bytesToHex)(selfCommitment.hiding),
|
|
1180
|
+
binding: (0, import_utils13.bytesToHex)(selfCommitment.binding)
|
|
1181
1181
|
},
|
|
1182
1182
|
statechainSignatures: Object.fromEntries(
|
|
1183
1183
|
Object.entries(statechainSignatures ?? {}).map(([k, v]) => [
|
|
1184
1184
|
k,
|
|
1185
|
-
(0,
|
|
1185
|
+
(0, import_utils13.bytesToHex)(v)
|
|
1186
1186
|
])
|
|
1187
1187
|
),
|
|
1188
|
-
selfSignature: (0,
|
|
1188
|
+
selfSignature: (0, import_utils13.bytesToHex)(selfSignature),
|
|
1189
1189
|
statechainPublicKeys: Object.fromEntries(
|
|
1190
1190
|
Object.entries(statechainPublicKeys ?? {}).map(([k, v]) => [
|
|
1191
1191
|
k,
|
|
1192
|
-
(0,
|
|
1192
|
+
(0, import_utils13.bytesToHex)(v)
|
|
1193
1193
|
])
|
|
1194
1194
|
),
|
|
1195
|
-
selfPublicKey: (0,
|
|
1196
|
-
verifyingKey: (0,
|
|
1197
|
-
adaptorPubKey: adaptorPubKey ? (0,
|
|
1195
|
+
selfPublicKey: (0, import_utils13.bytesToHex)(selfPublicKey),
|
|
1196
|
+
verifyingKey: (0, import_utils13.bytesToHex)(verifyingKey),
|
|
1197
|
+
adaptorPubKey: adaptorPubKey ? (0, import_utils13.bytesToHex)(adaptorPubKey) : void 0
|
|
1198
1198
|
});
|
|
1199
1199
|
SparkSdkLogger.get(LOGGER_NAMES.wasm).trace("aggregateFrost", logMsg);
|
|
1200
1200
|
const result = wasm_aggregate_frost(
|
|
@@ -1210,7 +1210,7 @@ function aggregateFrost({
|
|
|
1210
1210
|
);
|
|
1211
1211
|
SparkSdkLogger.get(LOGGER_NAMES.wasm).trace(
|
|
1212
1212
|
"aggregateFrost result",
|
|
1213
|
-
(0,
|
|
1213
|
+
(0, import_utils13.bytesToHex)(result)
|
|
1214
1214
|
);
|
|
1215
1215
|
return result;
|
|
1216
1216
|
}
|
|
@@ -1232,12 +1232,12 @@ function decryptEcies({
|
|
|
1232
1232
|
}) {
|
|
1233
1233
|
return decrypt_ecies(encryptedMsg, privateKey);
|
|
1234
1234
|
}
|
|
1235
|
-
var
|
|
1235
|
+
var import_utils13;
|
|
1236
1236
|
var init_wasm = __esm({
|
|
1237
1237
|
"src/spark_bindings/wasm/index.ts"() {
|
|
1238
1238
|
"use strict";
|
|
1239
1239
|
init_buffer();
|
|
1240
|
-
|
|
1240
|
+
import_utils13 = require("@noble/curves/utils");
|
|
1241
1241
|
init_spark_bindings();
|
|
1242
1242
|
init_logging();
|
|
1243
1243
|
}
|
|
@@ -1254,7 +1254,6 @@ __export(index_react_native_exports, {
|
|
|
1254
1254
|
DIRECT_TIMELOCK_OFFSET: () => DIRECT_TIMELOCK_OFFSET,
|
|
1255
1255
|
DefaultSparkSigner: () => ReactNativeSparkSigner,
|
|
1256
1256
|
HTLC_TIMELOCK_OFFSET: () => HTLC_TIMELOCK_OFFSET,
|
|
1257
|
-
INITIAL_DIRECT_SEQUENCE: () => INITIAL_DIRECT_SEQUENCE,
|
|
1258
1257
|
INITIAL_SEQUENCE: () => INITIAL_SEQUENCE,
|
|
1259
1258
|
InternalValidationError: () => InternalValidationError,
|
|
1260
1259
|
LOGGER_NAMES: () => LOGGER_NAMES,
|
|
@@ -1264,12 +1263,14 @@ __export(index_react_native_exports, {
|
|
|
1264
1263
|
NotImplementedError: () => NotImplementedError,
|
|
1265
1264
|
RPCError: () => RPCError,
|
|
1266
1265
|
ReactNativeSparkSigner: () => ReactNativeSparkSigner,
|
|
1266
|
+
ReactNativeTaprootSparkSigner: () => ReactNativeTaprootSparkSigner,
|
|
1267
1267
|
SparkSDKError: () => SparkSDKError,
|
|
1268
1268
|
SparkSdkLogger: () => SparkSdkLogger,
|
|
1269
1269
|
SparkWallet: () => SparkWalletReactNative,
|
|
1270
1270
|
SparkWalletEvent: () => SparkWalletEvent,
|
|
1271
1271
|
TEST_UNILATERAL_DIRECT_SEQUENCE: () => TEST_UNILATERAL_DIRECT_SEQUENCE,
|
|
1272
1272
|
TEST_UNILATERAL_SEQUENCE: () => TEST_UNILATERAL_SEQUENCE,
|
|
1273
|
+
TaprootSparkSigner: () => ReactNativeTaprootSparkSigner,
|
|
1273
1274
|
TokenTransactionService: () => TokenTransactionService,
|
|
1274
1275
|
ValidationError: () => ValidationError,
|
|
1275
1276
|
WalletConfig: () => WalletConfig,
|
|
@@ -1288,21 +1289,24 @@ __export(index_react_native_exports, {
|
|
|
1288
1289
|
constructFeeBumpTx: () => constructFeeBumpTx,
|
|
1289
1290
|
constructUnilateralExitFeeBumpPackages: () => constructUnilateralExitFeeBumpPackages,
|
|
1290
1291
|
constructUnilateralExitTxs: () => constructUnilateralExitTxs,
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1292
|
+
createConnectorRefundTxs: () => createConnectorRefundTxs,
|
|
1293
|
+
createCurrentTimelockRefundTxs: () => createCurrentTimelockRefundTxs,
|
|
1294
|
+
createDecrementedTimelockNodeTx: () => createDecrementedTimelockNodeTx,
|
|
1295
|
+
createDecrementedTimelockRefundTxs: () => createDecrementedTimelockRefundTxs,
|
|
1296
|
+
createInitialTimelockNodeTx: () => createInitialTimelockNodeTx,
|
|
1297
|
+
createInitialTimelockRefundTxs: () => createInitialTimelockRefundTxs,
|
|
1298
|
+
createRootNodeTx: () => createRootNodeTx,
|
|
1298
1299
|
createSigningCommitment: () => createSigningCommitment,
|
|
1299
1300
|
createSigningNonce: () => createSigningNonce,
|
|
1300
|
-
|
|
1301
|
+
createTestUnilateralRefundTxs: () => createTestUnilateralRefundTxs,
|
|
1302
|
+
createTestUnilateralTimelockNodeTx: () => createTestUnilateralTimelockNodeTx,
|
|
1303
|
+
createZeroTimelockNodeTx: () => createZeroTimelockNodeTx,
|
|
1301
1304
|
decodeBech32mTokenIdentifier: () => decodeBech32mTokenIdentifier,
|
|
1302
1305
|
decodeBytesToSigningCommitment: () => decodeBytesToSigningCommitment,
|
|
1303
1306
|
decodeBytesToSigningNonce: () => decodeBytesToSigningNonce,
|
|
1304
1307
|
decodeSparkAddress: () => decodeSparkAddress,
|
|
1305
1308
|
doesLeafNeedRefresh: () => doesLeafNeedRefresh,
|
|
1309
|
+
doesTxnNeedRenewed: () => doesTxnNeedRenewed,
|
|
1306
1310
|
encodeBech32mTokenIdentifier: () => encodeBech32mTokenIdentifier,
|
|
1307
1311
|
encodeSigningCommitmentToBytes: () => encodeSigningCommitmentToBytes,
|
|
1308
1312
|
encodeSigningNonceToBytes: () => encodeSigningNonceToBytes,
|
|
@@ -1340,12 +1344,14 @@ __export(index_react_native_exports, {
|
|
|
1340
1344
|
getTxFromRawTxHex: () => getTxFromRawTxHex,
|
|
1341
1345
|
getTxId: () => getTxId,
|
|
1342
1346
|
getTxIdNoReverse: () => getTxIdNoReverse,
|
|
1347
|
+
hash160: () => hash160,
|
|
1343
1348
|
isEphemeralAnchorOutput: () => isEphemeralAnchorOutput,
|
|
1344
1349
|
isLegacySparkAddress: () => isLegacySparkAddress,
|
|
1345
1350
|
isSafeForNumber: () => isSafeForNumber,
|
|
1346
1351
|
isTxBroadcast: () => isTxBroadcast,
|
|
1347
1352
|
isValidPublicKey: () => isValidPublicKey,
|
|
1348
1353
|
isValidSparkAddress: () => isValidSparkAddress,
|
|
1354
|
+
isZeroTimelock: () => isZeroTimelock,
|
|
1349
1355
|
lastKeyWithTarget: () => lastKeyWithTarget,
|
|
1350
1356
|
maybeApplyFee: () => maybeApplyFee,
|
|
1351
1357
|
modInverse: () => modInverse,
|
|
@@ -3945,6 +3951,12 @@ var RenewLeafRequest = {
|
|
|
3945
3951
|
writer.uint32(26).fork()
|
|
3946
3952
|
).join();
|
|
3947
3953
|
break;
|
|
3954
|
+
case "renewNodeZeroTimelockSigningJob":
|
|
3955
|
+
RenewNodeZeroTimelockSigningJob.encode(
|
|
3956
|
+
message.signingJobs.renewNodeZeroTimelockSigningJob,
|
|
3957
|
+
writer.uint32(34).fork()
|
|
3958
|
+
).join();
|
|
3959
|
+
break;
|
|
3948
3960
|
}
|
|
3949
3961
|
return writer;
|
|
3950
3962
|
},
|
|
@@ -3982,6 +3994,16 @@ var RenewLeafRequest = {
|
|
|
3982
3994
|
};
|
|
3983
3995
|
continue;
|
|
3984
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
|
+
}
|
|
3985
4007
|
}
|
|
3986
4008
|
if ((tag & 7) === 4 || tag === 0) {
|
|
3987
4009
|
break;
|
|
@@ -3999,6 +4021,11 @@ var RenewLeafRequest = {
|
|
|
3999
4021
|
} : isSet3(object.renewRefundTimelockSigningJob) ? {
|
|
4000
4022
|
$case: "renewRefundTimelockSigningJob",
|
|
4001
4023
|
renewRefundTimelockSigningJob: RenewRefundTimelockSigningJob.fromJSON(object.renewRefundTimelockSigningJob)
|
|
4024
|
+
} : isSet3(object.renewNodeZeroTimelockSigningJob) ? {
|
|
4025
|
+
$case: "renewNodeZeroTimelockSigningJob",
|
|
4026
|
+
renewNodeZeroTimelockSigningJob: RenewNodeZeroTimelockSigningJob.fromJSON(
|
|
4027
|
+
object.renewNodeZeroTimelockSigningJob
|
|
4028
|
+
)
|
|
4002
4029
|
} : void 0
|
|
4003
4030
|
};
|
|
4004
4031
|
},
|
|
@@ -4015,6 +4042,10 @@ var RenewLeafRequest = {
|
|
|
4015
4042
|
obj.renewRefundTimelockSigningJob = RenewRefundTimelockSigningJob.toJSON(
|
|
4016
4043
|
message.signingJobs.renewRefundTimelockSigningJob
|
|
4017
4044
|
);
|
|
4045
|
+
} else if (message.signingJobs?.$case === "renewNodeZeroTimelockSigningJob") {
|
|
4046
|
+
obj.renewNodeZeroTimelockSigningJob = RenewNodeZeroTimelockSigningJob.toJSON(
|
|
4047
|
+
message.signingJobs.renewNodeZeroTimelockSigningJob
|
|
4048
|
+
);
|
|
4018
4049
|
}
|
|
4019
4050
|
return obj;
|
|
4020
4051
|
},
|
|
@@ -4047,6 +4078,17 @@ var RenewLeafRequest = {
|
|
|
4047
4078
|
}
|
|
4048
4079
|
break;
|
|
4049
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
|
+
}
|
|
4050
4092
|
}
|
|
4051
4093
|
return message;
|
|
4052
4094
|
}
|
|
@@ -4321,6 +4363,125 @@ var RenewRefundTimelockSigningJob = {
|
|
|
4321
4363
|
return message;
|
|
4322
4364
|
}
|
|
4323
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
|
+
};
|
|
4324
4485
|
function createBaseRenewLeafResponse() {
|
|
4325
4486
|
return { renewResult: void 0 };
|
|
4326
4487
|
}
|
|
@@ -4333,6 +4494,9 @@ var RenewLeafResponse = {
|
|
|
4333
4494
|
case "renewRefundTimelockResult":
|
|
4334
4495
|
RenewRefundTimelockResult.encode(message.renewResult.renewRefundTimelockResult, writer.uint32(18).fork()).join();
|
|
4335
4496
|
break;
|
|
4497
|
+
case "renewNodeZeroTimelockResult":
|
|
4498
|
+
RenewNodeZeroTimelockResult.encode(message.renewResult.renewNodeZeroTimelockResult, writer.uint32(26).fork()).join();
|
|
4499
|
+
break;
|
|
4336
4500
|
}
|
|
4337
4501
|
return writer;
|
|
4338
4502
|
},
|
|
@@ -4363,6 +4527,16 @@ var RenewLeafResponse = {
|
|
|
4363
4527
|
};
|
|
4364
4528
|
continue;
|
|
4365
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
|
+
}
|
|
4366
4540
|
}
|
|
4367
4541
|
if ((tag & 7) === 4 || tag === 0) {
|
|
4368
4542
|
break;
|
|
@@ -4379,6 +4553,9 @@ var RenewLeafResponse = {
|
|
|
4379
4553
|
} : isSet3(object.renewRefundTimelockResult) ? {
|
|
4380
4554
|
$case: "renewRefundTimelockResult",
|
|
4381
4555
|
renewRefundTimelockResult: RenewRefundTimelockResult.fromJSON(object.renewRefundTimelockResult)
|
|
4556
|
+
} : isSet3(object.renewNodeZeroTimelockResult) ? {
|
|
4557
|
+
$case: "renewNodeZeroTimelockResult",
|
|
4558
|
+
renewNodeZeroTimelockResult: RenewNodeZeroTimelockResult.fromJSON(object.renewNodeZeroTimelockResult)
|
|
4382
4559
|
} : void 0
|
|
4383
4560
|
};
|
|
4384
4561
|
},
|
|
@@ -4388,6 +4565,10 @@ var RenewLeafResponse = {
|
|
|
4388
4565
|
obj.renewNodeTimelockResult = RenewNodeTimelockResult.toJSON(message.renewResult.renewNodeTimelockResult);
|
|
4389
4566
|
} else if (message.renewResult?.$case === "renewRefundTimelockResult") {
|
|
4390
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
|
+
);
|
|
4391
4572
|
}
|
|
4392
4573
|
return obj;
|
|
4393
4574
|
},
|
|
@@ -4417,6 +4598,17 @@ var RenewLeafResponse = {
|
|
|
4417
4598
|
}
|
|
4418
4599
|
break;
|
|
4419
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
|
+
}
|
|
4420
4612
|
}
|
|
4421
4613
|
return message;
|
|
4422
4614
|
}
|
|
@@ -4540,6 +4732,74 @@ var RenewRefundTimelockResult = {
|
|
|
4540
4732
|
return message;
|
|
4541
4733
|
}
|
|
4542
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
|
+
};
|
|
4543
4803
|
function createBaseNodeSignatureShares() {
|
|
4544
4804
|
return {
|
|
4545
4805
|
nodeId: "",
|
|
@@ -18242,7 +18502,11 @@ var BASE_CONFIG = {
|
|
|
18242
18502
|
console: {
|
|
18243
18503
|
otel: false
|
|
18244
18504
|
},
|
|
18245
|
-
events: {}
|
|
18505
|
+
events: {},
|
|
18506
|
+
optimizationOptions: {
|
|
18507
|
+
auto: true,
|
|
18508
|
+
multiplicity: 0
|
|
18509
|
+
}
|
|
18246
18510
|
};
|
|
18247
18511
|
var LOCAL_WALLET_CONFIG = {
|
|
18248
18512
|
...BASE_CONFIG,
|
|
@@ -19899,6 +20163,7 @@ function getTransferPackageSigningPayload(transferID, transferPackage) {
|
|
|
19899
20163
|
|
|
19900
20164
|
// src/utils/transaction.ts
|
|
19901
20165
|
init_buffer();
|
|
20166
|
+
var import_utils11 = require("@noble/hashes/utils");
|
|
19902
20167
|
var import_btc_signer = require("@scure/btc-signer");
|
|
19903
20168
|
var INITIAL_TIMELOCK = 2e3;
|
|
19904
20169
|
var TEST_UNILATERAL_TIMELOCK = 100;
|
|
@@ -19907,9 +20172,9 @@ var DIRECT_TIMELOCK_OFFSET = 50;
|
|
|
19907
20172
|
var HTLC_TIMELOCK_OFFSET = 70;
|
|
19908
20173
|
var DIRECT_HTLC_TIMELOCK_OFFSET = 85;
|
|
19909
20174
|
var INITIAL_SEQUENCE = 1 << 30 | INITIAL_TIMELOCK;
|
|
19910
|
-
var INITIAL_DIRECT_SEQUENCE = 1 << 30 | INITIAL_TIMELOCK + DIRECT_TIMELOCK_OFFSET;
|
|
19911
20175
|
var TEST_UNILATERAL_SEQUENCE = 1 << 30 | TEST_UNILATERAL_TIMELOCK;
|
|
19912
20176
|
var TEST_UNILATERAL_DIRECT_SEQUENCE = 1 << 30 | TEST_UNILATERAL_TIMELOCK + DIRECT_TIMELOCK_OFFSET;
|
|
20177
|
+
var INITIAL_ROOT_NODE_SEQUENCE = 1 << 30 | 0;
|
|
19913
20178
|
var ESTIMATED_TX_SIZE = 191;
|
|
19914
20179
|
var DEFAULT_SATS_PER_VBYTE = 5;
|
|
19915
20180
|
var DEFAULT_FEE_SATS = ESTIMATED_TX_SIZE * DEFAULT_SATS_PER_VBYTE;
|
|
@@ -19919,63 +20184,8 @@ function maybeApplyFee(amount) {
|
|
|
19919
20184
|
}
|
|
19920
20185
|
return amount;
|
|
19921
20186
|
}
|
|
19922
|
-
function createRootTx(depositOutPoint, depositTxOut) {
|
|
19923
|
-
const cpfpRootTx = new import_btc_signer.Transaction({
|
|
19924
|
-
version: 3,
|
|
19925
|
-
allowUnknownOutputs: true
|
|
19926
|
-
});
|
|
19927
|
-
cpfpRootTx.addInput(depositOutPoint);
|
|
19928
|
-
cpfpRootTx.addOutput(depositTxOut);
|
|
19929
|
-
cpfpRootTx.addOutput(getEphemeralAnchorOutput());
|
|
19930
|
-
const directRootTx = new import_btc_signer.Transaction({
|
|
19931
|
-
version: 3,
|
|
19932
|
-
allowUnknownOutputs: true
|
|
19933
|
-
});
|
|
19934
|
-
directRootTx.addInput(depositOutPoint);
|
|
19935
|
-
directRootTx.addOutput({
|
|
19936
|
-
script: depositTxOut.script,
|
|
19937
|
-
amount: maybeApplyFee(depositTxOut.amount ?? 0n)
|
|
19938
|
-
});
|
|
19939
|
-
return [cpfpRootTx, directRootTx];
|
|
19940
|
-
}
|
|
19941
|
-
function createSplitTx(parentOutPoint, childTxOuts) {
|
|
19942
|
-
const cpfpSplitTx = new import_btc_signer.Transaction({
|
|
19943
|
-
version: 3,
|
|
19944
|
-
allowUnknownOutputs: true
|
|
19945
|
-
});
|
|
19946
|
-
cpfpSplitTx.addInput(parentOutPoint);
|
|
19947
|
-
for (const txOut of childTxOuts) {
|
|
19948
|
-
cpfpSplitTx.addOutput(txOut);
|
|
19949
|
-
}
|
|
19950
|
-
cpfpSplitTx.addOutput(getEphemeralAnchorOutput());
|
|
19951
|
-
const directSplitTx = new import_btc_signer.Transaction({
|
|
19952
|
-
version: 3,
|
|
19953
|
-
allowUnknownOutputs: true
|
|
19954
|
-
});
|
|
19955
|
-
directSplitTx.addInput(parentOutPoint);
|
|
19956
|
-
let totalOutputAmount = 0n;
|
|
19957
|
-
for (const txOut of childTxOuts) {
|
|
19958
|
-
totalOutputAmount += txOut.amount ?? 0n;
|
|
19959
|
-
}
|
|
19960
|
-
if (totalOutputAmount > BigInt(DEFAULT_FEE_SATS)) {
|
|
19961
|
-
const feeRatio = Number(DEFAULT_FEE_SATS) / Number(totalOutputAmount);
|
|
19962
|
-
for (const txOut of childTxOuts) {
|
|
19963
|
-
const adjustedAmount = BigInt(
|
|
19964
|
-
Math.floor(Number(txOut.amount ?? 0n) * (1 - feeRatio))
|
|
19965
|
-
);
|
|
19966
|
-
directSplitTx.addOutput({
|
|
19967
|
-
script: txOut.script,
|
|
19968
|
-
amount: adjustedAmount
|
|
19969
|
-
});
|
|
19970
|
-
}
|
|
19971
|
-
} else {
|
|
19972
|
-
for (const txOut of childTxOuts) {
|
|
19973
|
-
directSplitTx.addOutput(txOut);
|
|
19974
|
-
}
|
|
19975
|
-
}
|
|
19976
|
-
return [cpfpSplitTx, directSplitTx];
|
|
19977
|
-
}
|
|
19978
20187
|
function createNodeTx({
|
|
20188
|
+
sequence,
|
|
19979
20189
|
txOut,
|
|
19980
20190
|
parentOutPoint,
|
|
19981
20191
|
applyFee,
|
|
@@ -19985,7 +20195,10 @@ function createNodeTx({
|
|
|
19985
20195
|
version: 3,
|
|
19986
20196
|
allowUnknownOutputs: true
|
|
19987
20197
|
});
|
|
19988
|
-
nodeTx.addInput(
|
|
20198
|
+
nodeTx.addInput({
|
|
20199
|
+
...parentOutPoint,
|
|
20200
|
+
sequence
|
|
20201
|
+
});
|
|
19989
20202
|
if (applyFee) {
|
|
19990
20203
|
nodeTx.addOutput({
|
|
19991
20204
|
script: txOut.script,
|
|
@@ -19999,52 +20212,92 @@ function createNodeTx({
|
|
|
19999
20212
|
}
|
|
20000
20213
|
return nodeTx;
|
|
20001
20214
|
}
|
|
20002
|
-
function createNodeTxs(
|
|
20003
|
-
|
|
20004
|
-
|
|
20005
|
-
|
|
20006
|
-
|
|
20007
|
-
|
|
20008
|
-
|
|
20009
|
-
if (
|
|
20010
|
-
|
|
20011
|
-
|
|
20012
|
-
|
|
20013
|
-
includeAnchor: false,
|
|
20014
|
-
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
|
|
20015
20226
|
});
|
|
20016
20227
|
}
|
|
20017
|
-
|
|
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 };
|
|
20018
20250
|
}
|
|
20019
|
-
function
|
|
20020
|
-
|
|
20021
|
-
|
|
20022
|
-
|
|
20251
|
+
function createRootNodeTx(parentTx, vout) {
|
|
20252
|
+
return createNodeTxs({
|
|
20253
|
+
parentTx,
|
|
20254
|
+
sequence: INITIAL_ROOT_NODE_SEQUENCE,
|
|
20255
|
+
vout
|
|
20023
20256
|
});
|
|
20024
|
-
|
|
20025
|
-
|
|
20026
|
-
|
|
20257
|
+
}
|
|
20258
|
+
function createZeroTimelockNodeTx(parentTx) {
|
|
20259
|
+
return createNodeTxs({
|
|
20260
|
+
parentTx,
|
|
20261
|
+
sequence: INITIAL_ROOT_NODE_SEQUENCE,
|
|
20262
|
+
directSequence: DIRECT_TIMELOCK_OFFSET,
|
|
20263
|
+
vout: 0
|
|
20027
20264
|
});
|
|
20028
|
-
|
|
20029
|
-
|
|
20030
|
-
|
|
20031
|
-
|
|
20032
|
-
|
|
20265
|
+
}
|
|
20266
|
+
function createInitialTimelockNodeTx(parentTx) {
|
|
20267
|
+
return createNodeTxs({
|
|
20268
|
+
parentTx,
|
|
20269
|
+
sequence: INITIAL_SEQUENCE,
|
|
20270
|
+
vout: 0
|
|
20033
20271
|
});
|
|
20034
|
-
|
|
20035
|
-
|
|
20036
|
-
|
|
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
|
|
20037
20285
|
});
|
|
20038
|
-
|
|
20039
|
-
|
|
20040
|
-
|
|
20041
|
-
|
|
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
|
+
});
|
|
20042
20294
|
}
|
|
20043
|
-
|
|
20044
|
-
|
|
20045
|
-
|
|
20295
|
+
const isBit30Defined = (sequence || 0) & 1 << 30;
|
|
20296
|
+
return createNodeTxs({
|
|
20297
|
+
parentTx,
|
|
20298
|
+
sequence: isBit30Defined | TEST_UNILATERAL_TIMELOCK,
|
|
20299
|
+
vout: 0
|
|
20046
20300
|
});
|
|
20047
|
-
return [cpfpLeafTx, directLeafTx];
|
|
20048
20301
|
}
|
|
20049
20302
|
function createRefundTx({
|
|
20050
20303
|
sequence,
|
|
@@ -20100,110 +20353,109 @@ function getNextHTLCTransactionSequence(currSequence, isNodeTx) {
|
|
|
20100
20353
|
};
|
|
20101
20354
|
}
|
|
20102
20355
|
function createRefundTxs({
|
|
20103
|
-
|
|
20104
|
-
|
|
20105
|
-
input,
|
|
20106
|
-
directInput,
|
|
20107
|
-
amountSats,
|
|
20356
|
+
nodeTx,
|
|
20357
|
+
directNodeTx,
|
|
20108
20358
|
receivingPubkey,
|
|
20109
|
-
network
|
|
20359
|
+
network,
|
|
20360
|
+
sequence
|
|
20110
20361
|
}) {
|
|
20111
|
-
const
|
|
20112
|
-
|
|
20113
|
-
|
|
20114
|
-
|
|
20115
|
-
|
|
20116
|
-
|
|
20117
|
-
|
|
20118
|
-
|
|
20119
|
-
|
|
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
|
+
}
|
|
20120
20373
|
let directRefundTx;
|
|
20121
|
-
|
|
20122
|
-
|
|
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
|
+
}
|
|
20123
20386
|
directRefundTx = createRefundTx({
|
|
20124
|
-
sequence:
|
|
20125
|
-
input:
|
|
20126
|
-
amountSats,
|
|
20127
|
-
receivingPubkey,
|
|
20128
|
-
network,
|
|
20129
|
-
shouldCalculateFee: true,
|
|
20130
|
-
includeAnchor: false
|
|
20131
|
-
});
|
|
20132
|
-
directFromCpfpRefundTx = createRefundTx({
|
|
20133
|
-
sequence: directSequence,
|
|
20134
|
-
input,
|
|
20135
|
-
amountSats,
|
|
20387
|
+
sequence: sequence + DIRECT_TIMELOCK_OFFSET,
|
|
20388
|
+
input: directRefundInput,
|
|
20389
|
+
amountSats: directAmountSats,
|
|
20136
20390
|
receivingPubkey,
|
|
20137
20391
|
network,
|
|
20138
20392
|
shouldCalculateFee: true,
|
|
20139
20393
|
includeAnchor: false
|
|
20140
20394
|
});
|
|
20141
|
-
} else if (directInput && !directSequence) {
|
|
20142
|
-
throw new ValidationError(
|
|
20143
|
-
"directSequence must be provided if directInput is",
|
|
20144
|
-
{
|
|
20145
|
-
field: "directSequence",
|
|
20146
|
-
value: directSequence
|
|
20147
|
-
}
|
|
20148
|
-
);
|
|
20149
20395
|
}
|
|
20150
|
-
|
|
20151
|
-
|
|
20152
|
-
|
|
20153
|
-
|
|
20154
|
-
|
|
20155
|
-
|
|
20396
|
+
const cpfpRefundTx = createRefundTx({
|
|
20397
|
+
sequence,
|
|
20398
|
+
input: refundInput,
|
|
20399
|
+
amountSats: nodeAmountSats,
|
|
20400
|
+
receivingPubkey,
|
|
20401
|
+
network,
|
|
20402
|
+
shouldCalculateFee: false,
|
|
20403
|
+
includeAnchor: true
|
|
20156
20404
|
});
|
|
20157
|
-
|
|
20158
|
-
|
|
20159
|
-
|
|
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
|
|
20160
20413
|
});
|
|
20161
|
-
cpfpRefundTx
|
|
20162
|
-
|
|
20163
|
-
|
|
20164
|
-
|
|
20165
|
-
|
|
20414
|
+
return { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx };
|
|
20415
|
+
}
|
|
20416
|
+
function createInitialTimelockRefundTxs(params) {
|
|
20417
|
+
return createRefundTxs({
|
|
20418
|
+
...params,
|
|
20419
|
+
sequence: INITIAL_SEQUENCE
|
|
20166
20420
|
});
|
|
20167
|
-
|
|
20168
|
-
|
|
20169
|
-
|
|
20421
|
+
}
|
|
20422
|
+
function createDecrementedTimelockRefundTxs(params) {
|
|
20423
|
+
const nextSequence = getNextTransactionSequence(params.sequence).nextSequence;
|
|
20424
|
+
return createRefundTxs({
|
|
20425
|
+
...params,
|
|
20426
|
+
sequence: nextSequence
|
|
20170
20427
|
});
|
|
20171
|
-
|
|
20172
|
-
|
|
20173
|
-
|
|
20428
|
+
}
|
|
20429
|
+
function createCurrentTimelockRefundTxs(params) {
|
|
20430
|
+
return createRefundTxs(params);
|
|
20431
|
+
}
|
|
20432
|
+
function createTestUnilateralRefundTxs(params) {
|
|
20433
|
+
return createRefundTxs({
|
|
20434
|
+
...params,
|
|
20435
|
+
sequence: TEST_UNILATERAL_SEQUENCE
|
|
20174
20436
|
});
|
|
20175
|
-
|
|
20176
|
-
|
|
20177
|
-
|
|
20178
|
-
|
|
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);
|
|
20179
20444
|
}
|
|
20180
|
-
|
|
20181
|
-
|
|
20182
|
-
|
|
20183
|
-
}
|
|
20184
|
-
const directFromCpfpTx = new import_btc_signer.Transaction({
|
|
20185
|
-
version: 3,
|
|
20186
|
-
allowUnknownOutputs: true
|
|
20187
|
-
});
|
|
20188
|
-
directFromCpfpTx.addInput({
|
|
20189
|
-
...cpfpNodeOutPoint,
|
|
20190
|
-
sequence
|
|
20191
|
-
});
|
|
20192
|
-
directFromCpfpTx.addInput(connectorOutput);
|
|
20193
|
-
directFromCpfpTx.addOutput({
|
|
20194
|
-
script: receiverScript,
|
|
20195
|
-
amount: outputAmount
|
|
20196
|
-
});
|
|
20197
|
-
return [cpfpRefundTx, directRefundTx, directFromCpfpTx];
|
|
20445
|
+
if (directFromCpfpRefundTx) {
|
|
20446
|
+
directFromCpfpRefundTx.addInput(connectorOutput);
|
|
20447
|
+
}
|
|
20448
|
+
return { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx };
|
|
20198
20449
|
}
|
|
20199
20450
|
function getCurrentTimelock(currSequence) {
|
|
20200
20451
|
return (currSequence || 0) & 65535;
|
|
20201
20452
|
}
|
|
20202
20453
|
function getTransactionSequence(currSequence) {
|
|
20203
20454
|
const timelock = getCurrentTimelock(currSequence);
|
|
20455
|
+
const isBit30Defined = (currSequence || 0) & 1 << 30;
|
|
20204
20456
|
return {
|
|
20205
|
-
nextSequence:
|
|
20206
|
-
nextDirectSequence:
|
|
20457
|
+
nextSequence: isBit30Defined | timelock,
|
|
20458
|
+
nextDirectSequence: isBit30Defined | timelock + DIRECT_TIMELOCK_OFFSET
|
|
20207
20459
|
};
|
|
20208
20460
|
}
|
|
20209
20461
|
function checkIfValidSequence(currSequence) {
|
|
@@ -20222,6 +20474,13 @@ function checkIfValidSequence(currSequence) {
|
|
|
20222
20474
|
});
|
|
20223
20475
|
}
|
|
20224
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
|
+
}
|
|
20225
20484
|
function doesLeafNeedRefresh(currSequence, isNodeTx) {
|
|
20226
20485
|
const currentTimelock = getCurrentTimelock(currSequence);
|
|
20227
20486
|
if (isNodeTx) {
|
|
@@ -20232,6 +20491,7 @@ function doesLeafNeedRefresh(currSequence, isNodeTx) {
|
|
|
20232
20491
|
function getNextTransactionSequence(currSequence, isNodeTx) {
|
|
20233
20492
|
const currentTimelock = getCurrentTimelock(currSequence);
|
|
20234
20493
|
const nextTimelock = currentTimelock - TIME_LOCK_INTERVAL;
|
|
20494
|
+
const isBit30Defined = (currSequence || 0) & 1 << 30;
|
|
20235
20495
|
if (isNodeTx && nextTimelock < 0) {
|
|
20236
20496
|
throw new ValidationError("timelock interval is less than 0", {
|
|
20237
20497
|
field: "nextTimelock",
|
|
@@ -20246,8 +20506,8 @@ function getNextTransactionSequence(currSequence, isNodeTx) {
|
|
|
20246
20506
|
});
|
|
20247
20507
|
}
|
|
20248
20508
|
return {
|
|
20249
|
-
nextSequence:
|
|
20250
|
-
nextDirectSequence:
|
|
20509
|
+
nextSequence: isBit30Defined | nextTimelock,
|
|
20510
|
+
nextDirectSequence: isBit30Defined | nextTimelock + DIRECT_TIMELOCK_OFFSET
|
|
20251
20511
|
};
|
|
20252
20512
|
}
|
|
20253
20513
|
function getEphemeralAnchorOutput() {
|
|
@@ -20260,7 +20520,7 @@ function getEphemeralAnchorOutput() {
|
|
|
20260
20520
|
|
|
20261
20521
|
// src/utils/unilateral-exit.ts
|
|
20262
20522
|
init_buffer();
|
|
20263
|
-
var
|
|
20523
|
+
var import_utils12 = require("@noble/curves/utils");
|
|
20264
20524
|
var import_legacy = require("@noble/hashes/legacy");
|
|
20265
20525
|
var import_sha25 = require("@noble/hashes/sha2");
|
|
20266
20526
|
var btc3 = __toESM(require("@scure/btc-signer"), 1);
|
|
@@ -20275,7 +20535,7 @@ function isEphemeralAnchorOutput(script, amount) {
|
|
|
20275
20535
|
}
|
|
20276
20536
|
async function constructUnilateralExitTxs(nodeHexStrings, sparkClient, network) {
|
|
20277
20537
|
const result = [];
|
|
20278
|
-
const nodes = nodeHexStrings.map((hex) => TreeNode.decode((0,
|
|
20538
|
+
const nodes = nodeHexStrings.map((hex) => TreeNode.decode((0, import_utils12.hexToBytes)(hex)));
|
|
20279
20539
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
20280
20540
|
for (const node of nodes) {
|
|
20281
20541
|
nodeMap.set(node.id, node);
|
|
@@ -20331,10 +20591,10 @@ async function constructUnilateralExitTxs(nodeHexStrings, sparkClient, network)
|
|
|
20331
20591
|
}
|
|
20332
20592
|
}
|
|
20333
20593
|
for (const chainNode of chain) {
|
|
20334
|
-
const nodeTx = (0,
|
|
20594
|
+
const nodeTx = (0, import_utils12.bytesToHex)(chainNode.nodeTx);
|
|
20335
20595
|
transactions.push(nodeTx);
|
|
20336
20596
|
if (chainNode.id === node.id) {
|
|
20337
|
-
const refundTx = (0,
|
|
20597
|
+
const refundTx = (0, import_utils12.bytesToHex)(chainNode.refundTx);
|
|
20338
20598
|
transactions.push(refundTx);
|
|
20339
20599
|
}
|
|
20340
20600
|
}
|
|
@@ -20364,7 +20624,7 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
20364
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.`
|
|
20365
20625
|
);
|
|
20366
20626
|
}
|
|
20367
|
-
const nodeBytes = (0,
|
|
20627
|
+
const nodeBytes = (0, import_utils12.hexToBytes)(hex);
|
|
20368
20628
|
const node = TreeNode.decode(nodeBytes);
|
|
20369
20629
|
if (!node.id) {
|
|
20370
20630
|
throw new Error(
|
|
@@ -20440,7 +20700,7 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
20440
20700
|
}
|
|
20441
20701
|
}
|
|
20442
20702
|
for (const chainNode of chain) {
|
|
20443
|
-
let nodeTxHex = (0,
|
|
20703
|
+
let nodeTxHex = (0, import_utils12.bytesToHex)(chainNode.nodeTx);
|
|
20444
20704
|
try {
|
|
20445
20705
|
const txObj = getTxFromRawTxHex(nodeTxHex);
|
|
20446
20706
|
const txid = getTxId(txObj);
|
|
@@ -20457,7 +20717,7 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
20457
20717
|
for (let i = txObj.outputsLength - 1; i >= 0; i--) {
|
|
20458
20718
|
const output = txObj.getOutput(i);
|
|
20459
20719
|
if (output?.amount === 0n && output.script) {
|
|
20460
|
-
anchorOutputScriptHex = (0,
|
|
20720
|
+
anchorOutputScriptHex = (0, import_utils12.bytesToHex)(output.script);
|
|
20461
20721
|
break;
|
|
20462
20722
|
}
|
|
20463
20723
|
}
|
|
@@ -20478,11 +20738,11 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
20478
20738
|
usedUtxos,
|
|
20479
20739
|
correctedParentTx
|
|
20480
20740
|
} = constructFeeBumpTx(nodeTxHex, availableUtxos, feeRate, void 0);
|
|
20481
|
-
const feeBumpTx = btc3.Transaction.fromPSBT((0,
|
|
20741
|
+
const feeBumpTx = btc3.Transaction.fromPSBT((0, import_utils12.hexToBytes)(nodeFeeBumpPsbt));
|
|
20482
20742
|
var feeBumpOut = feeBumpTx.outputsLength === 1 ? feeBumpTx.getOutput(0) : null;
|
|
20483
20743
|
var feeBumpOutPubKey = null;
|
|
20484
20744
|
for (const usedUtxo of usedUtxos) {
|
|
20485
|
-
if (feeBumpOut && (0,
|
|
20745
|
+
if (feeBumpOut && (0, import_utils12.bytesToHex)(feeBumpOut.script) == usedUtxo.script) {
|
|
20486
20746
|
feeBumpOutPubKey = usedUtxo.publicKey;
|
|
20487
20747
|
}
|
|
20488
20748
|
const index = availableUtxos.findIndex(
|
|
@@ -20497,20 +20757,20 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
20497
20757
|
txid: getTxId(feeBumpTx),
|
|
20498
20758
|
vout: 0,
|
|
20499
20759
|
value: feeBumpOut.amount,
|
|
20500
|
-
script: (0,
|
|
20760
|
+
script: (0, import_utils12.bytesToHex)(feeBumpOut.script),
|
|
20501
20761
|
publicKey: feeBumpOutPubKey
|
|
20502
20762
|
});
|
|
20503
20763
|
const finalNodeTx = correctedParentTx || nodeTxHex;
|
|
20504
20764
|
txPackages.push({ tx: finalNodeTx, feeBumpPsbt: nodeFeeBumpPsbt });
|
|
20505
20765
|
if (chainNode.id === node.id) {
|
|
20506
|
-
let refundTxHex = (0,
|
|
20766
|
+
let refundTxHex = (0, import_utils12.bytesToHex)(chainNode.refundTx);
|
|
20507
20767
|
try {
|
|
20508
20768
|
const txObj = getTxFromRawTxHex(refundTxHex);
|
|
20509
20769
|
let anchorOutputScriptHex;
|
|
20510
20770
|
for (let i = txObj.outputsLength - 1; i >= 0; i--) {
|
|
20511
20771
|
const output = txObj.getOutput(i);
|
|
20512
20772
|
if (output?.amount === 0n && output.script) {
|
|
20513
|
-
anchorOutputScriptHex = (0,
|
|
20773
|
+
anchorOutputScriptHex = (0, import_utils12.bytesToHex)(output.script);
|
|
20514
20774
|
break;
|
|
20515
20775
|
}
|
|
20516
20776
|
}
|
|
@@ -20533,12 +20793,12 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
20533
20793
|
void 0
|
|
20534
20794
|
);
|
|
20535
20795
|
const feeBumpTx2 = btc3.Transaction.fromPSBT(
|
|
20536
|
-
(0,
|
|
20796
|
+
(0, import_utils12.hexToBytes)(refundFeeBump.feeBumpPsbt)
|
|
20537
20797
|
);
|
|
20538
20798
|
var feeBumpOut = feeBumpTx2.outputsLength === 1 ? feeBumpTx2.getOutput(0) : null;
|
|
20539
20799
|
var feeBumpOutPubKey = null;
|
|
20540
20800
|
for (const usedUtxo of usedUtxos) {
|
|
20541
|
-
if (feeBumpOut && (0,
|
|
20801
|
+
if (feeBumpOut && (0, import_utils12.bytesToHex)(feeBumpOut.script) == usedUtxo.script) {
|
|
20542
20802
|
feeBumpOutPubKey = usedUtxo.publicKey;
|
|
20543
20803
|
}
|
|
20544
20804
|
const index = availableUtxos.findIndex(
|
|
@@ -20553,7 +20813,7 @@ async function constructUnilateralExitFeeBumpPackages(nodeHexStrings, utxos, fee
|
|
|
20553
20813
|
txid: getTxId(feeBumpTx2),
|
|
20554
20814
|
vout: 0,
|
|
20555
20815
|
value: feeBumpOut.amount,
|
|
20556
|
-
script: (0,
|
|
20816
|
+
script: (0, import_utils12.bytesToHex)(feeBumpOut.script),
|
|
20557
20817
|
publicKey: feeBumpOutPubKey
|
|
20558
20818
|
});
|
|
20559
20819
|
txPackages.push({
|
|
@@ -20648,10 +20908,10 @@ function constructFeeBumpTx(txHex, utxos, feeRate, previousFeeBumpTx) {
|
|
|
20648
20908
|
if (!fundingUtxo) {
|
|
20649
20909
|
throw new Error(`UTXO at index ${i} is undefined`);
|
|
20650
20910
|
}
|
|
20651
|
-
const pubKeyHash = hash160((0,
|
|
20911
|
+
const pubKeyHash = hash160((0, import_utils12.hexToBytes)(fundingUtxo.publicKey));
|
|
20652
20912
|
const scriptToUse = new Uint8Array([0, 20, ...pubKeyHash]);
|
|
20653
|
-
const providedScript = (0,
|
|
20654
|
-
if ((0,
|
|
20913
|
+
const providedScript = (0, import_utils12.hexToBytes)(fundingUtxo.script);
|
|
20914
|
+
if ((0, import_utils12.bytesToHex)(scriptToUse) !== (0, import_utils12.bytesToHex)(providedScript)) {
|
|
20655
20915
|
throw new Error(
|
|
20656
20916
|
`\u274C Derived script doesn't match provided script for UTXO ${i + 1}.`
|
|
20657
20917
|
);
|
|
@@ -20716,7 +20976,7 @@ function constructFeeBumpTx(txHex, utxos, feeRate, previousFeeBumpTx) {
|
|
|
20716
20976
|
}
|
|
20717
20977
|
let psbtHex;
|
|
20718
20978
|
try {
|
|
20719
|
-
psbtHex = (0,
|
|
20979
|
+
psbtHex = (0, import_utils12.bytesToHex)(builder.toPSBT());
|
|
20720
20980
|
} catch (error) {
|
|
20721
20981
|
throw new Error(`Failed to extract transaction: ${error}`);
|
|
20722
20982
|
}
|
|
@@ -20894,12 +21154,12 @@ var NativeSparkFrost = class {
|
|
|
20894
21154
|
init_buffer();
|
|
20895
21155
|
var import_secp256k17 = require("@bitcoinerlab/secp256k1");
|
|
20896
21156
|
var import_secp256k18 = require("@noble/curves/secp256k1");
|
|
20897
|
-
var
|
|
21157
|
+
var import_utils14 = require("@noble/curves/utils");
|
|
20898
21158
|
var import_sha26 = require("@noble/hashes/sha2");
|
|
20899
21159
|
var import_bip32 = require("@scure/bip32");
|
|
20900
21160
|
var import_bip39 = require("@scure/bip39");
|
|
20901
21161
|
var import_english = require("@scure/bip39/wordlists/english");
|
|
20902
|
-
var
|
|
21162
|
+
var import_utils15 = require("@scure/btc-signer/utils");
|
|
20903
21163
|
var ecies = __toESM(require("eciesjs"), 1);
|
|
20904
21164
|
|
|
20905
21165
|
// src/constants.ts
|
|
@@ -20912,7 +21172,7 @@ var isWebExtension = (
|
|
|
20912
21172
|
"chrome" in globalThis && globalThis.chrome.runtime?.id
|
|
20913
21173
|
);
|
|
20914
21174
|
var userAgent = "navigator" in globalThis ? globalThis.navigator.userAgent || "unknown-user-agent" : void 0;
|
|
20915
|
-
var packageVersion = true ? "0.
|
|
21175
|
+
var packageVersion = true ? "0.4.0" : "unknown";
|
|
20916
21176
|
var baseEnvStr = "unknown";
|
|
20917
21177
|
if (isBun) {
|
|
20918
21178
|
const bunVersion = "version" in globalThis.Bun ? globalThis.Bun.version : "unknown-version";
|
|
@@ -20991,6 +21251,63 @@ var DefaultSparkKeysGenerator = class {
|
|
|
20991
21251
|
};
|
|
20992
21252
|
}
|
|
20993
21253
|
};
|
|
21254
|
+
var TaprootOutputKeysGenerator = class {
|
|
21255
|
+
constructor(useAddressIndex = false) {
|
|
21256
|
+
this.useAddressIndex = useAddressIndex;
|
|
21257
|
+
}
|
|
21258
|
+
async deriveKeysFromSeed(seed, accountNumber) {
|
|
21259
|
+
const hdkey = import_bip32.HDKey.fromMasterSeed(seed);
|
|
21260
|
+
if (!hdkey.privateKey || !hdkey.publicKey) {
|
|
21261
|
+
throw new ValidationError("Failed to derive keys from seed", {
|
|
21262
|
+
field: "hdkey",
|
|
21263
|
+
value: seed
|
|
21264
|
+
});
|
|
21265
|
+
}
|
|
21266
|
+
const derivationPath = this.useAddressIndex ? `m/86'/0'/0'/0/${accountNumber}` : `m/86'/0'/${accountNumber}'/0/0`;
|
|
21267
|
+
const taprootInternalKey = hdkey.derive(derivationPath);
|
|
21268
|
+
let tweakedPrivateKey = (0, import_utils15.taprootTweakPrivKey)(taprootInternalKey.privateKey);
|
|
21269
|
+
let tweakedPublicKey = import_secp256k18.secp256k1.getPublicKey(tweakedPrivateKey);
|
|
21270
|
+
if (tweakedPublicKey[0] === 3) {
|
|
21271
|
+
tweakedPrivateKey = (0, import_secp256k17.privateNegate)(tweakedPrivateKey);
|
|
21272
|
+
tweakedPublicKey = import_secp256k18.secp256k1.getPublicKey(tweakedPrivateKey);
|
|
21273
|
+
}
|
|
21274
|
+
const identityKey = {
|
|
21275
|
+
publicKey: tweakedPublicKey,
|
|
21276
|
+
privateKey: tweakedPrivateKey
|
|
21277
|
+
};
|
|
21278
|
+
const signingKey = hdkey.derive(`${derivationPath}/1'`);
|
|
21279
|
+
const depositKey = hdkey.derive(`${derivationPath}/2'`);
|
|
21280
|
+
const staticDepositKey = hdkey.derive(`${derivationPath}/3'`);
|
|
21281
|
+
if (!signingKey.privateKey || !signingKey.publicKey || !depositKey.privateKey || !depositKey.publicKey || !staticDepositKey.privateKey || !staticDepositKey.publicKey) {
|
|
21282
|
+
throw new ValidationError(
|
|
21283
|
+
"Failed to derive all required keys from seed",
|
|
21284
|
+
{
|
|
21285
|
+
field: "derivedKeys"
|
|
21286
|
+
}
|
|
21287
|
+
);
|
|
21288
|
+
}
|
|
21289
|
+
return {
|
|
21290
|
+
identityKey: {
|
|
21291
|
+
privateKey: identityKey.privateKey,
|
|
21292
|
+
publicKey: identityKey.publicKey
|
|
21293
|
+
},
|
|
21294
|
+
signingHDKey: {
|
|
21295
|
+
hdKey: signingKey,
|
|
21296
|
+
privateKey: signingKey.privateKey,
|
|
21297
|
+
publicKey: signingKey.publicKey
|
|
21298
|
+
},
|
|
21299
|
+
depositKey: {
|
|
21300
|
+
privateKey: depositKey.privateKey,
|
|
21301
|
+
publicKey: depositKey.publicKey
|
|
21302
|
+
},
|
|
21303
|
+
staticDepositHDKey: {
|
|
21304
|
+
hdKey: staticDepositKey,
|
|
21305
|
+
privateKey: staticDepositKey.privateKey,
|
|
21306
|
+
publicKey: staticDepositKey.publicKey
|
|
21307
|
+
}
|
|
21308
|
+
};
|
|
21309
|
+
}
|
|
21310
|
+
};
|
|
20994
21311
|
var DefaultSparkSigner = class {
|
|
20995
21312
|
constructor({
|
|
20996
21313
|
sparkKeysGenerator
|
|
@@ -21026,7 +21343,7 @@ var DefaultSparkSigner = class {
|
|
|
21026
21343
|
});
|
|
21027
21344
|
}
|
|
21028
21345
|
const receiverEciesPrivKey = ecies.PrivateKey.fromHex(
|
|
21029
|
-
(0,
|
|
21346
|
+
(0, import_utils14.bytesToHex)(this.identityKey.privateKey)
|
|
21030
21347
|
);
|
|
21031
21348
|
const privateKey = ecies.decrypt(receiverEciesPrivKey.toHex(), ciphertext);
|
|
21032
21349
|
return privateKey;
|
|
@@ -21160,7 +21477,7 @@ var DefaultSparkSigner = class {
|
|
|
21160
21477
|
threshold,
|
|
21161
21478
|
numShares
|
|
21162
21479
|
}) {
|
|
21163
|
-
const secretAsInt = (0,
|
|
21480
|
+
const secretAsInt = (0, import_utils14.bytesToNumberBE)(secret);
|
|
21164
21481
|
return splitSecretWithProofs(secretAsInt, curveOrder, threshold, numShares);
|
|
21165
21482
|
}
|
|
21166
21483
|
async signFrost({
|
|
@@ -21196,7 +21513,7 @@ var DefaultSparkSigner = class {
|
|
|
21196
21513
|
publicKey,
|
|
21197
21514
|
verifyingKey
|
|
21198
21515
|
};
|
|
21199
|
-
const logMessage = (0,
|
|
21516
|
+
const logMessage = (0, import_utils14.bytesToHex)(message);
|
|
21200
21517
|
const result = await SparkFrost.signFrost({
|
|
21201
21518
|
message,
|
|
21202
21519
|
keyPackage,
|
|
@@ -21238,7 +21555,7 @@ var DefaultSparkSigner = class {
|
|
|
21238
21555
|
}
|
|
21239
21556
|
async createSparkWalletFromSeed(seed, accountNumber) {
|
|
21240
21557
|
if (typeof seed === "string") {
|
|
21241
|
-
seed = (0,
|
|
21558
|
+
seed = (0, import_utils14.hexToBytes)(seed);
|
|
21242
21559
|
}
|
|
21243
21560
|
const {
|
|
21244
21561
|
identityKey,
|
|
@@ -21250,7 +21567,7 @@ var DefaultSparkSigner = class {
|
|
|
21250
21567
|
this.depositKey = depositKey;
|
|
21251
21568
|
this.signingKey = signingKey.hdKey;
|
|
21252
21569
|
this.staticDepositKey = staticDepositKey.hdKey;
|
|
21253
|
-
return (0,
|
|
21570
|
+
return (0, import_utils14.bytesToHex)(identityKey.publicKey);
|
|
21254
21571
|
}
|
|
21255
21572
|
async signMessageWithIdentityKey(message, compact) {
|
|
21256
21573
|
if (!this.identityKey?.privateKey) {
|
|
@@ -21271,7 +21588,7 @@ var DefaultSparkSigner = class {
|
|
|
21271
21588
|
});
|
|
21272
21589
|
}
|
|
21273
21590
|
const receiverEciesPrivKey = ecies.PrivateKey.fromHex(
|
|
21274
|
-
(0,
|
|
21591
|
+
(0, import_utils14.bytesToHex)(this.identityKey.privateKey)
|
|
21275
21592
|
);
|
|
21276
21593
|
const privateKey = ecies.decrypt(receiverEciesPrivKey.toHex(), ciphertext);
|
|
21277
21594
|
const publicKey = import_secp256k18.secp256k1.getPublicKey(privateKey);
|
|
@@ -21295,20 +21612,27 @@ var DefaultSparkSigner = class {
|
|
|
21295
21612
|
}
|
|
21296
21613
|
signTransactionIndex(tx, index, publicKey) {
|
|
21297
21614
|
let privateKey;
|
|
21298
|
-
if ((0,
|
|
21615
|
+
if ((0, import_utils14.equalBytes)(publicKey, this.identityKey?.publicKey ?? new Uint8Array())) {
|
|
21299
21616
|
privateKey = this.identityKey?.privateKey;
|
|
21300
|
-
} else if ((0,
|
|
21617
|
+
} else if ((0, import_utils14.equalBytes)(publicKey, this.depositKey?.publicKey ?? new Uint8Array())) {
|
|
21301
21618
|
privateKey = this.depositKey?.privateKey;
|
|
21302
21619
|
}
|
|
21303
21620
|
if (!privateKey) {
|
|
21304
21621
|
throw new ValidationError("Private key not found for public key", {
|
|
21305
21622
|
field: "privateKey",
|
|
21306
|
-
value: (0,
|
|
21623
|
+
value: (0, import_utils14.bytesToHex)(publicKey)
|
|
21307
21624
|
});
|
|
21308
21625
|
}
|
|
21309
21626
|
tx.signIdx(privateKey, index);
|
|
21310
21627
|
}
|
|
21311
21628
|
};
|
|
21629
|
+
var TaprootSparkSigner = class extends DefaultSparkSigner {
|
|
21630
|
+
constructor(useAddressIndex = false) {
|
|
21631
|
+
super({
|
|
21632
|
+
sparkKeysGenerator: new TaprootOutputKeysGenerator(useAddressIndex)
|
|
21633
|
+
});
|
|
21634
|
+
}
|
|
21635
|
+
};
|
|
21312
21636
|
|
|
21313
21637
|
// src/signer/signer.react-native.ts
|
|
21314
21638
|
var ReactNativeSparkSigner = class extends DefaultSparkSigner {
|
|
@@ -21372,6 +21696,70 @@ var ReactNativeSparkSigner = class extends DefaultSparkSigner {
|
|
|
21372
21696
|
});
|
|
21373
21697
|
}
|
|
21374
21698
|
};
|
|
21699
|
+
var ReactNativeTaprootSparkSigner = class extends TaprootSparkSigner {
|
|
21700
|
+
constructor(useAddressIndex = false) {
|
|
21701
|
+
super(useAddressIndex);
|
|
21702
|
+
}
|
|
21703
|
+
async signFrost({
|
|
21704
|
+
message,
|
|
21705
|
+
keyDerivation,
|
|
21706
|
+
publicKey,
|
|
21707
|
+
verifyingKey,
|
|
21708
|
+
selfCommitment,
|
|
21709
|
+
statechainCommitments,
|
|
21710
|
+
adaptorPubKey
|
|
21711
|
+
}) {
|
|
21712
|
+
const signingPrivateKey = await this.getSigningPrivateKeyFromDerivation(keyDerivation);
|
|
21713
|
+
if (!signingPrivateKey) {
|
|
21714
|
+
throw new ValidationError("Private key not found for public key", {
|
|
21715
|
+
field: "privateKey"
|
|
21716
|
+
});
|
|
21717
|
+
}
|
|
21718
|
+
const commitment = selfCommitment.commitment;
|
|
21719
|
+
const nonce = this.commitmentToNonceMap.get(commitment);
|
|
21720
|
+
if (!nonce) {
|
|
21721
|
+
throw new ValidationError("Nonce not found for commitment", {
|
|
21722
|
+
field: "nonce"
|
|
21723
|
+
});
|
|
21724
|
+
}
|
|
21725
|
+
const keyPackage = {
|
|
21726
|
+
secretKey: signingPrivateKey,
|
|
21727
|
+
publicKey,
|
|
21728
|
+
verifyingKey
|
|
21729
|
+
};
|
|
21730
|
+
return NativeSparkFrost.signFrost({
|
|
21731
|
+
message,
|
|
21732
|
+
keyPackage,
|
|
21733
|
+
nonce,
|
|
21734
|
+
selfCommitment: commitment,
|
|
21735
|
+
statechainCommitments,
|
|
21736
|
+
adaptorPubKey
|
|
21737
|
+
});
|
|
21738
|
+
}
|
|
21739
|
+
async aggregateFrost({
|
|
21740
|
+
message,
|
|
21741
|
+
publicKey,
|
|
21742
|
+
verifyingKey,
|
|
21743
|
+
selfCommitment,
|
|
21744
|
+
statechainCommitments,
|
|
21745
|
+
adaptorPubKey,
|
|
21746
|
+
selfSignature,
|
|
21747
|
+
statechainSignatures,
|
|
21748
|
+
statechainPublicKeys
|
|
21749
|
+
}) {
|
|
21750
|
+
return NativeSparkFrost.aggregateFrost({
|
|
21751
|
+
message,
|
|
21752
|
+
statechainSignatures,
|
|
21753
|
+
statechainPublicKeys,
|
|
21754
|
+
verifyingKey,
|
|
21755
|
+
statechainCommitments,
|
|
21756
|
+
selfCommitment: selfCommitment.commitment,
|
|
21757
|
+
selfPublicKey: publicKey,
|
|
21758
|
+
selfSignature,
|
|
21759
|
+
adaptorPubKey
|
|
21760
|
+
});
|
|
21761
|
+
}
|
|
21762
|
+
};
|
|
21375
21763
|
|
|
21376
21764
|
// src/spark-wallet/spark-wallet.react-native.ts
|
|
21377
21765
|
init_buffer();
|
|
@@ -21513,7 +21901,16 @@ function headersToMetadata(headers) {
|
|
|
21513
21901
|
const parts = line.split(": ");
|
|
21514
21902
|
const header = parts.shift() ?? "";
|
|
21515
21903
|
const value = parts.join(": ");
|
|
21516
|
-
|
|
21904
|
+
if (header.endsWith("-bin")) {
|
|
21905
|
+
try {
|
|
21906
|
+
metadata.set(header, import_js_base64.Base64.toUint8Array(value));
|
|
21907
|
+
} catch (e) {
|
|
21908
|
+
console.warn(`Failed to decode binary metadata ${header}:`, e);
|
|
21909
|
+
metadata.set(header, value);
|
|
21910
|
+
}
|
|
21911
|
+
} else {
|
|
21912
|
+
metadata.set(header, value);
|
|
21913
|
+
}
|
|
21517
21914
|
});
|
|
21518
21915
|
return metadata;
|
|
21519
21916
|
}
|
|
@@ -21539,7 +21936,7 @@ function getStatusFromHttpCode(statusCode) {
|
|
|
21539
21936
|
}
|
|
21540
21937
|
}
|
|
21541
21938
|
function getErrorDetailsFromHttpResponse(statusCode, responseText) {
|
|
21542
|
-
return `Received HTTP ${statusCode} response: ` + (responseText
|
|
21939
|
+
return `Received HTTP ${statusCode} response: ` + (responseText?.length > 1e3 ? responseText?.slice(0, 1e3) + "... (truncated)" : responseText);
|
|
21543
21940
|
}
|
|
21544
21941
|
|
|
21545
21942
|
// src/spark-wallet/spark-wallet.ts
|
|
@@ -21549,7 +21946,7 @@ var import_secp256k114 = require("@noble/curves/secp256k1");
|
|
|
21549
21946
|
var import_utils25 = require("@noble/curves/utils");
|
|
21550
21947
|
var import_bip392 = require("@scure/bip39");
|
|
21551
21948
|
var import_english2 = require("@scure/bip39/wordlists/english");
|
|
21552
|
-
var
|
|
21949
|
+
var import_btc_signer5 = require("@scure/btc-signer");
|
|
21553
21950
|
var import_async_mutex = require("async-mutex");
|
|
21554
21951
|
var import_uuidv75 = require("uuidv7");
|
|
21555
21952
|
|
|
@@ -22798,28 +23195,22 @@ var WalletConfigService = class {
|
|
|
22798
23195
|
getEvents() {
|
|
22799
23196
|
return this.config.events;
|
|
22800
23197
|
}
|
|
23198
|
+
getOptimizationOptions() {
|
|
23199
|
+
return this.config.optimizationOptions;
|
|
23200
|
+
}
|
|
22801
23201
|
};
|
|
22802
23202
|
|
|
22803
23203
|
// src/services/coop-exit.ts
|
|
22804
23204
|
init_buffer();
|
|
22805
|
-
var import_btc_signer3 = require("@scure/btc-signer");
|
|
22806
23205
|
var import_uuidv73 = require("uuidv7");
|
|
22807
23206
|
|
|
22808
23207
|
// src/services/transfer.ts
|
|
22809
23208
|
init_buffer();
|
|
22810
23209
|
var import_secp256k19 = require("@noble/curves/secp256k1");
|
|
22811
|
-
var
|
|
23210
|
+
var import_utils16 = require("@noble/curves/utils");
|
|
22812
23211
|
var import_sha28 = require("@noble/hashes/sha2");
|
|
22813
|
-
var import_btc_signer2 = require("@scure/btc-signer");
|
|
22814
23212
|
var ecies2 = __toESM(require("eciesjs"), 1);
|
|
22815
23213
|
var import_uuidv72 = require("uuidv7");
|
|
22816
|
-
function getSigningJobProto(signingJob) {
|
|
22817
|
-
return {
|
|
22818
|
-
signingPublicKey: signingJob.signingPublicKey,
|
|
22819
|
-
rawTx: signingJob.rawTx,
|
|
22820
|
-
signingNonceCommitment: signingJob.signingNonceCommitment.commitment
|
|
22821
|
-
};
|
|
22822
|
-
}
|
|
22823
23214
|
var BaseTransferService = class {
|
|
22824
23215
|
constructor(config, connectionManager, signingService) {
|
|
22825
23216
|
__publicField(this, "config");
|
|
@@ -23166,7 +23557,7 @@ var BaseTransferService = class {
|
|
|
23166
23557
|
}
|
|
23167
23558
|
async prepareSendTransferKeyTweaks(transferID, receiverIdentityPubkey, leaves, cpfpRefundSignatureMap, directRefundSignatureMap, directFromCpfpRefundSignatureMap) {
|
|
23168
23559
|
const receiverEciesPubKey = ecies2.PublicKey.fromHex(
|
|
23169
|
-
(0,
|
|
23560
|
+
(0, import_utils16.bytesToHex)(receiverIdentityPubkey)
|
|
23170
23561
|
);
|
|
23171
23562
|
const leavesTweaksMap = /* @__PURE__ */ new Map();
|
|
23172
23563
|
for (const leaf of leaves) {
|
|
@@ -23207,7 +23598,7 @@ var BaseTransferService = class {
|
|
|
23207
23598
|
throw new Error(`Share not found for operator ${operator.id}`);
|
|
23208
23599
|
}
|
|
23209
23600
|
const pubkeyTweak = import_secp256k19.secp256k1.getPublicKey(
|
|
23210
|
-
(0,
|
|
23601
|
+
(0, import_utils16.numberToBytesBE)(share.share, 32),
|
|
23211
23602
|
true
|
|
23212
23603
|
);
|
|
23213
23604
|
pubkeySharesTweak.set(identifier, pubkeyTweak);
|
|
@@ -23232,7 +23623,7 @@ var BaseTransferService = class {
|
|
|
23232
23623
|
leafTweaksMap.set(identifier, {
|
|
23233
23624
|
leafId: leaf.leaf.id,
|
|
23234
23625
|
secretShareTweak: {
|
|
23235
|
-
secretShare: (0,
|
|
23626
|
+
secretShare: (0, import_utils16.numberToBytesBE)(share.share, 32),
|
|
23236
23627
|
proofs: share.proofs
|
|
23237
23628
|
},
|
|
23238
23629
|
pubkeySharesTweak: Object.fromEntries(pubkeySharesTweak),
|
|
@@ -23255,7 +23646,7 @@ var BaseTransferService = class {
|
|
|
23255
23646
|
return void 0;
|
|
23256
23647
|
}
|
|
23257
23648
|
compareTransfers(transfer1, transfer2) {
|
|
23258
|
-
return transfer1.id === transfer2.id && (0,
|
|
23649
|
+
return transfer1.id === transfer2.id && (0, import_utils16.equalBytes)(
|
|
23259
23650
|
transfer1.senderIdentityPublicKey,
|
|
23260
23651
|
transfer2.senderIdentityPublicKey
|
|
23261
23652
|
) && transfer1.status === transfer2.status && transfer1.totalValue === transfer2.totalValue && transfer1.expiryTime?.getTime() === transfer2.expiryTime?.getTime() && transfer1.leaves.length === transfer2.leaves.length;
|
|
@@ -23501,42 +23892,27 @@ var TransferService = class extends BaseTransferService {
|
|
|
23501
23892
|
throw new Error(`Leaf data not found for leaf ${leaf.leaf.id}`);
|
|
23502
23893
|
}
|
|
23503
23894
|
const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
23504
|
-
const cpfpNodeOutPoint = {
|
|
23505
|
-
txid: (0, import_utils15.hexToBytes)(getTxId(nodeTx)),
|
|
23506
|
-
index: 0
|
|
23507
|
-
};
|
|
23508
23895
|
let directNodeTx;
|
|
23509
|
-
let directNodeOutPoint;
|
|
23510
23896
|
if (leaf.leaf.directTx.length > 0) {
|
|
23511
23897
|
directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
|
|
23512
|
-
directNodeOutPoint = {
|
|
23513
|
-
txid: (0, import_utils15.hexToBytes)(getTxId(directNodeTx)),
|
|
23514
|
-
index: 0
|
|
23515
|
-
};
|
|
23516
23898
|
}
|
|
23517
23899
|
const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
23518
|
-
const
|
|
23519
|
-
if (!
|
|
23900
|
+
const currentSequence = currRefundTx.getInput(0).sequence;
|
|
23901
|
+
if (!currentSequence) {
|
|
23520
23902
|
throw new ValidationError("Invalid refund transaction", {
|
|
23521
23903
|
field: "sequence",
|
|
23522
23904
|
value: currRefundTx.getInput(0),
|
|
23523
23905
|
expected: "Non-null sequence"
|
|
23524
23906
|
});
|
|
23525
23907
|
}
|
|
23526
|
-
const
|
|
23527
|
-
|
|
23528
|
-
|
|
23529
|
-
|
|
23530
|
-
}
|
|
23531
|
-
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
23532
|
-
sequence: nextSequence,
|
|
23533
|
-
directSequence: nextDirectSequence,
|
|
23534
|
-
input: cpfpNodeOutPoint,
|
|
23535
|
-
directInput: directNodeOutPoint,
|
|
23536
|
-
amountSats,
|
|
23908
|
+
const refundTxsParams = {
|
|
23909
|
+
nodeTx,
|
|
23910
|
+
directNodeTx,
|
|
23911
|
+
sequence: currentSequence,
|
|
23537
23912
|
receivingPubkey: refundSigningData.receivingPubkey,
|
|
23538
23913
|
network: this.config.getNetwork()
|
|
23539
|
-
}
|
|
23914
|
+
};
|
|
23915
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = isForClaim ? createCurrentTimelockRefundTxs(refundTxsParams) : createDecrementedTimelockRefundTxs(refundTxsParams);
|
|
23540
23916
|
refundSigningData.refundTx = cpfpRefundTx;
|
|
23541
23917
|
refundSigningData.directRefundTx = directRefundTx;
|
|
23542
23918
|
refundSigningData.directFromCpfpRefundTx = directFromCpfpRefundTx;
|
|
@@ -23644,7 +24020,7 @@ var TransferService = class extends BaseTransferService {
|
|
|
23644
24020
|
throw new Error(`Share not found for operator ${operator.id}`);
|
|
23645
24021
|
}
|
|
23646
24022
|
const pubkeyTweak = import_secp256k19.secp256k1.getPublicKey(
|
|
23647
|
-
(0,
|
|
24023
|
+
(0, import_utils16.numberToBytesBE)(share.share, 32)
|
|
23648
24024
|
);
|
|
23649
24025
|
pubkeySharesTweak.set(identifier, pubkeyTweak);
|
|
23650
24026
|
}
|
|
@@ -23657,7 +24033,7 @@ var TransferService = class extends BaseTransferService {
|
|
|
23657
24033
|
leafTweaksMap.set(identifier, {
|
|
23658
24034
|
leafId: leaf.leaf.id,
|
|
23659
24035
|
secretShareTweak: {
|
|
23660
|
-
secretShare: (0,
|
|
24036
|
+
secretShare: (0, import_utils16.numberToBytesBE)(share.share, 32),
|
|
23661
24037
|
proofs: share.proofs
|
|
23662
24038
|
},
|
|
23663
24039
|
pubkeySharesTweak: Object.fromEntries(pubkeySharesTweak)
|
|
@@ -23749,71 +24125,127 @@ var TransferService = class extends BaseTransferService {
|
|
|
23749
24125
|
throw new Error(`Error querying pending transfers by sender: ${error}`);
|
|
23750
24126
|
}
|
|
23751
24127
|
}
|
|
23752
|
-
async
|
|
23753
|
-
const
|
|
23754
|
-
|
|
23755
|
-
|
|
23756
|
-
|
|
23757
|
-
|
|
24128
|
+
async renewRefundTxn(node, parentNode) {
|
|
24129
|
+
const sparkClient = await this.connectionManager.createSparkClient(
|
|
24130
|
+
this.config.getCoordinatorAddress()
|
|
24131
|
+
);
|
|
24132
|
+
const signingJobs = await this.createRenewRefundSigningJobs(
|
|
24133
|
+
node,
|
|
24134
|
+
parentNode
|
|
24135
|
+
);
|
|
24136
|
+
const statechainCommitments = await sparkClient.get_signing_commitments({
|
|
24137
|
+
nodeIds: [node.id],
|
|
24138
|
+
count: signingJobs.length
|
|
24139
|
+
});
|
|
24140
|
+
const mappedSigningJobs = signingJobs.map((signingJob, index) => {
|
|
24141
|
+
const signingNonceCommitments = statechainCommitments.signingCommitments[index]?.signingNonceCommitments;
|
|
24142
|
+
if (!signingNonceCommitments) {
|
|
24143
|
+
throw new Error("Signing nonce commitments not found");
|
|
24144
|
+
}
|
|
24145
|
+
return {
|
|
24146
|
+
...signingJob,
|
|
24147
|
+
signingNonceCommitments
|
|
24148
|
+
};
|
|
24149
|
+
});
|
|
24150
|
+
const userSignedTxSigningJobs = await this.signingService.signSigningJobs(mappedSigningJobs);
|
|
24151
|
+
const renewRefundTimelockSigningJob = {
|
|
24152
|
+
nodeTxSigningJob: userSignedTxSigningJobs.get("node"),
|
|
24153
|
+
refundTxSigningJob: userSignedTxSigningJobs.get("cpfp"),
|
|
24154
|
+
directNodeTxSigningJob: userSignedTxSigningJobs.get("directNode"),
|
|
24155
|
+
directRefundTxSigningJob: userSignedTxSigningJobs.get("direct"),
|
|
24156
|
+
directFromCpfpRefundTxSigningJob: userSignedTxSigningJobs.get("directFromCpfp")
|
|
24157
|
+
};
|
|
24158
|
+
const response = await sparkClient.renew_leaf({
|
|
24159
|
+
leafId: node.id,
|
|
24160
|
+
signingJobs: {
|
|
24161
|
+
$case: "renewRefundTimelockSigningJob",
|
|
24162
|
+
renewRefundTimelockSigningJob
|
|
24163
|
+
}
|
|
24164
|
+
});
|
|
24165
|
+
if (response.renewResult?.$case !== "renewRefundTimelockResult" || !response.renewResult?.renewRefundTimelockResult.node) {
|
|
24166
|
+
throw new ValidationError("Unexpected renew result", {
|
|
24167
|
+
field: "renewResult",
|
|
24168
|
+
value: response.renewResult
|
|
24169
|
+
});
|
|
23758
24170
|
}
|
|
23759
|
-
|
|
23760
|
-
|
|
23761
|
-
|
|
23762
|
-
|
|
23763
|
-
|
|
23764
|
-
|
|
23765
|
-
|
|
23766
|
-
|
|
23767
|
-
|
|
23768
|
-
|
|
23769
|
-
|
|
23770
|
-
|
|
23771
|
-
|
|
23772
|
-
|
|
23773
|
-
|
|
23774
|
-
|
|
23775
|
-
|
|
23776
|
-
|
|
24171
|
+
return response.renewResult?.renewRefundTimelockResult.node;
|
|
24172
|
+
}
|
|
24173
|
+
async renewNodeTxn(node, parentNode) {
|
|
24174
|
+
const sparkClient = await this.connectionManager.createSparkClient(
|
|
24175
|
+
this.config.getCoordinatorAddress()
|
|
24176
|
+
);
|
|
24177
|
+
const signingJobs = await this.createRenewNodeSigningJobs(node, parentNode);
|
|
24178
|
+
const statechainCommitments = await sparkClient.get_signing_commitments({
|
|
24179
|
+
nodeIds: [node.id],
|
|
24180
|
+
count: signingJobs.length
|
|
24181
|
+
});
|
|
24182
|
+
const mappedSigningJobs = signingJobs.map((signingJob, index) => {
|
|
24183
|
+
const signingNonceCommitments = statechainCommitments.signingCommitments[index]?.signingNonceCommitments;
|
|
24184
|
+
if (!signingNonceCommitments) {
|
|
24185
|
+
throw new Error("Signing nonce commitments not found");
|
|
24186
|
+
}
|
|
24187
|
+
return {
|
|
24188
|
+
...signingJob,
|
|
24189
|
+
signingNonceCommitments
|
|
24190
|
+
};
|
|
24191
|
+
});
|
|
24192
|
+
const userSignedTxSigningJobs = await this.signingService.signSigningJobs(mappedSigningJobs);
|
|
24193
|
+
const response = await sparkClient.renew_leaf({
|
|
24194
|
+
leafId: node.id,
|
|
24195
|
+
signingJobs: {
|
|
24196
|
+
$case: "renewNodeTimelockSigningJob",
|
|
24197
|
+
renewNodeTimelockSigningJob: {
|
|
24198
|
+
splitNodeTxSigningJob: userSignedTxSigningJobs.get("split"),
|
|
24199
|
+
splitNodeDirectTxSigningJob: userSignedTxSigningJobs.get("directSplit"),
|
|
24200
|
+
nodeTxSigningJob: userSignedTxSigningJobs.get("node"),
|
|
24201
|
+
directNodeTxSigningJob: userSignedTxSigningJobs.get("directNode"),
|
|
24202
|
+
refundTxSigningJob: userSignedTxSigningJobs.get("cpfp"),
|
|
24203
|
+
directRefundTxSigningJob: userSignedTxSigningJobs.get("direct"),
|
|
24204
|
+
directFromCpfpRefundTxSigningJob: userSignedTxSigningJobs.get("directFromCpfp")
|
|
24205
|
+
}
|
|
24206
|
+
}
|
|
24207
|
+
});
|
|
24208
|
+
if (response.renewResult?.$case !== "renewNodeTimelockResult" || !response.renewResult?.renewNodeTimelockResult.node) {
|
|
24209
|
+
throw new ValidationError("Unexpected renew result", {
|
|
24210
|
+
field: "renewResult",
|
|
24211
|
+
value: response.renewResult
|
|
23777
24212
|
});
|
|
23778
24213
|
}
|
|
23779
|
-
|
|
23780
|
-
|
|
23781
|
-
|
|
24214
|
+
return response.renewResult.renewNodeTimelockResult.node;
|
|
24215
|
+
}
|
|
24216
|
+
async createRenewRefundSigningJobs(node, parentNode) {
|
|
24217
|
+
const signingJobs = [];
|
|
24218
|
+
const parentTx = getTxFromRawTxBytes(parentNode.nodeTx);
|
|
24219
|
+
const parentNodeOutput = getTxFromRawTxBytes(parentNode.nodeTx).getOutput(
|
|
24220
|
+
0
|
|
23782
24221
|
);
|
|
23783
|
-
|
|
24222
|
+
if (!parentNodeOutput) {
|
|
24223
|
+
throw new Error("Parent node output not found");
|
|
24224
|
+
}
|
|
24225
|
+
const unsignedParentNodeOutput = {
|
|
23784
24226
|
script: parentNodeOutput.script,
|
|
23785
24227
|
amount: parentNodeOutput.amount
|
|
23786
24228
|
};
|
|
23787
|
-
const
|
|
23788
|
-
txid: nodeInput.txid,
|
|
23789
|
-
index: nodeInput.index,
|
|
23790
|
-
sequence: useTestUnilateralSequence ? TEST_UNILATERAL_SEQUENCE : nextSequence
|
|
23791
|
-
};
|
|
23792
|
-
const newDirectInput = directNodeTx && directNodeInput ? {
|
|
23793
|
-
txid: directNodeInput.txid,
|
|
23794
|
-
index: directNodeInput.index,
|
|
23795
|
-
sequence: useTestUnilateralSequence ? TEST_UNILATERAL_DIRECT_SEQUENCE : nextDirectSequence
|
|
23796
|
-
} : void 0;
|
|
23797
|
-
const { cpfpNodeTx, directNodeTx: newDirectNodeTx } = createNodeTxs(
|
|
23798
|
-
output,
|
|
23799
|
-
newNodeInput,
|
|
23800
|
-
newDirectInput
|
|
23801
|
-
);
|
|
23802
|
-
const newCpfpNodeOutput = cpfpNodeTx.getOutput(0);
|
|
23803
|
-
if (!newCpfpNodeOutput) {
|
|
23804
|
-
throw Error("Could not get new cpfp node output");
|
|
23805
|
-
}
|
|
23806
|
-
const newDirectNodeOutput = newDirectNodeTx?.getOutput(0);
|
|
23807
|
-
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation({
|
|
24229
|
+
const keyDerivation = {
|
|
23808
24230
|
type: "leaf" /* LEAF */,
|
|
23809
24231
|
path: node.id
|
|
23810
|
-
}
|
|
24232
|
+
};
|
|
24233
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
24234
|
+
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
24235
|
+
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
24236
|
+
const { nodeTx: newNodeTx, directNodeTx: newDirectNodeTx } = createDecrementedTimelockNodeTx(parentTx, nodeTx);
|
|
23811
24237
|
signingJobs.push({
|
|
23812
24238
|
signingPublicKey,
|
|
23813
|
-
rawTx:
|
|
24239
|
+
rawTx: newNodeTx.toBytes(),
|
|
23814
24240
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
23815
24241
|
type: "node",
|
|
23816
|
-
parentTxOut:
|
|
24242
|
+
parentTxOut: unsignedParentNodeOutput,
|
|
24243
|
+
leafId: node.id,
|
|
24244
|
+
keyDerivation: {
|
|
24245
|
+
type: "leaf" /* LEAF */,
|
|
24246
|
+
path: node.id
|
|
24247
|
+
},
|
|
24248
|
+
verifyingKey: node.verifyingPublicKey
|
|
23817
24249
|
});
|
|
23818
24250
|
if (newDirectNodeTx) {
|
|
23819
24251
|
signingJobs.push({
|
|
@@ -23821,537 +24253,299 @@ var TransferService = class extends BaseTransferService {
|
|
|
23821
24253
|
rawTx: newDirectNodeTx.toBytes(),
|
|
23822
24254
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
23823
24255
|
type: "directNode",
|
|
23824
|
-
parentTxOut:
|
|
24256
|
+
parentTxOut: unsignedParentNodeOutput,
|
|
24257
|
+
leafId: node.id,
|
|
24258
|
+
keyDerivation: {
|
|
24259
|
+
type: "leaf" /* LEAF */,
|
|
24260
|
+
path: node.id
|
|
24261
|
+
},
|
|
24262
|
+
verifyingKey: node.verifyingPublicKey
|
|
23825
24263
|
});
|
|
23826
24264
|
}
|
|
23827
|
-
const
|
|
23828
|
-
|
|
23829
|
-
|
|
23830
|
-
};
|
|
23831
|
-
let newDirectRefundOutPoint;
|
|
23832
|
-
if (newDirectNodeTx) {
|
|
23833
|
-
newDirectRefundOutPoint = {
|
|
23834
|
-
txid: (0, import_utils15.hexToBytes)(getTxId(newDirectNodeTx)),
|
|
23835
|
-
index: 0
|
|
23836
|
-
};
|
|
24265
|
+
const newCpfpNodeOutput = newNodeTx.getOutput(0);
|
|
24266
|
+
if (!newCpfpNodeOutput) {
|
|
24267
|
+
throw Error("Could not get new cpfp node output");
|
|
23837
24268
|
}
|
|
23838
|
-
const
|
|
23839
|
-
|
|
23840
|
-
|
|
23841
|
-
|
|
23842
|
-
|
|
23843
|
-
|
|
23844
|
-
|
|
23845
|
-
|
|
23846
|
-
|
|
23847
|
-
|
|
24269
|
+
const newDirectNodeOutput = newDirectNodeTx?.getOutput(0);
|
|
24270
|
+
const amountSats = refundTx.getOutput(0).amount;
|
|
24271
|
+
if (amountSats === void 0) {
|
|
24272
|
+
throw new Error("Amount not found in extendTimelock");
|
|
24273
|
+
}
|
|
24274
|
+
const directAmountSats = newDirectNodeOutput?.amount;
|
|
24275
|
+
if (directAmountSats === void 0) {
|
|
24276
|
+
throw new Error("Amount not found in extendTimelock");
|
|
24277
|
+
}
|
|
24278
|
+
const {
|
|
24279
|
+
cpfpRefundTx: newRefundTx,
|
|
24280
|
+
directRefundTx: newDirectRefundTx,
|
|
24281
|
+
directFromCpfpRefundTx: newDirectFromCpfpRefundTx
|
|
24282
|
+
} = createInitialTimelockRefundTxs({
|
|
24283
|
+
nodeTx: newNodeTx,
|
|
24284
|
+
directNodeTx: newDirectNodeTx,
|
|
24285
|
+
receivingPubkey: signingPublicKey,
|
|
23848
24286
|
network: this.config.getNetwork()
|
|
23849
24287
|
});
|
|
23850
24288
|
signingJobs.push({
|
|
23851
24289
|
signingPublicKey,
|
|
23852
|
-
rawTx:
|
|
24290
|
+
rawTx: newRefundTx.toBytes(),
|
|
23853
24291
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
23854
24292
|
type: "cpfp",
|
|
23855
|
-
parentTxOut: newCpfpNodeOutput
|
|
24293
|
+
parentTxOut: newCpfpNodeOutput,
|
|
24294
|
+
leafId: node.id,
|
|
24295
|
+
keyDerivation,
|
|
24296
|
+
verifyingKey: node.verifyingPublicKey
|
|
23856
24297
|
});
|
|
23857
|
-
if (
|
|
24298
|
+
if (newDirectRefundTx && newDirectNodeOutput) {
|
|
23858
24299
|
signingJobs.push({
|
|
23859
24300
|
signingPublicKey,
|
|
23860
|
-
rawTx:
|
|
24301
|
+
rawTx: newDirectRefundTx.toBytes(),
|
|
23861
24302
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
23862
24303
|
type: "direct",
|
|
23863
|
-
parentTxOut: newDirectNodeOutput
|
|
24304
|
+
parentTxOut: newDirectNodeOutput,
|
|
24305
|
+
leafId: node.id,
|
|
24306
|
+
keyDerivation,
|
|
24307
|
+
verifyingKey: node.verifyingPublicKey
|
|
23864
24308
|
});
|
|
23865
24309
|
}
|
|
23866
|
-
if (
|
|
24310
|
+
if (newDirectFromCpfpRefundTx && newDirectNodeOutput) {
|
|
23867
24311
|
signingJobs.push({
|
|
23868
24312
|
signingPublicKey,
|
|
23869
|
-
rawTx:
|
|
24313
|
+
rawTx: newDirectFromCpfpRefundTx.toBytes(),
|
|
23870
24314
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
23871
24315
|
type: "directFromCpfp",
|
|
23872
|
-
parentTxOut: newCpfpNodeOutput
|
|
24316
|
+
parentTxOut: newCpfpNodeOutput,
|
|
24317
|
+
leafId: node.id,
|
|
24318
|
+
keyDerivation,
|
|
24319
|
+
verifyingKey: node.verifyingPublicKey
|
|
23873
24320
|
});
|
|
23874
24321
|
}
|
|
23875
|
-
|
|
23876
|
-
this.config.getCoordinatorAddress()
|
|
23877
|
-
);
|
|
23878
|
-
const response = await sparkClient.refresh_timelock_v2({
|
|
23879
|
-
leafId: node.id,
|
|
23880
|
-
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
23881
|
-
signingJobs: signingJobs.map(getSigningJobProto)
|
|
23882
|
-
});
|
|
23883
|
-
if (signingJobs.length !== response.signingResults.length) {
|
|
23884
|
-
throw Error(
|
|
23885
|
-
`number of signing jobs and signing results do not match: ${signingJobs.length} !== ${response.signingResults.length}`
|
|
23886
|
-
);
|
|
23887
|
-
}
|
|
23888
|
-
let nodeSignatures = [];
|
|
23889
|
-
let leafCpfpSignature;
|
|
23890
|
-
let leafDirectSignature;
|
|
23891
|
-
let cpfpRefundSignature;
|
|
23892
|
-
let directRefundSignature;
|
|
23893
|
-
let directFromCpfpRefundSignature;
|
|
23894
|
-
for (const [i, signingResult] of response.signingResults.entries()) {
|
|
23895
|
-
const signingJob = signingJobs[i];
|
|
23896
|
-
if (!signingJob || !signingResult) {
|
|
23897
|
-
throw Error("Signing job does not exist");
|
|
23898
|
-
}
|
|
23899
|
-
const rawTx = getTxFromRawTxBytes(signingJob.rawTx);
|
|
23900
|
-
const txOut = signingJob.parentTxOut;
|
|
23901
|
-
if (!txOut) {
|
|
23902
|
-
throw Error("Could not get tx out");
|
|
23903
|
-
}
|
|
23904
|
-
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
23905
|
-
const userSignature = await this.config.signer.signFrost({
|
|
23906
|
-
message: rawTxSighash,
|
|
23907
|
-
keyDerivation: {
|
|
23908
|
-
type: "leaf" /* LEAF */,
|
|
23909
|
-
path: node.id
|
|
23910
|
-
},
|
|
23911
|
-
publicKey: signingJob.signingPublicKey,
|
|
23912
|
-
verifyingKey: signingResult.verifyingKey,
|
|
23913
|
-
selfCommitment: signingJob.signingNonceCommitment,
|
|
23914
|
-
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
23915
|
-
adaptorPubKey: new Uint8Array()
|
|
23916
|
-
});
|
|
23917
|
-
const signature = await this.config.signer.aggregateFrost({
|
|
23918
|
-
message: rawTxSighash,
|
|
23919
|
-
statechainSignatures: signingResult.signingResult?.signatureShares,
|
|
23920
|
-
statechainPublicKeys: signingResult.signingResult?.publicKeys,
|
|
23921
|
-
verifyingKey: signingResult.verifyingKey,
|
|
23922
|
-
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
23923
|
-
selfCommitment: signingJob.signingNonceCommitment,
|
|
23924
|
-
publicKey: signingJob.signingPublicKey,
|
|
23925
|
-
selfSignature: userSignature,
|
|
23926
|
-
adaptorPubKey: new Uint8Array()
|
|
23927
|
-
});
|
|
23928
|
-
if (signingJob.type === "node") {
|
|
23929
|
-
leafCpfpSignature = signature;
|
|
23930
|
-
} else if (signingJob.type === "directNode") {
|
|
23931
|
-
leafDirectSignature = signature;
|
|
23932
|
-
} else if (signingJob.type === "cpfp") {
|
|
23933
|
-
cpfpRefundSignature = signature;
|
|
23934
|
-
} else if (signingJob.type === "direct") {
|
|
23935
|
-
directRefundSignature = signature;
|
|
23936
|
-
} else if (signingJob.type === "directFromCpfp") {
|
|
23937
|
-
directFromCpfpRefundSignature = signature;
|
|
23938
|
-
}
|
|
23939
|
-
}
|
|
23940
|
-
nodeSignatures.push({
|
|
23941
|
-
nodeId: node.id,
|
|
23942
|
-
nodeTxSignature: leafCpfpSignature || new Uint8Array(),
|
|
23943
|
-
directNodeTxSignature: leafDirectSignature || new Uint8Array(),
|
|
23944
|
-
refundTxSignature: cpfpRefundSignature || new Uint8Array(),
|
|
23945
|
-
directRefundTxSignature: directRefundSignature || new Uint8Array(),
|
|
23946
|
-
directFromCpfpRefundTxSignature: directFromCpfpRefundSignature || new Uint8Array()
|
|
23947
|
-
});
|
|
23948
|
-
const result = await sparkClient.finalize_node_signatures_v2({
|
|
23949
|
-
intent: 3 /* REFRESH */,
|
|
23950
|
-
nodeSignatures
|
|
23951
|
-
});
|
|
23952
|
-
return result;
|
|
23953
|
-
}
|
|
23954
|
-
async refreshTimelockNodes(node, parentNode) {
|
|
23955
|
-
return await this.refreshTimelockNodesInternal(node, parentNode);
|
|
24322
|
+
return signingJobs;
|
|
23956
24323
|
}
|
|
23957
|
-
async
|
|
23958
|
-
const
|
|
23959
|
-
const
|
|
23960
|
-
const
|
|
23961
|
-
|
|
23962
|
-
txid: (0, import_utils15.hexToBytes)(getTxId(nodeTx)),
|
|
23963
|
-
index: 0
|
|
23964
|
-
};
|
|
23965
|
-
const {
|
|
23966
|
-
nextSequence: newNodeSequence,
|
|
23967
|
-
nextDirectSequence: newDirectNodeSequence
|
|
23968
|
-
} = getNextTransactionSequence(refundSequence);
|
|
23969
|
-
const newNodeTx = new import_btc_signer2.Transaction({
|
|
23970
|
-
version: 3,
|
|
23971
|
-
allowUnknownOutputs: true
|
|
23972
|
-
});
|
|
23973
|
-
newNodeTx.addInput({ ...newNodeOutPoint, sequence: newNodeSequence });
|
|
23974
|
-
const originalOutput = nodeTx.getOutput(0);
|
|
23975
|
-
if (!originalOutput) {
|
|
23976
|
-
throw Error("Could not get original node output");
|
|
23977
|
-
}
|
|
23978
|
-
newNodeTx.addOutput({
|
|
23979
|
-
script: originalOutput.script,
|
|
23980
|
-
amount: originalOutput.amount
|
|
23981
|
-
});
|
|
23982
|
-
newNodeTx.addOutput(getEphemeralAnchorOutput());
|
|
23983
|
-
let newDirectNodeTx;
|
|
23984
|
-
if (node.directTx.length > 0) {
|
|
23985
|
-
newDirectNodeTx = new import_btc_signer2.Transaction({
|
|
23986
|
-
version: 3,
|
|
23987
|
-
allowUnknownOutputs: true
|
|
23988
|
-
});
|
|
23989
|
-
newDirectNodeTx.addInput({
|
|
23990
|
-
...newNodeOutPoint,
|
|
23991
|
-
sequence: newDirectNodeSequence
|
|
23992
|
-
});
|
|
23993
|
-
newDirectNodeTx.addOutput({
|
|
23994
|
-
script: originalOutput.script,
|
|
23995
|
-
amount: maybeApplyFee(originalOutput.amount)
|
|
23996
|
-
});
|
|
23997
|
-
}
|
|
23998
|
-
const newCpfpRefundOutPoint = {
|
|
23999
|
-
txid: (0, import_utils15.hexToBytes)(getTxId(newNodeTx)),
|
|
24000
|
-
index: 0
|
|
24001
|
-
};
|
|
24002
|
-
let newDirectRefundOutPoint;
|
|
24003
|
-
if (newDirectNodeTx) {
|
|
24004
|
-
newDirectRefundOutPoint = {
|
|
24005
|
-
txid: (0, import_utils15.hexToBytes)(getTxId(newDirectNodeTx)),
|
|
24006
|
-
index: 0
|
|
24007
|
-
};
|
|
24008
|
-
}
|
|
24009
|
-
const amountSats = refundTx.getOutput(0).amount;
|
|
24010
|
-
if (amountSats === void 0) {
|
|
24011
|
-
throw new Error("Amount not found in extendTimelock");
|
|
24012
|
-
}
|
|
24013
|
-
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation({
|
|
24014
|
-
type: "leaf" /* LEAF */,
|
|
24015
|
-
path: node.id
|
|
24016
|
-
});
|
|
24017
|
-
const {
|
|
24018
|
-
cpfpRefundTx: newCpfpRefundTx,
|
|
24019
|
-
directRefundTx: newDirectRefundTx,
|
|
24020
|
-
directFromCpfpRefundTx: newDirectFromCpfpRefundTx
|
|
24021
|
-
} = createRefundTxs({
|
|
24022
|
-
sequence: INITIAL_SEQUENCE,
|
|
24023
|
-
directSequence: INITIAL_DIRECT_SEQUENCE,
|
|
24024
|
-
input: newCpfpRefundOutPoint,
|
|
24025
|
-
directInput: newDirectRefundOutPoint,
|
|
24026
|
-
amountSats,
|
|
24027
|
-
receivingPubkey: signingPublicKey,
|
|
24028
|
-
network: this.config.getNetwork()
|
|
24029
|
-
});
|
|
24030
|
-
if (!newCpfpRefundTx) {
|
|
24031
|
-
throw new ValidationError(
|
|
24032
|
-
"Failed to create refund transactions in extendTimelock"
|
|
24033
|
-
);
|
|
24034
|
-
}
|
|
24035
|
-
const nodeSighash = getSigHashFromTx(newNodeTx, 0, nodeTx.getOutput(0));
|
|
24036
|
-
const directNodeSighash = newDirectNodeTx ? getSigHashFromTx(newDirectNodeTx, 0, nodeTx.getOutput(0)) : void 0;
|
|
24037
|
-
const cpfpRefundSighash = getSigHashFromTx(
|
|
24038
|
-
newCpfpRefundTx,
|
|
24039
|
-
0,
|
|
24040
|
-
newNodeTx.getOutput(0)
|
|
24324
|
+
async createRenewNodeSigningJobs(node, parentNode) {
|
|
24325
|
+
const signingJobs = [];
|
|
24326
|
+
const parentTx = getTxFromRawTxBytes(parentNode.nodeTx);
|
|
24327
|
+
const parentNodeOutput = getTxFromRawTxBytes(parentNode.nodeTx).getOutput(
|
|
24328
|
+
0
|
|
24041
24329
|
);
|
|
24042
|
-
const
|
|
24043
|
-
|
|
24044
|
-
|
|
24045
|
-
signingPublicKey,
|
|
24046
|
-
rawTx: newNodeTx.toBytes(),
|
|
24047
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
24048
|
-
};
|
|
24049
|
-
const newDirectNodeSigningJob = newDirectNodeTx ? {
|
|
24050
|
-
signingPublicKey,
|
|
24051
|
-
rawTx: newDirectNodeTx.toBytes(),
|
|
24052
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
24053
|
-
} : void 0;
|
|
24054
|
-
const newCpfpRefundSigningJob = {
|
|
24055
|
-
signingPublicKey,
|
|
24056
|
-
rawTx: newCpfpRefundTx.toBytes(),
|
|
24057
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
24330
|
+
const unsignedParentNodeOutput = {
|
|
24331
|
+
script: parentNodeOutput.script,
|
|
24332
|
+
amount: parentNodeOutput.amount
|
|
24058
24333
|
};
|
|
24059
|
-
const newDirectRefundSigningJob = newDirectRefundTx ? {
|
|
24060
|
-
signingPublicKey,
|
|
24061
|
-
rawTx: newDirectRefundTx.toBytes(),
|
|
24062
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
24063
|
-
} : void 0;
|
|
24064
|
-
const newDirectFromCpfpRefundSigningJob = newDirectFromCpfpRefundTx ? {
|
|
24065
|
-
signingPublicKey,
|
|
24066
|
-
rawTx: newDirectFromCpfpRefundTx.toBytes(),
|
|
24067
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
24068
|
-
} : void 0;
|
|
24069
|
-
const sparkClient = await this.connectionManager.createSparkClient(
|
|
24070
|
-
this.config.getCoordinatorAddress()
|
|
24071
|
-
);
|
|
24072
|
-
const response = await sparkClient.extend_leaf_v2({
|
|
24073
|
-
leafId: node.id,
|
|
24074
|
-
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
24075
|
-
nodeTxSigningJob: getSigningJobProto(newNodeSigningJob),
|
|
24076
|
-
directNodeTxSigningJob: newDirectNodeSigningJob ? getSigningJobProto(newDirectNodeSigningJob) : void 0,
|
|
24077
|
-
refundTxSigningJob: getSigningJobProto(newCpfpRefundSigningJob),
|
|
24078
|
-
directRefundTxSigningJob: newDirectRefundSigningJob ? getSigningJobProto(newDirectRefundSigningJob) : void 0,
|
|
24079
|
-
directFromCpfpRefundTxSigningJob: newDirectFromCpfpRefundSigningJob ? getSigningJobProto(newDirectFromCpfpRefundSigningJob) : void 0
|
|
24080
|
-
});
|
|
24081
|
-
if (!response.nodeTxSigningResult || !response.refundTxSigningResult) {
|
|
24082
|
-
throw new Error("Signing result does not exist");
|
|
24083
|
-
}
|
|
24084
24334
|
const keyDerivation = {
|
|
24085
24335
|
type: "leaf" /* LEAF */,
|
|
24086
24336
|
path: node.id
|
|
24087
24337
|
};
|
|
24088
|
-
const
|
|
24089
|
-
|
|
24338
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
24339
|
+
const { nodeTx: splitNodeTx, directNodeTx: splitNodeDirectTx } = createZeroTimelockNodeTx(parentTx);
|
|
24340
|
+
signingJobs.push({
|
|
24341
|
+
signingPublicKey,
|
|
24342
|
+
rawTx: splitNodeTx.toBytes(),
|
|
24343
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24344
|
+
type: "split",
|
|
24345
|
+
parentTxOut: unsignedParentNodeOutput,
|
|
24346
|
+
leafId: node.id,
|
|
24090
24347
|
keyDerivation,
|
|
24091
|
-
|
|
24092
|
-
verifyingKey: response.nodeTxSigningResult.verifyingKey,
|
|
24093
|
-
selfCommitment: newNodeSigningJob.signingNonceCommitment,
|
|
24094
|
-
statechainCommitments: response.nodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
24095
|
-
adaptorPubKey: new Uint8Array()
|
|
24348
|
+
verifyingKey: node.verifyingPublicKey
|
|
24096
24349
|
});
|
|
24097
|
-
|
|
24098
|
-
|
|
24099
|
-
|
|
24100
|
-
|
|
24101
|
-
|
|
24102
|
-
|
|
24103
|
-
|
|
24104
|
-
|
|
24105
|
-
selfSignature: nodeUserSig,
|
|
24106
|
-
adaptorPubKey: new Uint8Array()
|
|
24107
|
-
});
|
|
24108
|
-
let directNodeSig;
|
|
24109
|
-
if (directNodeSighash && newDirectNodeSigningJob && response.directNodeTxSigningResult) {
|
|
24110
|
-
const directNodeUserSig = await this.config.signer.signFrost({
|
|
24111
|
-
message: directNodeSighash,
|
|
24350
|
+
if (splitNodeDirectTx) {
|
|
24351
|
+
signingJobs.push({
|
|
24352
|
+
signingPublicKey,
|
|
24353
|
+
rawTx: splitNodeDirectTx.toBytes(),
|
|
24354
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24355
|
+
type: "directSplit",
|
|
24356
|
+
parentTxOut: unsignedParentNodeOutput,
|
|
24357
|
+
leafId: node.id,
|
|
24112
24358
|
keyDerivation,
|
|
24113
|
-
|
|
24114
|
-
verifyingKey: response.directNodeTxSigningResult.verifyingKey,
|
|
24115
|
-
selfCommitment: newDirectNodeSigningJob.signingNonceCommitment,
|
|
24116
|
-
statechainCommitments: response.directNodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
24117
|
-
adaptorPubKey: new Uint8Array()
|
|
24118
|
-
});
|
|
24119
|
-
directNodeSig = await this.config.signer.aggregateFrost({
|
|
24120
|
-
message: directNodeSighash,
|
|
24121
|
-
statechainSignatures: response.directNodeTxSigningResult.signingResult?.signatureShares,
|
|
24122
|
-
statechainPublicKeys: response.directNodeTxSigningResult.signingResult?.publicKeys,
|
|
24123
|
-
verifyingKey: response.directNodeTxSigningResult.verifyingKey,
|
|
24124
|
-
statechainCommitments: response.directNodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
24125
|
-
selfCommitment: newDirectNodeSigningJob.signingNonceCommitment,
|
|
24126
|
-
publicKey: signingPublicKey,
|
|
24127
|
-
selfSignature: directNodeUserSig,
|
|
24128
|
-
adaptorPubKey: new Uint8Array()
|
|
24359
|
+
verifyingKey: node.verifyingPublicKey
|
|
24129
24360
|
});
|
|
24130
24361
|
}
|
|
24131
|
-
const
|
|
24132
|
-
|
|
24362
|
+
const splitNodeOutput = splitNodeTx.getOutput(0);
|
|
24363
|
+
const splitNodeDirectOutput = splitNodeDirectTx.getOutput(0);
|
|
24364
|
+
if (!splitNodeDirectOutput.amount || !splitNodeDirectOutput.script) {
|
|
24365
|
+
throw new Error("Could not get split node output");
|
|
24366
|
+
}
|
|
24367
|
+
const unsignedSplitNodeOutput = {
|
|
24368
|
+
script: splitNodeDirectOutput.script,
|
|
24369
|
+
amount: splitNodeDirectOutput.amount
|
|
24370
|
+
};
|
|
24371
|
+
const { nodeTx: newNodeTx, directNodeTx: newDirectNodeTx } = createInitialTimelockNodeTx(splitNodeTx);
|
|
24372
|
+
signingJobs.push({
|
|
24373
|
+
signingPublicKey,
|
|
24374
|
+
rawTx: newNodeTx.toBytes(),
|
|
24375
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24376
|
+
type: "node",
|
|
24377
|
+
parentTxOut: splitNodeOutput,
|
|
24378
|
+
leafId: node.id,
|
|
24133
24379
|
keyDerivation,
|
|
24134
|
-
|
|
24135
|
-
verifyingKey: response.refundTxSigningResult.verifyingKey,
|
|
24136
|
-
selfCommitment: newCpfpRefundSigningJob.signingNonceCommitment,
|
|
24137
|
-
statechainCommitments: response.refundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
24138
|
-
adaptorPubKey: new Uint8Array()
|
|
24380
|
+
verifyingKey: node.verifyingPublicKey
|
|
24139
24381
|
});
|
|
24140
|
-
|
|
24141
|
-
|
|
24142
|
-
|
|
24143
|
-
|
|
24144
|
-
|
|
24145
|
-
|
|
24146
|
-
|
|
24147
|
-
|
|
24148
|
-
selfSignature: cpfpRefundUserSig,
|
|
24149
|
-
adaptorPubKey: new Uint8Array()
|
|
24150
|
-
});
|
|
24151
|
-
let directRefundSig;
|
|
24152
|
-
if (directRefundSighash && newDirectRefundSigningJob && response.directRefundTxSigningResult) {
|
|
24153
|
-
const directRefundUserSig = await this.config.signer.signFrost({
|
|
24154
|
-
message: directRefundSighash,
|
|
24155
|
-
keyDerivation,
|
|
24156
|
-
publicKey: signingPublicKey,
|
|
24157
|
-
verifyingKey: response.directRefundTxSigningResult.verifyingKey,
|
|
24158
|
-
selfCommitment: newDirectRefundSigningJob.signingNonceCommitment,
|
|
24159
|
-
statechainCommitments: response.directRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
24160
|
-
adaptorPubKey: new Uint8Array()
|
|
24161
|
-
});
|
|
24162
|
-
directRefundSig = await this.config.signer.aggregateFrost({
|
|
24163
|
-
message: directRefundSighash,
|
|
24164
|
-
statechainSignatures: response.directRefundTxSigningResult.signingResult?.signatureShares,
|
|
24165
|
-
statechainPublicKeys: response.directRefundTxSigningResult.signingResult?.publicKeys,
|
|
24166
|
-
verifyingKey: response.directRefundTxSigningResult.verifyingKey,
|
|
24167
|
-
statechainCommitments: response.directRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
24168
|
-
selfCommitment: newDirectRefundSigningJob.signingNonceCommitment,
|
|
24169
|
-
publicKey: signingPublicKey,
|
|
24170
|
-
selfSignature: directRefundUserSig,
|
|
24171
|
-
adaptorPubKey: new Uint8Array()
|
|
24172
|
-
});
|
|
24173
|
-
}
|
|
24174
|
-
let directFromCpfpRefundSig;
|
|
24175
|
-
if (directFromCpfpRefundSighash && newDirectFromCpfpRefundSigningJob && response.directFromCpfpRefundTxSigningResult) {
|
|
24176
|
-
const directFromCpfpRefundUserSig = await this.config.signer.signFrost({
|
|
24177
|
-
message: directFromCpfpRefundSighash,
|
|
24382
|
+
if (newDirectNodeTx) {
|
|
24383
|
+
signingJobs.push({
|
|
24384
|
+
signingPublicKey,
|
|
24385
|
+
rawTx: newDirectNodeTx.toBytes(),
|
|
24386
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24387
|
+
type: "directNode",
|
|
24388
|
+
parentTxOut: splitNodeOutput,
|
|
24389
|
+
leafId: node.id,
|
|
24178
24390
|
keyDerivation,
|
|
24179
|
-
|
|
24180
|
-
verifyingKey: response.directFromCpfpRefundTxSigningResult.verifyingKey,
|
|
24181
|
-
selfCommitment: newDirectFromCpfpRefundSigningJob.signingNonceCommitment,
|
|
24182
|
-
statechainCommitments: response.directFromCpfpRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
24183
|
-
adaptorPubKey: new Uint8Array()
|
|
24184
|
-
});
|
|
24185
|
-
directFromCpfpRefundSig = await this.config.signer.aggregateFrost({
|
|
24186
|
-
message: directFromCpfpRefundSighash,
|
|
24187
|
-
statechainSignatures: response.directFromCpfpRefundTxSigningResult.signingResult?.signatureShares,
|
|
24188
|
-
statechainPublicKeys: response.directFromCpfpRefundTxSigningResult.signingResult?.publicKeys,
|
|
24189
|
-
verifyingKey: response.directFromCpfpRefundTxSigningResult.verifyingKey,
|
|
24190
|
-
statechainCommitments: response.directFromCpfpRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
24191
|
-
selfCommitment: newDirectFromCpfpRefundSigningJob.signingNonceCommitment,
|
|
24192
|
-
publicKey: signingPublicKey,
|
|
24193
|
-
selfSignature: directFromCpfpRefundUserSig,
|
|
24194
|
-
adaptorPubKey: new Uint8Array()
|
|
24195
|
-
});
|
|
24196
|
-
}
|
|
24197
|
-
return await sparkClient.finalize_node_signatures_v2({
|
|
24198
|
-
intent: 4 /* EXTEND */,
|
|
24199
|
-
nodeSignatures: [
|
|
24200
|
-
{
|
|
24201
|
-
nodeId: response.leafId,
|
|
24202
|
-
nodeTxSignature: nodeSig,
|
|
24203
|
-
directNodeTxSignature: directNodeSig,
|
|
24204
|
-
refundTxSignature: cpfpRefundSig,
|
|
24205
|
-
directRefundTxSignature: directRefundSig,
|
|
24206
|
-
directFromCpfpRefundTxSignature: directFromCpfpRefundSig
|
|
24207
|
-
}
|
|
24208
|
-
]
|
|
24209
|
-
});
|
|
24210
|
-
}
|
|
24211
|
-
async testonly_expireTimeLockNodeTx(node, parentNode) {
|
|
24212
|
-
return await this.refreshTimelockNodesInternal(node, parentNode, true);
|
|
24213
|
-
}
|
|
24214
|
-
async testonly_expireTimeLockRefundtx(node) {
|
|
24215
|
-
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
24216
|
-
const directNodeTx = node.directTx.length > 0 ? getTxFromRawTxBytes(node.directTx) : void 0;
|
|
24217
|
-
const cpfpRefundTx = getTxFromRawTxBytes(node.refundTx);
|
|
24218
|
-
const currSequence = cpfpRefundTx.getInput(0).sequence || 0;
|
|
24219
|
-
const currTimelock = getCurrentTimelock(currSequence);
|
|
24220
|
-
if (currTimelock <= 100) {
|
|
24221
|
-
throw new ValidationError("Cannot expire timelock below 100", {
|
|
24222
|
-
field: "currTimelock",
|
|
24223
|
-
value: currTimelock,
|
|
24224
|
-
expected: "Timelock greater than 100"
|
|
24391
|
+
verifyingKey: node.verifyingPublicKey
|
|
24225
24392
|
});
|
|
24226
24393
|
}
|
|
24227
|
-
const
|
|
24228
|
-
|
|
24229
|
-
|
|
24230
|
-
if (!nodeOutput) {
|
|
24231
|
-
throw Error("Could not get node output");
|
|
24232
|
-
}
|
|
24233
|
-
const keyDerivation = {
|
|
24234
|
-
type: "leaf" /* LEAF */,
|
|
24235
|
-
path: node.id
|
|
24236
|
-
};
|
|
24237
|
-
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
24238
|
-
const cpfpRefundOutPoint = {
|
|
24239
|
-
txid: (0, import_utils15.hexToBytes)(getTxId(nodeTx)),
|
|
24240
|
-
index: 0
|
|
24241
|
-
};
|
|
24242
|
-
let directRefundOutPoint;
|
|
24243
|
-
if (directNodeTx) {
|
|
24244
|
-
directRefundOutPoint = {
|
|
24245
|
-
txid: (0, import_utils15.hexToBytes)(getTxId(directNodeTx)),
|
|
24246
|
-
index: 0
|
|
24247
|
-
};
|
|
24394
|
+
const newCpfpNodeOutput = newNodeTx.getOutput(0);
|
|
24395
|
+
if (!newCpfpNodeOutput) {
|
|
24396
|
+
throw Error("Could not get new cpfp node output");
|
|
24248
24397
|
}
|
|
24398
|
+
const newDirectNodeOutput = newDirectNodeTx?.getOutput(0);
|
|
24249
24399
|
const {
|
|
24250
|
-
cpfpRefundTx:
|
|
24400
|
+
cpfpRefundTx: newRefundTx,
|
|
24251
24401
|
directRefundTx: newDirectRefundTx,
|
|
24252
24402
|
directFromCpfpRefundTx: newDirectFromCpfpRefundTx
|
|
24253
|
-
} =
|
|
24254
|
-
|
|
24255
|
-
|
|
24256
|
-
input: cpfpRefundOutPoint,
|
|
24257
|
-
directInput: directRefundOutPoint,
|
|
24258
|
-
amountSats: nodeOutput.amount,
|
|
24403
|
+
} = createInitialTimelockRefundTxs({
|
|
24404
|
+
nodeTx: newNodeTx,
|
|
24405
|
+
directNodeTx: newDirectNodeTx,
|
|
24259
24406
|
receivingPubkey: signingPublicKey,
|
|
24260
24407
|
network: this.config.getNetwork()
|
|
24261
24408
|
});
|
|
24262
|
-
const signingJobs = [];
|
|
24263
24409
|
signingJobs.push({
|
|
24264
24410
|
signingPublicKey,
|
|
24265
|
-
rawTx:
|
|
24411
|
+
rawTx: newRefundTx.toBytes(),
|
|
24266
24412
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24267
24413
|
type: "cpfp",
|
|
24268
|
-
parentTxOut:
|
|
24414
|
+
parentTxOut: newCpfpNodeOutput,
|
|
24415
|
+
leafId: node.id,
|
|
24416
|
+
keyDerivation,
|
|
24417
|
+
verifyingKey: node.verifyingPublicKey
|
|
24269
24418
|
});
|
|
24270
|
-
|
|
24271
|
-
if (newDirectRefundTx && directNodeTxOut) {
|
|
24419
|
+
if (newDirectRefundTx && newDirectNodeOutput) {
|
|
24272
24420
|
signingJobs.push({
|
|
24273
24421
|
signingPublicKey,
|
|
24274
24422
|
rawTx: newDirectRefundTx.toBytes(),
|
|
24275
24423
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24276
24424
|
type: "direct",
|
|
24277
|
-
parentTxOut:
|
|
24425
|
+
parentTxOut: newDirectNodeOutput,
|
|
24426
|
+
leafId: node.id,
|
|
24427
|
+
keyDerivation,
|
|
24428
|
+
verifyingKey: node.verifyingPublicKey
|
|
24278
24429
|
});
|
|
24279
24430
|
}
|
|
24280
|
-
if (newDirectFromCpfpRefundTx) {
|
|
24431
|
+
if (newDirectFromCpfpRefundTx && newDirectNodeOutput) {
|
|
24281
24432
|
signingJobs.push({
|
|
24282
24433
|
signingPublicKey,
|
|
24283
24434
|
rawTx: newDirectFromCpfpRefundTx.toBytes(),
|
|
24284
24435
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24285
24436
|
type: "directFromCpfp",
|
|
24286
|
-
parentTxOut:
|
|
24437
|
+
parentTxOut: newCpfpNodeOutput,
|
|
24438
|
+
leafId: node.id,
|
|
24439
|
+
keyDerivation,
|
|
24440
|
+
verifyingKey: node.verifyingPublicKey
|
|
24287
24441
|
});
|
|
24288
24442
|
}
|
|
24443
|
+
return signingJobs;
|
|
24444
|
+
}
|
|
24445
|
+
async renewZeroTimelockNodeTxn(node) {
|
|
24289
24446
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
24290
24447
|
this.config.getCoordinatorAddress()
|
|
24291
24448
|
);
|
|
24292
|
-
const
|
|
24293
|
-
|
|
24294
|
-
|
|
24295
|
-
|
|
24449
|
+
const signingJobs = await this.createRenewZeroTimelockNodeSigningJobs(node);
|
|
24450
|
+
const statechainCommitments = await sparkClient.get_signing_commitments({
|
|
24451
|
+
nodeIds: [node.id],
|
|
24452
|
+
count: signingJobs.length
|
|
24296
24453
|
});
|
|
24297
|
-
|
|
24298
|
-
|
|
24299
|
-
|
|
24300
|
-
|
|
24301
|
-
|
|
24302
|
-
|
|
24303
|
-
|
|
24304
|
-
let directFromCpfpRefundSignature;
|
|
24305
|
-
for (const [i, signingJob] of signingJobs.entries()) {
|
|
24306
|
-
const signingResult = response.signingResults[i];
|
|
24307
|
-
if (!signingResult) {
|
|
24308
|
-
throw Error("Signing result does not exist");
|
|
24454
|
+
const mappedSigningJobs = signingJobs.map((signingJob, index) => {
|
|
24455
|
+
const signingNonceCommitments = statechainCommitments.signingCommitments[index]?.signingNonceCommitments;
|
|
24456
|
+
if (!signingNonceCommitments) {
|
|
24457
|
+
throw new ValidationError("Signing nonce commitments not found", {
|
|
24458
|
+
field: "signingNonceCommitments",
|
|
24459
|
+
value: signingNonceCommitments
|
|
24460
|
+
});
|
|
24309
24461
|
}
|
|
24310
|
-
|
|
24311
|
-
|
|
24312
|
-
|
|
24313
|
-
|
|
24314
|
-
|
|
24315
|
-
|
|
24316
|
-
|
|
24317
|
-
|
|
24318
|
-
|
|
24319
|
-
|
|
24320
|
-
|
|
24321
|
-
|
|
24322
|
-
|
|
24323
|
-
|
|
24324
|
-
|
|
24325
|
-
|
|
24326
|
-
|
|
24327
|
-
|
|
24328
|
-
selfCommitment: signingJob.signingNonceCommitment,
|
|
24329
|
-
publicKey: signingPublicKey,
|
|
24330
|
-
selfSignature: userSignature,
|
|
24331
|
-
adaptorPubKey: new Uint8Array()
|
|
24332
|
-
});
|
|
24333
|
-
if (signingJob.type === "cpfp") {
|
|
24334
|
-
cpfpRefundSignature = signature;
|
|
24335
|
-
} else if (signingJob.type === "direct") {
|
|
24336
|
-
directRefundSignature = signature;
|
|
24337
|
-
} else if (signingJob.type === "directFromCpfp") {
|
|
24338
|
-
directFromCpfpRefundSignature = signature;
|
|
24462
|
+
return {
|
|
24463
|
+
...signingJob,
|
|
24464
|
+
signingNonceCommitments
|
|
24465
|
+
};
|
|
24466
|
+
});
|
|
24467
|
+
const userSignedTxSigningJobs = await this.signingService.signSigningJobs(mappedSigningJobs);
|
|
24468
|
+
const renewZeroTimelockNodeSigningJob = {
|
|
24469
|
+
nodeTxSigningJob: userSignedTxSigningJobs.get("node"),
|
|
24470
|
+
refundTxSigningJob: userSignedTxSigningJobs.get("cpfp"),
|
|
24471
|
+
directNodeTxSigningJob: userSignedTxSigningJobs.get("directNode"),
|
|
24472
|
+
directRefundTxSigningJob: void 0,
|
|
24473
|
+
directFromCpfpRefundTxSigningJob: userSignedTxSigningJobs.get("directFromCpfp")
|
|
24474
|
+
};
|
|
24475
|
+
const response = await sparkClient.renew_leaf({
|
|
24476
|
+
leafId: node.id,
|
|
24477
|
+
signingJobs: {
|
|
24478
|
+
$case: "renewNodeZeroTimelockSigningJob",
|
|
24479
|
+
renewNodeZeroTimelockSigningJob: renewZeroTimelockNodeSigningJob
|
|
24339
24480
|
}
|
|
24481
|
+
});
|
|
24482
|
+
if (response.renewResult?.$case !== "renewNodeZeroTimelockResult" || !response.renewResult?.renewNodeZeroTimelockResult.node) {
|
|
24483
|
+
throw new ValidationError("Unexpected renew result", {
|
|
24484
|
+
field: "renewResult",
|
|
24485
|
+
value: response.renewResult
|
|
24486
|
+
});
|
|
24340
24487
|
}
|
|
24341
|
-
|
|
24342
|
-
|
|
24343
|
-
|
|
24344
|
-
|
|
24345
|
-
|
|
24346
|
-
|
|
24347
|
-
|
|
24348
|
-
|
|
24349
|
-
|
|
24350
|
-
|
|
24351
|
-
|
|
24352
|
-
|
|
24488
|
+
return response.renewResult.renewNodeZeroTimelockResult.node;
|
|
24489
|
+
}
|
|
24490
|
+
async createRenewZeroTimelockNodeSigningJobs(node) {
|
|
24491
|
+
const signingJobs = [];
|
|
24492
|
+
const keyDerivation = {
|
|
24493
|
+
type: "leaf" /* LEAF */,
|
|
24494
|
+
path: node.id
|
|
24495
|
+
};
|
|
24496
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
24497
|
+
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
24498
|
+
const { nodeTx: newNodeTx, directNodeTx: newDirectNodeTx } = createZeroTimelockNodeTx(nodeTx);
|
|
24499
|
+
signingJobs.push({
|
|
24500
|
+
signingPublicKey,
|
|
24501
|
+
rawTx: newNodeTx.toBytes(),
|
|
24502
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24503
|
+
type: "node",
|
|
24504
|
+
parentTxOut: nodeTx.getOutput(0),
|
|
24505
|
+
leafId: node.id,
|
|
24506
|
+
keyDerivation,
|
|
24507
|
+
verifyingKey: node.verifyingPublicKey
|
|
24353
24508
|
});
|
|
24354
|
-
|
|
24509
|
+
signingJobs.push({
|
|
24510
|
+
signingPublicKey,
|
|
24511
|
+
rawTx: newDirectNodeTx.toBytes(),
|
|
24512
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24513
|
+
type: "directNode",
|
|
24514
|
+
parentTxOut: nodeTx.getOutput(0),
|
|
24515
|
+
leafId: node.id,
|
|
24516
|
+
keyDerivation,
|
|
24517
|
+
verifyingKey: node.verifyingPublicKey
|
|
24518
|
+
});
|
|
24519
|
+
const { cpfpRefundTx, directFromCpfpRefundTx } = createInitialTimelockRefundTxs({
|
|
24520
|
+
nodeTx: newNodeTx,
|
|
24521
|
+
directNodeTx: newDirectNodeTx,
|
|
24522
|
+
receivingPubkey: signingPublicKey,
|
|
24523
|
+
network: this.config.getNetwork()
|
|
24524
|
+
});
|
|
24525
|
+
signingJobs.push({
|
|
24526
|
+
signingPublicKey,
|
|
24527
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
24528
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24529
|
+
type: "cpfp",
|
|
24530
|
+
parentTxOut: newNodeTx.getOutput(0),
|
|
24531
|
+
leafId: node.id,
|
|
24532
|
+
keyDerivation,
|
|
24533
|
+
verifyingKey: node.verifyingPublicKey
|
|
24534
|
+
});
|
|
24535
|
+
if (!directFromCpfpRefundTx) {
|
|
24536
|
+
throw new Error("Could not create direct refund transactions");
|
|
24537
|
+
}
|
|
24538
|
+
signingJobs.push({
|
|
24539
|
+
signingPublicKey,
|
|
24540
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
24541
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24542
|
+
type: "directFromCpfp",
|
|
24543
|
+
parentTxOut: newNodeTx.getOutput(0),
|
|
24544
|
+
leafId: node.id,
|
|
24545
|
+
keyDerivation,
|
|
24546
|
+
verifyingKey: node.verifyingPublicKey
|
|
24547
|
+
});
|
|
24548
|
+
return signingJobs;
|
|
24355
24549
|
}
|
|
24356
24550
|
};
|
|
24357
24551
|
|
|
@@ -24393,71 +24587,6 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
24393
24587
|
directFromCpfpSignaturesMap
|
|
24394
24588
|
};
|
|
24395
24589
|
}
|
|
24396
|
-
createConnectorRefundTransactions(sequence, directSequence, cpfpNodeOutPoint, directNodeOutPoint, connectorOutput, amountSats, receiverPubKey) {
|
|
24397
|
-
const cpfpRefundTx = new import_btc_signer3.Transaction();
|
|
24398
|
-
if (!cpfpNodeOutPoint.txid || cpfpNodeOutPoint.index === void 0) {
|
|
24399
|
-
throw new ValidationError("Invalid CPFP node outpoint", {
|
|
24400
|
-
field: "cpfpNodeOutPoint",
|
|
24401
|
-
value: { txid: cpfpNodeOutPoint.txid, index: cpfpNodeOutPoint.index },
|
|
24402
|
-
expected: "Both txid and index must be defined"
|
|
24403
|
-
});
|
|
24404
|
-
}
|
|
24405
|
-
cpfpRefundTx.addInput({
|
|
24406
|
-
txid: cpfpNodeOutPoint.txid,
|
|
24407
|
-
index: cpfpNodeOutPoint.index,
|
|
24408
|
-
sequence
|
|
24409
|
-
});
|
|
24410
|
-
cpfpRefundTx.addInput(connectorOutput);
|
|
24411
|
-
const receiverScript = getP2TRScriptFromPublicKey(
|
|
24412
|
-
receiverPubKey,
|
|
24413
|
-
this.config.getNetwork()
|
|
24414
|
-
);
|
|
24415
|
-
cpfpRefundTx.addOutput({
|
|
24416
|
-
script: receiverScript,
|
|
24417
|
-
amount: amountSats
|
|
24418
|
-
});
|
|
24419
|
-
let directRefundTx;
|
|
24420
|
-
let directFromCpfpRefundTx;
|
|
24421
|
-
if (directNodeOutPoint) {
|
|
24422
|
-
if (!directNodeOutPoint.txid || directNodeOutPoint.index === void 0) {
|
|
24423
|
-
throw new ValidationError("Invalid direct node outpoint", {
|
|
24424
|
-
field: "directNodeOutPoint",
|
|
24425
|
-
value: {
|
|
24426
|
-
txid: directNodeOutPoint.txid,
|
|
24427
|
-
index: directNodeOutPoint.index
|
|
24428
|
-
},
|
|
24429
|
-
expected: "Both txid and index must be defined"
|
|
24430
|
-
});
|
|
24431
|
-
}
|
|
24432
|
-
directRefundTx = new import_btc_signer3.Transaction();
|
|
24433
|
-
directRefundTx.addInput({
|
|
24434
|
-
txid: directNodeOutPoint.txid,
|
|
24435
|
-
index: directNodeOutPoint.index,
|
|
24436
|
-
sequence: directSequence
|
|
24437
|
-
});
|
|
24438
|
-
directRefundTx.addInput(connectorOutput);
|
|
24439
|
-
directRefundTx.addOutput({
|
|
24440
|
-
script: receiverScript,
|
|
24441
|
-
amount: maybeApplyFee(amountSats)
|
|
24442
|
-
});
|
|
24443
|
-
directFromCpfpRefundTx = new import_btc_signer3.Transaction();
|
|
24444
|
-
directFromCpfpRefundTx.addInput({
|
|
24445
|
-
txid: cpfpNodeOutPoint.txid,
|
|
24446
|
-
index: cpfpNodeOutPoint.index,
|
|
24447
|
-
sequence: directSequence
|
|
24448
|
-
});
|
|
24449
|
-
directFromCpfpRefundTx.addInput(connectorOutput);
|
|
24450
|
-
directFromCpfpRefundTx.addOutput({
|
|
24451
|
-
script: receiverScript,
|
|
24452
|
-
amount: maybeApplyFee(amountSats)
|
|
24453
|
-
});
|
|
24454
|
-
}
|
|
24455
|
-
return {
|
|
24456
|
-
cpfpRefundTx,
|
|
24457
|
-
directRefundTx,
|
|
24458
|
-
directFromCpfpRefundTx
|
|
24459
|
-
};
|
|
24460
|
-
}
|
|
24461
24590
|
async signCoopExitRefunds(leaves, exitTxId, connectorOutputs, receiverPubKey, transferId) {
|
|
24462
24591
|
if (leaves.length !== connectorOutputs.length) {
|
|
24463
24592
|
throw new ValidationError(
|
|
@@ -24491,29 +24620,39 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
24491
24620
|
expected: "Valid connector output"
|
|
24492
24621
|
});
|
|
24493
24622
|
}
|
|
24623
|
+
const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
24624
|
+
let directNodeTx;
|
|
24625
|
+
if (leaf.leaf.directTx.length > 0) {
|
|
24626
|
+
directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
|
|
24627
|
+
}
|
|
24494
24628
|
const currentRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
24495
|
-
|
|
24496
|
-
|
|
24629
|
+
if (!currentRefundTx) {
|
|
24630
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
24631
|
+
field: "currentRefundTx",
|
|
24632
|
+
value: currentRefundTx,
|
|
24633
|
+
expected: "Non-null refund transaction"
|
|
24634
|
+
});
|
|
24635
|
+
}
|
|
24636
|
+
const currentSequence = currentRefundTx.getInput(0).sequence;
|
|
24637
|
+
if (!currentSequence) {
|
|
24497
24638
|
throw new ValidationError("Invalid refund transaction", {
|
|
24498
24639
|
field: "sequence",
|
|
24499
24640
|
value: currentRefundTx.getInput(0),
|
|
24500
24641
|
expected: "Non-null sequence"
|
|
24501
24642
|
});
|
|
24502
24643
|
}
|
|
24503
|
-
const { nextSequence, nextDirectSequence } = getNextTransactionSequence(sequence);
|
|
24504
24644
|
let currentDirectRefundTx;
|
|
24505
24645
|
if (leaf.leaf.directRefundTx.length > 0) {
|
|
24506
24646
|
currentDirectRefundTx = getTxFromRawTxBytes(leaf.leaf.directRefundTx);
|
|
24507
24647
|
}
|
|
24508
|
-
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } =
|
|
24509
|
-
|
|
24510
|
-
|
|
24511
|
-
|
|
24512
|
-
currentDirectRefundTx?.getInput(0),
|
|
24648
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createConnectorRefundTxs({
|
|
24649
|
+
nodeTx,
|
|
24650
|
+
directNodeTx,
|
|
24651
|
+
sequence: currentSequence,
|
|
24513
24652
|
connectorOutput,
|
|
24514
|
-
|
|
24515
|
-
|
|
24516
|
-
);
|
|
24653
|
+
receivingPubkey: receiverPubKey,
|
|
24654
|
+
network: this.config.getNetwork()
|
|
24655
|
+
});
|
|
24517
24656
|
const signingNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
24518
24657
|
const directSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
24519
24658
|
const directFromCpfpSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
@@ -24620,9 +24759,9 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
24620
24759
|
init_buffer();
|
|
24621
24760
|
var import_secp256k110 = require("@noble/curves/secp256k1");
|
|
24622
24761
|
var import_sha29 = require("@noble/hashes/sha2");
|
|
24623
|
-
var
|
|
24624
|
-
var
|
|
24625
|
-
var
|
|
24762
|
+
var import_utils17 = require("@noble/hashes/utils");
|
|
24763
|
+
var import_btc_signer2 = require("@scure/btc-signer");
|
|
24764
|
+
var import_utils18 = require("@scure/btc-signer/utils");
|
|
24626
24765
|
var DepositService = class {
|
|
24627
24766
|
constructor(config, connectionManager) {
|
|
24628
24767
|
__publicField(this, "config");
|
|
@@ -24650,7 +24789,7 @@ var DepositService = class {
|
|
|
24650
24789
|
operatorPubkey,
|
|
24651
24790
|
address.address
|
|
24652
24791
|
);
|
|
24653
|
-
const taprootKey = (0,
|
|
24792
|
+
const taprootKey = (0, import_btc_signer2.p2tr)(
|
|
24654
24793
|
operatorPubkey.slice(1, 33),
|
|
24655
24794
|
void 0,
|
|
24656
24795
|
getNetwork(this.config.getNetwork())
|
|
@@ -24674,7 +24813,7 @@ var DepositService = class {
|
|
|
24674
24813
|
if (operator.identifier === this.config.getCoordinatorIdentifier() && !verifyCoordinatorProof) {
|
|
24675
24814
|
continue;
|
|
24676
24815
|
}
|
|
24677
|
-
const operatorPubkey2 = (0,
|
|
24816
|
+
const operatorPubkey2 = (0, import_utils17.hexToBytes)(operator.identityPublicKey);
|
|
24678
24817
|
const operatorSig = address.depositAddressProof.addressSignatures[operator.identifier];
|
|
24679
24818
|
if (!operatorSig) {
|
|
24680
24819
|
throw new ValidationError("Operator signature not found", {
|
|
@@ -24793,38 +24932,18 @@ var DepositService = class {
|
|
|
24793
24932
|
expected: "Valid output index"
|
|
24794
24933
|
});
|
|
24795
24934
|
}
|
|
24796
|
-
const
|
|
24797
|
-
|
|
24798
|
-
|
|
24799
|
-
throw new ValidationError("No script or amount found in deposit tx", {
|
|
24800
|
-
field: "output",
|
|
24801
|
-
value: output,
|
|
24802
|
-
expected: "Output with script and amount"
|
|
24803
|
-
});
|
|
24804
|
-
}
|
|
24805
|
-
const depositOutPoint = {
|
|
24806
|
-
txid: (0, import_utils16.hexToBytes)(getTxId(depositTx)),
|
|
24807
|
-
index: vout
|
|
24808
|
-
};
|
|
24809
|
-
const depositTxOut = {
|
|
24810
|
-
script,
|
|
24811
|
-
amount
|
|
24812
|
-
};
|
|
24813
|
-
const [cpfpRootTx, directRootTx] = createRootTx(
|
|
24814
|
-
depositOutPoint,
|
|
24815
|
-
depositTxOut
|
|
24935
|
+
const { nodeTx: cpfpRootTx, directNodeTx: directRootTx } = createRootNodeTx(
|
|
24936
|
+
depositTx,
|
|
24937
|
+
vout
|
|
24816
24938
|
);
|
|
24817
24939
|
const cpfpRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
24818
24940
|
const directRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
24819
24941
|
const cpfpRootTxSighash = getSigHashFromTx(cpfpRootTx, 0, output);
|
|
24820
24942
|
const directRootTxSighash = getSigHashFromTx(directRootTx, 0, output);
|
|
24821
24943
|
const signingPubKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
24822
|
-
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } =
|
|
24823
|
-
|
|
24824
|
-
|
|
24825
|
-
input: { txid: (0, import_utils16.hexToBytes)(getTxId(cpfpRootTx)), index: 0 },
|
|
24826
|
-
directInput: { txid: (0, import_utils16.hexToBytes)(getTxId(directRootTx)), index: 0 },
|
|
24827
|
-
amountSats: amount,
|
|
24944
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createInitialTimelockRefundTxs({
|
|
24945
|
+
nodeTx: cpfpRootTx,
|
|
24946
|
+
directNodeTx: directRootTx,
|
|
24828
24947
|
receivingPubkey: signingPubKey,
|
|
24829
24948
|
network: this.config.getNetwork()
|
|
24830
24949
|
});
|
|
@@ -24953,7 +25072,7 @@ var DepositService = class {
|
|
|
24953
25072
|
}
|
|
24954
25073
|
);
|
|
24955
25074
|
}
|
|
24956
|
-
if (!(0,
|
|
25075
|
+
if (!(0, import_utils18.equalBytes)(treeResp.rootNodeSignatureShares.verifyingKey, verifyingKey)) {
|
|
24957
25076
|
throw new ValidationError("Verifying key mismatch", {
|
|
24958
25077
|
field: "verifyingKey",
|
|
24959
25078
|
value: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
@@ -25116,22 +25235,12 @@ var DepositService = class {
|
|
|
25116
25235
|
expected: "Output with script and amount"
|
|
25117
25236
|
});
|
|
25118
25237
|
}
|
|
25119
|
-
const
|
|
25120
|
-
txid: (0, import_utils16.hexToBytes)(getTxId(depositTx)),
|
|
25121
|
-
index: vout
|
|
25122
|
-
};
|
|
25123
|
-
const depositTxOut = {
|
|
25124
|
-
script,
|
|
25125
|
-
amount
|
|
25126
|
-
};
|
|
25127
|
-
const [cpfpRootTx, _] = createRootTx(depositOutPoint, depositTxOut);
|
|
25238
|
+
const { nodeTx: cpfpRootTx } = createRootNodeTx(depositTx, vout);
|
|
25128
25239
|
const cpfpRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
25129
25240
|
const cpfpRootTxSighash = getSigHashFromTx(cpfpRootTx, 0, output);
|
|
25130
25241
|
const signingPubKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
25131
|
-
const { cpfpRefundTx } =
|
|
25132
|
-
|
|
25133
|
-
input: { txid: (0, import_utils16.hexToBytes)(getTxId(cpfpRootTx)), index: 0 },
|
|
25134
|
-
amountSats: amount,
|
|
25242
|
+
const { cpfpRefundTx } = createInitialTimelockRefundTxs({
|
|
25243
|
+
nodeTx: cpfpRootTx,
|
|
25135
25244
|
receivingPubkey: signingPubKey,
|
|
25136
25245
|
network: this.config.getNetwork()
|
|
25137
25246
|
});
|
|
@@ -25200,7 +25309,7 @@ var DepositService = class {
|
|
|
25200
25309
|
}
|
|
25201
25310
|
);
|
|
25202
25311
|
}
|
|
25203
|
-
if (!(0,
|
|
25312
|
+
if (!(0, import_utils18.equalBytes)(treeResp.rootNodeSignatureShares.verifyingKey, verifyingKey)) {
|
|
25204
25313
|
throw new ValidationError("Verifying key mismatch", {
|
|
25205
25314
|
field: "verifyingKey",
|
|
25206
25315
|
value: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
@@ -25277,7 +25386,7 @@ var DepositService = class {
|
|
|
25277
25386
|
// src/services/lightning.ts
|
|
25278
25387
|
init_buffer();
|
|
25279
25388
|
var import_secp256k111 = require("@noble/curves/secp256k1");
|
|
25280
|
-
var
|
|
25389
|
+
var import_utils19 = require("@noble/curves/utils");
|
|
25281
25390
|
var import_sha210 = require("@noble/hashes/sha2");
|
|
25282
25391
|
var import_uuidv74 = require("uuidv7");
|
|
25283
25392
|
|
|
@@ -25363,8 +25472,8 @@ var LightningService = class {
|
|
|
25363
25472
|
}) {
|
|
25364
25473
|
const crypto = getCrypto();
|
|
25365
25474
|
const randBytes = crypto.getRandomValues(new Uint8Array(32));
|
|
25366
|
-
const preimage = (0,
|
|
25367
|
-
(0,
|
|
25475
|
+
const preimage = (0, import_utils19.numberToBytesBE)(
|
|
25476
|
+
(0, import_utils19.bytesToNumberBE)(randBytes) % import_secp256k111.secp256k1.CURVE.n,
|
|
25368
25477
|
32
|
|
25369
25478
|
);
|
|
25370
25479
|
return await this.createLightningInvoiceWithPreImage({
|
|
@@ -25419,12 +25528,12 @@ var LightningService = class {
|
|
|
25419
25528
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
25420
25529
|
operator.address
|
|
25421
25530
|
);
|
|
25422
|
-
const userIdentityPublicKey = receiverIdentityPubkey ? (0,
|
|
25531
|
+
const userIdentityPublicKey = receiverIdentityPubkey ? (0, import_utils19.hexToBytes)(receiverIdentityPubkey) : await this.config.signer.getIdentityPublicKey();
|
|
25423
25532
|
try {
|
|
25424
25533
|
await sparkClient.store_preimage_share({
|
|
25425
25534
|
paymentHash,
|
|
25426
25535
|
preimageShare: {
|
|
25427
|
-
secretShare: (0,
|
|
25536
|
+
secretShare: (0, import_utils19.numberToBytesBE)(share.share, 32),
|
|
25428
25537
|
proofs: share.proofs
|
|
25429
25538
|
},
|
|
25430
25539
|
threshold: this.config.getThreshold(),
|
|
@@ -25642,8 +25751,8 @@ var LightningService = class {
|
|
|
25642
25751
|
|
|
25643
25752
|
// src/services/token-transactions.ts
|
|
25644
25753
|
init_buffer();
|
|
25645
|
-
var
|
|
25646
|
-
var
|
|
25754
|
+
var import_utils20 = require("@noble/curves/utils");
|
|
25755
|
+
var import_utils21 = require("@noble/hashes/utils");
|
|
25647
25756
|
|
|
25648
25757
|
// src/utils/token-hashing.ts
|
|
25649
25758
|
init_buffer();
|
|
@@ -29788,14 +29897,14 @@ var TokenTransactionService = class {
|
|
|
29788
29897
|
}
|
|
29789
29898
|
if (receiverAddress.sparkInvoiceFields) {
|
|
29790
29899
|
return {
|
|
29791
|
-
receiverPublicKey: (0,
|
|
29900
|
+
receiverPublicKey: (0, import_utils21.hexToBytes)(receiverAddress.identityPublicKey),
|
|
29792
29901
|
rawTokenIdentifier,
|
|
29793
29902
|
tokenAmount: transfer.tokenAmount,
|
|
29794
29903
|
sparkInvoice: transfer.receiverSparkAddress
|
|
29795
29904
|
};
|
|
29796
29905
|
}
|
|
29797
29906
|
return {
|
|
29798
|
-
receiverPublicKey: (0,
|
|
29907
|
+
receiverPublicKey: (0, import_utils21.hexToBytes)(receiverAddress.identityPublicKey),
|
|
29799
29908
|
rawTokenIdentifier,
|
|
29800
29909
|
tokenAmount: transfer.tokenAmount
|
|
29801
29910
|
};
|
|
@@ -29825,7 +29934,7 @@ var TokenTransactionService = class {
|
|
|
29825
29934
|
(output) => ({
|
|
29826
29935
|
ownerPublicKey: output.receiverPublicKey,
|
|
29827
29936
|
tokenIdentifier: output.rawTokenIdentifier,
|
|
29828
|
-
tokenAmount: (0,
|
|
29937
|
+
tokenAmount: (0, import_utils20.numberToBytesBE)(output.tokenAmount, 16)
|
|
29829
29938
|
})
|
|
29830
29939
|
);
|
|
29831
29940
|
if (availableTokenAmount > totalRequestedAmount) {
|
|
@@ -29834,7 +29943,7 @@ var TokenTransactionService = class {
|
|
|
29834
29943
|
tokenOutputs.push({
|
|
29835
29944
|
ownerPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
29836
29945
|
tokenIdentifier: firstTokenIdentifierBytes,
|
|
29837
|
-
tokenAmount: (0,
|
|
29946
|
+
tokenAmount: (0, import_utils20.numberToBytesBE)(changeAmount, 16)
|
|
29838
29947
|
});
|
|
29839
29948
|
}
|
|
29840
29949
|
return {
|
|
@@ -29861,7 +29970,7 @@ var TokenTransactionService = class {
|
|
|
29861
29970
|
for (const [_, operator] of Object.entries(
|
|
29862
29971
|
this.config.getSigningOperators()
|
|
29863
29972
|
)) {
|
|
29864
|
-
operatorKeys.push((0,
|
|
29973
|
+
operatorKeys.push((0, import_utils21.hexToBytes)(operator.identityPublicKey));
|
|
29865
29974
|
}
|
|
29866
29975
|
return operatorKeys;
|
|
29867
29976
|
}
|
|
@@ -29878,7 +29987,7 @@ var TokenTransactionService = class {
|
|
|
29878
29987
|
finalTokenTransactionHash,
|
|
29879
29988
|
signingOperators
|
|
29880
29989
|
);
|
|
29881
|
-
return (0,
|
|
29990
|
+
return (0, import_utils20.bytesToHex)(finalTokenTransactionHash);
|
|
29882
29991
|
}
|
|
29883
29992
|
async startTokenTransaction(tokenTransaction, signingOperators, outputsToSpendSigningPublicKeys, outputsToSpendCommitments) {
|
|
29884
29993
|
const sparkClient = await this.connectionManager.createSparkTokenClient(
|
|
@@ -30053,10 +30162,10 @@ var TokenTransactionService = class {
|
|
|
30053
30162
|
});
|
|
30054
30163
|
}
|
|
30055
30164
|
for (const ownerPublicKey of ownerPublicKeys) {
|
|
30056
|
-
isValidPublicKey((0,
|
|
30165
|
+
isValidPublicKey((0, import_utils20.bytesToHex)(ownerPublicKey));
|
|
30057
30166
|
}
|
|
30058
30167
|
for (const issuerPublicKey of issuerPublicKeys) {
|
|
30059
|
-
isValidPublicKey((0,
|
|
30168
|
+
isValidPublicKey((0, import_utils20.bytesToHex)(issuerPublicKey));
|
|
30060
30169
|
}
|
|
30061
30170
|
for (const tokenIdentifier of tokenIdentifiers) {
|
|
30062
30171
|
if (tokenIdentifier.length !== 32) {
|
|
@@ -30124,8 +30233,8 @@ var TokenTransactionService = class {
|
|
|
30124
30233
|
this.config.getCoordinatorAddress()
|
|
30125
30234
|
);
|
|
30126
30235
|
let queryParams = {
|
|
30127
|
-
issuerPublicKeys: issuerPublicKeys?.map(
|
|
30128
|
-
ownerPublicKeys: ownerPublicKeys?.map(
|
|
30236
|
+
issuerPublicKeys: issuerPublicKeys?.map(import_utils21.hexToBytes),
|
|
30237
|
+
ownerPublicKeys: ownerPublicKeys?.map(import_utils21.hexToBytes),
|
|
30129
30238
|
tokenIdentifiers: tokenIdentifiers?.map((identifier) => {
|
|
30130
30239
|
const { tokenIdentifier } = decodeBech32mTokenIdentifier(
|
|
30131
30240
|
identifier,
|
|
@@ -30133,7 +30242,7 @@ var TokenTransactionService = class {
|
|
|
30133
30242
|
);
|
|
30134
30243
|
return tokenIdentifier;
|
|
30135
30244
|
}),
|
|
30136
|
-
tokenTransactionHashes: tokenTransactionHashes?.map(
|
|
30245
|
+
tokenTransactionHashes: tokenTransactionHashes?.map(import_utils21.hexToBytes),
|
|
30137
30246
|
outputIds: outputIds || [],
|
|
30138
30247
|
limit: pageSize,
|
|
30139
30248
|
offset
|
|
@@ -30168,7 +30277,7 @@ var TokenTransactionService = class {
|
|
|
30168
30277
|
});
|
|
30169
30278
|
}
|
|
30170
30279
|
const exactMatch = tokenOutputs.find(
|
|
30171
|
-
(item) => (0,
|
|
30280
|
+
(item) => (0, import_utils20.bytesToNumberBE)(item.output.tokenAmount) === tokenAmount
|
|
30172
30281
|
);
|
|
30173
30282
|
if (exactMatch) {
|
|
30174
30283
|
return [exactMatch];
|
|
@@ -30179,7 +30288,7 @@ var TokenTransactionService = class {
|
|
|
30179
30288
|
for (const outputWithPreviousTransactionData of tokenOutputs) {
|
|
30180
30289
|
if (remainingAmount <= 0n) break;
|
|
30181
30290
|
selectedOutputs.push(outputWithPreviousTransactionData);
|
|
30182
|
-
remainingAmount -= (0,
|
|
30291
|
+
remainingAmount -= (0, import_utils20.bytesToNumberBE)(
|
|
30183
30292
|
outputWithPreviousTransactionData.output.tokenAmount
|
|
30184
30293
|
);
|
|
30185
30294
|
}
|
|
@@ -30194,14 +30303,14 @@ var TokenTransactionService = class {
|
|
|
30194
30303
|
sortTokenOutputsByStrategy(tokenOutputs, strategy) {
|
|
30195
30304
|
if (strategy === "SMALL_FIRST") {
|
|
30196
30305
|
tokenOutputs.sort((a, b) => {
|
|
30197
|
-
const amountA = (0,
|
|
30198
|
-
const amountB = (0,
|
|
30306
|
+
const amountA = (0, import_utils20.bytesToNumberBE)(a.output.tokenAmount);
|
|
30307
|
+
const amountB = (0, import_utils20.bytesToNumberBE)(b.output.tokenAmount);
|
|
30199
30308
|
return amountA < amountB ? -1 : amountA > amountB ? 1 : 0;
|
|
30200
30309
|
});
|
|
30201
30310
|
} else {
|
|
30202
30311
|
tokenOutputs.sort((a, b) => {
|
|
30203
|
-
const amountA = (0,
|
|
30204
|
-
const amountB = (0,
|
|
30312
|
+
const amountA = (0, import_utils20.bytesToNumberBE)(a.output.tokenAmount);
|
|
30313
|
+
const amountB = (0, import_utils20.bytesToNumberBE)(b.output.tokenAmount);
|
|
30205
30314
|
return amountB < amountA ? -1 : amountB > amountA ? 1 : 0;
|
|
30206
30315
|
});
|
|
30207
30316
|
}
|
|
@@ -30209,7 +30318,7 @@ var TokenTransactionService = class {
|
|
|
30209
30318
|
// Helper function for deciding if the signer public key is the identity public key
|
|
30210
30319
|
async signMessageWithKey(message, publicKey) {
|
|
30211
30320
|
const tokenSignatures = this.config.getTokenSignatures();
|
|
30212
|
-
if ((0,
|
|
30321
|
+
if ((0, import_utils20.bytesToHex)(publicKey) === (0, import_utils20.bytesToHex)(await this.config.signer.getIdentityPublicKey())) {
|
|
30213
30322
|
if (tokenSignatures === "SCHNORR") {
|
|
30214
30323
|
return await this.config.signer.signSchnorrWithIdentityKey(message);
|
|
30215
30324
|
} else {
|
|
@@ -30218,8 +30327,8 @@ var TokenTransactionService = class {
|
|
|
30218
30327
|
} else {
|
|
30219
30328
|
throw new ValidationError("Invalid public key", {
|
|
30220
30329
|
field: "publicKey",
|
|
30221
|
-
value: (0,
|
|
30222
|
-
expected: (0,
|
|
30330
|
+
value: (0, import_utils20.bytesToHex)(publicKey),
|
|
30331
|
+
expected: (0, import_utils20.bytesToHex)(await this.config.signer.getIdentityPublicKey())
|
|
30223
30332
|
});
|
|
30224
30333
|
}
|
|
30225
30334
|
}
|
|
@@ -30238,7 +30347,7 @@ var TokenTransactionService = class {
|
|
|
30238
30347
|
}
|
|
30239
30348
|
const payload = {
|
|
30240
30349
|
finalTokenTransactionHash,
|
|
30241
|
-
operatorIdentityPublicKey: (0,
|
|
30350
|
+
operatorIdentityPublicKey: (0, import_utils21.hexToBytes)(operator.identityPublicKey)
|
|
30242
30351
|
};
|
|
30243
30352
|
const payloadHash = await hashOperatorSpecificTokenTransactionSignablePayload(payload);
|
|
30244
30353
|
const ownerSignature = await this.signMessageWithKey(
|
|
@@ -30260,7 +30369,7 @@ var TokenTransactionService = class {
|
|
|
30260
30369
|
}
|
|
30261
30370
|
const payload = {
|
|
30262
30371
|
finalTokenTransactionHash,
|
|
30263
|
-
operatorIdentityPublicKey: (0,
|
|
30372
|
+
operatorIdentityPublicKey: (0, import_utils21.hexToBytes)(operator.identityPublicKey)
|
|
30264
30373
|
};
|
|
30265
30374
|
const payloadHash = await hashOperatorSpecificTokenTransactionSignablePayload(payload);
|
|
30266
30375
|
const ownerSignature = await this.signMessageWithKey(
|
|
@@ -30276,7 +30385,7 @@ var TokenTransactionService = class {
|
|
|
30276
30385
|
for (let i = 0; i < transferInput.outputsToSpend.length; i++) {
|
|
30277
30386
|
const payload = {
|
|
30278
30387
|
finalTokenTransactionHash,
|
|
30279
|
-
operatorIdentityPublicKey: (0,
|
|
30388
|
+
operatorIdentityPublicKey: (0, import_utils21.hexToBytes)(operator.identityPublicKey)
|
|
30280
30389
|
};
|
|
30281
30390
|
const payloadHash = await hashOperatorSpecificTokenTransactionSignablePayload(payload);
|
|
30282
30391
|
let ownerSignature;
|
|
@@ -30293,7 +30402,7 @@ var TokenTransactionService = class {
|
|
|
30293
30402
|
}
|
|
30294
30403
|
inputTtxoSignaturesPerOperator.push({
|
|
30295
30404
|
ttxoSignatures,
|
|
30296
|
-
operatorIdentityPublicKey: (0,
|
|
30405
|
+
operatorIdentityPublicKey: (0, import_utils21.hexToBytes)(operator.identityPublicKey)
|
|
30297
30406
|
});
|
|
30298
30407
|
}
|
|
30299
30408
|
return inputTtxoSignaturesPerOperator;
|
|
@@ -30309,13 +30418,12 @@ var import_nice_grpc_common2 = require("nice-grpc-common");
|
|
|
30309
30418
|
|
|
30310
30419
|
// src/services/signing.ts
|
|
30311
30420
|
init_buffer();
|
|
30312
|
-
var import_utils22 = require("@noble/curves/utils");
|
|
30313
30421
|
|
|
30314
30422
|
// src/utils/htlc-transactions.ts
|
|
30315
30423
|
init_buffer();
|
|
30316
|
-
var
|
|
30424
|
+
var import_btc_signer3 = require("@scure/btc-signer");
|
|
30317
30425
|
var import_secp256k112 = require("@noble/curves/secp256k1");
|
|
30318
|
-
var
|
|
30426
|
+
var import_utils22 = require("@noble/curves/utils");
|
|
30319
30427
|
var PUB_KEY_BYTES = "0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0";
|
|
30320
30428
|
function numsPoint() {
|
|
30321
30429
|
const withdrawalPubKeyPoint = import_secp256k112.secp256k1.Point.fromHex(PUB_KEY_BYTES);
|
|
@@ -30393,10 +30501,10 @@ function createLightningHTLCTransaction({
|
|
|
30393
30501
|
outAmount = maybeApplyFee(outAmount);
|
|
30394
30502
|
}
|
|
30395
30503
|
const input = {
|
|
30396
|
-
txid: (0,
|
|
30504
|
+
txid: (0, import_utils22.hexToBytes)(getTxId(nodeTx)),
|
|
30397
30505
|
index: 0
|
|
30398
30506
|
};
|
|
30399
|
-
const htlcTransaction = new
|
|
30507
|
+
const htlcTransaction = new import_btc_signer3.Transaction({
|
|
30400
30508
|
version: 3,
|
|
30401
30509
|
allowUnknownOutputs: true
|
|
30402
30510
|
});
|
|
@@ -30435,12 +30543,12 @@ function createHTLCTaprootAddress({
|
|
|
30435
30543
|
);
|
|
30436
30544
|
const hashLockLeaf = { leafVersion: 192, script: hashLockScript };
|
|
30437
30545
|
const sequenceLockLeaf = { leafVersion: 192, script: sequenceLockScript };
|
|
30438
|
-
const scriptTree = (0,
|
|
30439
|
-
const p2trScript = (0,
|
|
30546
|
+
const scriptTree = (0, import_btc_signer3.taprootListToTree)([hashLockLeaf, sequenceLockLeaf]);
|
|
30547
|
+
const p2trScript = (0, import_btc_signer3.p2tr)(numsKey, scriptTree, network, true).script;
|
|
30440
30548
|
return p2trScript;
|
|
30441
30549
|
}
|
|
30442
30550
|
function createHashLockScript(hash, pubkey) {
|
|
30443
|
-
const result =
|
|
30551
|
+
const result = import_btc_signer3.Script.encode([
|
|
30444
30552
|
"SHA256",
|
|
30445
30553
|
hash,
|
|
30446
30554
|
"EQUALVERIFY",
|
|
@@ -30450,8 +30558,8 @@ function createHashLockScript(hash, pubkey) {
|
|
|
30450
30558
|
return result;
|
|
30451
30559
|
}
|
|
30452
30560
|
function createSequenceLockScript(sequence, sequenceLockDestinationPubkey) {
|
|
30453
|
-
const result =
|
|
30454
|
-
(0,
|
|
30561
|
+
const result = import_btc_signer3.Script.encode([
|
|
30562
|
+
(0, import_btc_signer3.ScriptNum)().encode(BigInt(sequence)),
|
|
30455
30563
|
"CHECKSEQUENCEVERIFY",
|
|
30456
30564
|
"DROP",
|
|
30457
30565
|
sequenceLockDestinationPubkey.slice(1, 33),
|
|
@@ -30515,20 +30623,7 @@ var SigningService = class {
|
|
|
30515
30623
|
});
|
|
30516
30624
|
}
|
|
30517
30625
|
const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
30518
|
-
const cpfpNodeOutPoint = {
|
|
30519
|
-
txid: (0, import_utils22.hexToBytes)(getTxId(nodeTx)),
|
|
30520
|
-
index: 0
|
|
30521
|
-
};
|
|
30522
30626
|
const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
30523
|
-
const sequence = currRefundTx.getInput(0).sequence;
|
|
30524
|
-
if (!sequence) {
|
|
30525
|
-
throw new ValidationError("Invalid refund transaction", {
|
|
30526
|
-
field: "sequence",
|
|
30527
|
-
value: currRefundTx.getInput(0),
|
|
30528
|
-
expected: "Non-null sequence"
|
|
30529
|
-
});
|
|
30530
|
-
}
|
|
30531
|
-
const { nextSequence, nextDirectSequence } = getNextTransactionSequence(sequence);
|
|
30532
30627
|
const amountSats = currRefundTx.getOutput(0).amount;
|
|
30533
30628
|
if (amountSats === void 0) {
|
|
30534
30629
|
throw new ValidationError("Invalid refund transaction", {
|
|
@@ -30538,20 +30633,21 @@ var SigningService = class {
|
|
|
30538
30633
|
});
|
|
30539
30634
|
}
|
|
30540
30635
|
let directNodeTx;
|
|
30541
|
-
let directNodeOutPoint;
|
|
30542
30636
|
if (leaf.leaf.directTx.length > 0) {
|
|
30543
30637
|
directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
|
|
30544
|
-
directNodeOutPoint = {
|
|
30545
|
-
txid: (0, import_utils22.hexToBytes)(getTxId(directNodeTx)),
|
|
30546
|
-
index: 0
|
|
30547
|
-
};
|
|
30548
30638
|
}
|
|
30549
|
-
const
|
|
30550
|
-
|
|
30551
|
-
|
|
30552
|
-
|
|
30553
|
-
|
|
30554
|
-
|
|
30639
|
+
const currentSequence = currRefundTx.getInput(0).sequence;
|
|
30640
|
+
if (!currentSequence) {
|
|
30641
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
30642
|
+
field: "sequence",
|
|
30643
|
+
value: currRefundTx.getInput(0),
|
|
30644
|
+
expected: "Non-null sequence"
|
|
30645
|
+
});
|
|
30646
|
+
}
|
|
30647
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createDecrementedTimelockRefundTxs({
|
|
30648
|
+
nodeTx,
|
|
30649
|
+
directNodeTx,
|
|
30650
|
+
sequence: currentSequence,
|
|
30555
30651
|
receivingPubkey: receiverIdentityPubkey,
|
|
30556
30652
|
network: this.config.getNetwork()
|
|
30557
30653
|
});
|
|
@@ -30567,7 +30663,8 @@ var SigningService = class {
|
|
|
30567
30663
|
cpfpSigningCommitments[i]?.signingNonceCommitments
|
|
30568
30664
|
);
|
|
30569
30665
|
cpfpLeafSigningJobs.push(...signingJobs);
|
|
30570
|
-
|
|
30666
|
+
const isZeroNode = getCurrentTimelock(nodeTx.getInput(0).sequence);
|
|
30667
|
+
if (directRefundTx && !isZeroNode) {
|
|
30571
30668
|
if (!directNodeTx) {
|
|
30572
30669
|
throw new ValidationError(
|
|
30573
30670
|
"Direct node transaction undefined while direct refund transaction is defined",
|
|
@@ -30592,16 +30689,6 @@ var SigningService = class {
|
|
|
30592
30689
|
directLeafSigningJobs.push(...signingJobs2);
|
|
30593
30690
|
}
|
|
30594
30691
|
if (directFromCpfpRefundTx) {
|
|
30595
|
-
if (!directNodeTx) {
|
|
30596
|
-
throw new ValidationError(
|
|
30597
|
-
"Direct node transaction undefined while direct from CPFP refund transaction is defined",
|
|
30598
|
-
{
|
|
30599
|
-
field: "directNodeTx",
|
|
30600
|
-
value: directNodeTx,
|
|
30601
|
-
expected: "Non-null direct node transaction"
|
|
30602
|
-
}
|
|
30603
|
-
);
|
|
30604
|
-
}
|
|
30605
30692
|
const refundSighash2 = getSigHashFromTx(
|
|
30606
30693
|
directFromCpfpRefundTx,
|
|
30607
30694
|
0,
|
|
@@ -30728,6 +30815,35 @@ var SigningService = class {
|
|
|
30728
30815
|
directFromCpfpLeafSigningJobs
|
|
30729
30816
|
};
|
|
30730
30817
|
}
|
|
30818
|
+
async signSigningJobs(signingJobs) {
|
|
30819
|
+
const userSignedTxSigningJobs = /* @__PURE__ */ new Map();
|
|
30820
|
+
for (const signingJob of signingJobs) {
|
|
30821
|
+
const rawTx = getTxFromRawTxBytes(signingJob.rawTx);
|
|
30822
|
+
const txOut = signingJob.parentTxOut;
|
|
30823
|
+
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
30824
|
+
const userSignature = await this.config.signer.signFrost({
|
|
30825
|
+
message: rawTxSighash,
|
|
30826
|
+
keyDerivation: signingJob.keyDerivation,
|
|
30827
|
+
publicKey: signingJob.signingPublicKey,
|
|
30828
|
+
verifyingKey: signingJob.verifyingKey,
|
|
30829
|
+
selfCommitment: signingJob.signingNonceCommitment,
|
|
30830
|
+
statechainCommitments: signingJob.signingNonceCommitments,
|
|
30831
|
+
adaptorPubKey: new Uint8Array()
|
|
30832
|
+
});
|
|
30833
|
+
const userSignedTxSigningJob = {
|
|
30834
|
+
leafId: signingJob.leafId,
|
|
30835
|
+
signingPublicKey: signingJob.signingPublicKey,
|
|
30836
|
+
rawTx: rawTx.toBytes(),
|
|
30837
|
+
signingNonceCommitment: signingJob.signingNonceCommitment.commitment,
|
|
30838
|
+
signingCommitments: {
|
|
30839
|
+
signingCommitments: signingJob.signingNonceCommitments
|
|
30840
|
+
},
|
|
30841
|
+
userSignature
|
|
30842
|
+
};
|
|
30843
|
+
userSignedTxSigningJobs.set(signingJob.type, userSignedTxSigningJob);
|
|
30844
|
+
}
|
|
30845
|
+
return userSignedTxSigningJobs;
|
|
30846
|
+
}
|
|
30731
30847
|
};
|
|
30732
30848
|
|
|
30733
30849
|
// src/tests/utils/test-faucet.ts
|
|
@@ -30735,7 +30851,7 @@ init_buffer();
|
|
|
30735
30851
|
var import_secp256k113 = require("@noble/curves/secp256k1");
|
|
30736
30852
|
var import_utils23 = require("@noble/curves/utils");
|
|
30737
30853
|
var btc5 = __toESM(require("@scure/btc-signer"), 1);
|
|
30738
|
-
var
|
|
30854
|
+
var import_btc_signer4 = require("@scure/btc-signer");
|
|
30739
30855
|
var import_utils24 = require("@scure/btc-signer/utils");
|
|
30740
30856
|
var STATIC_FAUCET_KEY = (0, import_utils23.hexToBytes)(
|
|
30741
30857
|
"deadbeef1337cafe4242424242424242deadbeef1337cafe4242424242424242"
|
|
@@ -30822,7 +30938,7 @@ var _BitcoinFaucet = class _BitcoinFaucet {
|
|
|
30822
30938
|
);
|
|
30823
30939
|
await this.generateToAddress(1, address);
|
|
30824
30940
|
const fundingTxRaw = await this.getRawTransaction(fundingTxid);
|
|
30825
|
-
const fundingTx =
|
|
30941
|
+
const fundingTx = import_btc_signer4.Transaction.fromRaw((0, import_utils23.hexToBytes)(fundingTxRaw.hex));
|
|
30826
30942
|
for (let i = 0; i < fundingTx.outputsLength; i++) {
|
|
30827
30943
|
const output = fundingTx.getOutput(i);
|
|
30828
30944
|
if (!output.script || !output.amount) continue;
|
|
@@ -30853,7 +30969,7 @@ var _BitcoinFaucet = class _BitcoinFaucet {
|
|
|
30853
30969
|
`Selected UTXO (${selectedUtxoAmountSats} sats) is too small to create even one faucet coin of ${COIN_AMOUNT} sats`
|
|
30854
30970
|
);
|
|
30855
30971
|
}
|
|
30856
|
-
const splitTx = new
|
|
30972
|
+
const splitTx = new import_btc_signer4.Transaction();
|
|
30857
30973
|
splitTx.addInput({
|
|
30858
30974
|
txid: selectedUtxo.txid,
|
|
30859
30975
|
index: selectedUtxo.vout
|
|
@@ -30896,7 +31012,7 @@ var _BitcoinFaucet = class _BitcoinFaucet {
|
|
|
30896
31012
|
}
|
|
30897
31013
|
}
|
|
30898
31014
|
async sendFaucetCoinToP2WPKHAddress(pubKey) {
|
|
30899
|
-
const sendToPubKeyTx = new
|
|
31015
|
+
const sendToPubKeyTx = new import_btc_signer4.Transaction();
|
|
30900
31016
|
const p2wpkhAddress = btc5.p2wpkh(pubKey, getNetwork(4 /* LOCAL */)).address;
|
|
30901
31017
|
if (!p2wpkhAddress) {
|
|
30902
31018
|
throw new Error("Invalid P2WPKH address");
|
|
@@ -30932,7 +31048,7 @@ var _BitcoinFaucet = class _BitcoinFaucet {
|
|
|
30932
31048
|
const sighash = unsignedTx.preimageWitnessV1(
|
|
30933
31049
|
0,
|
|
30934
31050
|
new Array(unsignedTx.inputsLength).fill(script),
|
|
30935
|
-
|
|
31051
|
+
import_btc_signer4.SigHash.DEFAULT,
|
|
30936
31052
|
new Array(unsignedTx.inputsLength).fill(fundingTxOut.amount)
|
|
30937
31053
|
);
|
|
30938
31054
|
const merkleRoot = new Uint8Array();
|
|
@@ -30951,6 +31067,14 @@ var _BitcoinFaucet = class _BitcoinFaucet {
|
|
|
30951
31067
|
async mineBlocks(numBlocks) {
|
|
30952
31068
|
return await this.generateToAddress(numBlocks, this.miningAddress);
|
|
30953
31069
|
}
|
|
31070
|
+
async mineBlocksAndWaitForMiningToComplete(numBlocks) {
|
|
31071
|
+
const startBlock = await this.getBlockCount();
|
|
31072
|
+
await this.mineBlocks(numBlocks);
|
|
31073
|
+
await this.waitForBlocksMined({
|
|
31074
|
+
startBlock,
|
|
31075
|
+
expectedIncrease: numBlocks
|
|
31076
|
+
});
|
|
31077
|
+
}
|
|
30954
31078
|
async call(method, params) {
|
|
30955
31079
|
try {
|
|
30956
31080
|
const { fetch, Headers: Headers2 } = getFetch();
|
|
@@ -31003,27 +31127,62 @@ var _BitcoinFaucet = class _BitcoinFaucet {
|
|
|
31003
31127
|
async getBlock(blockHash) {
|
|
31004
31128
|
return await this.call("getblock", [blockHash, 2]);
|
|
31005
31129
|
}
|
|
31130
|
+
async getBlockCount() {
|
|
31131
|
+
return await this.call("getblockcount", []);
|
|
31132
|
+
}
|
|
31133
|
+
async waitForBlocksMined({
|
|
31134
|
+
startBlock,
|
|
31135
|
+
expectedIncrease,
|
|
31136
|
+
timeoutMs = 3e4,
|
|
31137
|
+
intervalMs = 5e3
|
|
31138
|
+
}) {
|
|
31139
|
+
const deadline = Date.now() + timeoutMs;
|
|
31140
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
31141
|
+
const start = startBlock;
|
|
31142
|
+
const target = start + expectedIncrease;
|
|
31143
|
+
while (Date.now() < deadline) {
|
|
31144
|
+
const currentBlock = await this.getBlockCount();
|
|
31145
|
+
if (currentBlock >= target) return currentBlock;
|
|
31146
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
31147
|
+
}
|
|
31148
|
+
throw new Error(
|
|
31149
|
+
`Timed out waiting for ${expectedIncrease} blocks (target height ${target})`
|
|
31150
|
+
);
|
|
31151
|
+
}
|
|
31006
31152
|
async broadcastTx(txHex) {
|
|
31007
31153
|
let response = await this.call("sendrawtransaction", [txHex, 0]);
|
|
31008
31154
|
return response;
|
|
31009
31155
|
}
|
|
31156
|
+
async submitPackage(txHexs) {
|
|
31157
|
+
let response = await this.call("submitpackage", [txHexs]);
|
|
31158
|
+
return response;
|
|
31159
|
+
}
|
|
31010
31160
|
async getNewAddress() {
|
|
31011
31161
|
const key = import_secp256k113.secp256k1.utils.randomPrivateKey();
|
|
31012
31162
|
const pubKey = import_secp256k113.secp256k1.getPublicKey(key);
|
|
31013
31163
|
return getP2TRAddressFromPublicKey(pubKey, 4 /* LOCAL */);
|
|
31014
31164
|
}
|
|
31165
|
+
async getNewExternalWallet() {
|
|
31166
|
+
const key = import_secp256k113.secp256k1.utils.randomPrivateKey();
|
|
31167
|
+
const pubKey = import_secp256k113.secp256k1.getPublicKey(key);
|
|
31168
|
+
return {
|
|
31169
|
+
address: getP2TRAddressFromPublicKey(pubKey, 4 /* LOCAL */),
|
|
31170
|
+
key,
|
|
31171
|
+
pubKey
|
|
31172
|
+
};
|
|
31173
|
+
}
|
|
31015
31174
|
async sendToAddress(address, amount, blocksToGenerate = 1) {
|
|
31016
31175
|
const coin = await this.fund();
|
|
31017
31176
|
if (!coin) {
|
|
31018
31177
|
throw new Error("No coins available");
|
|
31019
31178
|
}
|
|
31020
|
-
const tx = new
|
|
31179
|
+
const tx = new import_btc_signer4.Transaction();
|
|
31021
31180
|
tx.addInput(coin.outpoint);
|
|
31022
31181
|
const availableAmount = COIN_AMOUNT - FEE_AMOUNT;
|
|
31023
|
-
const destinationAddress = (0,
|
|
31182
|
+
const destinationAddress = (0, import_btc_signer4.Address)(getNetwork(4 /* LOCAL */)).decode(
|
|
31024
31183
|
address
|
|
31025
31184
|
);
|
|
31026
|
-
const destinationScript =
|
|
31185
|
+
const destinationScript = import_btc_signer4.OutScript.encode(destinationAddress);
|
|
31027
31186
|
tx.addOutput({
|
|
31028
31187
|
script: destinationScript,
|
|
31029
31188
|
amount
|
|
@@ -31070,76 +31229,6 @@ function chunkArray(arr, size) {
|
|
|
31070
31229
|
return chunks;
|
|
31071
31230
|
}
|
|
31072
31231
|
|
|
31073
|
-
// src/utils/optimize.ts
|
|
31074
|
-
init_buffer();
|
|
31075
|
-
var DENOMINATIONS = Array.from({ length: 28 }, (_, i) => 2 ** i);
|
|
31076
|
-
function assert(condition, message) {
|
|
31077
|
-
if (!condition) {
|
|
31078
|
-
throw new InternalValidationError(message || "Assertion failed");
|
|
31079
|
-
}
|
|
31080
|
-
}
|
|
31081
|
-
function sum(arr) {
|
|
31082
|
-
return arr.reduce((a, b) => a + b, 0);
|
|
31083
|
-
}
|
|
31084
|
-
function sorted(arr) {
|
|
31085
|
-
return [...arr].sort((a, b) => a - b);
|
|
31086
|
-
}
|
|
31087
|
-
function equals(a, b) {
|
|
31088
|
-
return a.length === b.length && a.every((val, index) => val === b[index]);
|
|
31089
|
-
}
|
|
31090
|
-
function greedyLeaves(amount) {
|
|
31091
|
-
const leaves = [];
|
|
31092
|
-
let remaining = amount;
|
|
31093
|
-
for (let i = DENOMINATIONS.length - 1; i >= 0; i--) {
|
|
31094
|
-
const leaf = DENOMINATIONS[i];
|
|
31095
|
-
if (typeof leaf === "number" && leaf > 0) {
|
|
31096
|
-
while (remaining >= leaf) {
|
|
31097
|
-
remaining -= leaf;
|
|
31098
|
-
leaves.push(leaf);
|
|
31099
|
-
}
|
|
31100
|
-
}
|
|
31101
|
-
}
|
|
31102
|
-
assert(sum(leaves) === amount, "greedy_leaves: sum mismatch");
|
|
31103
|
-
return sorted(leaves);
|
|
31104
|
-
}
|
|
31105
|
-
var Swap = class {
|
|
31106
|
-
constructor(inLeaves, outLeaves) {
|
|
31107
|
-
__publicField(this, "inLeaves");
|
|
31108
|
-
__publicField(this, "outLeaves");
|
|
31109
|
-
this.inLeaves = [...inLeaves];
|
|
31110
|
-
this.outLeaves = [...outLeaves];
|
|
31111
|
-
assert(
|
|
31112
|
-
sum(this.inLeaves) === sum(this.outLeaves),
|
|
31113
|
-
"Swap in/out leaves must sum to same value for swap: " + this.toString()
|
|
31114
|
-
);
|
|
31115
|
-
}
|
|
31116
|
-
toString() {
|
|
31117
|
-
return `Swap(in=${JSON.stringify(this.inLeaves)}, out=${JSON.stringify(this.outLeaves)})`;
|
|
31118
|
-
}
|
|
31119
|
-
};
|
|
31120
|
-
function maximizeUnilateralExit(inputLeaves, maxLeavesPerSwap = 64) {
|
|
31121
|
-
const swaps = [];
|
|
31122
|
-
let batch = [];
|
|
31123
|
-
let leaves = sorted(inputLeaves);
|
|
31124
|
-
while (leaves.length > 0) {
|
|
31125
|
-
batch.push(leaves.shift());
|
|
31126
|
-
const target = greedyLeaves(sum(batch));
|
|
31127
|
-
if (batch.length >= maxLeavesPerSwap || target.length >= maxLeavesPerSwap) {
|
|
31128
|
-
if (!equals(target, batch)) {
|
|
31129
|
-
swaps.push(new Swap([...batch], target));
|
|
31130
|
-
}
|
|
31131
|
-
batch = [];
|
|
31132
|
-
}
|
|
31133
|
-
}
|
|
31134
|
-
if (batch.length > 0) {
|
|
31135
|
-
const target = greedyLeaves(sum(batch));
|
|
31136
|
-
if (!equals(target, batch)) {
|
|
31137
|
-
swaps.push(new Swap([...batch], target));
|
|
31138
|
-
}
|
|
31139
|
-
}
|
|
31140
|
-
return swaps;
|
|
31141
|
-
}
|
|
31142
|
-
|
|
31143
31232
|
// src/utils/retry.ts
|
|
31144
31233
|
init_buffer();
|
|
31145
31234
|
var DEFAULT_RETRY_CONFIG = {
|
|
@@ -31218,6 +31307,200 @@ var SparkWalletEvent = {
|
|
|
31218
31307
|
StreamReconnecting: "stream:reconnecting"
|
|
31219
31308
|
};
|
|
31220
31309
|
|
|
31310
|
+
// src/utils/optimize.ts
|
|
31311
|
+
init_buffer();
|
|
31312
|
+
var DENOMINATIONS = Array.from({ length: 28 }, (_, i) => 2 ** i);
|
|
31313
|
+
function assert(condition, message) {
|
|
31314
|
+
if (!condition) {
|
|
31315
|
+
throw new InternalValidationError(message || "Assertion failed");
|
|
31316
|
+
}
|
|
31317
|
+
}
|
|
31318
|
+
function sum(arr) {
|
|
31319
|
+
return arr.reduce((a, b) => a + b, 0);
|
|
31320
|
+
}
|
|
31321
|
+
function sorted(arr) {
|
|
31322
|
+
return [...arr].sort((a, b) => a - b);
|
|
31323
|
+
}
|
|
31324
|
+
function equals(a, b) {
|
|
31325
|
+
return a.length === b.length && a.every((val, index) => val === b[index]);
|
|
31326
|
+
}
|
|
31327
|
+
function countOccurrences(arr) {
|
|
31328
|
+
const map = /* @__PURE__ */ new Map();
|
|
31329
|
+
for (const x of arr) {
|
|
31330
|
+
map.set(x, (map.get(x) ?? 0) + 1);
|
|
31331
|
+
}
|
|
31332
|
+
return map;
|
|
31333
|
+
}
|
|
31334
|
+
function subtractCounters(a, b) {
|
|
31335
|
+
const result = /* @__PURE__ */ new Map();
|
|
31336
|
+
for (const [key, value] of a.entries()) {
|
|
31337
|
+
const diff = value - (b.get(key) ?? 0);
|
|
31338
|
+
if (diff > 0) {
|
|
31339
|
+
result.set(key, diff);
|
|
31340
|
+
}
|
|
31341
|
+
}
|
|
31342
|
+
return result;
|
|
31343
|
+
}
|
|
31344
|
+
function counterToFlatArray(counter) {
|
|
31345
|
+
const arr = [];
|
|
31346
|
+
for (const [k, v] of Array.from(counter.entries()).sort(
|
|
31347
|
+
(a, b) => a[0] - b[0]
|
|
31348
|
+
)) {
|
|
31349
|
+
for (let i = 0; i < v; i++) {
|
|
31350
|
+
arr.push(k);
|
|
31351
|
+
}
|
|
31352
|
+
}
|
|
31353
|
+
return arr;
|
|
31354
|
+
}
|
|
31355
|
+
function greedyLeaves(amount) {
|
|
31356
|
+
const leaves = [];
|
|
31357
|
+
let remaining = amount;
|
|
31358
|
+
for (let i = DENOMINATIONS.length - 1; i >= 0; i--) {
|
|
31359
|
+
const leaf = DENOMINATIONS[i];
|
|
31360
|
+
if (typeof leaf === "number" && leaf > 0) {
|
|
31361
|
+
while (remaining >= leaf) {
|
|
31362
|
+
remaining -= leaf;
|
|
31363
|
+
leaves.push(leaf);
|
|
31364
|
+
}
|
|
31365
|
+
}
|
|
31366
|
+
}
|
|
31367
|
+
assert(sum(leaves) === amount, "greedy_leaves: sum mismatch");
|
|
31368
|
+
return sorted(leaves);
|
|
31369
|
+
}
|
|
31370
|
+
function swapMinimizingLeaves(amount, multiplicity = 1) {
|
|
31371
|
+
const leaves = [];
|
|
31372
|
+
let remaining = amount;
|
|
31373
|
+
assert(multiplicity > 0, "multiplicity must be > 0");
|
|
31374
|
+
for (const leaf of DENOMINATIONS) {
|
|
31375
|
+
if (typeof leaf === "number" && leaf > 0) {
|
|
31376
|
+
for (let i = 0; i < multiplicity; i++) {
|
|
31377
|
+
if (remaining >= leaf) {
|
|
31378
|
+
remaining -= leaf;
|
|
31379
|
+
leaves.push(leaf);
|
|
31380
|
+
}
|
|
31381
|
+
}
|
|
31382
|
+
}
|
|
31383
|
+
}
|
|
31384
|
+
leaves.push(...greedyLeaves(remaining));
|
|
31385
|
+
assert(sum(leaves) === amount, "swap_minimizing_leaves: sum mismatch");
|
|
31386
|
+
return sorted(leaves);
|
|
31387
|
+
}
|
|
31388
|
+
var Swap = class {
|
|
31389
|
+
constructor(inLeaves, outLeaves) {
|
|
31390
|
+
__publicField(this, "inLeaves");
|
|
31391
|
+
__publicField(this, "outLeaves");
|
|
31392
|
+
this.inLeaves = [...inLeaves];
|
|
31393
|
+
this.outLeaves = [...outLeaves];
|
|
31394
|
+
assert(
|
|
31395
|
+
sum(this.inLeaves) === sum(this.outLeaves),
|
|
31396
|
+
"Swap in/out leaves must sum to same value for swap: " + this.toString()
|
|
31397
|
+
);
|
|
31398
|
+
}
|
|
31399
|
+
toString() {
|
|
31400
|
+
return `Swap(in=${JSON.stringify(this.inLeaves)}, out=${JSON.stringify(this.outLeaves)})`;
|
|
31401
|
+
}
|
|
31402
|
+
};
|
|
31403
|
+
function maximizeUnilateralExit(inputLeaves, maxLeavesPerSwap = 64) {
|
|
31404
|
+
const swaps = [];
|
|
31405
|
+
let batch = [];
|
|
31406
|
+
let leaves = sorted(inputLeaves);
|
|
31407
|
+
while (leaves.length > 0) {
|
|
31408
|
+
batch.push(leaves.shift());
|
|
31409
|
+
const target = greedyLeaves(sum(batch));
|
|
31410
|
+
if (batch.length >= maxLeavesPerSwap || target.length >= maxLeavesPerSwap) {
|
|
31411
|
+
if (!equals(target, batch)) {
|
|
31412
|
+
swaps.push(new Swap([...batch], target));
|
|
31413
|
+
}
|
|
31414
|
+
batch = [];
|
|
31415
|
+
}
|
|
31416
|
+
}
|
|
31417
|
+
if (batch.length > 0) {
|
|
31418
|
+
const target = greedyLeaves(sum(batch));
|
|
31419
|
+
if (!equals(target, batch)) {
|
|
31420
|
+
swaps.push(new Swap([...batch], target));
|
|
31421
|
+
}
|
|
31422
|
+
}
|
|
31423
|
+
return swaps;
|
|
31424
|
+
}
|
|
31425
|
+
function minimizeTransferSwap(inputLeaves, multiplicity = 1, maxLeavesPerSwap = 64) {
|
|
31426
|
+
const balance = sum(inputLeaves);
|
|
31427
|
+
const optimalLeaves = swapMinimizingLeaves(balance, multiplicity);
|
|
31428
|
+
const walletCounter = countOccurrences(inputLeaves);
|
|
31429
|
+
const optimalCounter = countOccurrences(optimalLeaves);
|
|
31430
|
+
const leavesToGive = subtractCounters(walletCounter, optimalCounter);
|
|
31431
|
+
const leavesToReceive = subtractCounters(optimalCounter, walletCounter);
|
|
31432
|
+
const leavesToGiveFlat = counterToFlatArray(leavesToGive);
|
|
31433
|
+
const leavesToReceiveFlat = counterToFlatArray(leavesToReceive);
|
|
31434
|
+
const swaps = [];
|
|
31435
|
+
let toGiveBatch = [];
|
|
31436
|
+
let toReceiveBatch = [];
|
|
31437
|
+
let give = [...leavesToGiveFlat];
|
|
31438
|
+
let receive = [...leavesToReceiveFlat];
|
|
31439
|
+
while (give.length > 0 || receive.length > 0) {
|
|
31440
|
+
if (sum(toGiveBatch) > sum(toReceiveBatch)) {
|
|
31441
|
+
if (receive.length === 0) break;
|
|
31442
|
+
toReceiveBatch.push(receive.shift());
|
|
31443
|
+
} else {
|
|
31444
|
+
if (give.length === 0) break;
|
|
31445
|
+
toGiveBatch.push(give.shift());
|
|
31446
|
+
}
|
|
31447
|
+
if (toGiveBatch.length > 0 && toReceiveBatch.length > 0 && sum(toGiveBatch) === sum(toReceiveBatch)) {
|
|
31448
|
+
if (toGiveBatch.length > maxLeavesPerSwap) {
|
|
31449
|
+
for (let i = 0; i < toGiveBatch.length; i += maxLeavesPerSwap) {
|
|
31450
|
+
const subset = toGiveBatch.slice(i, i + maxLeavesPerSwap);
|
|
31451
|
+
swaps.push(new Swap(subset, greedyLeaves(sum(subset))));
|
|
31452
|
+
}
|
|
31453
|
+
} else if (toReceiveBatch.length > maxLeavesPerSwap) {
|
|
31454
|
+
for (let cutoff = maxLeavesPerSwap; cutoff > 0; cutoff--) {
|
|
31455
|
+
const sumCut = sum(toReceiveBatch.slice(0, cutoff));
|
|
31456
|
+
const remainder = sum(toGiveBatch) - sumCut;
|
|
31457
|
+
const alternateBatch = [
|
|
31458
|
+
...toReceiveBatch.slice(0, cutoff),
|
|
31459
|
+
...greedyLeaves(remainder)
|
|
31460
|
+
];
|
|
31461
|
+
if (alternateBatch.length <= maxLeavesPerSwap) {
|
|
31462
|
+
swaps.push(new Swap([...toGiveBatch], alternateBatch));
|
|
31463
|
+
break;
|
|
31464
|
+
}
|
|
31465
|
+
}
|
|
31466
|
+
} else {
|
|
31467
|
+
swaps.push(new Swap([...toGiveBatch], [...toReceiveBatch]));
|
|
31468
|
+
}
|
|
31469
|
+
toGiveBatch = [];
|
|
31470
|
+
toReceiveBatch = [];
|
|
31471
|
+
}
|
|
31472
|
+
}
|
|
31473
|
+
return swaps;
|
|
31474
|
+
}
|
|
31475
|
+
function shouldOptimize(inputLeaves, multiplicity = 1, maxLeavesPerSwap = 64) {
|
|
31476
|
+
if (multiplicity == 0) {
|
|
31477
|
+
const swaps = maximizeUnilateralExit(inputLeaves, maxLeavesPerSwap);
|
|
31478
|
+
const numInputs = sum(swaps.map((swap) => swap.inLeaves.length));
|
|
31479
|
+
const numOutputs = sum(swaps.map((swap) => swap.outLeaves.length));
|
|
31480
|
+
return numOutputs * 5 < numInputs;
|
|
31481
|
+
} else {
|
|
31482
|
+
const swaps = minimizeTransferSwap(
|
|
31483
|
+
inputLeaves,
|
|
31484
|
+
multiplicity,
|
|
31485
|
+
maxLeavesPerSwap
|
|
31486
|
+
);
|
|
31487
|
+
const inputCounter = countOccurrences(
|
|
31488
|
+
swaps.flatMap((swap) => swap.inLeaves)
|
|
31489
|
+
);
|
|
31490
|
+
const outputCounter = countOccurrences(
|
|
31491
|
+
swaps.flatMap((swap) => swap.outLeaves)
|
|
31492
|
+
);
|
|
31493
|
+
return Math.abs(inputCounter.size - outputCounter.size) > 1;
|
|
31494
|
+
}
|
|
31495
|
+
}
|
|
31496
|
+
function optimize(inputLeaves, multiplicity = 1, maxLeavesPerSwap = 64) {
|
|
31497
|
+
if (multiplicity == 0) {
|
|
31498
|
+
return maximizeUnilateralExit(inputLeaves, maxLeavesPerSwap);
|
|
31499
|
+
} else {
|
|
31500
|
+
return minimizeTransferSwap(inputLeaves, multiplicity, maxLeavesPerSwap);
|
|
31501
|
+
}
|
|
31502
|
+
}
|
|
31503
|
+
|
|
31221
31504
|
// src/spark-wallet/spark-wallet.ts
|
|
31222
31505
|
var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
31223
31506
|
constructor(options, signerArg) {
|
|
@@ -31322,16 +31605,13 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
31322
31605
|
if (event.transfer.transfer && !(0, import_utils25.equalBytes)(senderIdentityPublicKey, receiverIdentityPublicKey)) {
|
|
31323
31606
|
await this.claimTransfer({
|
|
31324
31607
|
transfer: event.transfer.transfer,
|
|
31325
|
-
emit: true
|
|
31326
|
-
optimize: true
|
|
31608
|
+
emit: true
|
|
31327
31609
|
});
|
|
31328
31610
|
}
|
|
31329
31611
|
} else if (isDepositStreamEvent(event)) {
|
|
31330
31612
|
const deposit = event.deposit.deposit;
|
|
31331
|
-
|
|
31332
|
-
|
|
31333
|
-
type: "leaf" /* LEAF */,
|
|
31334
|
-
path: deposit.id
|
|
31613
|
+
await this.withLeaves(async () => {
|
|
31614
|
+
this.leaves.push(deposit);
|
|
31335
31615
|
});
|
|
31336
31616
|
this.emit(
|
|
31337
31617
|
SparkWalletEvent.DepositConfirmed,
|
|
@@ -31507,19 +31787,6 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
31507
31787
|
}
|
|
31508
31788
|
return availableLeaves.filter(([_, node]) => !leavesToIgnore.has(node.id)).map(([_, node]) => node);
|
|
31509
31789
|
}
|
|
31510
|
-
async checkExtendLeaves(leaves) {
|
|
31511
|
-
await this.withLeaves(async () => {
|
|
31512
|
-
for (const leaf of leaves) {
|
|
31513
|
-
if (!leaf.parentNodeId && leaf.status === "AVAILABLE") {
|
|
31514
|
-
const res = await this.transferService.extendTimelock(leaf);
|
|
31515
|
-
await this.transferLeavesToSelf(res.nodes, {
|
|
31516
|
-
type: "leaf" /* LEAF */,
|
|
31517
|
-
path: leaf.id
|
|
31518
|
-
});
|
|
31519
|
-
}
|
|
31520
|
-
}
|
|
31521
|
-
});
|
|
31522
|
-
}
|
|
31523
31790
|
verifyKey(pubkey1, pubkey2, verifyingKey) {
|
|
31524
31791
|
return (0, import_utils25.equalBytes)(addPublicKeys(pubkey1, pubkey2), verifyingKey);
|
|
31525
31792
|
}
|
|
@@ -31629,75 +31896,84 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
31629
31896
|
}
|
|
31630
31897
|
return nodes;
|
|
31631
31898
|
}
|
|
31632
|
-
|
|
31633
|
-
const
|
|
31634
|
-
if (
|
|
31635
|
-
|
|
31636
|
-
}
|
|
31637
|
-
|
|
31638
|
-
let remainingAmount = totalAmount;
|
|
31639
|
-
let optimalLeavesLength = 0;
|
|
31640
|
-
for (let i = nextLowerPowerOfTwo; i >= 0; i--) {
|
|
31641
|
-
const denomination = 2 ** i;
|
|
31642
|
-
while (remainingAmount >= denomination) {
|
|
31643
|
-
remainingAmount -= denomination;
|
|
31644
|
-
optimalLeavesLength++;
|
|
31645
|
-
}
|
|
31899
|
+
async *optimizeLeaves(multiplicity = void 0) {
|
|
31900
|
+
const multiplicityValue = multiplicity ?? this.config.getOptimizationOptions().multiplicity ?? 0;
|
|
31901
|
+
if (multiplicityValue < 0) {
|
|
31902
|
+
throw new ValidationError("Multiplicity cannot be negative");
|
|
31903
|
+
} else if (multiplicityValue > 5) {
|
|
31904
|
+
throw new ValidationError("Multiplicity cannot be greater than 5");
|
|
31646
31905
|
}
|
|
31647
|
-
|
|
31648
|
-
|
|
31649
|
-
|
|
31650
|
-
|
|
31906
|
+
if (this.optimizationInProgress || !shouldOptimize(
|
|
31907
|
+
this.leaves.map((leaf) => leaf.value),
|
|
31908
|
+
multiplicityValue
|
|
31909
|
+
)) {
|
|
31651
31910
|
return;
|
|
31652
31911
|
}
|
|
31653
|
-
|
|
31912
|
+
const controller = new AbortController();
|
|
31913
|
+
const release = await this.leavesMutex.acquire();
|
|
31914
|
+
try {
|
|
31654
31915
|
this.optimizationInProgress = true;
|
|
31655
|
-
|
|
31656
|
-
|
|
31657
|
-
|
|
31658
|
-
|
|
31659
|
-
|
|
31660
|
-
|
|
31661
|
-
|
|
31662
|
-
|
|
31663
|
-
|
|
31664
|
-
|
|
31665
|
-
|
|
31666
|
-
|
|
31667
|
-
|
|
31668
|
-
|
|
31669
|
-
|
|
31670
|
-
|
|
31671
|
-
|
|
31672
|
-
|
|
31673
|
-
|
|
31674
|
-
|
|
31675
|
-
|
|
31676
|
-
|
|
31677
|
-
|
|
31678
|
-
|
|
31916
|
+
this.leaves = await this.getLeaves();
|
|
31917
|
+
const swaps = optimize(
|
|
31918
|
+
this.leaves.map((leaf) => leaf.value),
|
|
31919
|
+
multiplicityValue
|
|
31920
|
+
);
|
|
31921
|
+
if (swaps.length === 0) {
|
|
31922
|
+
return;
|
|
31923
|
+
}
|
|
31924
|
+
yield {
|
|
31925
|
+
step: 0,
|
|
31926
|
+
total: swaps.length,
|
|
31927
|
+
controller
|
|
31928
|
+
};
|
|
31929
|
+
const valueToNodes = /* @__PURE__ */ new Map();
|
|
31930
|
+
this.leaves.forEach((leaf) => {
|
|
31931
|
+
if (!valueToNodes.has(leaf.value)) {
|
|
31932
|
+
valueToNodes.set(leaf.value, []);
|
|
31933
|
+
}
|
|
31934
|
+
valueToNodes.get(leaf.value).push(leaf);
|
|
31935
|
+
});
|
|
31936
|
+
for (const swap of swaps) {
|
|
31937
|
+
if (controller.signal.aborted) {
|
|
31938
|
+
break;
|
|
31939
|
+
}
|
|
31940
|
+
const leavesToSend = [];
|
|
31941
|
+
for (const leafValue of swap.inLeaves) {
|
|
31942
|
+
const nodes = valueToNodes.get(leafValue);
|
|
31943
|
+
if (nodes && nodes.length > 0) {
|
|
31944
|
+
const node = nodes.shift();
|
|
31945
|
+
leavesToSend.push(node);
|
|
31946
|
+
} else {
|
|
31947
|
+
throw new InternalValidationError(
|
|
31948
|
+
`No unused leaf with value ${leafValue} found in leaves`
|
|
31949
|
+
);
|
|
31679
31950
|
}
|
|
31680
|
-
await this.requestLeavesSwap({
|
|
31681
|
-
leaves: leavesToSend,
|
|
31682
|
-
targetAmounts: swap.outLeaves
|
|
31683
|
-
});
|
|
31684
31951
|
}
|
|
31685
|
-
|
|
31686
|
-
|
|
31687
|
-
|
|
31952
|
+
await this.requestLeavesSwap({
|
|
31953
|
+
leaves: leavesToSend,
|
|
31954
|
+
targetAmounts: swap.outLeaves
|
|
31955
|
+
});
|
|
31956
|
+
yield {
|
|
31957
|
+
step: swaps.indexOf(swap) + 1,
|
|
31958
|
+
total: swaps.length,
|
|
31959
|
+
controller
|
|
31960
|
+
};
|
|
31688
31961
|
}
|
|
31689
|
-
|
|
31962
|
+
this.leaves = await this.getLeaves();
|
|
31963
|
+
} finally {
|
|
31964
|
+
this.optimizationInProgress = false;
|
|
31965
|
+
release();
|
|
31966
|
+
}
|
|
31690
31967
|
}
|
|
31691
31968
|
async syncWallet() {
|
|
31692
31969
|
await this.syncTokenOutputs();
|
|
31693
31970
|
let leaves = await this.getLeaves();
|
|
31694
|
-
leaves = await this.
|
|
31695
|
-
leaves = await this.checkExtendTimeLockNodes(leaves);
|
|
31971
|
+
leaves = await this.checkRenewLeaves(leaves);
|
|
31696
31972
|
this.leaves = leaves;
|
|
31697
|
-
this.
|
|
31698
|
-
|
|
31699
|
-
|
|
31700
|
-
}
|
|
31973
|
+
if (this.config.getOptimizationOptions().auto) {
|
|
31974
|
+
for await (const _ of this.optimizeLeaves()) {
|
|
31975
|
+
}
|
|
31976
|
+
}
|
|
31701
31977
|
}
|
|
31702
31978
|
async withLeaves(operation) {
|
|
31703
31979
|
const release = await this.leavesMutex.acquire();
|
|
@@ -32280,8 +32556,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
32280
32556
|
}
|
|
32281
32557
|
return await this.claimTransfer({
|
|
32282
32558
|
transfer: incomingTransfer,
|
|
32283
|
-
emit: false
|
|
32284
|
-
optimize: false
|
|
32559
|
+
emit: false
|
|
32285
32560
|
});
|
|
32286
32561
|
} catch (e) {
|
|
32287
32562
|
console.error("[processSwapBatch] Error details:", {
|
|
@@ -32675,16 +32950,16 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
32675
32950
|
}
|
|
32676
32951
|
);
|
|
32677
32952
|
}
|
|
32678
|
-
const tx = new
|
|
32953
|
+
const tx = new import_btc_signer5.Transaction();
|
|
32679
32954
|
tx.addInput({
|
|
32680
32955
|
txid: depositTransactionId,
|
|
32681
32956
|
index: outputIndex,
|
|
32682
32957
|
witnessScript: new Uint8Array()
|
|
32683
32958
|
});
|
|
32684
|
-
const addressDecoded = (0,
|
|
32959
|
+
const addressDecoded = (0, import_btc_signer5.Address)(getNetwork(network)).decode(
|
|
32685
32960
|
destinationAddress
|
|
32686
32961
|
);
|
|
32687
|
-
const outputScript =
|
|
32962
|
+
const outputScript = import_btc_signer5.OutScript.encode(addressDecoded);
|
|
32688
32963
|
tx.addOutput({
|
|
32689
32964
|
script: outputScript,
|
|
32690
32965
|
amount: BigInt(creditAmountSats)
|
|
@@ -32868,8 +33143,8 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
32868
33143
|
if (!output) {
|
|
32869
33144
|
continue;
|
|
32870
33145
|
}
|
|
32871
|
-
const parsedScript =
|
|
32872
|
-
const address = (0,
|
|
33146
|
+
const parsedScript = import_btc_signer5.OutScript.decode(output.script);
|
|
33147
|
+
const address = (0, import_btc_signer5.Address)(getNetwork(this.config.getNetwork())).encode(
|
|
32873
33148
|
parsedScript
|
|
32874
33149
|
);
|
|
32875
33150
|
if (staticDepositAddresses.has(address)) {
|
|
@@ -32946,26 +33221,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
32946
33221
|
depositTx,
|
|
32947
33222
|
vout
|
|
32948
33223
|
});
|
|
32949
|
-
|
|
32950
|
-
for (const node of res.nodes) {
|
|
32951
|
-
if (node.status === "AVAILABLE") {
|
|
32952
|
-
const { nodes } = await this.transferService.extendTimelock(node);
|
|
32953
|
-
for (const n of nodes) {
|
|
32954
|
-
if (n.status === "AVAILABLE") {
|
|
32955
|
-
const transfer = await this.transferLeavesToSelf([n], {
|
|
32956
|
-
type: "leaf" /* LEAF */,
|
|
32957
|
-
path: node.id
|
|
32958
|
-
});
|
|
32959
|
-
resultingNodes.push(...transfer);
|
|
32960
|
-
} else {
|
|
32961
|
-
resultingNodes.push(n);
|
|
32962
|
-
}
|
|
32963
|
-
}
|
|
32964
|
-
} else {
|
|
32965
|
-
resultingNodes.push(node);
|
|
32966
|
-
}
|
|
32967
|
-
}
|
|
32968
|
-
return resultingNodes;
|
|
33224
|
+
return res.nodes;
|
|
32969
33225
|
}
|
|
32970
33226
|
/**
|
|
32971
33227
|
* Gets all unused deposit addresses for the wallet.
|
|
@@ -33074,8 +33330,8 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33074
33330
|
if (!output) {
|
|
33075
33331
|
continue;
|
|
33076
33332
|
}
|
|
33077
|
-
const parsedScript =
|
|
33078
|
-
const address = (0,
|
|
33333
|
+
const parsedScript = import_btc_signer5.OutScript.decode(output.script);
|
|
33334
|
+
const address = (0, import_btc_signer5.Address)(getNetwork(this.config.getNetwork())).encode(
|
|
33079
33335
|
parsedScript
|
|
33080
33336
|
);
|
|
33081
33337
|
if (unusedDepositAddresses.has(address)) {
|
|
@@ -33107,6 +33363,9 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33107
33363
|
depositTx,
|
|
33108
33364
|
vout
|
|
33109
33365
|
});
|
|
33366
|
+
await this.withLeaves(async () => {
|
|
33367
|
+
this.leaves.push(...nodes2);
|
|
33368
|
+
});
|
|
33110
33369
|
return nodes2;
|
|
33111
33370
|
});
|
|
33112
33371
|
this.mutexes.delete(txid);
|
|
@@ -33135,8 +33394,8 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33135
33394
|
if (!output) {
|
|
33136
33395
|
continue;
|
|
33137
33396
|
}
|
|
33138
|
-
const parsedScript =
|
|
33139
|
-
const address = (0,
|
|
33397
|
+
const parsedScript = import_btc_signer5.OutScript.decode(output.script);
|
|
33398
|
+
const address = (0, import_btc_signer5.Address)(getNetwork(this.config.getNetwork())).encode(
|
|
33140
33399
|
parsedScript
|
|
33141
33400
|
);
|
|
33142
33401
|
const unusedDepositAddress = unusedDepositAddresses.get(address);
|
|
@@ -33283,8 +33542,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33283
33542
|
`TreeNode group at index ${groupIndex} not found for amount ${amount} after selection`
|
|
33284
33543
|
);
|
|
33285
33544
|
}
|
|
33286
|
-
|
|
33287
|
-
available = await this.checkExtendTimeLockNodes(available);
|
|
33545
|
+
const available = await this.checkRenewLeaves(group);
|
|
33288
33546
|
if (available.length < group.length) {
|
|
33289
33547
|
throw new Error(
|
|
33290
33548
|
`Not enough available nodes after refresh/extend. Expected ${group.length}, got ${available.length}`
|
|
@@ -33327,7 +33585,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33327
33585
|
transfer.id
|
|
33328
33586
|
);
|
|
33329
33587
|
if (pending) {
|
|
33330
|
-
await this.claimTransfer({ transfer: pending
|
|
33588
|
+
await this.claimTransfer({ transfer: pending });
|
|
33331
33589
|
}
|
|
33332
33590
|
}
|
|
33333
33591
|
return {
|
|
@@ -33377,75 +33635,45 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33377
33635
|
newKeyDerivation: { type: "random" /* RANDOM */ }
|
|
33378
33636
|
};
|
|
33379
33637
|
}
|
|
33380
|
-
async
|
|
33381
|
-
const
|
|
33638
|
+
async checkRenewLeaves(nodes) {
|
|
33639
|
+
const nodesToRenewNode = [];
|
|
33640
|
+
const nodesToRenewRefund = [];
|
|
33641
|
+
const nodesToRenewZeroTimelock = [];
|
|
33382
33642
|
const nodeIds = [];
|
|
33383
33643
|
const validNodes = [];
|
|
33384
33644
|
for (const node of nodes) {
|
|
33385
33645
|
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
33386
|
-
const
|
|
33387
|
-
|
|
33646
|
+
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
33647
|
+
const nodeSequence = nodeTx.getInput(0).sequence;
|
|
33648
|
+
const refundSequence = refundTx.getInput(0).sequence;
|
|
33649
|
+
if (nodeSequence === void 0) {
|
|
33388
33650
|
throw new ValidationError("Invalid node transaction", {
|
|
33389
33651
|
field: "sequence",
|
|
33390
33652
|
value: nodeTx.getInput(0),
|
|
33391
33653
|
expected: "Non-null sequence"
|
|
33392
33654
|
});
|
|
33393
33655
|
}
|
|
33394
|
-
|
|
33395
|
-
if (needsRefresh) {
|
|
33396
|
-
nodesToExtend.push(node);
|
|
33397
|
-
nodeIds.push(node.id);
|
|
33398
|
-
} else {
|
|
33399
|
-
validNodes.push(node);
|
|
33400
|
-
}
|
|
33401
|
-
}
|
|
33402
|
-
if (nodesToExtend.length === 0) {
|
|
33403
|
-
return validNodes;
|
|
33404
|
-
}
|
|
33405
|
-
const nodesToAdd = [];
|
|
33406
|
-
for (const node of nodesToExtend) {
|
|
33407
|
-
const { nodes: nodes2 } = await this.transferService.extendTimelock(node);
|
|
33408
|
-
this.leaves = this.leaves.filter((leaf) => leaf.id !== node.id);
|
|
33409
|
-
const newNodes = await this.transferLeavesToSelf(nodes2, {
|
|
33410
|
-
type: "leaf" /* LEAF */,
|
|
33411
|
-
path: node.id
|
|
33412
|
-
});
|
|
33413
|
-
nodesToAdd.push(...newNodes);
|
|
33414
|
-
}
|
|
33415
|
-
this.updateLeaves(nodeIds, nodesToAdd);
|
|
33416
|
-
validNodes.push(...nodesToAdd);
|
|
33417
|
-
return validNodes;
|
|
33418
|
-
}
|
|
33419
|
-
/**
|
|
33420
|
-
* Internal method to refresh timelock nodes.
|
|
33421
|
-
*
|
|
33422
|
-
* @param {string} nodeId - The optional ID of the node to refresh. If not provided, all nodes will be checked.
|
|
33423
|
-
* @returns {Promise<void>}
|
|
33424
|
-
* @private
|
|
33425
|
-
*/
|
|
33426
|
-
async checkRefreshTimelockNodes(nodes) {
|
|
33427
|
-
const nodesToRefresh = [];
|
|
33428
|
-
const nodeIds = [];
|
|
33429
|
-
const validNodes = [];
|
|
33430
|
-
for (const node of nodes) {
|
|
33431
|
-
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
33432
|
-
const sequence = refundTx.getInput(0).sequence;
|
|
33433
|
-
if (!sequence) {
|
|
33656
|
+
if (!refundSequence) {
|
|
33434
33657
|
throw new ValidationError("Invalid refund transaction", {
|
|
33435
33658
|
field: "sequence",
|
|
33436
33659
|
value: refundTx.getInput(0),
|
|
33437
33660
|
expected: "Non-null sequence"
|
|
33438
33661
|
});
|
|
33439
33662
|
}
|
|
33440
|
-
|
|
33441
|
-
|
|
33442
|
-
|
|
33663
|
+
if (doesTxnNeedRenewed(refundSequence)) {
|
|
33664
|
+
if (isZeroTimelock(nodeSequence)) {
|
|
33665
|
+
nodesToRenewZeroTimelock.push(node);
|
|
33666
|
+
} else if (doesTxnNeedRenewed(nodeSequence)) {
|
|
33667
|
+
nodesToRenewNode.push(node);
|
|
33668
|
+
} else {
|
|
33669
|
+
nodesToRenewRefund.push(node);
|
|
33670
|
+
}
|
|
33443
33671
|
nodeIds.push(node.id);
|
|
33444
33672
|
} else {
|
|
33445
33673
|
validNodes.push(node);
|
|
33446
33674
|
}
|
|
33447
33675
|
}
|
|
33448
|
-
if (
|
|
33676
|
+
if (nodesToRenewNode.length === 0 && nodesToRenewRefund.length === 0 && nodesToRenewZeroTimelock.length === 0) {
|
|
33449
33677
|
return validNodes;
|
|
33450
33678
|
}
|
|
33451
33679
|
const nodesResp = await this.queryNodes({
|
|
@@ -33463,7 +33691,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33463
33691
|
nodesMap.set(node.id, node);
|
|
33464
33692
|
}
|
|
33465
33693
|
const nodesToAdd = [];
|
|
33466
|
-
for (const node of
|
|
33694
|
+
for (const node of nodesToRenewNode) {
|
|
33467
33695
|
if (!node.parentNodeId) {
|
|
33468
33696
|
throw new Error(`node ${node.id} has no parent`);
|
|
33469
33697
|
}
|
|
@@ -33471,17 +33699,25 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33471
33699
|
if (!parentNode) {
|
|
33472
33700
|
throw new Error(`parent node ${node.parentNodeId} not found`);
|
|
33473
33701
|
}
|
|
33474
|
-
const
|
|
33702
|
+
const newNode = await this.transferService.renewNodeTxn(node, parentNode);
|
|
33703
|
+
nodesToAdd.push(newNode);
|
|
33704
|
+
}
|
|
33705
|
+
for (const node of nodesToRenewRefund) {
|
|
33706
|
+
if (!node.parentNodeId) {
|
|
33707
|
+
throw new Error(`node ${node.id} has no parent`);
|
|
33708
|
+
}
|
|
33709
|
+
const parentNode = nodesMap.get(node.parentNodeId);
|
|
33710
|
+
if (!parentNode) {
|
|
33711
|
+
throw new Error(`parent node ${node.parentNodeId} not found`);
|
|
33712
|
+
}
|
|
33713
|
+
const newNode = await this.transferService.renewRefundTxn(
|
|
33475
33714
|
node,
|
|
33476
33715
|
parentNode
|
|
33477
33716
|
);
|
|
33478
|
-
|
|
33479
|
-
|
|
33480
|
-
|
|
33481
|
-
const newNode =
|
|
33482
|
-
if (!newNode) {
|
|
33483
|
-
throw new Error("Failed to refresh timelock node");
|
|
33484
|
-
}
|
|
33717
|
+
nodesToAdd.push(newNode);
|
|
33718
|
+
}
|
|
33719
|
+
for (const node of nodesToRenewZeroTimelock) {
|
|
33720
|
+
const newNode = await this.transferService.renewZeroTimelockNodeTxn(node);
|
|
33485
33721
|
nodesToAdd.push(newNode);
|
|
33486
33722
|
}
|
|
33487
33723
|
this.updateLeaves(nodeIds, nodesToAdd);
|
|
@@ -33522,14 +33758,14 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33522
33758
|
return response.nodes;
|
|
33523
33759
|
});
|
|
33524
33760
|
}
|
|
33525
|
-
async processClaimedTransferResults(result, transfer, emit
|
|
33526
|
-
result = await this.
|
|
33527
|
-
result = await this.checkExtendTimeLockNodes(result);
|
|
33761
|
+
async processClaimedTransferResults(result, transfer, emit) {
|
|
33762
|
+
result = await this.checkRenewLeaves(result);
|
|
33528
33763
|
const existingIds = new Set(this.leaves.map((leaf) => leaf.id));
|
|
33529
33764
|
const uniqueResults = result.filter((node) => !existingIds.has(node.id));
|
|
33530
33765
|
this.leaves.push(...uniqueResults);
|
|
33531
|
-
if (
|
|
33532
|
-
await this.optimizeLeaves()
|
|
33766
|
+
if (this.config.getOptimizationOptions().auto && transfer.type !== 40 /* COUNTER_SWAP */) {
|
|
33767
|
+
for await (const _ of this.optimizeLeaves()) {
|
|
33768
|
+
}
|
|
33533
33769
|
}
|
|
33534
33770
|
if (emit) {
|
|
33535
33771
|
this.emit(
|
|
@@ -33548,8 +33784,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33548
33784
|
*/
|
|
33549
33785
|
async claimTransfer({
|
|
33550
33786
|
transfer,
|
|
33551
|
-
emit
|
|
33552
|
-
optimize
|
|
33787
|
+
emit
|
|
33553
33788
|
}) {
|
|
33554
33789
|
const onError = async (context) => {
|
|
33555
33790
|
const error = context.error;
|
|
@@ -33594,12 +33829,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33594
33829
|
if (result.length === 0) {
|
|
33595
33830
|
return [];
|
|
33596
33831
|
}
|
|
33597
|
-
return await this.processClaimedTransferResults(
|
|
33598
|
-
result,
|
|
33599
|
-
transfer,
|
|
33600
|
-
emit,
|
|
33601
|
-
optimize
|
|
33602
|
-
);
|
|
33832
|
+
return await this.processClaimedTransferResults(result, transfer, emit);
|
|
33603
33833
|
} catch (error) {
|
|
33604
33834
|
console.warn(
|
|
33605
33835
|
`Failed to claim transfer after all retries. Please try reinitializing your wallet in a few minutes. Transfer ID: ${transfer.id}`,
|
|
@@ -33632,7 +33862,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33632
33862
|
continue;
|
|
33633
33863
|
}
|
|
33634
33864
|
promises.push(
|
|
33635
|
-
this.claimTransfer({ transfer, emit
|
|
33865
|
+
this.claimTransfer({ transfer, emit }).then(() => transfer.id).catch((error) => {
|
|
33636
33866
|
console.warn(`Failed to claim transfer ${transfer.id}:`, error);
|
|
33637
33867
|
return null;
|
|
33638
33868
|
})
|
|
@@ -33903,8 +34133,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
33903
34133
|
selectedLeaves,
|
|
33904
34134
|
`no leaves for ${totalAmount}`
|
|
33905
34135
|
);
|
|
33906
|
-
leaves = await this.
|
|
33907
|
-
leaves = await this.checkExtendTimeLockNodes(leaves);
|
|
34136
|
+
leaves = await this.checkRenewLeaves(leaves);
|
|
33908
34137
|
const leavesToSend = await Promise.all(
|
|
33909
34138
|
leaves.map(async (leaf) => ({
|
|
33910
34139
|
leaf,
|
|
@@ -34235,10 +34464,8 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
34235
34464
|
leavesToSendToSsp = leavesForTargetAmount;
|
|
34236
34465
|
leavesToSendToSE = leavesForFee;
|
|
34237
34466
|
}
|
|
34238
|
-
leavesToSendToSsp = await this.
|
|
34239
|
-
|
|
34240
|
-
leavesToSendToSE = await this.checkRefreshTimelockNodes(leavesToSendToSE);
|
|
34241
|
-
leavesToSendToSE = await this.checkExtendTimeLockNodes(leavesToSendToSE);
|
|
34467
|
+
leavesToSendToSsp = await this.checkRenewLeaves(leavesToSendToSsp);
|
|
34468
|
+
leavesToSendToSE = await this.checkRenewLeaves(leavesToSendToSE);
|
|
34242
34469
|
const leafKeyTweaks = await Promise.all(
|
|
34243
34470
|
[...leavesToSendToSE, ...leavesToSendToSsp].map(async (leaf) => ({
|
|
34244
34471
|
leaf,
|
|
@@ -34324,8 +34551,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
34324
34551
|
(await this.selectLeaves([amountSats])).get(amountSats),
|
|
34325
34552
|
`no leaves for ${amountSats}`
|
|
34326
34553
|
);
|
|
34327
|
-
leaves = await this.
|
|
34328
|
-
leaves = await this.checkExtendTimeLockNodes(leaves);
|
|
34554
|
+
leaves = await this.checkRenewLeaves(leaves);
|
|
34329
34555
|
const feeEstimate = await sspClient.getCoopExitFeeQuote({
|
|
34330
34556
|
leafExternalIds: leaves.map((leaf) => leaf.id),
|
|
34331
34557
|
withdrawalAddress
|
|
@@ -34613,7 +34839,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
34613
34839
|
*/
|
|
34614
34840
|
async signTransaction(txHex, keyType = "auto-detect") {
|
|
34615
34841
|
try {
|
|
34616
|
-
const tx =
|
|
34842
|
+
const tx = import_btc_signer5.Transaction.fromRaw((0, import_utils25.hexToBytes)(txHex));
|
|
34617
34843
|
let publicKey;
|
|
34618
34844
|
switch (keyType.toLowerCase()) {
|
|
34619
34845
|
case "identity":
|
|
@@ -34820,15 +35046,6 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
34820
35046
|
}
|
|
34821
35047
|
);
|
|
34822
35048
|
}
|
|
34823
|
-
if (!nodeInput.sequence) {
|
|
34824
|
-
throw new ValidationError(
|
|
34825
|
-
`Node transaction has no sequence for ${isRootNode ? "root" : "non-root"} node`,
|
|
34826
|
-
{
|
|
34827
|
-
field: "sequence",
|
|
34828
|
-
value: nodeInput.sequence
|
|
34829
|
-
}
|
|
34830
|
-
);
|
|
34831
|
-
}
|
|
34832
35049
|
const refundInput = refundTx.getInput(0);
|
|
34833
35050
|
if (!refundInput) {
|
|
34834
35051
|
throw new ValidationError(
|
|
@@ -34864,89 +35081,6 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
34864
35081
|
);
|
|
34865
35082
|
}
|
|
34866
35083
|
}
|
|
34867
|
-
/**
|
|
34868
|
-
* Refresh the timelock of a specific node.
|
|
34869
|
-
*
|
|
34870
|
-
* @param {string} nodeId - The ID of the node to refresh
|
|
34871
|
-
* @returns {Promise<void>} Promise that resolves when the timelock is refreshed
|
|
34872
|
-
*/
|
|
34873
|
-
async testOnly_expireTimelock(nodeId) {
|
|
34874
|
-
const sparkClient = await this.connectionManager.createSparkClient(
|
|
34875
|
-
this.config.getCoordinatorAddress()
|
|
34876
|
-
);
|
|
34877
|
-
try {
|
|
34878
|
-
const response = await sparkClient.query_nodes({
|
|
34879
|
-
source: {
|
|
34880
|
-
$case: "nodeIds",
|
|
34881
|
-
nodeIds: {
|
|
34882
|
-
nodeIds: [nodeId]
|
|
34883
|
-
}
|
|
34884
|
-
},
|
|
34885
|
-
includeParents: true
|
|
34886
|
-
});
|
|
34887
|
-
let leaf = response.nodes[nodeId];
|
|
34888
|
-
if (!leaf) {
|
|
34889
|
-
throw new ValidationError("Node not found", {
|
|
34890
|
-
field: "nodeId",
|
|
34891
|
-
value: nodeId
|
|
34892
|
-
});
|
|
34893
|
-
}
|
|
34894
|
-
let parentNode;
|
|
34895
|
-
let hasParentNode = false;
|
|
34896
|
-
if (!leaf.parentNodeId) {
|
|
34897
|
-
} else {
|
|
34898
|
-
hasParentNode = true;
|
|
34899
|
-
parentNode = response.nodes[leaf.parentNodeId];
|
|
34900
|
-
if (!parentNode) {
|
|
34901
|
-
throw new ValidationError("Parent node not found", {
|
|
34902
|
-
field: "parentNodeId",
|
|
34903
|
-
value: leaf.parentNodeId
|
|
34904
|
-
});
|
|
34905
|
-
}
|
|
34906
|
-
}
|
|
34907
|
-
const nodeTx = getTxFromRawTxBytes(leaf.nodeTx);
|
|
34908
|
-
const refundTx = getTxFromRawTxBytes(leaf.refundTx);
|
|
34909
|
-
if (hasParentNode) {
|
|
34910
|
-
const nodeTimelock = getCurrentTimelock(nodeTx.getInput(0).sequence);
|
|
34911
|
-
if (nodeTimelock > 100) {
|
|
34912
|
-
const expiredNodeTxLeaf = await this.transferService.testonly_expireTimeLockNodeTx(
|
|
34913
|
-
leaf,
|
|
34914
|
-
parentNode
|
|
34915
|
-
);
|
|
34916
|
-
if (!expiredNodeTxLeaf.nodes[0]) {
|
|
34917
|
-
throw new ValidationError("No expired node tx leaf", {
|
|
34918
|
-
field: "expiredNodeTxLeaf",
|
|
34919
|
-
value: expiredNodeTxLeaf
|
|
34920
|
-
});
|
|
34921
|
-
}
|
|
34922
|
-
leaf = expiredNodeTxLeaf.nodes[0];
|
|
34923
|
-
}
|
|
34924
|
-
}
|
|
34925
|
-
const refundTimelock = getCurrentTimelock(refundTx.getInput(0).sequence);
|
|
34926
|
-
if (refundTimelock > 100) {
|
|
34927
|
-
const expiredTxLeaf = await this.transferService.testonly_expireTimeLockRefundtx(leaf);
|
|
34928
|
-
if (!expiredTxLeaf.nodes[0]) {
|
|
34929
|
-
throw new ValidationError("No expired tx leaf", {
|
|
34930
|
-
field: "expiredTxLeaf",
|
|
34931
|
-
value: expiredTxLeaf
|
|
34932
|
-
});
|
|
34933
|
-
}
|
|
34934
|
-
leaf = expiredTxLeaf.nodes[0];
|
|
34935
|
-
}
|
|
34936
|
-
const leafIndex = this.leaves.findIndex((leaf2) => leaf2.id === leaf2.id);
|
|
34937
|
-
if (leafIndex !== -1) {
|
|
34938
|
-
this.leaves[leafIndex] = leaf;
|
|
34939
|
-
}
|
|
34940
|
-
} catch (error) {
|
|
34941
|
-
throw new NetworkError(
|
|
34942
|
-
"Failed to refresh timelock",
|
|
34943
|
-
{
|
|
34944
|
-
method: "refresh_timelock"
|
|
34945
|
-
},
|
|
34946
|
-
error
|
|
34947
|
-
);
|
|
34948
|
-
}
|
|
34949
|
-
}
|
|
34950
35084
|
cleanup() {
|
|
34951
35085
|
if (this.claimTransfersInterval) {
|
|
34952
35086
|
clearInterval(this.claimTransfersInterval);
|
|
@@ -35101,8 +35235,7 @@ var SparkWallet = class extends import_eventemitter3.EventEmitter {
|
|
|
35101
35235
|
"getLightningReceiveRequest",
|
|
35102
35236
|
"getLightningSendRequest",
|
|
35103
35237
|
"getCoopExitRequest",
|
|
35104
|
-
"checkTimelock"
|
|
35105
|
-
"testOnly_expireTimelock"
|
|
35238
|
+
"checkTimelock"
|
|
35106
35239
|
];
|
|
35107
35240
|
methods.forEach((m) => this.wrapPublicSparkWalletMethodWithOtelSpan(m));
|
|
35108
35241
|
this.initWallet = this.wrapWithOtelSpan(
|
|
@@ -36070,7 +36203,6 @@ setCrypto(globalThis.crypto);
|
|
|
36070
36203
|
DIRECT_TIMELOCK_OFFSET,
|
|
36071
36204
|
DefaultSparkSigner,
|
|
36072
36205
|
HTLC_TIMELOCK_OFFSET,
|
|
36073
|
-
INITIAL_DIRECT_SEQUENCE,
|
|
36074
36206
|
INITIAL_SEQUENCE,
|
|
36075
36207
|
InternalValidationError,
|
|
36076
36208
|
LOGGER_NAMES,
|
|
@@ -36080,12 +36212,14 @@ setCrypto(globalThis.crypto);
|
|
|
36080
36212
|
NotImplementedError,
|
|
36081
36213
|
RPCError,
|
|
36082
36214
|
ReactNativeSparkSigner,
|
|
36215
|
+
ReactNativeTaprootSparkSigner,
|
|
36083
36216
|
SparkSDKError,
|
|
36084
36217
|
SparkSdkLogger,
|
|
36085
36218
|
SparkWallet,
|
|
36086
36219
|
SparkWalletEvent,
|
|
36087
36220
|
TEST_UNILATERAL_DIRECT_SEQUENCE,
|
|
36088
36221
|
TEST_UNILATERAL_SEQUENCE,
|
|
36222
|
+
TaprootSparkSigner,
|
|
36089
36223
|
TokenTransactionService,
|
|
36090
36224
|
ValidationError,
|
|
36091
36225
|
WalletConfig,
|
|
@@ -36104,21 +36238,24 @@ setCrypto(globalThis.crypto);
|
|
|
36104
36238
|
constructFeeBumpTx,
|
|
36105
36239
|
constructUnilateralExitFeeBumpPackages,
|
|
36106
36240
|
constructUnilateralExitTxs,
|
|
36107
|
-
|
|
36108
|
-
|
|
36109
|
-
|
|
36110
|
-
|
|
36111
|
-
|
|
36112
|
-
|
|
36113
|
-
|
|
36241
|
+
createConnectorRefundTxs,
|
|
36242
|
+
createCurrentTimelockRefundTxs,
|
|
36243
|
+
createDecrementedTimelockNodeTx,
|
|
36244
|
+
createDecrementedTimelockRefundTxs,
|
|
36245
|
+
createInitialTimelockNodeTx,
|
|
36246
|
+
createInitialTimelockRefundTxs,
|
|
36247
|
+
createRootNodeTx,
|
|
36114
36248
|
createSigningCommitment,
|
|
36115
36249
|
createSigningNonce,
|
|
36116
|
-
|
|
36250
|
+
createTestUnilateralRefundTxs,
|
|
36251
|
+
createTestUnilateralTimelockNodeTx,
|
|
36252
|
+
createZeroTimelockNodeTx,
|
|
36117
36253
|
decodeBech32mTokenIdentifier,
|
|
36118
36254
|
decodeBytesToSigningCommitment,
|
|
36119
36255
|
decodeBytesToSigningNonce,
|
|
36120
36256
|
decodeSparkAddress,
|
|
36121
36257
|
doesLeafNeedRefresh,
|
|
36258
|
+
doesTxnNeedRenewed,
|
|
36122
36259
|
encodeBech32mTokenIdentifier,
|
|
36123
36260
|
encodeSigningCommitmentToBytes,
|
|
36124
36261
|
encodeSigningNonceToBytes,
|
|
@@ -36156,12 +36293,14 @@ setCrypto(globalThis.crypto);
|
|
|
36156
36293
|
getTxFromRawTxHex,
|
|
36157
36294
|
getTxId,
|
|
36158
36295
|
getTxIdNoReverse,
|
|
36296
|
+
hash160,
|
|
36159
36297
|
isEphemeralAnchorOutput,
|
|
36160
36298
|
isLegacySparkAddress,
|
|
36161
36299
|
isSafeForNumber,
|
|
36162
36300
|
isTxBroadcast,
|
|
36163
36301
|
isValidPublicKey,
|
|
36164
36302
|
isValidSparkAddress,
|
|
36303
|
+
isZeroTimelock,
|
|
36165
36304
|
lastKeyWithTarget,
|
|
36166
36305
|
maybeApplyFee,
|
|
36167
36306
|
modInverse,
|