@buildonspark/spark-sdk 0.2.2 → 0.2.4
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 +15 -0
- package/dist/{chunk-TM6CHQXC.js → chunk-3SEOTO43.js} +1 -1
- package/dist/{chunk-2ENZX6LT.js → chunk-AAZWSPUK.js} +84 -8
- package/dist/{chunk-4JD4HIAN.js → chunk-G4MSZ6DE.js} +299 -1
- package/dist/{chunk-S2AL73MZ.js → chunk-TVUMSHWA.js} +1 -1
- package/dist/{chunk-2TUM3R6C.js → chunk-W4ZRBSWM.js} +2351 -797
- package/dist/{chunk-CDLETEDT.js → chunk-WAQKYSDI.js} +13 -1
- package/dist/{client-CGTRS23n.d.ts → client-BF4cn8F4.d.ts} +15 -3
- package/dist/{client-CcYzmpmj.d.cts → client-KhNkrXz4.d.cts} +15 -3
- package/dist/debug.cjs +2948 -1023
- package/dist/debug.d.cts +19 -6
- package/dist/debug.d.ts +19 -6
- package/dist/debug.js +5 -5
- package/dist/graphql/objects/index.cjs +13 -1
- package/dist/graphql/objects/index.d.cts +2 -2
- package/dist/graphql/objects/index.d.ts +2 -2
- package/dist/graphql/objects/index.js +1 -1
- package/dist/index.cjs +2794 -858
- package/dist/index.d.cts +190 -9
- package/dist/index.d.ts +190 -9
- package/dist/index.js +32 -6
- package/dist/index.node.cjs +2931 -892
- package/dist/index.node.d.cts +10 -188
- package/dist/index.node.d.ts +10 -188
- package/dist/index.node.js +134 -6
- package/dist/native/index.cjs +2794 -858
- package/dist/native/index.d.cts +148 -40
- package/dist/native/index.d.ts +148 -40
- package/dist/native/index.js +2799 -877
- package/dist/proto/lrc20.d.cts +1 -1
- package/dist/proto/lrc20.d.ts +1 -1
- package/dist/proto/lrc20.js +1 -1
- package/dist/proto/spark.cjs +84 -8
- package/dist/proto/spark.d.cts +1 -1
- package/dist/proto/spark.d.ts +1 -1
- package/dist/proto/spark.js +1 -1
- package/dist/proto/spark_token.cjs +301 -0
- package/dist/proto/spark_token.d.cts +35 -2
- package/dist/proto/spark_token.d.ts +35 -2
- package/dist/proto/spark_token.js +8 -2
- package/dist/{sdk-types-DJ2ve9YY.d.cts → sdk-types-CB9HrW5O.d.cts} +1 -1
- package/dist/{sdk-types-DCIVdKUT.d.ts → sdk-types-CkRNraXT.d.ts} +1 -1
- package/dist/{spark-BUOx3U7Q.d.cts → spark-B_7nZx6T.d.cts} +112 -10
- package/dist/{spark-BUOx3U7Q.d.ts → spark-B_7nZx6T.d.ts} +112 -10
- package/dist/{spark-wallet-B_96y9BS.d.ts → spark-wallet-C1Tr_VKI.d.ts} +38 -28
- package/dist/{spark-wallet-CHwKQYJu.d.cts → spark-wallet-DG3x2obf.d.cts} +38 -28
- package/dist/spark-wallet.node-CGxoeCpH.d.ts +13 -0
- package/dist/spark-wallet.node-CN9LoB_O.d.cts +13 -0
- package/dist/tests/test-utils.cjs +1086 -218
- package/dist/tests/test-utils.d.cts +13 -13
- package/dist/tests/test-utils.d.ts +13 -13
- package/dist/tests/test-utils.js +56 -19
- package/dist/types/index.cjs +97 -9
- package/dist/types/index.d.cts +3 -3
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.js +3 -3
- package/dist/{xchain-address-D5MIHCDL.d.cts → xchain-address-BHu6CpZC.d.ts} +55 -8
- package/dist/{xchain-address-DLbW1iDh.d.ts → xchain-address-HBr6isnc.d.cts} +55 -8
- package/package.json +1 -1
- package/src/graphql/client.ts +8 -0
- package/src/graphql/mutations/CompleteLeavesSwap.ts +9 -1
- package/src/graphql/mutations/RequestSwapLeaves.ts +4 -0
- package/src/graphql/objects/CompleteLeavesSwapInput.ts +34 -34
- package/src/graphql/objects/LeavesSwapRequest.ts +4 -0
- package/src/graphql/objects/RequestLeavesSwapInput.ts +48 -47
- package/src/graphql/objects/SwapLeaf.ts +40 -32
- package/src/graphql/objects/UserLeafInput.ts +24 -0
- package/src/graphql/objects/UserRequest.ts +4 -0
- package/src/index.node.ts +1 -1
- package/src/native/index.ts +4 -5
- package/src/proto/spark.ts +172 -16
- package/src/proto/spark_token.ts +369 -0
- package/src/services/coop-exit.ts +171 -36
- package/src/services/deposit.ts +471 -74
- package/src/services/lightning.ts +18 -5
- package/src/services/signing.ts +162 -50
- package/src/services/token-transactions.ts +6 -2
- package/src/services/transfer.ts +950 -384
- package/src/services/tree-creation.ts +342 -121
- package/src/spark-wallet/spark-wallet.node.ts +71 -66
- package/src/spark-wallet/spark-wallet.ts +459 -166
- package/src/tests/integration/coop-exit.test.ts +3 -8
- package/src/tests/integration/deposit.test.ts +3 -3
- package/src/tests/integration/lightning.test.ts +521 -466
- package/src/tests/integration/swap.test.ts +559 -307
- package/src/tests/integration/transfer.test.ts +625 -623
- package/src/tests/integration/wallet.test.ts +2 -2
- package/src/tests/integration/watchtower.test.ts +211 -0
- package/src/tests/test-utils.ts +63 -14
- package/src/tests/utils/test-faucet.ts +4 -2
- package/src/utils/adaptor-signature.ts +15 -5
- package/src/utils/fetch.ts +75 -0
- package/src/utils/mempool.ts +9 -4
- package/src/utils/transaction.ts +388 -26
package/dist/native/index.js
CHANGED
|
@@ -14336,14 +14336,6 @@ var SparkServiceDefinition = {
|
|
|
14336
14336
|
responseStream: false,
|
|
14337
14337
|
options: {}
|
|
14338
14338
|
},
|
|
14339
|
-
create_tree_v2: {
|
|
14340
|
-
name: "create_tree_v2",
|
|
14341
|
-
requestType: CreateTreeRequest,
|
|
14342
|
-
requestStream: false,
|
|
14343
|
-
responseType: CreateTreeResponse,
|
|
14344
|
-
responseStream: false,
|
|
14345
|
-
options: {}
|
|
14346
|
-
},
|
|
14347
14339
|
get_signing_operator_list: {
|
|
14348
14340
|
name: "get_signing_operator_list",
|
|
14349
14341
|
requestType: Empty,
|
|
@@ -14510,6 +14502,90 @@ var SparkServiceDefinition = {
|
|
|
14510
14502
|
responseType: ExitSingleNodeTreesResponse,
|
|
14511
14503
|
responseStream: false,
|
|
14512
14504
|
options: {}
|
|
14505
|
+
},
|
|
14506
|
+
/**
|
|
14507
|
+
* The following endpoints enforce inclusion of Direct Transactions used
|
|
14508
|
+
* for unilateral exits
|
|
14509
|
+
*/
|
|
14510
|
+
create_tree_v2: {
|
|
14511
|
+
name: "create_tree_v2",
|
|
14512
|
+
requestType: CreateTreeRequest,
|
|
14513
|
+
requestStream: false,
|
|
14514
|
+
responseType: CreateTreeResponse,
|
|
14515
|
+
responseStream: false,
|
|
14516
|
+
options: {}
|
|
14517
|
+
},
|
|
14518
|
+
cooperative_exit_v2: {
|
|
14519
|
+
name: "cooperative_exit_v2",
|
|
14520
|
+
requestType: CooperativeExitRequest,
|
|
14521
|
+
requestStream: false,
|
|
14522
|
+
responseType: CooperativeExitResponse,
|
|
14523
|
+
responseStream: false,
|
|
14524
|
+
options: {}
|
|
14525
|
+
},
|
|
14526
|
+
extend_leaf_v2: {
|
|
14527
|
+
name: "extend_leaf_v2",
|
|
14528
|
+
requestType: ExtendLeafRequest,
|
|
14529
|
+
requestStream: false,
|
|
14530
|
+
responseType: ExtendLeafResponse,
|
|
14531
|
+
responseStream: false,
|
|
14532
|
+
options: {}
|
|
14533
|
+
},
|
|
14534
|
+
claim_transfer_sign_refunds_v2: {
|
|
14535
|
+
name: "claim_transfer_sign_refunds_v2",
|
|
14536
|
+
requestType: ClaimTransferSignRefundsRequest,
|
|
14537
|
+
requestStream: false,
|
|
14538
|
+
responseType: ClaimTransferSignRefundsResponse,
|
|
14539
|
+
responseStream: false,
|
|
14540
|
+
options: {}
|
|
14541
|
+
},
|
|
14542
|
+
finalize_node_signatures_v2: {
|
|
14543
|
+
name: "finalize_node_signatures_v2",
|
|
14544
|
+
requestType: FinalizeNodeSignaturesRequest,
|
|
14545
|
+
requestStream: false,
|
|
14546
|
+
responseType: FinalizeNodeSignaturesResponse,
|
|
14547
|
+
responseStream: false,
|
|
14548
|
+
options: {}
|
|
14549
|
+
},
|
|
14550
|
+
initiate_preimage_swap_v2: {
|
|
14551
|
+
name: "initiate_preimage_swap_v2",
|
|
14552
|
+
requestType: InitiatePreimageSwapRequest,
|
|
14553
|
+
requestStream: false,
|
|
14554
|
+
responseType: InitiatePreimageSwapResponse,
|
|
14555
|
+
responseStream: false,
|
|
14556
|
+
options: {}
|
|
14557
|
+
},
|
|
14558
|
+
start_leaf_swap_v2: {
|
|
14559
|
+
name: "start_leaf_swap_v2",
|
|
14560
|
+
requestType: StartTransferRequest,
|
|
14561
|
+
requestStream: false,
|
|
14562
|
+
responseType: StartTransferResponse,
|
|
14563
|
+
responseStream: false,
|
|
14564
|
+
options: {}
|
|
14565
|
+
},
|
|
14566
|
+
counter_leaf_swap_v2: {
|
|
14567
|
+
name: "counter_leaf_swap_v2",
|
|
14568
|
+
requestType: CounterLeafSwapRequest,
|
|
14569
|
+
requestStream: false,
|
|
14570
|
+
responseType: CounterLeafSwapResponse,
|
|
14571
|
+
responseStream: false,
|
|
14572
|
+
options: {}
|
|
14573
|
+
},
|
|
14574
|
+
start_transfer_v2: {
|
|
14575
|
+
name: "start_transfer_v2",
|
|
14576
|
+
requestType: StartTransferRequest,
|
|
14577
|
+
requestStream: false,
|
|
14578
|
+
responseType: StartTransferResponse,
|
|
14579
|
+
responseStream: false,
|
|
14580
|
+
options: {}
|
|
14581
|
+
},
|
|
14582
|
+
refresh_timelock_v2: {
|
|
14583
|
+
name: "refresh_timelock_v2",
|
|
14584
|
+
requestType: RefreshTimelockRequest,
|
|
14585
|
+
requestStream: false,
|
|
14586
|
+
responseType: RefreshTimelockResponse,
|
|
14587
|
+
responseStream: false,
|
|
14588
|
+
options: {}
|
|
14513
14589
|
}
|
|
14514
14590
|
}
|
|
14515
14591
|
};
|
|
@@ -14732,13 +14808,24 @@ function applyAdaptorToSignature(pubkey, hash, signature, adaptorPrivateKeyBytes
|
|
|
14732
14808
|
const adaptorPrivateKey = bytesToNumberBE2(adaptorPrivateKeyBytes);
|
|
14733
14809
|
const newS = mod(sBigInt + adaptorPrivateKey, secp256k12.CURVE.n);
|
|
14734
14810
|
const newSig = new Uint8Array([...r, ...numberToBytesBE(newS, 32)]);
|
|
14735
|
-
|
|
14736
|
-
|
|
14811
|
+
try {
|
|
14812
|
+
if (schnorr.verify(newSig, hash, pubkey)) {
|
|
14813
|
+
return newSig;
|
|
14814
|
+
}
|
|
14815
|
+
} catch (e) {
|
|
14816
|
+
console.error("[applyAdaptorToSignature] Addition verification failed:", e);
|
|
14737
14817
|
}
|
|
14738
14818
|
const altS = mod(sBigInt - adaptorPrivateKey, secp256k12.CURVE.n);
|
|
14739
14819
|
const altSig = new Uint8Array([...r, ...numberToBytesBE(altS, 32)]);
|
|
14740
|
-
|
|
14741
|
-
|
|
14820
|
+
try {
|
|
14821
|
+
if (schnorr.verify(altSig, hash, pubkey)) {
|
|
14822
|
+
return altSig;
|
|
14823
|
+
}
|
|
14824
|
+
} catch (e) {
|
|
14825
|
+
console.error(
|
|
14826
|
+
"[applyAdaptorToSignature] Subtraction verification failed:",
|
|
14827
|
+
e
|
|
14828
|
+
);
|
|
14742
14829
|
}
|
|
14743
14830
|
throw new Error("Cannot apply adaptor to signature");
|
|
14744
14831
|
}
|
|
@@ -15605,7 +15692,11 @@ var SwapLeafFromJson = (obj) => {
|
|
|
15605
15692
|
return {
|
|
15606
15693
|
leafId: obj["swap_leaf_leaf_id"],
|
|
15607
15694
|
rawUnsignedRefundTransaction: obj["swap_leaf_raw_unsigned_refund_transaction"],
|
|
15608
|
-
adaptorSignedSignature: obj["swap_leaf_adaptor_signed_signature"]
|
|
15695
|
+
adaptorSignedSignature: obj["swap_leaf_adaptor_signed_signature"],
|
|
15696
|
+
directRawUnsignedRefundTransaction: obj["swap_leaf_direct_raw_unsigned_refund_transaction"],
|
|
15697
|
+
directAdaptorSignedSignature: obj["swap_leaf_direct_adaptor_signed_signature"],
|
|
15698
|
+
directFromCpfpRawUnsignedRefundTransaction: obj["swap_leaf_direct_from_cpfp_raw_unsigned_refund_transaction"],
|
|
15699
|
+
directFromCpfpAdaptorSignedSignature: obj["swap_leaf_direct_from_cpfp_adaptor_signed_signature"]
|
|
15609
15700
|
};
|
|
15610
15701
|
};
|
|
15611
15702
|
|
|
@@ -15851,6 +15942,10 @@ fragment LeavesSwapRequestFragment on LeavesSwapRequest {
|
|
|
15851
15942
|
swap_leaf_leaf_id: leaf_id
|
|
15852
15943
|
swap_leaf_raw_unsigned_refund_transaction: raw_unsigned_refund_transaction
|
|
15853
15944
|
swap_leaf_adaptor_signed_signature: adaptor_signed_signature
|
|
15945
|
+
swap_leaf_direct_raw_unsigned_refund_transaction: direct_raw_unsigned_refund_transaction
|
|
15946
|
+
swap_leaf_direct_adaptor_signed_signature: direct_adaptor_signed_signature
|
|
15947
|
+
swap_leaf_direct_from_cpfp_raw_unsigned_refund_transaction: direct_from_cpfp_raw_unsigned_refund_transaction
|
|
15948
|
+
swap_leaf_direct_from_cpfp_adaptor_signed_signature: direct_from_cpfp_adaptor_signed_signature
|
|
15854
15949
|
}
|
|
15855
15950
|
}`;
|
|
15856
15951
|
|
|
@@ -16180,6 +16275,10 @@ fragment UserRequestFragment on UserRequest {
|
|
|
16180
16275
|
swap_leaf_leaf_id: leaf_id
|
|
16181
16276
|
swap_leaf_raw_unsigned_refund_transaction: raw_unsigned_refund_transaction
|
|
16182
16277
|
swap_leaf_adaptor_signed_signature: adaptor_signed_signature
|
|
16278
|
+
swap_leaf_direct_raw_unsigned_refund_transaction: direct_raw_unsigned_refund_transaction
|
|
16279
|
+
swap_leaf_direct_adaptor_signed_signature: direct_adaptor_signed_signature
|
|
16280
|
+
swap_leaf_direct_from_cpfp_raw_unsigned_refund_transaction: direct_from_cpfp_raw_unsigned_refund_transaction
|
|
16281
|
+
swap_leaf_direct_from_cpfp_adaptor_signed_signature: direct_from_cpfp_adaptor_signed_signature
|
|
16183
16282
|
}
|
|
16184
16283
|
}
|
|
16185
16284
|
... on LightningReceiveRequest {
|
|
@@ -16304,18 +16403,39 @@ function mapTransferToWalletTransfer(proto, identityPublicKey) {
|
|
|
16304
16403
|
};
|
|
16305
16404
|
}
|
|
16306
16405
|
|
|
16406
|
+
// src/utils/fetch.ts
|
|
16407
|
+
var fetchImpl = typeof window !== "undefined" && window.fetch ? window.fetch.bind(window) : globalThis.fetch ? globalThis.fetch : null;
|
|
16408
|
+
var Headers = globalThis.Headers ?? null;
|
|
16409
|
+
var getFetch = () => {
|
|
16410
|
+
if (!fetchImpl) {
|
|
16411
|
+
throw new Error(
|
|
16412
|
+
"Fetch implementation is not set. Please set it using setFetch()."
|
|
16413
|
+
);
|
|
16414
|
+
}
|
|
16415
|
+
if (!Headers) {
|
|
16416
|
+
throw new Error(
|
|
16417
|
+
"Headers implementation is not set. Please set it using setFetch()."
|
|
16418
|
+
);
|
|
16419
|
+
}
|
|
16420
|
+
return {
|
|
16421
|
+
fetch: fetchImpl,
|
|
16422
|
+
Headers
|
|
16423
|
+
};
|
|
16424
|
+
};
|
|
16425
|
+
|
|
16307
16426
|
// src/utils/mempool.ts
|
|
16308
16427
|
async function getLatestDepositTxId(address2) {
|
|
16428
|
+
const { fetch: fetch2, Headers: Headers2 } = getFetch();
|
|
16309
16429
|
const network = getNetworkFromAddress(address2);
|
|
16310
16430
|
const baseUrl = network === BitcoinNetwork_default.REGTEST ? getElectrsUrl("REGTEST") : getElectrsUrl("MAINNET");
|
|
16311
|
-
const headers =
|
|
16431
|
+
const headers = new Headers2();
|
|
16312
16432
|
if (network === BitcoinNetwork_default.REGTEST) {
|
|
16313
16433
|
const auth = btoa(
|
|
16314
16434
|
`${ELECTRS_CREDENTIALS.username}:${ELECTRS_CREDENTIALS.password}`
|
|
16315
16435
|
);
|
|
16316
|
-
headers
|
|
16436
|
+
headers.set("Authorization", `Basic ${auth}`);
|
|
16317
16437
|
}
|
|
16318
|
-
const response = await
|
|
16438
|
+
const response = await fetch2(`${baseUrl}/address/${address2}/txs`, {
|
|
16319
16439
|
headers
|
|
16320
16440
|
});
|
|
16321
16441
|
const addressTxs = await response.json();
|
|
@@ -16332,14 +16452,15 @@ async function getLatestDepositTxId(address2) {
|
|
|
16332
16452
|
return null;
|
|
16333
16453
|
}
|
|
16334
16454
|
async function isTxBroadcast(txid, baseUrl, network) {
|
|
16335
|
-
const
|
|
16455
|
+
const { fetch: fetch2, Headers: Headers2 } = getFetch();
|
|
16456
|
+
const headers = new Headers2();
|
|
16336
16457
|
if (network === 3 /* REGTEST */) {
|
|
16337
16458
|
const auth = btoa(
|
|
16338
16459
|
`${ELECTRS_CREDENTIALS.username}:${ELECTRS_CREDENTIALS.password}`
|
|
16339
16460
|
);
|
|
16340
|
-
headers
|
|
16461
|
+
headers.set("Authorization", `Basic ${auth}`);
|
|
16341
16462
|
}
|
|
16342
|
-
const response = await
|
|
16463
|
+
const response = await fetch2(`${baseUrl}/tx/${txid}`, {
|
|
16343
16464
|
headers
|
|
16344
16465
|
});
|
|
16345
16466
|
const tx = await response.json();
|
|
@@ -16802,7 +16923,14 @@ function getTransferPackageSigningPayload(transferID, transferPackage) {
|
|
|
16802
16923
|
|
|
16803
16924
|
// src/utils/transaction.ts
|
|
16804
16925
|
import { Transaction as Transaction2 } from "@scure/btc-signer";
|
|
16926
|
+
var INITIAL_TIMELOCK = 2e3;
|
|
16927
|
+
var TEST_UNILATERAL_TIMELOCK = 100;
|
|
16805
16928
|
var TIME_LOCK_INTERVAL = 100;
|
|
16929
|
+
var DIRECT_TIMELOCK_OFFSET = 50;
|
|
16930
|
+
var INITIAL_SEQUENCE = 1 << 30 | INITIAL_TIMELOCK;
|
|
16931
|
+
var INITIAL_DIRECT_SEQUENCE = 1 << 30 | INITIAL_TIMELOCK + DIRECT_TIMELOCK_OFFSET;
|
|
16932
|
+
var TEST_UNILATERAL_SEQUENCE = 1 << 30 | TEST_UNILATERAL_TIMELOCK;
|
|
16933
|
+
var TEST_UNILATERAL_DIRECT_SEQUENCE = 1 << 30 | TEST_UNILATERAL_TIMELOCK + DIRECT_TIMELOCK_OFFSET;
|
|
16806
16934
|
var ESTIMATED_TX_SIZE = 191;
|
|
16807
16935
|
var DEFAULT_SATS_PER_VBYTE = 5;
|
|
16808
16936
|
var DEFAULT_FEE_SATS = ESTIMATED_TX_SIZE * DEFAULT_SATS_PER_VBYTE;
|
|
@@ -16812,29 +16940,270 @@ function maybeApplyFee(amount) {
|
|
|
16812
16940
|
}
|
|
16813
16941
|
return amount;
|
|
16814
16942
|
}
|
|
16815
|
-
function
|
|
16816
|
-
const
|
|
16943
|
+
function createRootTx(depositOutPoint, depositTxOut) {
|
|
16944
|
+
const cpfpRootTx = new Transaction2({
|
|
16945
|
+
version: 3,
|
|
16946
|
+
allowUnknownOutputs: true
|
|
16947
|
+
});
|
|
16948
|
+
cpfpRootTx.addInput(depositOutPoint);
|
|
16949
|
+
cpfpRootTx.addOutput(depositTxOut);
|
|
16950
|
+
cpfpRootTx.addOutput(getEphemeralAnchorOutput());
|
|
16951
|
+
const directRootTx = new Transaction2({
|
|
16952
|
+
version: 3,
|
|
16953
|
+
allowUnknownOutputs: true
|
|
16954
|
+
});
|
|
16955
|
+
directRootTx.addInput(depositOutPoint);
|
|
16956
|
+
directRootTx.addOutput({
|
|
16957
|
+
script: depositTxOut.script,
|
|
16958
|
+
amount: maybeApplyFee(depositTxOut.amount ?? 0n)
|
|
16959
|
+
});
|
|
16960
|
+
return [cpfpRootTx, directRootTx];
|
|
16961
|
+
}
|
|
16962
|
+
function createSplitTx(parentOutPoint, childTxOuts) {
|
|
16963
|
+
const cpfpSplitTx = new Transaction2({
|
|
16964
|
+
version: 3,
|
|
16965
|
+
allowUnknownOutputs: true
|
|
16966
|
+
});
|
|
16967
|
+
cpfpSplitTx.addInput(parentOutPoint);
|
|
16968
|
+
for (const txOut of childTxOuts) {
|
|
16969
|
+
cpfpSplitTx.addOutput(txOut);
|
|
16970
|
+
}
|
|
16971
|
+
cpfpSplitTx.addOutput(getEphemeralAnchorOutput());
|
|
16972
|
+
const directSplitTx = new Transaction2({
|
|
16973
|
+
version: 3,
|
|
16974
|
+
allowUnknownOutputs: true
|
|
16975
|
+
});
|
|
16976
|
+
directSplitTx.addInput(parentOutPoint);
|
|
16977
|
+
let totalOutputAmount = 0n;
|
|
16978
|
+
for (const txOut of childTxOuts) {
|
|
16979
|
+
totalOutputAmount += txOut.amount ?? 0n;
|
|
16980
|
+
}
|
|
16981
|
+
if (totalOutputAmount > BigInt(DEFAULT_FEE_SATS)) {
|
|
16982
|
+
const feeRatio = Number(DEFAULT_FEE_SATS) / Number(totalOutputAmount);
|
|
16983
|
+
for (const txOut of childTxOuts) {
|
|
16984
|
+
const adjustedAmount = BigInt(
|
|
16985
|
+
Math.floor(Number(txOut.amount ?? 0n) * (1 - feeRatio))
|
|
16986
|
+
);
|
|
16987
|
+
directSplitTx.addOutput({
|
|
16988
|
+
script: txOut.script,
|
|
16989
|
+
amount: adjustedAmount
|
|
16990
|
+
});
|
|
16991
|
+
}
|
|
16992
|
+
} else {
|
|
16993
|
+
for (const txOut of childTxOuts) {
|
|
16994
|
+
directSplitTx.addOutput(txOut);
|
|
16995
|
+
}
|
|
16996
|
+
}
|
|
16997
|
+
return [cpfpSplitTx, directSplitTx];
|
|
16998
|
+
}
|
|
16999
|
+
function createNodeTx({
|
|
17000
|
+
txOut,
|
|
17001
|
+
parentOutPoint,
|
|
17002
|
+
applyFee,
|
|
17003
|
+
includeAnchor
|
|
17004
|
+
}) {
|
|
17005
|
+
const nodeTx = new Transaction2({
|
|
17006
|
+
version: 3,
|
|
17007
|
+
allowUnknownOutputs: true
|
|
17008
|
+
});
|
|
17009
|
+
nodeTx.addInput(parentOutPoint);
|
|
17010
|
+
if (applyFee) {
|
|
17011
|
+
nodeTx.addOutput({
|
|
17012
|
+
script: txOut.script,
|
|
17013
|
+
amount: maybeApplyFee(txOut.amount ?? 0n)
|
|
17014
|
+
});
|
|
17015
|
+
} else {
|
|
17016
|
+
nodeTx.addOutput(txOut);
|
|
17017
|
+
}
|
|
17018
|
+
if (includeAnchor) {
|
|
17019
|
+
nodeTx.addOutput(getEphemeralAnchorOutput());
|
|
17020
|
+
}
|
|
17021
|
+
return nodeTx;
|
|
17022
|
+
}
|
|
17023
|
+
function createNodeTxs(txOut, txIn, directTxIn) {
|
|
17024
|
+
const cpfpNodeTx = createNodeTx({
|
|
17025
|
+
txOut,
|
|
17026
|
+
parentOutPoint: txIn,
|
|
17027
|
+
includeAnchor: true
|
|
17028
|
+
});
|
|
17029
|
+
let directNodeTx;
|
|
17030
|
+
if (directTxIn) {
|
|
17031
|
+
directNodeTx = createNodeTx({
|
|
17032
|
+
txOut,
|
|
17033
|
+
parentOutPoint: directTxIn,
|
|
17034
|
+
includeAnchor: false,
|
|
17035
|
+
applyFee: true
|
|
17036
|
+
});
|
|
17037
|
+
}
|
|
17038
|
+
return { cpfpNodeTx, directNodeTx };
|
|
17039
|
+
}
|
|
17040
|
+
function createLeafNodeTx(sequence, directSequence, parentOutPoint, txOut, shouldCalculateFee) {
|
|
17041
|
+
const cpfpLeafTx = new Transaction2({
|
|
17042
|
+
version: 3,
|
|
17043
|
+
allowUnknownOutputs: true
|
|
17044
|
+
});
|
|
17045
|
+
cpfpLeafTx.addInput({
|
|
17046
|
+
...parentOutPoint,
|
|
17047
|
+
sequence
|
|
17048
|
+
});
|
|
17049
|
+
cpfpLeafTx.addOutput(txOut);
|
|
17050
|
+
cpfpLeafTx.addOutput(getEphemeralAnchorOutput());
|
|
17051
|
+
const directLeafTx = new Transaction2({
|
|
17052
|
+
version: 3,
|
|
17053
|
+
allowUnknownOutputs: true
|
|
17054
|
+
});
|
|
17055
|
+
directLeafTx.addInput({
|
|
17056
|
+
...parentOutPoint,
|
|
17057
|
+
sequence: directSequence
|
|
17058
|
+
});
|
|
17059
|
+
const amountSats = txOut.amount ?? 0n;
|
|
17060
|
+
let outputAmount = amountSats;
|
|
17061
|
+
if (shouldCalculateFee) {
|
|
17062
|
+
outputAmount = maybeApplyFee(amountSats);
|
|
17063
|
+
}
|
|
17064
|
+
directLeafTx.addOutput({
|
|
17065
|
+
script: txOut.script,
|
|
17066
|
+
amount: outputAmount
|
|
17067
|
+
});
|
|
17068
|
+
return [cpfpLeafTx, directLeafTx];
|
|
17069
|
+
}
|
|
17070
|
+
function createRefundTx({
|
|
17071
|
+
sequence,
|
|
17072
|
+
input,
|
|
17073
|
+
amountSats,
|
|
17074
|
+
receivingPubkey,
|
|
17075
|
+
network,
|
|
17076
|
+
shouldCalculateFee,
|
|
17077
|
+
includeAnchor
|
|
17078
|
+
}) {
|
|
17079
|
+
const refundTx = new Transaction2({
|
|
16817
17080
|
version: 3,
|
|
16818
17081
|
allowUnknownOutputs: true
|
|
16819
17082
|
});
|
|
16820
|
-
|
|
16821
|
-
...
|
|
17083
|
+
refundTx.addInput({
|
|
17084
|
+
...input,
|
|
16822
17085
|
sequence
|
|
16823
17086
|
});
|
|
16824
17087
|
const refundPkScript = getP2TRScriptFromPublicKey(receivingPubkey, network);
|
|
16825
|
-
|
|
17088
|
+
let outputAmount = amountSats;
|
|
17089
|
+
if (shouldCalculateFee) {
|
|
17090
|
+
outputAmount = maybeApplyFee(amountSats);
|
|
17091
|
+
}
|
|
17092
|
+
refundTx.addOutput({
|
|
16826
17093
|
script: refundPkScript,
|
|
17094
|
+
amount: outputAmount
|
|
17095
|
+
});
|
|
17096
|
+
if (includeAnchor) {
|
|
17097
|
+
refundTx.addOutput(getEphemeralAnchorOutput());
|
|
17098
|
+
}
|
|
17099
|
+
return refundTx;
|
|
17100
|
+
}
|
|
17101
|
+
function createRefundTxs({
|
|
17102
|
+
sequence,
|
|
17103
|
+
directSequence,
|
|
17104
|
+
input,
|
|
17105
|
+
directInput,
|
|
17106
|
+
amountSats,
|
|
17107
|
+
receivingPubkey,
|
|
17108
|
+
network
|
|
17109
|
+
}) {
|
|
17110
|
+
const cpfpRefundTx = createRefundTx({
|
|
17111
|
+
sequence,
|
|
17112
|
+
input,
|
|
17113
|
+
amountSats,
|
|
17114
|
+
receivingPubkey,
|
|
17115
|
+
network,
|
|
17116
|
+
shouldCalculateFee: false,
|
|
17117
|
+
includeAnchor: true
|
|
17118
|
+
});
|
|
17119
|
+
let directRefundTx;
|
|
17120
|
+
let directFromCpfpRefundTx;
|
|
17121
|
+
if (directSequence && directInput) {
|
|
17122
|
+
directRefundTx = createRefundTx({
|
|
17123
|
+
sequence: directSequence,
|
|
17124
|
+
input: directInput,
|
|
17125
|
+
amountSats,
|
|
17126
|
+
receivingPubkey,
|
|
17127
|
+
network,
|
|
17128
|
+
shouldCalculateFee: true,
|
|
17129
|
+
includeAnchor: false
|
|
17130
|
+
});
|
|
17131
|
+
directFromCpfpRefundTx = createRefundTx({
|
|
17132
|
+
sequence: directSequence,
|
|
17133
|
+
input,
|
|
17134
|
+
amountSats,
|
|
17135
|
+
receivingPubkey,
|
|
17136
|
+
network,
|
|
17137
|
+
shouldCalculateFee: true,
|
|
17138
|
+
includeAnchor: false
|
|
17139
|
+
});
|
|
17140
|
+
} else if (directInput && !directSequence) {
|
|
17141
|
+
throw new ValidationError(
|
|
17142
|
+
"directSequence must be provided if directInput is",
|
|
17143
|
+
{
|
|
17144
|
+
field: "directSequence",
|
|
17145
|
+
value: directSequence
|
|
17146
|
+
}
|
|
17147
|
+
);
|
|
17148
|
+
}
|
|
17149
|
+
return { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx };
|
|
17150
|
+
}
|
|
17151
|
+
function createConnectorRefundTransactions(sequence, cpfpNodeOutPoint, directNodeOutPoint, connectorOutput, amountSats, receiverPubKey, network, shouldCalculateFee) {
|
|
17152
|
+
const cpfpRefundTx = new Transaction2({
|
|
17153
|
+
version: 3,
|
|
17154
|
+
allowUnknownOutputs: true
|
|
17155
|
+
});
|
|
17156
|
+
cpfpRefundTx.addInput({
|
|
17157
|
+
...cpfpNodeOutPoint,
|
|
17158
|
+
sequence
|
|
17159
|
+
});
|
|
17160
|
+
cpfpRefundTx.addInput(connectorOutput);
|
|
17161
|
+
const receiverScript = getP2TRScriptFromPublicKey(receiverPubKey, network);
|
|
17162
|
+
cpfpRefundTx.addOutput({
|
|
17163
|
+
script: receiverScript,
|
|
16827
17164
|
amount: amountSats
|
|
16828
17165
|
});
|
|
16829
|
-
|
|
16830
|
-
|
|
17166
|
+
const directRefundTx = new Transaction2({
|
|
17167
|
+
version: 3,
|
|
17168
|
+
allowUnknownOutputs: true
|
|
17169
|
+
});
|
|
17170
|
+
directRefundTx.addInput({
|
|
17171
|
+
...directNodeOutPoint,
|
|
17172
|
+
sequence
|
|
17173
|
+
});
|
|
17174
|
+
directRefundTx.addInput(connectorOutput);
|
|
17175
|
+
let outputAmount = amountSats;
|
|
17176
|
+
if (shouldCalculateFee) {
|
|
17177
|
+
outputAmount = maybeApplyFee(amountSats);
|
|
17178
|
+
}
|
|
17179
|
+
directRefundTx.addOutput({
|
|
17180
|
+
script: receiverScript,
|
|
17181
|
+
amount: outputAmount
|
|
17182
|
+
});
|
|
17183
|
+
const directFromCpfpTx = new Transaction2({
|
|
17184
|
+
version: 3,
|
|
17185
|
+
allowUnknownOutputs: true
|
|
17186
|
+
});
|
|
17187
|
+
directFromCpfpTx.addInput({
|
|
17188
|
+
...cpfpNodeOutPoint,
|
|
17189
|
+
sequence
|
|
17190
|
+
});
|
|
17191
|
+
directFromCpfpTx.addInput(connectorOutput);
|
|
17192
|
+
directFromCpfpTx.addOutput({
|
|
17193
|
+
script: receiverScript,
|
|
17194
|
+
amount: outputAmount
|
|
17195
|
+
});
|
|
17196
|
+
return [cpfpRefundTx, directRefundTx, directFromCpfpTx];
|
|
16831
17197
|
}
|
|
16832
17198
|
function getCurrentTimelock(currSequence) {
|
|
16833
17199
|
return (currSequence || 0) & 65535;
|
|
16834
17200
|
}
|
|
16835
17201
|
function getTransactionSequence(currSequence) {
|
|
16836
17202
|
const timelock = getCurrentTimelock(currSequence);
|
|
16837
|
-
return
|
|
17203
|
+
return {
|
|
17204
|
+
nextSequence: 1 << 30 | timelock,
|
|
17205
|
+
nextDirectSequence: 1 << 30 | timelock + DIRECT_TIMELOCK_OFFSET
|
|
17206
|
+
};
|
|
16838
17207
|
}
|
|
16839
17208
|
function checkIfValidSequence(currSequence) {
|
|
16840
17209
|
const TIME_LOCK_ACTIVE = (currSequence || 0) & 2147483648;
|
|
@@ -16852,24 +17221,32 @@ function checkIfValidSequence(currSequence) {
|
|
|
16852
17221
|
});
|
|
16853
17222
|
}
|
|
16854
17223
|
}
|
|
16855
|
-
function
|
|
17224
|
+
function doesLeafNeedRefresh(currSequence, isNodeTx) {
|
|
16856
17225
|
const currentTimelock = getCurrentTimelock(currSequence);
|
|
16857
|
-
|
|
16858
|
-
|
|
16859
|
-
return {
|
|
16860
|
-
nextSequence: 1 << 30 | nextTimelock,
|
|
16861
|
-
needRefresh: true
|
|
16862
|
-
};
|
|
17226
|
+
if (isNodeTx) {
|
|
17227
|
+
return currentTimelock === 0;
|
|
16863
17228
|
}
|
|
16864
|
-
|
|
17229
|
+
return currentTimelock <= 100;
|
|
17230
|
+
}
|
|
17231
|
+
function getNextTransactionSequence(currSequence, isNodeTx) {
|
|
17232
|
+
const currentTimelock = getCurrentTimelock(currSequence);
|
|
17233
|
+
const nextTimelock = currentTimelock - TIME_LOCK_INTERVAL;
|
|
17234
|
+
if (isNodeTx && nextTimelock < 0) {
|
|
16865
17235
|
throw new ValidationError("timelock interval is less than 0", {
|
|
16866
17236
|
field: "nextTimelock",
|
|
16867
|
-
value: nextTimelock
|
|
17237
|
+
value: nextTimelock,
|
|
17238
|
+
expected: "Non-negative timelock interval"
|
|
17239
|
+
});
|
|
17240
|
+
} else if (!isNodeTx && nextTimelock <= 0) {
|
|
17241
|
+
throw new ValidationError("timelock interval is less than or equal to 0", {
|
|
17242
|
+
field: "nextTimelock",
|
|
17243
|
+
value: nextTimelock,
|
|
17244
|
+
expected: "Timelock greater than 0"
|
|
16868
17245
|
});
|
|
16869
17246
|
}
|
|
16870
17247
|
return {
|
|
16871
17248
|
nextSequence: 1 << 30 | nextTimelock,
|
|
16872
|
-
|
|
17249
|
+
nextDirectSequence: 1 << 30 | nextTimelock + DIRECT_TIMELOCK_OFFSET
|
|
16873
17250
|
};
|
|
16874
17251
|
}
|
|
16875
17252
|
function getEphemeralAnchorOutput() {
|
|
@@ -17528,7 +17905,7 @@ import * as ecies from "eciesjs";
|
|
|
17528
17905
|
import { isNode } from "@lightsparkdev/core";
|
|
17529
17906
|
var isReactNative = typeof navigator !== "undefined" && navigator.product === "ReactNative";
|
|
17530
17907
|
var isBun = globalThis.Bun !== void 0;
|
|
17531
|
-
var packageVersion = true ? "0.2.
|
|
17908
|
+
var packageVersion = true ? "0.2.4" : "unknown";
|
|
17532
17909
|
var baseEnvStr = "unknown";
|
|
17533
17910
|
if (isBun) {
|
|
17534
17911
|
const bunVersion = "version" in globalThis.Bun ? globalThis.Bun.version : "unknown-version";
|
|
@@ -18021,7 +18398,7 @@ import {
|
|
|
18021
18398
|
import { secp256k1 as secp256k114 } from "@noble/curves/secp256k1";
|
|
18022
18399
|
import { validateMnemonic } from "@scure/bip39";
|
|
18023
18400
|
import { wordlist as wordlist2 } from "@scure/bip39/wordlists/english";
|
|
18024
|
-
import { Address as
|
|
18401
|
+
import { Address as Address6, OutScript as OutScript4, Transaction as Transaction9 } from "@scure/btc-signer";
|
|
18025
18402
|
import { Mutex } from "async-mutex";
|
|
18026
18403
|
import { uuidv7 as uuidv75, uuidv7obj } from "uuidv7";
|
|
18027
18404
|
|
|
@@ -18172,10 +18549,18 @@ var CompleteCoopExit = `
|
|
|
18172
18549
|
var CompleteLeavesSwap = `
|
|
18173
18550
|
mutation CompleteLeavesSwap(
|
|
18174
18551
|
$adaptor_secret_key: String!
|
|
18552
|
+
$direct_adaptor_secret_key: String!
|
|
18553
|
+
$direct_from_cpfp_adaptor_secret_key: String!
|
|
18175
18554
|
$user_outbound_transfer_external_id: UUID!
|
|
18176
18555
|
$leaves_swap_request_id: ID!
|
|
18177
18556
|
) {
|
|
18178
|
-
complete_leaves_swap(input: {
|
|
18557
|
+
complete_leaves_swap(input: {
|
|
18558
|
+
adaptor_secret_key: $adaptor_secret_key,
|
|
18559
|
+
direct_adaptor_secret_key: $direct_adaptor_secret_key,
|
|
18560
|
+
direct_from_cpfp_adaptor_secret_key: $direct_from_cpfp_adaptor_secret_key,
|
|
18561
|
+
user_outbound_transfer_external_id: $user_outbound_transfer_external_id,
|
|
18562
|
+
leaves_swap_request_id: $leaves_swap_request_id
|
|
18563
|
+
}) {
|
|
18179
18564
|
request {
|
|
18180
18565
|
...LeavesSwapRequestFragment
|
|
18181
18566
|
}
|
|
@@ -18298,6 +18683,8 @@ var RequestLightningSend = `
|
|
|
18298
18683
|
var RequestSwapLeaves = `
|
|
18299
18684
|
mutation RequestSwapLeaves(
|
|
18300
18685
|
$adaptor_pubkey: PublicKey!
|
|
18686
|
+
$direct_adaptor_pubkey: PublicKey
|
|
18687
|
+
$direct_from_cpfp_adaptor_pubkey: PublicKey
|
|
18301
18688
|
$total_amount_sats: Long!
|
|
18302
18689
|
$target_amount_sats: Long!
|
|
18303
18690
|
$fee_sats: Long!
|
|
@@ -18307,6 +18694,8 @@ var RequestSwapLeaves = `
|
|
|
18307
18694
|
) {
|
|
18308
18695
|
request_leaves_swap(input: {
|
|
18309
18696
|
adaptor_pubkey: $adaptor_pubkey
|
|
18697
|
+
direct_adaptor_pubkey: $direct_adaptor_pubkey
|
|
18698
|
+
direct_from_cpfp_adaptor_pubkey: $direct_from_cpfp_adaptor_pubkey
|
|
18310
18699
|
total_amount_sats: $total_amount_sats
|
|
18311
18700
|
target_amount_sats: $target_amount_sats
|
|
18312
18701
|
fee_sats: $fee_sats
|
|
@@ -18797,6 +19186,8 @@ var SspClient = class {
|
|
|
18797
19186
|
}
|
|
18798
19187
|
async requestLeaveSwap({
|
|
18799
19188
|
adaptorPubkey,
|
|
19189
|
+
directAdaptorPubkey,
|
|
19190
|
+
directFromCpfpAdaptorPubkey,
|
|
18800
19191
|
totalAmountSats,
|
|
18801
19192
|
targetAmountSats,
|
|
18802
19193
|
feeSats,
|
|
@@ -18808,6 +19199,8 @@ var SspClient = class {
|
|
|
18808
19199
|
queryPayload: RequestSwapLeaves,
|
|
18809
19200
|
variables: {
|
|
18810
19201
|
adaptor_pubkey: adaptorPubkey,
|
|
19202
|
+
direct_adaptor_pubkey: directAdaptorPubkey,
|
|
19203
|
+
direct_from_cpfp_adaptor_pubkey: directFromCpfpAdaptorPubkey,
|
|
18811
19204
|
total_amount_sats: totalAmountSats,
|
|
18812
19205
|
target_amount_sats: targetAmountSats,
|
|
18813
19206
|
fee_sats: feeSats,
|
|
@@ -18826,6 +19219,8 @@ var SspClient = class {
|
|
|
18826
19219
|
}
|
|
18827
19220
|
async completeLeaveSwap({
|
|
18828
19221
|
adaptorSecretKey,
|
|
19222
|
+
directAdaptorSecretKey,
|
|
19223
|
+
directFromCpfpAdaptorSecretKey,
|
|
18829
19224
|
userOutboundTransferExternalId,
|
|
18830
19225
|
leavesSwapRequestId
|
|
18831
19226
|
}) {
|
|
@@ -18833,6 +19228,8 @@ var SspClient = class {
|
|
|
18833
19228
|
queryPayload: CompleteLeavesSwap,
|
|
18834
19229
|
variables: {
|
|
18835
19230
|
adaptor_secret_key: adaptorSecretKey,
|
|
19231
|
+
direct_adaptor_secret_key: directAdaptorSecretKey,
|
|
19232
|
+
direct_from_cpfp_adaptor_secret_key: directFromCpfpAdaptorSecretKey,
|
|
18836
19233
|
user_outbound_transfer_external_id: userOutboundTransferExternalId,
|
|
18837
19234
|
leaves_swap_request_id: leavesSwapRequestId
|
|
18838
19235
|
},
|
|
@@ -22193,72 +22590,367 @@ var TokenTransactionWithStatus2 = {
|
|
|
22193
22590
|
return message;
|
|
22194
22591
|
}
|
|
22195
22592
|
};
|
|
22196
|
-
|
|
22197
|
-
|
|
22198
|
-
|
|
22199
|
-
|
|
22200
|
-
|
|
22201
|
-
|
|
22202
|
-
|
|
22203
|
-
|
|
22204
|
-
|
|
22205
|
-
|
|
22206
|
-
|
|
22207
|
-
|
|
22208
|
-
|
|
22209
|
-
|
|
22210
|
-
|
|
22211
|
-
},
|
|
22212
|
-
/**
|
|
22213
|
-
* Complete the transaction and commit it with all SOs. This will be
|
|
22214
|
-
* coordinated by one SO.
|
|
22215
|
-
*/
|
|
22216
|
-
commit_transaction: {
|
|
22217
|
-
name: "commit_transaction",
|
|
22218
|
-
requestType: CommitTransactionRequest,
|
|
22219
|
-
requestStream: false,
|
|
22220
|
-
responseType: CommitTransactionResponse,
|
|
22221
|
-
responseStream: false,
|
|
22222
|
-
options: {}
|
|
22223
|
-
},
|
|
22224
|
-
query_token_metadata: {
|
|
22225
|
-
name: "query_token_metadata",
|
|
22226
|
-
requestType: QueryTokenMetadataRequest,
|
|
22227
|
-
requestStream: false,
|
|
22228
|
-
responseType: QueryTokenMetadataResponse,
|
|
22229
|
-
responseStream: false,
|
|
22230
|
-
options: {}
|
|
22231
|
-
},
|
|
22232
|
-
query_token_transactions: {
|
|
22233
|
-
name: "query_token_transactions",
|
|
22234
|
-
requestType: QueryTokenTransactionsRequest2,
|
|
22235
|
-
requestStream: false,
|
|
22236
|
-
responseType: QueryTokenTransactionsResponse2,
|
|
22237
|
-
responseStream: false,
|
|
22238
|
-
options: {}
|
|
22239
|
-
},
|
|
22240
|
-
query_token_outputs: {
|
|
22241
|
-
name: "query_token_outputs",
|
|
22242
|
-
requestType: QueryTokenOutputsRequest2,
|
|
22243
|
-
requestStream: false,
|
|
22244
|
-
responseType: QueryTokenOutputsResponse2,
|
|
22245
|
-
responseStream: false,
|
|
22246
|
-
options: {}
|
|
22593
|
+
function createBaseFreezeTokensPayload2() {
|
|
22594
|
+
return {
|
|
22595
|
+
version: 0,
|
|
22596
|
+
ownerPublicKey: new Uint8Array(0),
|
|
22597
|
+
tokenPublicKey: void 0,
|
|
22598
|
+
tokenIdentifier: void 0,
|
|
22599
|
+
issuerProvidedTimestamp: 0,
|
|
22600
|
+
operatorIdentityPublicKey: new Uint8Array(0),
|
|
22601
|
+
shouldUnfreeze: false
|
|
22602
|
+
};
|
|
22603
|
+
}
|
|
22604
|
+
var FreezeTokensPayload2 = {
|
|
22605
|
+
encode(message, writer = new BinaryWriter7()) {
|
|
22606
|
+
if (message.version !== 0) {
|
|
22607
|
+
writer.uint32(8).uint32(message.version);
|
|
22247
22608
|
}
|
|
22248
|
-
|
|
22249
|
-
|
|
22250
|
-
function bytesFromBase645(b64) {
|
|
22251
|
-
if (globalThis.Buffer) {
|
|
22252
|
-
return Uint8Array.from(globalThis.Buffer.from(b64, "base64"));
|
|
22253
|
-
} else {
|
|
22254
|
-
const bin = globalThis.atob(b64);
|
|
22255
|
-
const arr = new Uint8Array(bin.length);
|
|
22256
|
-
for (let i = 0; i < bin.length; ++i) {
|
|
22257
|
-
arr[i] = bin.charCodeAt(i);
|
|
22609
|
+
if (message.ownerPublicKey.length !== 0) {
|
|
22610
|
+
writer.uint32(18).bytes(message.ownerPublicKey);
|
|
22258
22611
|
}
|
|
22259
|
-
|
|
22260
|
-
|
|
22261
|
-
}
|
|
22612
|
+
if (message.tokenPublicKey !== void 0) {
|
|
22613
|
+
writer.uint32(26).bytes(message.tokenPublicKey);
|
|
22614
|
+
}
|
|
22615
|
+
if (message.tokenIdentifier !== void 0) {
|
|
22616
|
+
writer.uint32(34).bytes(message.tokenIdentifier);
|
|
22617
|
+
}
|
|
22618
|
+
if (message.issuerProvidedTimestamp !== 0) {
|
|
22619
|
+
writer.uint32(40).uint64(message.issuerProvidedTimestamp);
|
|
22620
|
+
}
|
|
22621
|
+
if (message.operatorIdentityPublicKey.length !== 0) {
|
|
22622
|
+
writer.uint32(50).bytes(message.operatorIdentityPublicKey);
|
|
22623
|
+
}
|
|
22624
|
+
if (message.shouldUnfreeze !== false) {
|
|
22625
|
+
writer.uint32(56).bool(message.shouldUnfreeze);
|
|
22626
|
+
}
|
|
22627
|
+
return writer;
|
|
22628
|
+
},
|
|
22629
|
+
decode(input, length) {
|
|
22630
|
+
const reader = input instanceof BinaryReader7 ? input : new BinaryReader7(input);
|
|
22631
|
+
const end = length === void 0 ? reader.len : reader.pos + length;
|
|
22632
|
+
const message = createBaseFreezeTokensPayload2();
|
|
22633
|
+
while (reader.pos < end) {
|
|
22634
|
+
const tag = reader.uint32();
|
|
22635
|
+
switch (tag >>> 3) {
|
|
22636
|
+
case 1: {
|
|
22637
|
+
if (tag !== 8) {
|
|
22638
|
+
break;
|
|
22639
|
+
}
|
|
22640
|
+
message.version = reader.uint32();
|
|
22641
|
+
continue;
|
|
22642
|
+
}
|
|
22643
|
+
case 2: {
|
|
22644
|
+
if (tag !== 18) {
|
|
22645
|
+
break;
|
|
22646
|
+
}
|
|
22647
|
+
message.ownerPublicKey = reader.bytes();
|
|
22648
|
+
continue;
|
|
22649
|
+
}
|
|
22650
|
+
case 3: {
|
|
22651
|
+
if (tag !== 26) {
|
|
22652
|
+
break;
|
|
22653
|
+
}
|
|
22654
|
+
message.tokenPublicKey = reader.bytes();
|
|
22655
|
+
continue;
|
|
22656
|
+
}
|
|
22657
|
+
case 4: {
|
|
22658
|
+
if (tag !== 34) {
|
|
22659
|
+
break;
|
|
22660
|
+
}
|
|
22661
|
+
message.tokenIdentifier = reader.bytes();
|
|
22662
|
+
continue;
|
|
22663
|
+
}
|
|
22664
|
+
case 5: {
|
|
22665
|
+
if (tag !== 40) {
|
|
22666
|
+
break;
|
|
22667
|
+
}
|
|
22668
|
+
message.issuerProvidedTimestamp = longToNumber4(reader.uint64());
|
|
22669
|
+
continue;
|
|
22670
|
+
}
|
|
22671
|
+
case 6: {
|
|
22672
|
+
if (tag !== 50) {
|
|
22673
|
+
break;
|
|
22674
|
+
}
|
|
22675
|
+
message.operatorIdentityPublicKey = reader.bytes();
|
|
22676
|
+
continue;
|
|
22677
|
+
}
|
|
22678
|
+
case 7: {
|
|
22679
|
+
if (tag !== 56) {
|
|
22680
|
+
break;
|
|
22681
|
+
}
|
|
22682
|
+
message.shouldUnfreeze = reader.bool();
|
|
22683
|
+
continue;
|
|
22684
|
+
}
|
|
22685
|
+
}
|
|
22686
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
22687
|
+
break;
|
|
22688
|
+
}
|
|
22689
|
+
reader.skip(tag & 7);
|
|
22690
|
+
}
|
|
22691
|
+
return message;
|
|
22692
|
+
},
|
|
22693
|
+
fromJSON(object) {
|
|
22694
|
+
return {
|
|
22695
|
+
version: isSet6(object.version) ? globalThis.Number(object.version) : 0,
|
|
22696
|
+
ownerPublicKey: isSet6(object.ownerPublicKey) ? bytesFromBase645(object.ownerPublicKey) : new Uint8Array(0),
|
|
22697
|
+
tokenPublicKey: isSet6(object.tokenPublicKey) ? bytesFromBase645(object.tokenPublicKey) : void 0,
|
|
22698
|
+
tokenIdentifier: isSet6(object.tokenIdentifier) ? bytesFromBase645(object.tokenIdentifier) : void 0,
|
|
22699
|
+
issuerProvidedTimestamp: isSet6(object.issuerProvidedTimestamp) ? globalThis.Number(object.issuerProvidedTimestamp) : 0,
|
|
22700
|
+
operatorIdentityPublicKey: isSet6(object.operatorIdentityPublicKey) ? bytesFromBase645(object.operatorIdentityPublicKey) : new Uint8Array(0),
|
|
22701
|
+
shouldUnfreeze: isSet6(object.shouldUnfreeze) ? globalThis.Boolean(object.shouldUnfreeze) : false
|
|
22702
|
+
};
|
|
22703
|
+
},
|
|
22704
|
+
toJSON(message) {
|
|
22705
|
+
const obj = {};
|
|
22706
|
+
if (message.version !== 0) {
|
|
22707
|
+
obj.version = Math.round(message.version);
|
|
22708
|
+
}
|
|
22709
|
+
if (message.ownerPublicKey.length !== 0) {
|
|
22710
|
+
obj.ownerPublicKey = base64FromBytes5(message.ownerPublicKey);
|
|
22711
|
+
}
|
|
22712
|
+
if (message.tokenPublicKey !== void 0) {
|
|
22713
|
+
obj.tokenPublicKey = base64FromBytes5(message.tokenPublicKey);
|
|
22714
|
+
}
|
|
22715
|
+
if (message.tokenIdentifier !== void 0) {
|
|
22716
|
+
obj.tokenIdentifier = base64FromBytes5(message.tokenIdentifier);
|
|
22717
|
+
}
|
|
22718
|
+
if (message.issuerProvidedTimestamp !== 0) {
|
|
22719
|
+
obj.issuerProvidedTimestamp = Math.round(message.issuerProvidedTimestamp);
|
|
22720
|
+
}
|
|
22721
|
+
if (message.operatorIdentityPublicKey.length !== 0) {
|
|
22722
|
+
obj.operatorIdentityPublicKey = base64FromBytes5(message.operatorIdentityPublicKey);
|
|
22723
|
+
}
|
|
22724
|
+
if (message.shouldUnfreeze !== false) {
|
|
22725
|
+
obj.shouldUnfreeze = message.shouldUnfreeze;
|
|
22726
|
+
}
|
|
22727
|
+
return obj;
|
|
22728
|
+
},
|
|
22729
|
+
create(base) {
|
|
22730
|
+
return FreezeTokensPayload2.fromPartial(base ?? {});
|
|
22731
|
+
},
|
|
22732
|
+
fromPartial(object) {
|
|
22733
|
+
const message = createBaseFreezeTokensPayload2();
|
|
22734
|
+
message.version = object.version ?? 0;
|
|
22735
|
+
message.ownerPublicKey = object.ownerPublicKey ?? new Uint8Array(0);
|
|
22736
|
+
message.tokenPublicKey = object.tokenPublicKey ?? void 0;
|
|
22737
|
+
message.tokenIdentifier = object.tokenIdentifier ?? void 0;
|
|
22738
|
+
message.issuerProvidedTimestamp = object.issuerProvidedTimestamp ?? 0;
|
|
22739
|
+
message.operatorIdentityPublicKey = object.operatorIdentityPublicKey ?? new Uint8Array(0);
|
|
22740
|
+
message.shouldUnfreeze = object.shouldUnfreeze ?? false;
|
|
22741
|
+
return message;
|
|
22742
|
+
}
|
|
22743
|
+
};
|
|
22744
|
+
function createBaseFreezeTokensRequest2() {
|
|
22745
|
+
return { freezeTokensPayload: void 0, issuerSignature: new Uint8Array(0) };
|
|
22746
|
+
}
|
|
22747
|
+
var FreezeTokensRequest2 = {
|
|
22748
|
+
encode(message, writer = new BinaryWriter7()) {
|
|
22749
|
+
if (message.freezeTokensPayload !== void 0) {
|
|
22750
|
+
FreezeTokensPayload2.encode(message.freezeTokensPayload, writer.uint32(10).fork()).join();
|
|
22751
|
+
}
|
|
22752
|
+
if (message.issuerSignature.length !== 0) {
|
|
22753
|
+
writer.uint32(18).bytes(message.issuerSignature);
|
|
22754
|
+
}
|
|
22755
|
+
return writer;
|
|
22756
|
+
},
|
|
22757
|
+
decode(input, length) {
|
|
22758
|
+
const reader = input instanceof BinaryReader7 ? input : new BinaryReader7(input);
|
|
22759
|
+
const end = length === void 0 ? reader.len : reader.pos + length;
|
|
22760
|
+
const message = createBaseFreezeTokensRequest2();
|
|
22761
|
+
while (reader.pos < end) {
|
|
22762
|
+
const tag = reader.uint32();
|
|
22763
|
+
switch (tag >>> 3) {
|
|
22764
|
+
case 1: {
|
|
22765
|
+
if (tag !== 10) {
|
|
22766
|
+
break;
|
|
22767
|
+
}
|
|
22768
|
+
message.freezeTokensPayload = FreezeTokensPayload2.decode(reader, reader.uint32());
|
|
22769
|
+
continue;
|
|
22770
|
+
}
|
|
22771
|
+
case 2: {
|
|
22772
|
+
if (tag !== 18) {
|
|
22773
|
+
break;
|
|
22774
|
+
}
|
|
22775
|
+
message.issuerSignature = reader.bytes();
|
|
22776
|
+
continue;
|
|
22777
|
+
}
|
|
22778
|
+
}
|
|
22779
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
22780
|
+
break;
|
|
22781
|
+
}
|
|
22782
|
+
reader.skip(tag & 7);
|
|
22783
|
+
}
|
|
22784
|
+
return message;
|
|
22785
|
+
},
|
|
22786
|
+
fromJSON(object) {
|
|
22787
|
+
return {
|
|
22788
|
+
freezeTokensPayload: isSet6(object.freezeTokensPayload) ? FreezeTokensPayload2.fromJSON(object.freezeTokensPayload) : void 0,
|
|
22789
|
+
issuerSignature: isSet6(object.issuerSignature) ? bytesFromBase645(object.issuerSignature) : new Uint8Array(0)
|
|
22790
|
+
};
|
|
22791
|
+
},
|
|
22792
|
+
toJSON(message) {
|
|
22793
|
+
const obj = {};
|
|
22794
|
+
if (message.freezeTokensPayload !== void 0) {
|
|
22795
|
+
obj.freezeTokensPayload = FreezeTokensPayload2.toJSON(message.freezeTokensPayload);
|
|
22796
|
+
}
|
|
22797
|
+
if (message.issuerSignature.length !== 0) {
|
|
22798
|
+
obj.issuerSignature = base64FromBytes5(message.issuerSignature);
|
|
22799
|
+
}
|
|
22800
|
+
return obj;
|
|
22801
|
+
},
|
|
22802
|
+
create(base) {
|
|
22803
|
+
return FreezeTokensRequest2.fromPartial(base ?? {});
|
|
22804
|
+
},
|
|
22805
|
+
fromPartial(object) {
|
|
22806
|
+
const message = createBaseFreezeTokensRequest2();
|
|
22807
|
+
message.freezeTokensPayload = object.freezeTokensPayload !== void 0 && object.freezeTokensPayload !== null ? FreezeTokensPayload2.fromPartial(object.freezeTokensPayload) : void 0;
|
|
22808
|
+
message.issuerSignature = object.issuerSignature ?? new Uint8Array(0);
|
|
22809
|
+
return message;
|
|
22810
|
+
}
|
|
22811
|
+
};
|
|
22812
|
+
function createBaseFreezeTokensResponse2() {
|
|
22813
|
+
return { impactedOutputIds: [], impactedTokenAmount: new Uint8Array(0) };
|
|
22814
|
+
}
|
|
22815
|
+
var FreezeTokensResponse2 = {
|
|
22816
|
+
encode(message, writer = new BinaryWriter7()) {
|
|
22817
|
+
for (const v of message.impactedOutputIds) {
|
|
22818
|
+
writer.uint32(10).string(v);
|
|
22819
|
+
}
|
|
22820
|
+
if (message.impactedTokenAmount.length !== 0) {
|
|
22821
|
+
writer.uint32(18).bytes(message.impactedTokenAmount);
|
|
22822
|
+
}
|
|
22823
|
+
return writer;
|
|
22824
|
+
},
|
|
22825
|
+
decode(input, length) {
|
|
22826
|
+
const reader = input instanceof BinaryReader7 ? input : new BinaryReader7(input);
|
|
22827
|
+
const end = length === void 0 ? reader.len : reader.pos + length;
|
|
22828
|
+
const message = createBaseFreezeTokensResponse2();
|
|
22829
|
+
while (reader.pos < end) {
|
|
22830
|
+
const tag = reader.uint32();
|
|
22831
|
+
switch (tag >>> 3) {
|
|
22832
|
+
case 1: {
|
|
22833
|
+
if (tag !== 10) {
|
|
22834
|
+
break;
|
|
22835
|
+
}
|
|
22836
|
+
message.impactedOutputIds.push(reader.string());
|
|
22837
|
+
continue;
|
|
22838
|
+
}
|
|
22839
|
+
case 2: {
|
|
22840
|
+
if (tag !== 18) {
|
|
22841
|
+
break;
|
|
22842
|
+
}
|
|
22843
|
+
message.impactedTokenAmount = reader.bytes();
|
|
22844
|
+
continue;
|
|
22845
|
+
}
|
|
22846
|
+
}
|
|
22847
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
22848
|
+
break;
|
|
22849
|
+
}
|
|
22850
|
+
reader.skip(tag & 7);
|
|
22851
|
+
}
|
|
22852
|
+
return message;
|
|
22853
|
+
},
|
|
22854
|
+
fromJSON(object) {
|
|
22855
|
+
return {
|
|
22856
|
+
impactedOutputIds: globalThis.Array.isArray(object?.impactedOutputIds) ? object.impactedOutputIds.map((e) => globalThis.String(e)) : [],
|
|
22857
|
+
impactedTokenAmount: isSet6(object.impactedTokenAmount) ? bytesFromBase645(object.impactedTokenAmount) : new Uint8Array(0)
|
|
22858
|
+
};
|
|
22859
|
+
},
|
|
22860
|
+
toJSON(message) {
|
|
22861
|
+
const obj = {};
|
|
22862
|
+
if (message.impactedOutputIds?.length) {
|
|
22863
|
+
obj.impactedOutputIds = message.impactedOutputIds;
|
|
22864
|
+
}
|
|
22865
|
+
if (message.impactedTokenAmount.length !== 0) {
|
|
22866
|
+
obj.impactedTokenAmount = base64FromBytes5(message.impactedTokenAmount);
|
|
22867
|
+
}
|
|
22868
|
+
return obj;
|
|
22869
|
+
},
|
|
22870
|
+
create(base) {
|
|
22871
|
+
return FreezeTokensResponse2.fromPartial(base ?? {});
|
|
22872
|
+
},
|
|
22873
|
+
fromPartial(object) {
|
|
22874
|
+
const message = createBaseFreezeTokensResponse2();
|
|
22875
|
+
message.impactedOutputIds = object.impactedOutputIds?.map((e) => e) || [];
|
|
22876
|
+
message.impactedTokenAmount = object.impactedTokenAmount ?? new Uint8Array(0);
|
|
22877
|
+
return message;
|
|
22878
|
+
}
|
|
22879
|
+
};
|
|
22880
|
+
var SparkTokenServiceDefinition = {
|
|
22881
|
+
name: "SparkTokenService",
|
|
22882
|
+
fullName: "spark_token.SparkTokenService",
|
|
22883
|
+
methods: {
|
|
22884
|
+
/**
|
|
22885
|
+
* Start process to create final token transaction with all inputs required
|
|
22886
|
+
* from user and SOs (including revocation secret commitment)
|
|
22887
|
+
*/
|
|
22888
|
+
start_transaction: {
|
|
22889
|
+
name: "start_transaction",
|
|
22890
|
+
requestType: StartTransactionRequest,
|
|
22891
|
+
requestStream: false,
|
|
22892
|
+
responseType: StartTransactionResponse,
|
|
22893
|
+
responseStream: false,
|
|
22894
|
+
options: {}
|
|
22895
|
+
},
|
|
22896
|
+
/**
|
|
22897
|
+
* Complete the transaction and commit it with all SOs. This will be
|
|
22898
|
+
* coordinated by one SO.
|
|
22899
|
+
*/
|
|
22900
|
+
commit_transaction: {
|
|
22901
|
+
name: "commit_transaction",
|
|
22902
|
+
requestType: CommitTransactionRequest,
|
|
22903
|
+
requestStream: false,
|
|
22904
|
+
responseType: CommitTransactionResponse,
|
|
22905
|
+
responseStream: false,
|
|
22906
|
+
options: {}
|
|
22907
|
+
},
|
|
22908
|
+
query_token_metadata: {
|
|
22909
|
+
name: "query_token_metadata",
|
|
22910
|
+
requestType: QueryTokenMetadataRequest,
|
|
22911
|
+
requestStream: false,
|
|
22912
|
+
responseType: QueryTokenMetadataResponse,
|
|
22913
|
+
responseStream: false,
|
|
22914
|
+
options: {}
|
|
22915
|
+
},
|
|
22916
|
+
query_token_transactions: {
|
|
22917
|
+
name: "query_token_transactions",
|
|
22918
|
+
requestType: QueryTokenTransactionsRequest2,
|
|
22919
|
+
requestStream: false,
|
|
22920
|
+
responseType: QueryTokenTransactionsResponse2,
|
|
22921
|
+
responseStream: false,
|
|
22922
|
+
options: {}
|
|
22923
|
+
},
|
|
22924
|
+
query_token_outputs: {
|
|
22925
|
+
name: "query_token_outputs",
|
|
22926
|
+
requestType: QueryTokenOutputsRequest2,
|
|
22927
|
+
requestStream: false,
|
|
22928
|
+
responseType: QueryTokenOutputsResponse2,
|
|
22929
|
+
responseStream: false,
|
|
22930
|
+
options: {}
|
|
22931
|
+
},
|
|
22932
|
+
freeze_tokens: {
|
|
22933
|
+
name: "freeze_tokens",
|
|
22934
|
+
requestType: FreezeTokensRequest2,
|
|
22935
|
+
requestStream: false,
|
|
22936
|
+
responseType: FreezeTokensResponse2,
|
|
22937
|
+
responseStream: false,
|
|
22938
|
+
options: {}
|
|
22939
|
+
}
|
|
22940
|
+
}
|
|
22941
|
+
};
|
|
22942
|
+
function bytesFromBase645(b64) {
|
|
22943
|
+
if (globalThis.Buffer) {
|
|
22944
|
+
return Uint8Array.from(globalThis.Buffer.from(b64, "base64"));
|
|
22945
|
+
} else {
|
|
22946
|
+
const bin = globalThis.atob(b64);
|
|
22947
|
+
const arr = new Uint8Array(bin.length);
|
|
22948
|
+
for (let i = 0; i < bin.length; ++i) {
|
|
22949
|
+
arr[i] = bin.charCodeAt(i);
|
|
22950
|
+
}
|
|
22951
|
+
return arr;
|
|
22952
|
+
}
|
|
22953
|
+
}
|
|
22262
22954
|
function base64FromBytes5(arr) {
|
|
22263
22955
|
if (globalThis.Buffer) {
|
|
22264
22956
|
return globalThis.Buffer.from(arr).toString("base64");
|
|
@@ -22700,11 +23392,7 @@ import { sha256 as sha2568 } from "@noble/hashes/sha2";
|
|
|
22700
23392
|
import { Transaction as Transaction4 } from "@scure/btc-signer";
|
|
22701
23393
|
import * as ecies2 from "eciesjs";
|
|
22702
23394
|
import { uuidv7 as uuidv72 } from "uuidv7";
|
|
22703
|
-
var INITIAL_TIME_LOCK = 2e3;
|
|
22704
23395
|
var DEFAULT_EXPIRY_TIME = 10 * 60 * 1e3;
|
|
22705
|
-
function initialSequence() {
|
|
22706
|
-
return 1 << 30 | INITIAL_TIME_LOCK;
|
|
22707
|
-
}
|
|
22708
23396
|
function getSigningJobProto(signingJob) {
|
|
22709
23397
|
return {
|
|
22710
23398
|
signingPublicKey: signingJob.signingPublicKey,
|
|
@@ -22721,12 +23409,14 @@ var BaseTransferService = class {
|
|
|
22721
23409
|
this.connectionManager = connectionManager;
|
|
22722
23410
|
this.signingService = signingService;
|
|
22723
23411
|
}
|
|
22724
|
-
async sendTransferTweakKey(transfer, leaves,
|
|
23412
|
+
async sendTransferTweakKey(transfer, leaves, cpfpRefundSignatureMap, directRefundSignatureMap, directFromCpfpRefundSignatureMap) {
|
|
22725
23413
|
const keyTweakInputMap = await this.prepareSendTransferKeyTweaks(
|
|
22726
23414
|
transfer.id,
|
|
22727
23415
|
transfer.receiverIdentityPublicKey,
|
|
22728
23416
|
leaves,
|
|
22729
|
-
|
|
23417
|
+
cpfpRefundSignatureMap,
|
|
23418
|
+
directRefundSignatureMap,
|
|
23419
|
+
directFromCpfpRefundSignatureMap
|
|
22730
23420
|
);
|
|
22731
23421
|
let updatedTransfer;
|
|
22732
23422
|
const coordinatorOperator = this.config.getSigningOperators()[this.config.getCoordinatorIdentifier()];
|
|
@@ -22764,13 +23454,26 @@ var BaseTransferService = class {
|
|
|
22764
23454
|
}
|
|
22765
23455
|
return updatedTransfer;
|
|
22766
23456
|
}
|
|
22767
|
-
async deliverTransferPackage(transfer, leaves,
|
|
23457
|
+
async deliverTransferPackage(transfer, leaves, cpfpRefundSignatureMap, directRefundSignatureMap, directFromCpfpRefundSignatureMap) {
|
|
22768
23458
|
const keyTweakInputMap = await this.prepareSendTransferKeyTweaks(
|
|
22769
23459
|
transfer.id,
|
|
22770
23460
|
transfer.receiverIdentityPublicKey,
|
|
22771
23461
|
leaves,
|
|
22772
|
-
|
|
23462
|
+
cpfpRefundSignatureMap,
|
|
23463
|
+
directRefundSignatureMap,
|
|
23464
|
+
directFromCpfpRefundSignatureMap
|
|
22773
23465
|
);
|
|
23466
|
+
for (const [key, operator] of Object.entries(
|
|
23467
|
+
this.config.getSigningOperators()
|
|
23468
|
+
)) {
|
|
23469
|
+
const tweaks = keyTweakInputMap.get(key);
|
|
23470
|
+
if (!tweaks) {
|
|
23471
|
+
throw new ValidationError("No tweaks for operator", {
|
|
23472
|
+
field: "operator",
|
|
23473
|
+
value: key
|
|
23474
|
+
});
|
|
23475
|
+
}
|
|
23476
|
+
}
|
|
22774
23477
|
const transferPackage = await this.prepareTransferPackage(
|
|
22775
23478
|
transfer.id,
|
|
22776
23479
|
keyTweakInputMap,
|
|
@@ -22796,6 +23499,8 @@ var BaseTransferService = class {
|
|
|
22796
23499
|
transferID,
|
|
22797
23500
|
receiverIdentityPubkey,
|
|
22798
23501
|
leaves,
|
|
23502
|
+
/* @__PURE__ */ new Map(),
|
|
23503
|
+
/* @__PURE__ */ new Map(),
|
|
22799
23504
|
/* @__PURE__ */ new Map()
|
|
22800
23505
|
);
|
|
22801
23506
|
const transferPackage = await this.prepareTransferPackage(
|
|
@@ -22809,7 +23514,7 @@ var BaseTransferService = class {
|
|
|
22809
23514
|
);
|
|
22810
23515
|
let response;
|
|
22811
23516
|
try {
|
|
22812
|
-
response = await sparkClient.
|
|
23517
|
+
response = await sparkClient.start_transfer_v2({
|
|
22813
23518
|
transferId: transferID,
|
|
22814
23519
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
22815
23520
|
receiverIdentityPublicKey: receiverIdentityPubkey,
|
|
@@ -22838,12 +23543,22 @@ var BaseTransferService = class {
|
|
|
22838
23543
|
nodes.push(leaf.leaf.id);
|
|
22839
23544
|
}
|
|
22840
23545
|
const signingCommitments = await sparkClient.get_signing_commitments({
|
|
22841
|
-
nodeIds: nodes
|
|
23546
|
+
nodeIds: nodes,
|
|
23547
|
+
count: 3
|
|
22842
23548
|
});
|
|
22843
|
-
const
|
|
23549
|
+
const {
|
|
23550
|
+
cpfpLeafSigningJobs,
|
|
23551
|
+
directLeafSigningJobs,
|
|
23552
|
+
directFromCpfpLeafSigningJobs
|
|
23553
|
+
} = await this.signingService.signRefunds(
|
|
22844
23554
|
leaves,
|
|
22845
|
-
|
|
22846
|
-
|
|
23555
|
+
receiverIdentityPubkey,
|
|
23556
|
+
signingCommitments.signingCommitments.slice(0, leaves.length),
|
|
23557
|
+
signingCommitments.signingCommitments.slice(
|
|
23558
|
+
leaves.length,
|
|
23559
|
+
2 * leaves.length
|
|
23560
|
+
),
|
|
23561
|
+
signingCommitments.signingCommitments.slice(2 * leaves.length)
|
|
22847
23562
|
);
|
|
22848
23563
|
const encryptedKeyTweaks = {};
|
|
22849
23564
|
for (const [key, value] of keyTweakInputMap) {
|
|
@@ -22863,12 +23578,11 @@ var BaseTransferService = class {
|
|
|
22863
23578
|
encryptedKeyTweaks[key] = Uint8Array.from(encryptedProto);
|
|
22864
23579
|
}
|
|
22865
23580
|
const transferPackage = {
|
|
22866
|
-
leavesToSend:
|
|
23581
|
+
leavesToSend: cpfpLeafSigningJobs,
|
|
22867
23582
|
keyTweakPackage: encryptedKeyTweaks,
|
|
22868
23583
|
userSignature: new Uint8Array(),
|
|
22869
|
-
|
|
22870
|
-
|
|
22871
|
-
directFromCpfpLeavesToSend: []
|
|
23584
|
+
directLeavesToSend: directLeafSigningJobs,
|
|
23585
|
+
directFromCpfpLeavesToSend: directFromCpfpLeafSigningJobs
|
|
22872
23586
|
};
|
|
22873
23587
|
const transferPackageSigningPayload = getTransferPackageSigningPayload(
|
|
22874
23588
|
transferID,
|
|
@@ -22928,7 +23642,7 @@ var BaseTransferService = class {
|
|
|
22928
23642
|
}
|
|
22929
23643
|
return updatedTransfer;
|
|
22930
23644
|
}
|
|
22931
|
-
async signRefunds(leafDataMap, operatorSigningResults,
|
|
23645
|
+
async signRefunds(leafDataMap, operatorSigningResults, cpfpAdaptorPubKey, directAdaptorPubKey, directFromCpfpAdaptorPubKey) {
|
|
22932
23646
|
const nodeSignatures = [];
|
|
22933
23647
|
for (const operatorSigningResult of operatorSigningResults) {
|
|
22934
23648
|
const leafData = leafDataMap.get(operatorSigningResult.leafId);
|
|
@@ -22943,54 +23657,120 @@ var BaseTransferService = class {
|
|
|
22943
23657
|
`Output not found for leaf ${operatorSigningResult.leafId}`
|
|
22944
23658
|
);
|
|
22945
23659
|
}
|
|
22946
|
-
const
|
|
23660
|
+
const cpfpRefundTxSighash = getSigHashFromTx(
|
|
23661
|
+
leafData.refundTx,
|
|
23662
|
+
0,
|
|
23663
|
+
txOutput
|
|
23664
|
+
);
|
|
22947
23665
|
const publicKey = await this.config.signer.getPublicKeyFromDerivation(
|
|
22948
23666
|
leafData.keyDerivation
|
|
22949
23667
|
);
|
|
22950
|
-
const
|
|
22951
|
-
message:
|
|
23668
|
+
const cpfpUserSignature = await this.config.signer.signFrost({
|
|
23669
|
+
message: cpfpRefundTxSighash,
|
|
22952
23670
|
publicKey,
|
|
22953
23671
|
keyDerivation: leafData.keyDerivation,
|
|
22954
23672
|
selfCommitment: leafData.signingNonceCommitment,
|
|
22955
23673
|
statechainCommitments: operatorSigningResult.refundTxSigningResult?.signingNonceCommitments,
|
|
22956
|
-
adaptorPubKey,
|
|
23674
|
+
adaptorPubKey: cpfpAdaptorPubKey,
|
|
22957
23675
|
verifyingKey: operatorSigningResult.verifyingKey
|
|
22958
23676
|
});
|
|
22959
|
-
const
|
|
22960
|
-
message:
|
|
23677
|
+
const cpfpRefundAggregate = await this.config.signer.aggregateFrost({
|
|
23678
|
+
message: cpfpRefundTxSighash,
|
|
22961
23679
|
statechainSignatures: operatorSigningResult.refundTxSigningResult?.signatureShares,
|
|
22962
23680
|
statechainPublicKeys: operatorSigningResult.refundTxSigningResult?.publicKeys,
|
|
22963
23681
|
verifyingKey: operatorSigningResult.verifyingKey,
|
|
22964
23682
|
statechainCommitments: operatorSigningResult.refundTxSigningResult?.signingNonceCommitments,
|
|
22965
23683
|
selfCommitment: leafData.signingNonceCommitment,
|
|
22966
23684
|
publicKey,
|
|
22967
|
-
selfSignature:
|
|
22968
|
-
adaptorPubKey
|
|
23685
|
+
selfSignature: cpfpUserSignature,
|
|
23686
|
+
adaptorPubKey: cpfpAdaptorPubKey
|
|
22969
23687
|
});
|
|
23688
|
+
let directRefundAggregate;
|
|
23689
|
+
let directFromCpfpRefundAggregate;
|
|
23690
|
+
if (leafData.directTx) {
|
|
23691
|
+
const directTxOutput = leafData.directTx.getOutput(0);
|
|
23692
|
+
if (leafData.directRefundTx) {
|
|
23693
|
+
const directRefundTxSighash = getSigHashFromTx(
|
|
23694
|
+
leafData.directRefundTx,
|
|
23695
|
+
0,
|
|
23696
|
+
directTxOutput
|
|
23697
|
+
);
|
|
23698
|
+
const directUserSignature = await this.config.signer.signFrost({
|
|
23699
|
+
message: directRefundTxSighash,
|
|
23700
|
+
publicKey,
|
|
23701
|
+
keyDerivation: leafData.keyDerivation,
|
|
23702
|
+
selfCommitment: leafData.directSigningNonceCommitment,
|
|
23703
|
+
statechainCommitments: operatorSigningResult.directRefundTxSigningResult?.signingNonceCommitments,
|
|
23704
|
+
adaptorPubKey: directAdaptorPubKey,
|
|
23705
|
+
verifyingKey: operatorSigningResult.verifyingKey
|
|
23706
|
+
});
|
|
23707
|
+
directRefundAggregate = await this.config.signer.aggregateFrost({
|
|
23708
|
+
message: directRefundTxSighash,
|
|
23709
|
+
statechainSignatures: operatorSigningResult.directRefundTxSigningResult?.signatureShares,
|
|
23710
|
+
statechainPublicKeys: operatorSigningResult.directRefundTxSigningResult?.publicKeys,
|
|
23711
|
+
verifyingKey: operatorSigningResult.verifyingKey,
|
|
23712
|
+
statechainCommitments: operatorSigningResult.directRefundTxSigningResult?.signingNonceCommitments,
|
|
23713
|
+
selfCommitment: leafData.directSigningNonceCommitment,
|
|
23714
|
+
publicKey,
|
|
23715
|
+
selfSignature: directUserSignature,
|
|
23716
|
+
adaptorPubKey: directAdaptorPubKey
|
|
23717
|
+
});
|
|
23718
|
+
}
|
|
23719
|
+
if (leafData.directFromCpfpRefundTx) {
|
|
23720
|
+
const directFromCpfpRefundTxSighash = getSigHashFromTx(
|
|
23721
|
+
leafData.directFromCpfpRefundTx,
|
|
23722
|
+
0,
|
|
23723
|
+
txOutput
|
|
23724
|
+
);
|
|
23725
|
+
const directFromCpfpUserSignature = await this.config.signer.signFrost({
|
|
23726
|
+
message: directFromCpfpRefundTxSighash,
|
|
23727
|
+
publicKey,
|
|
23728
|
+
keyDerivation: leafData.keyDerivation,
|
|
23729
|
+
selfCommitment: leafData.directFromCpfpRefundSigningNonceCommitment,
|
|
23730
|
+
statechainCommitments: operatorSigningResult.directFromCpfpRefundTxSigningResult?.signingNonceCommitments,
|
|
23731
|
+
adaptorPubKey: directFromCpfpAdaptorPubKey,
|
|
23732
|
+
verifyingKey: operatorSigningResult.verifyingKey
|
|
23733
|
+
});
|
|
23734
|
+
directFromCpfpRefundAggregate = await this.config.signer.aggregateFrost({
|
|
23735
|
+
message: directFromCpfpRefundTxSighash,
|
|
23736
|
+
statechainSignatures: operatorSigningResult.directFromCpfpRefundTxSigningResult?.signatureShares,
|
|
23737
|
+
statechainPublicKeys: operatorSigningResult.directFromCpfpRefundTxSigningResult?.publicKeys,
|
|
23738
|
+
verifyingKey: operatorSigningResult.verifyingKey,
|
|
23739
|
+
statechainCommitments: operatorSigningResult.directFromCpfpRefundTxSigningResult?.signingNonceCommitments,
|
|
23740
|
+
selfCommitment: leafData.directFromCpfpRefundSigningNonceCommitment,
|
|
23741
|
+
publicKey,
|
|
23742
|
+
selfSignature: directFromCpfpUserSignature,
|
|
23743
|
+
adaptorPubKey: directFromCpfpAdaptorPubKey
|
|
23744
|
+
});
|
|
23745
|
+
}
|
|
23746
|
+
}
|
|
22970
23747
|
nodeSignatures.push({
|
|
22971
23748
|
nodeId: operatorSigningResult.leafId,
|
|
22972
|
-
refundTxSignature: refundAggregate,
|
|
22973
23749
|
nodeTxSignature: new Uint8Array(),
|
|
22974
|
-
// TODO: Add direct refund signature
|
|
22975
23750
|
directNodeTxSignature: new Uint8Array(),
|
|
22976
|
-
|
|
22977
|
-
|
|
23751
|
+
refundTxSignature: cpfpRefundAggregate,
|
|
23752
|
+
directRefundTxSignature: directRefundAggregate ?? new Uint8Array(),
|
|
23753
|
+
directFromCpfpRefundTxSignature: directFromCpfpRefundAggregate ?? new Uint8Array()
|
|
22978
23754
|
});
|
|
22979
23755
|
}
|
|
22980
23756
|
return nodeSignatures;
|
|
22981
23757
|
}
|
|
22982
|
-
async prepareSendTransferKeyTweaks(transferID, receiverIdentityPubkey, leaves,
|
|
23758
|
+
async prepareSendTransferKeyTweaks(transferID, receiverIdentityPubkey, leaves, cpfpRefundSignatureMap, directRefundSignatureMap, directFromCpfpRefundSignatureMap) {
|
|
22983
23759
|
const receiverEciesPubKey = ecies2.PublicKey.fromHex(
|
|
22984
23760
|
bytesToHex10(receiverIdentityPubkey)
|
|
22985
23761
|
);
|
|
22986
23762
|
const leavesTweaksMap = /* @__PURE__ */ new Map();
|
|
22987
23763
|
for (const leaf of leaves) {
|
|
22988
|
-
const
|
|
23764
|
+
const cpfpRefundSignature = cpfpRefundSignatureMap.get(leaf.leaf.id);
|
|
23765
|
+
const directRefundSignature = directRefundSignatureMap.get(leaf.leaf.id);
|
|
23766
|
+
const directFromCpfpRefundSignature = directFromCpfpRefundSignatureMap.get(leaf.leaf.id);
|
|
22989
23767
|
const leafTweaksMap = await this.prepareSingleSendTransferKeyTweak(
|
|
22990
23768
|
transferID,
|
|
22991
23769
|
leaf,
|
|
22992
23770
|
receiverEciesPubKey,
|
|
22993
|
-
|
|
23771
|
+
cpfpRefundSignature,
|
|
23772
|
+
directRefundSignature,
|
|
23773
|
+
directFromCpfpRefundSignature
|
|
22994
23774
|
);
|
|
22995
23775
|
for (const [identifier, leafTweak] of leafTweaksMap) {
|
|
22996
23776
|
leavesTweaksMap.set(identifier, [
|
|
@@ -23001,7 +23781,7 @@ var BaseTransferService = class {
|
|
|
23001
23781
|
}
|
|
23002
23782
|
return leavesTweaksMap;
|
|
23003
23783
|
}
|
|
23004
|
-
async prepareSingleSendTransferKeyTweak(transferID, leaf, receiverEciesPubKey,
|
|
23784
|
+
async prepareSingleSendTransferKeyTweak(transferID, leaf, receiverEciesPubKey, cpfpRefundSignature, directRefundSignature, directFromCpfpRefundSignature) {
|
|
23005
23785
|
const signingOperators = this.config.getSigningOperators();
|
|
23006
23786
|
const { shares, secretCipher } = await this.config.signer.subtractSplitAndEncrypt({
|
|
23007
23787
|
first: leaf.keyDerivation,
|
|
@@ -23049,10 +23829,9 @@ var BaseTransferService = class {
|
|
|
23049
23829
|
pubkeySharesTweak: Object.fromEntries(pubkeySharesTweak),
|
|
23050
23830
|
secretCipher,
|
|
23051
23831
|
signature,
|
|
23052
|
-
refundSignature:
|
|
23053
|
-
|
|
23054
|
-
|
|
23055
|
-
directFromCpfpRefundSignature: new Uint8Array()
|
|
23832
|
+
refundSignature: cpfpRefundSignature ?? new Uint8Array(),
|
|
23833
|
+
directRefundSignature: directRefundSignature ?? new Uint8Array(),
|
|
23834
|
+
directFromCpfpRefundSignature: directFromCpfpRefundSignature ?? new Uint8Array()
|
|
23056
23835
|
});
|
|
23057
23836
|
}
|
|
23058
23837
|
return leafTweaksMap;
|
|
@@ -23082,7 +23861,12 @@ var TransferService = class extends BaseTransferService {
|
|
|
23082
23861
|
* Deprecated in v0.1.32
|
|
23083
23862
|
*/
|
|
23084
23863
|
async sendTransfer(leaves, receiverIdentityPubkey) {
|
|
23085
|
-
const {
|
|
23864
|
+
const {
|
|
23865
|
+
transfer,
|
|
23866
|
+
signatureMap,
|
|
23867
|
+
directSignatureMap,
|
|
23868
|
+
directFromCpfpSignatureMap
|
|
23869
|
+
} = await this.sendTransferSignRefund(
|
|
23086
23870
|
leaves,
|
|
23087
23871
|
receiverIdentityPubkey,
|
|
23088
23872
|
new Date(Date.now() + DEFAULT_EXPIRY_TIME)
|
|
@@ -23090,7 +23874,9 @@ var TransferService = class extends BaseTransferService {
|
|
|
23090
23874
|
const transferWithTweakedKeys = await this.sendTransferTweakKey(
|
|
23091
23875
|
transfer,
|
|
23092
23876
|
leaves,
|
|
23093
|
-
signatureMap
|
|
23877
|
+
signatureMap,
|
|
23878
|
+
directSignatureMap,
|
|
23879
|
+
directFromCpfpSignatureMap
|
|
23094
23880
|
);
|
|
23095
23881
|
return transferWithTweakedKeys;
|
|
23096
23882
|
}
|
|
@@ -23194,7 +23980,13 @@ var TransferService = class extends BaseTransferService {
|
|
|
23194
23980
|
return transferResp.transfers[0];
|
|
23195
23981
|
}
|
|
23196
23982
|
async sendTransferSignRefund(leaves, receiverIdentityPubkey, expiryTime) {
|
|
23197
|
-
const {
|
|
23983
|
+
const {
|
|
23984
|
+
transfer,
|
|
23985
|
+
signatureMap,
|
|
23986
|
+
directSignatureMap,
|
|
23987
|
+
directFromCpfpSignatureMap,
|
|
23988
|
+
leafDataMap
|
|
23989
|
+
} = await this.sendTransferSignRefundInternal(
|
|
23198
23990
|
leaves,
|
|
23199
23991
|
receiverIdentityPubkey,
|
|
23200
23992
|
expiryTime,
|
|
@@ -23203,11 +23995,19 @@ var TransferService = class extends BaseTransferService {
|
|
|
23203
23995
|
return {
|
|
23204
23996
|
transfer,
|
|
23205
23997
|
signatureMap,
|
|
23998
|
+
directSignatureMap,
|
|
23999
|
+
directFromCpfpSignatureMap,
|
|
23206
24000
|
leafDataMap
|
|
23207
24001
|
};
|
|
23208
24002
|
}
|
|
23209
24003
|
async startSwapSignRefund(leaves, receiverIdentityPubkey, expiryTime) {
|
|
23210
|
-
const {
|
|
24004
|
+
const {
|
|
24005
|
+
transfer,
|
|
24006
|
+
signatureMap,
|
|
24007
|
+
directSignatureMap,
|
|
24008
|
+
directFromCpfpSignatureMap,
|
|
24009
|
+
leafDataMap
|
|
24010
|
+
} = await this.sendTransferSignRefundInternal(
|
|
23211
24011
|
leaves,
|
|
23212
24012
|
receiverIdentityPubkey,
|
|
23213
24013
|
expiryTime,
|
|
@@ -23216,31 +24016,45 @@ var TransferService = class extends BaseTransferService {
|
|
|
23216
24016
|
return {
|
|
23217
24017
|
transfer,
|
|
23218
24018
|
signatureMap,
|
|
24019
|
+
directSignatureMap,
|
|
24020
|
+
directFromCpfpSignatureMap,
|
|
23219
24021
|
leafDataMap
|
|
23220
24022
|
};
|
|
23221
24023
|
}
|
|
23222
|
-
async counterSwapSignRefund(leaves, receiverIdentityPubkey, expiryTime,
|
|
24024
|
+
async counterSwapSignRefund(leaves, receiverIdentityPubkey, expiryTime, cpfpAdaptorPubKey, directAdaptorPubKey, directFromCpfpAdaptorPubKey) {
|
|
23223
24025
|
return this.sendTransferSignRefundInternal(
|
|
23224
24026
|
leaves,
|
|
23225
24027
|
receiverIdentityPubkey,
|
|
23226
24028
|
expiryTime,
|
|
23227
24029
|
true,
|
|
23228
|
-
|
|
24030
|
+
cpfpAdaptorPubKey,
|
|
24031
|
+
directAdaptorPubKey,
|
|
24032
|
+
directFromCpfpAdaptorPubKey
|
|
23229
24033
|
);
|
|
23230
24034
|
}
|
|
23231
|
-
async sendTransferSignRefundInternal(leaves, receiverIdentityPubkey, expiryTime, forSwap,
|
|
24035
|
+
async sendTransferSignRefundInternal(leaves, receiverIdentityPubkey, expiryTime, forSwap, cpfpAdaptorPubKey, directAdaptorPubKey, directFromCpfpAdaptorPubKey) {
|
|
23232
24036
|
const transferId = uuidv72();
|
|
23233
24037
|
const leafDataMap = /* @__PURE__ */ new Map();
|
|
23234
24038
|
for (const leaf of leaves) {
|
|
23235
24039
|
const signingNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
24040
|
+
const directSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
24041
|
+
const directFromCpfpRefundSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
23236
24042
|
const tx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
23237
24043
|
const refundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
24044
|
+
const directTx = leaf.leaf.directTx.length > 0 ? getTxFromRawTxBytes(leaf.leaf.directTx) : void 0;
|
|
24045
|
+
const directRefundTx = leaf.leaf.directRefundTx.length > 0 ? getTxFromRawTxBytes(leaf.leaf.directRefundTx) : void 0;
|
|
24046
|
+
const directFromCpfpRefundTx = leaf.leaf.directFromCpfpRefundTx.length > 0 ? getTxFromRawTxBytes(leaf.leaf.directFromCpfpRefundTx) : void 0;
|
|
23238
24047
|
leafDataMap.set(leaf.leaf.id, {
|
|
23239
24048
|
keyDerivation: leaf.keyDerivation,
|
|
23240
24049
|
receivingPubkey: receiverIdentityPubkey,
|
|
23241
24050
|
signingNonceCommitment,
|
|
24051
|
+
directSigningNonceCommitment,
|
|
23242
24052
|
tx,
|
|
24053
|
+
directTx,
|
|
23243
24054
|
refundTx,
|
|
24055
|
+
directRefundTx,
|
|
24056
|
+
directFromCpfpRefundTx,
|
|
24057
|
+
directFromCpfpRefundSigningNonceCommitment,
|
|
23244
24058
|
vout: leaf.leaf.vout
|
|
23245
24059
|
});
|
|
23246
24060
|
}
|
|
@@ -23253,8 +24067,8 @@ var TransferService = class extends BaseTransferService {
|
|
|
23253
24067
|
);
|
|
23254
24068
|
let response;
|
|
23255
24069
|
try {
|
|
23256
|
-
if (
|
|
23257
|
-
response = await sparkClient.
|
|
24070
|
+
if (cpfpAdaptorPubKey !== void 0 || directAdaptorPubKey !== void 0 || directFromCpfpAdaptorPubKey !== void 0) {
|
|
24071
|
+
response = await sparkClient.counter_leaf_swap_v2({
|
|
23258
24072
|
transfer: {
|
|
23259
24073
|
transferId,
|
|
23260
24074
|
leavesToSend: signingJobs,
|
|
@@ -23263,10 +24077,12 @@ var TransferService = class extends BaseTransferService {
|
|
|
23263
24077
|
expiryTime
|
|
23264
24078
|
},
|
|
23265
24079
|
swapId: uuidv72(),
|
|
23266
|
-
adaptorPublicKey:
|
|
24080
|
+
adaptorPublicKey: cpfpAdaptorPubKey,
|
|
24081
|
+
directAdaptorPublicKey: directAdaptorPubKey,
|
|
24082
|
+
directFromCpfpAdaptorPublicKey: directFromCpfpAdaptorPubKey
|
|
23267
24083
|
});
|
|
23268
24084
|
} else if (forSwap) {
|
|
23269
|
-
response = await sparkClient.
|
|
24085
|
+
response = await sparkClient.start_leaf_swap_v2({
|
|
23270
24086
|
transferId,
|
|
23271
24087
|
leavesToSend: signingJobs,
|
|
23272
24088
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
@@ -23274,7 +24090,7 @@ var TransferService = class extends BaseTransferService {
|
|
|
23274
24090
|
expiryTime
|
|
23275
24091
|
});
|
|
23276
24092
|
} else {
|
|
23277
|
-
response = await sparkClient.
|
|
24093
|
+
response = await sparkClient.start_transfer_v2({
|
|
23278
24094
|
transferId,
|
|
23279
24095
|
leavesToSend: signingJobs,
|
|
23280
24096
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
@@ -23291,15 +24107,29 @@ var TransferService = class extends BaseTransferService {
|
|
|
23291
24107
|
const signatures = await this.signRefunds(
|
|
23292
24108
|
leafDataMap,
|
|
23293
24109
|
response.signingResults,
|
|
23294
|
-
|
|
24110
|
+
cpfpAdaptorPubKey,
|
|
24111
|
+
directAdaptorPubKey,
|
|
24112
|
+
directFromCpfpAdaptorPubKey
|
|
23295
24113
|
);
|
|
23296
|
-
const
|
|
24114
|
+
const cpfpSignatureMap = /* @__PURE__ */ new Map();
|
|
24115
|
+
const directSignatureMap = /* @__PURE__ */ new Map();
|
|
24116
|
+
const directFromCpfpSignatureMap = /* @__PURE__ */ new Map();
|
|
23297
24117
|
for (const signature of signatures) {
|
|
23298
|
-
|
|
24118
|
+
cpfpSignatureMap.set(signature.nodeId, signature.refundTxSignature);
|
|
24119
|
+
directSignatureMap.set(
|
|
24120
|
+
signature.nodeId,
|
|
24121
|
+
signature.directRefundTxSignature
|
|
24122
|
+
);
|
|
24123
|
+
directFromCpfpSignatureMap.set(
|
|
24124
|
+
signature.nodeId,
|
|
24125
|
+
signature.directFromCpfpRefundTxSignature
|
|
24126
|
+
);
|
|
23299
24127
|
}
|
|
23300
24128
|
return {
|
|
23301
24129
|
transfer: response.transfer,
|
|
23302
|
-
signatureMap,
|
|
24130
|
+
signatureMap: cpfpSignatureMap,
|
|
24131
|
+
directSignatureMap,
|
|
24132
|
+
directFromCpfpSignatureMap,
|
|
23303
24133
|
leafDataMap,
|
|
23304
24134
|
signingResults: response.signingResults
|
|
23305
24135
|
};
|
|
@@ -23312,38 +24142,68 @@ var TransferService = class extends BaseTransferService {
|
|
|
23312
24142
|
throw new Error(`Leaf data not found for leaf ${leaf.leaf.id}`);
|
|
23313
24143
|
}
|
|
23314
24144
|
const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
23315
|
-
const
|
|
24145
|
+
const cpfpNodeOutPoint = {
|
|
23316
24146
|
txid: hexToBytes6(getTxId(nodeTx)),
|
|
23317
24147
|
index: 0
|
|
23318
24148
|
};
|
|
24149
|
+
let directNodeTx;
|
|
24150
|
+
let directNodeOutPoint;
|
|
24151
|
+
if (leaf.leaf.directTx.length > 0) {
|
|
24152
|
+
directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
|
|
24153
|
+
directNodeOutPoint = {
|
|
24154
|
+
txid: hexToBytes6(getTxId(directNodeTx)),
|
|
24155
|
+
index: 0
|
|
24156
|
+
};
|
|
24157
|
+
}
|
|
23319
24158
|
const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
23320
|
-
const
|
|
24159
|
+
const sequence = currRefundTx.getInput(0).sequence;
|
|
24160
|
+
if (!sequence) {
|
|
24161
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
24162
|
+
field: "sequence",
|
|
24163
|
+
value: currRefundTx.getInput(0),
|
|
24164
|
+
expected: "Non-null sequence"
|
|
24165
|
+
});
|
|
24166
|
+
}
|
|
24167
|
+
const { nextSequence, nextDirectSequence } = isForClaim ? getTransactionSequence(sequence) : getNextTransactionSequence(sequence);
|
|
23321
24168
|
const amountSats = currRefundTx.getOutput(0).amount;
|
|
23322
24169
|
if (amountSats === void 0) {
|
|
23323
24170
|
throw new Error("Amount not found in signRefunds");
|
|
23324
24171
|
}
|
|
23325
|
-
const
|
|
23326
|
-
nextSequence,
|
|
23327
|
-
|
|
24172
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
24173
|
+
sequence: nextSequence,
|
|
24174
|
+
directSequence: nextDirectSequence,
|
|
24175
|
+
input: cpfpNodeOutPoint,
|
|
24176
|
+
directInput: directNodeOutPoint,
|
|
23328
24177
|
amountSats,
|
|
23329
|
-
refundSigningData.receivingPubkey,
|
|
23330
|
-
this.config.getNetwork()
|
|
24178
|
+
receivingPubkey: refundSigningData.receivingPubkey,
|
|
24179
|
+
network: this.config.getNetwork()
|
|
24180
|
+
});
|
|
24181
|
+
refundSigningData.refundTx = cpfpRefundTx;
|
|
24182
|
+
refundSigningData.directRefundTx = directRefundTx;
|
|
24183
|
+
refundSigningData.directFromCpfpRefundTx = directFromCpfpRefundTx;
|
|
24184
|
+
const cpfpRefundNonceCommitmentProto = refundSigningData.signingNonceCommitment;
|
|
24185
|
+
const directRefundNonceCommitmentProto = refundSigningData.directSigningNonceCommitment;
|
|
24186
|
+
const directFromCpfpRefundNonceCommitmentProto = refundSigningData.directFromCpfpRefundSigningNonceCommitment;
|
|
24187
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(
|
|
24188
|
+
refundSigningData.keyDerivation
|
|
23331
24189
|
);
|
|
23332
|
-
refundSigningData.refundTx = refundTx;
|
|
23333
|
-
const refundNonceCommitmentProto = refundSigningData.signingNonceCommitment;
|
|
23334
24190
|
signingJobs.push({
|
|
23335
24191
|
leafId: leaf.leaf.id,
|
|
23336
24192
|
refundTxSigningJob: {
|
|
23337
|
-
signingPublicKey
|
|
23338
|
-
|
|
23339
|
-
|
|
23340
|
-
rawTx: refundTx.toBytes(),
|
|
23341
|
-
signingNonceCommitment: refundNonceCommitmentProto.commitment
|
|
24193
|
+
signingPublicKey,
|
|
24194
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
24195
|
+
signingNonceCommitment: cpfpRefundNonceCommitmentProto.commitment
|
|
23342
24196
|
},
|
|
23343
|
-
|
|
23344
|
-
|
|
23345
|
-
|
|
23346
|
-
|
|
24197
|
+
directRefundTxSigningJob: directRefundTx ? {
|
|
24198
|
+
signingPublicKey,
|
|
24199
|
+
rawTx: directRefundTx.toBytes(),
|
|
24200
|
+
signingNonceCommitment: directRefundNonceCommitmentProto.commitment
|
|
24201
|
+
} : void 0,
|
|
24202
|
+
directFromCpfpRefundTxSigningJob: directFromCpfpRefundTx ? {
|
|
24203
|
+
signingPublicKey,
|
|
24204
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
24205
|
+
signingNonceCommitment: directFromCpfpRefundNonceCommitmentProto.commitment
|
|
24206
|
+
} : void 0
|
|
23347
24207
|
});
|
|
23348
24208
|
}
|
|
23349
24209
|
return signingJobs;
|
|
@@ -23464,13 +24324,17 @@ var TransferService = class extends BaseTransferService {
|
|
|
23464
24324
|
const leafDataMap = /* @__PURE__ */ new Map();
|
|
23465
24325
|
for (const leafKey of leafKeys) {
|
|
23466
24326
|
const tx = getTxFromRawTxBytes(leafKey.leaf.nodeTx);
|
|
24327
|
+
const directTx = leafKey.leaf.directTx.length > 0 ? getTxFromRawTxBytes(leafKey.leaf.directTx) : void 0;
|
|
23467
24328
|
leafDataMap.set(leafKey.leaf.id, {
|
|
23468
24329
|
keyDerivation: leafKey.newKeyDerivation,
|
|
23469
24330
|
receivingPubkey: await this.config.signer.getPublicKeyFromDerivation(
|
|
23470
24331
|
leafKey.newKeyDerivation
|
|
23471
24332
|
),
|
|
23472
24333
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24334
|
+
directSigningNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24335
|
+
directFromCpfpRefundSigningNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
23473
24336
|
tx,
|
|
24337
|
+
directTx,
|
|
23474
24338
|
vout: leafKey.leaf.vout
|
|
23475
24339
|
});
|
|
23476
24340
|
}
|
|
@@ -23492,7 +24356,7 @@ var TransferService = class extends BaseTransferService {
|
|
|
23492
24356
|
}
|
|
23493
24357
|
}
|
|
23494
24358
|
try {
|
|
23495
|
-
resp = await sparkClient.
|
|
24359
|
+
resp = await sparkClient.claim_transfer_sign_refunds_v2({
|
|
23496
24360
|
transferId: transfer.id,
|
|
23497
24361
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
23498
24362
|
signingJobs
|
|
@@ -23507,7 +24371,7 @@ var TransferService = class extends BaseTransferService {
|
|
|
23507
24371
|
this.config.getCoordinatorAddress()
|
|
23508
24372
|
);
|
|
23509
24373
|
try {
|
|
23510
|
-
return await sparkClient.
|
|
24374
|
+
return await sparkClient.finalize_node_signatures_v2({
|
|
23511
24375
|
intent: 1 /* TRANSFER */,
|
|
23512
24376
|
nodeSignatures
|
|
23513
24377
|
});
|
|
@@ -23546,109 +24410,134 @@ var TransferService = class extends BaseTransferService {
|
|
|
23546
24410
|
throw new Error(`Error querying pending transfers by sender: ${error}`);
|
|
23547
24411
|
}
|
|
23548
24412
|
}
|
|
23549
|
-
async
|
|
23550
|
-
if (nodes.length === 0) {
|
|
23551
|
-
throw Error("no nodes to refresh");
|
|
23552
|
-
}
|
|
24413
|
+
async refreshTimelockNodesInternal(node, parentNode, useTestUnilateralSequence) {
|
|
23553
24414
|
const signingJobs = [];
|
|
23554
|
-
const
|
|
23555
|
-
|
|
23556
|
-
|
|
23557
|
-
|
|
23558
|
-
|
|
23559
|
-
|
|
23560
|
-
|
|
23561
|
-
|
|
23562
|
-
|
|
23563
|
-
|
|
23564
|
-
|
|
23565
|
-
|
|
23566
|
-
|
|
23567
|
-
|
|
23568
|
-
|
|
23569
|
-
|
|
23570
|
-
|
|
23571
|
-
|
|
23572
|
-
|
|
24415
|
+
const parentNodeTx = getTxFromRawTxBytes(parentNode.nodeTx);
|
|
24416
|
+
const parentNodeOutput = parentNodeTx.getOutput(0);
|
|
24417
|
+
if (!parentNodeOutput) {
|
|
24418
|
+
throw Error("Could not get parent node output");
|
|
24419
|
+
}
|
|
24420
|
+
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
24421
|
+
const nodeInput = nodeTx.getInput(0);
|
|
24422
|
+
const nodeOutput = nodeTx.getOutput(0);
|
|
24423
|
+
if (!nodeOutput) {
|
|
24424
|
+
throw Error("Could not get node output");
|
|
24425
|
+
}
|
|
24426
|
+
let directNodeTx;
|
|
24427
|
+
let directNodeInput;
|
|
24428
|
+
if (node.directTx.length > 0) {
|
|
24429
|
+
directNodeTx = getTxFromRawTxBytes(node.directTx);
|
|
24430
|
+
directNodeInput = directNodeTx.getInput(0);
|
|
24431
|
+
}
|
|
24432
|
+
const currSequence = nodeInput.sequence;
|
|
24433
|
+
if (!currSequence) {
|
|
24434
|
+
throw new ValidationError("Invalid node transaction", {
|
|
24435
|
+
field: "sequence",
|
|
24436
|
+
value: nodeInput,
|
|
24437
|
+
expected: "Non-null sequence"
|
|
23573
24438
|
});
|
|
23574
|
-
|
|
23575
|
-
|
|
23576
|
-
|
|
23577
|
-
|
|
23578
|
-
|
|
23579
|
-
|
|
23580
|
-
|
|
23581
|
-
|
|
23582
|
-
|
|
23583
|
-
|
|
23584
|
-
|
|
23585
|
-
|
|
23586
|
-
|
|
23587
|
-
|
|
23588
|
-
|
|
23589
|
-
|
|
23590
|
-
|
|
23591
|
-
|
|
23592
|
-
|
|
24439
|
+
}
|
|
24440
|
+
let { nextSequence, nextDirectSequence } = getNextTransactionSequence(
|
|
24441
|
+
currSequence,
|
|
24442
|
+
true
|
|
24443
|
+
);
|
|
24444
|
+
const output = {
|
|
24445
|
+
script: parentNodeOutput.script,
|
|
24446
|
+
amount: parentNodeOutput.amount
|
|
24447
|
+
};
|
|
24448
|
+
const newNodeInput = {
|
|
24449
|
+
txid: nodeInput.txid,
|
|
24450
|
+
index: nodeInput.index,
|
|
24451
|
+
sequence: useTestUnilateralSequence ? TEST_UNILATERAL_SEQUENCE : nextSequence
|
|
24452
|
+
};
|
|
24453
|
+
const newDirectInput = directNodeTx && directNodeInput ? {
|
|
24454
|
+
txid: directNodeInput.txid,
|
|
24455
|
+
index: directNodeInput.index,
|
|
24456
|
+
sequence: useTestUnilateralSequence ? TEST_UNILATERAL_DIRECT_SEQUENCE : nextDirectSequence
|
|
24457
|
+
} : void 0;
|
|
24458
|
+
const { cpfpNodeTx, directNodeTx: newDirectNodeTx } = createNodeTxs(
|
|
24459
|
+
output,
|
|
24460
|
+
newNodeInput,
|
|
24461
|
+
newDirectInput
|
|
24462
|
+
);
|
|
24463
|
+
const newCpfpNodeOutput = cpfpNodeTx.getOutput(0);
|
|
24464
|
+
if (!newCpfpNodeOutput) {
|
|
24465
|
+
throw Error("Could not get new cpfp node output");
|
|
24466
|
+
}
|
|
24467
|
+
const newDirectNodeOutput = newDirectNodeTx?.getOutput(0);
|
|
24468
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation({
|
|
24469
|
+
type: "leaf" /* LEAF */,
|
|
24470
|
+
path: node.id
|
|
24471
|
+
});
|
|
24472
|
+
signingJobs.push({
|
|
24473
|
+
signingPublicKey,
|
|
24474
|
+
rawTx: cpfpNodeTx.toBytes(),
|
|
24475
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24476
|
+
type: "node",
|
|
24477
|
+
parentTxOut: parentNodeOutput
|
|
24478
|
+
});
|
|
24479
|
+
if (newDirectNodeTx) {
|
|
23593
24480
|
signingJobs.push({
|
|
23594
|
-
signingPublicKey
|
|
23595
|
-
|
|
23596
|
-
|
|
23597
|
-
|
|
23598
|
-
|
|
23599
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
24481
|
+
signingPublicKey,
|
|
24482
|
+
rawTx: newDirectNodeTx.toBytes(),
|
|
24483
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24484
|
+
type: "directNode",
|
|
24485
|
+
parentTxOut: parentNodeOutput
|
|
23600
24486
|
});
|
|
23601
|
-
newNodeTxs[i] = newTx;
|
|
23602
24487
|
}
|
|
23603
|
-
const
|
|
23604
|
-
|
|
23605
|
-
|
|
24488
|
+
const newCpfpRefundOutPoint = {
|
|
24489
|
+
txid: hexToBytes6(getTxId(cpfpNodeTx)),
|
|
24490
|
+
index: 0
|
|
24491
|
+
};
|
|
24492
|
+
let newDirectRefundOutPoint;
|
|
24493
|
+
if (newDirectNodeTx) {
|
|
24494
|
+
newDirectRefundOutPoint = {
|
|
24495
|
+
txid: hexToBytes6(getTxId(newDirectNodeTx)),
|
|
24496
|
+
index: 0
|
|
24497
|
+
};
|
|
23606
24498
|
}
|
|
23607
|
-
const
|
|
23608
|
-
|
|
23609
|
-
|
|
23610
|
-
|
|
24499
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
24500
|
+
sequence: INITIAL_SEQUENCE,
|
|
24501
|
+
directSequence: INITIAL_DIRECT_SEQUENCE,
|
|
24502
|
+
input: newCpfpRefundOutPoint,
|
|
24503
|
+
directInput: newDirectRefundOutPoint,
|
|
24504
|
+
amountSats: nodeOutput.amount,
|
|
24505
|
+
receivingPubkey: await this.config.signer.getPublicKeyFromDerivation({
|
|
24506
|
+
type: "leaf" /* LEAF */,
|
|
24507
|
+
path: node.id
|
|
24508
|
+
}),
|
|
24509
|
+
network: this.config.getNetwork()
|
|
23611
24510
|
});
|
|
23612
|
-
|
|
23613
|
-
|
|
23614
|
-
|
|
23615
|
-
|
|
23616
|
-
|
|
23617
|
-
|
|
23618
|
-
amount: originalRefundOutput.amount
|
|
24511
|
+
signingJobs.push({
|
|
24512
|
+
signingPublicKey,
|
|
24513
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
24514
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24515
|
+
type: "cpfp",
|
|
24516
|
+
parentTxOut: newCpfpNodeOutput
|
|
23619
24517
|
});
|
|
23620
|
-
|
|
23621
|
-
|
|
23622
|
-
|
|
23623
|
-
|
|
23624
|
-
|
|
23625
|
-
|
|
23626
|
-
|
|
23627
|
-
|
|
23628
|
-
throw Error("refund tx doesn't have input");
|
|
24518
|
+
if (directRefundTx && newDirectNodeOutput) {
|
|
24519
|
+
signingJobs.push({
|
|
24520
|
+
signingPublicKey,
|
|
24521
|
+
rawTx: directRefundTx.toBytes(),
|
|
24522
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24523
|
+
type: "direct",
|
|
24524
|
+
parentTxOut: newDirectNodeOutput
|
|
24525
|
+
});
|
|
23629
24526
|
}
|
|
23630
|
-
if (
|
|
23631
|
-
|
|
24527
|
+
if (directFromCpfpRefundTx && newCpfpNodeOutput) {
|
|
24528
|
+
signingJobs.push({
|
|
24529
|
+
signingPublicKey,
|
|
24530
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
24531
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24532
|
+
type: "directFromCpfp",
|
|
24533
|
+
parentTxOut: newCpfpNodeOutput
|
|
24534
|
+
});
|
|
23632
24535
|
}
|
|
23633
|
-
newRefundTx.addInput({
|
|
23634
|
-
...refundTxInput,
|
|
23635
|
-
sequence: initialSequence(),
|
|
23636
|
-
txid: getTxId(newNodeTxs[newNodeTxs.length - 1])
|
|
23637
|
-
});
|
|
23638
|
-
const refundSigningJob = {
|
|
23639
|
-
signingPublicKey: await this.config.signer.getPublicKeyFromDerivation({
|
|
23640
|
-
type: "leaf" /* LEAF */,
|
|
23641
|
-
path: leaf.id
|
|
23642
|
-
}),
|
|
23643
|
-
rawTx: newRefundTx.toBytes(),
|
|
23644
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
23645
|
-
};
|
|
23646
|
-
signingJobs.push(refundSigningJob);
|
|
23647
24536
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
23648
24537
|
this.config.getCoordinatorAddress()
|
|
23649
24538
|
);
|
|
23650
|
-
const response = await sparkClient.
|
|
23651
|
-
leafId:
|
|
24539
|
+
const response = await sparkClient.refresh_timelock_v2({
|
|
24540
|
+
leafId: node.id,
|
|
23652
24541
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
23653
24542
|
signingJobs: signingJobs.map(getSigningJobProto)
|
|
23654
24543
|
});
|
|
@@ -23658,45 +24547,27 @@ var TransferService = class extends BaseTransferService {
|
|
|
23658
24547
|
);
|
|
23659
24548
|
}
|
|
23660
24549
|
let nodeSignatures = [];
|
|
23661
|
-
let
|
|
23662
|
-
let
|
|
23663
|
-
let
|
|
23664
|
-
|
|
23665
|
-
|
|
24550
|
+
let leafCpfpSignature;
|
|
24551
|
+
let leafDirectSignature;
|
|
24552
|
+
let cpfpRefundSignature;
|
|
24553
|
+
let directRefundSignature;
|
|
24554
|
+
let directFromCpfpRefundSignature;
|
|
24555
|
+
for (const [i, signingResult] of response.signingResults.entries()) {
|
|
23666
24556
|
const signingJob = signingJobs[i];
|
|
23667
24557
|
if (!signingJob || !signingResult) {
|
|
23668
24558
|
throw Error("Signing job does not exist");
|
|
23669
24559
|
}
|
|
23670
|
-
if (!signingJob.signingNonceCommitment) {
|
|
23671
|
-
throw Error("nonce commitment does not exist");
|
|
23672
|
-
}
|
|
23673
24560
|
const rawTx = getTxFromRawTxBytes(signingJob.rawTx);
|
|
23674
|
-
|
|
23675
|
-
|
|
23676
|
-
|
|
23677
|
-
if (i === nodes.length) {
|
|
23678
|
-
nodeId = nodes[i - 1]?.id;
|
|
23679
|
-
parentTx = newNodeTxs[i - 1];
|
|
23680
|
-
vout = 0;
|
|
23681
|
-
} else if (i === 0) {
|
|
23682
|
-
nodeId = nodes[i]?.id;
|
|
23683
|
-
parentTx = getTxFromRawTxBytes(parentNode.nodeTx);
|
|
23684
|
-
vout = nodes[i]?.vout;
|
|
23685
|
-
} else {
|
|
23686
|
-
nodeId = nodes[i]?.id;
|
|
23687
|
-
parentTx = newNodeTxs[i - 1];
|
|
23688
|
-
vout = nodes[i]?.vout;
|
|
24561
|
+
const txOut = signingJob.parentTxOut;
|
|
24562
|
+
if (!txOut) {
|
|
24563
|
+
throw Error("Could not get tx out");
|
|
23689
24564
|
}
|
|
23690
|
-
if (!parentTx || !nodeId || vout === void 0) {
|
|
23691
|
-
throw Error("Could not parse signing results");
|
|
23692
|
-
}
|
|
23693
|
-
const txOut = parentTx.getOutput(vout);
|
|
23694
24565
|
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
23695
24566
|
const userSignature = await this.config.signer.signFrost({
|
|
23696
24567
|
message: rawTxSighash,
|
|
23697
24568
|
keyDerivation: {
|
|
23698
24569
|
type: "leaf" /* LEAF */,
|
|
23699
|
-
path:
|
|
24570
|
+
path: node.id
|
|
23700
24571
|
},
|
|
23701
24572
|
publicKey: signingJob.signingPublicKey,
|
|
23702
24573
|
verifyingKey: signingResult.verifyingKey,
|
|
@@ -23715,41 +24586,35 @@ var TransferService = class extends BaseTransferService {
|
|
|
23715
24586
|
selfSignature: userSignature,
|
|
23716
24587
|
adaptorPubKey: new Uint8Array()
|
|
23717
24588
|
});
|
|
23718
|
-
if (
|
|
23719
|
-
|
|
23720
|
-
|
|
23721
|
-
|
|
23722
|
-
|
|
23723
|
-
|
|
23724
|
-
|
|
23725
|
-
|
|
23726
|
-
|
|
23727
|
-
|
|
23728
|
-
} else if (i === nodes.length) {
|
|
23729
|
-
refundSignature = signature;
|
|
23730
|
-
} else if (i === nodes.length - 1) {
|
|
23731
|
-
leafNodeId = nodeId;
|
|
23732
|
-
leafSignature = signature;
|
|
24589
|
+
if (signingJob.type === "node") {
|
|
24590
|
+
leafCpfpSignature = signature;
|
|
24591
|
+
} else if (signingJob.type === "directNode") {
|
|
24592
|
+
leafDirectSignature = signature;
|
|
24593
|
+
} else if (signingJob.type === "cpfp") {
|
|
24594
|
+
cpfpRefundSignature = signature;
|
|
24595
|
+
} else if (signingJob.type === "direct") {
|
|
24596
|
+
directRefundSignature = signature;
|
|
24597
|
+
} else if (signingJob.type === "directFromCpfp") {
|
|
24598
|
+
directFromCpfpRefundSignature = signature;
|
|
23733
24599
|
}
|
|
23734
24600
|
}
|
|
23735
|
-
if (!leafSignature || !refundSignature || !leafNodeId) {
|
|
23736
|
-
throw Error("leaf or refund signature does not exist");
|
|
23737
|
-
}
|
|
23738
24601
|
nodeSignatures.push({
|
|
23739
|
-
nodeId:
|
|
23740
|
-
nodeTxSignature:
|
|
23741
|
-
|
|
23742
|
-
|
|
23743
|
-
|
|
23744
|
-
|
|
23745
|
-
directFromCpfpRefundTxSignature: new Uint8Array()
|
|
24602
|
+
nodeId: node.id,
|
|
24603
|
+
nodeTxSignature: leafCpfpSignature || new Uint8Array(),
|
|
24604
|
+
directNodeTxSignature: leafDirectSignature || new Uint8Array(),
|
|
24605
|
+
refundTxSignature: cpfpRefundSignature || new Uint8Array(),
|
|
24606
|
+
directRefundTxSignature: directRefundSignature || new Uint8Array(),
|
|
24607
|
+
directFromCpfpRefundTxSignature: directFromCpfpRefundSignature || new Uint8Array()
|
|
23746
24608
|
});
|
|
23747
|
-
const result = await sparkClient.
|
|
24609
|
+
const result = await sparkClient.finalize_node_signatures_v2({
|
|
23748
24610
|
intent: 3 /* REFRESH */,
|
|
23749
24611
|
nodeSignatures
|
|
23750
24612
|
});
|
|
23751
24613
|
return result;
|
|
23752
24614
|
}
|
|
24615
|
+
async refreshTimelockNodes(node, parentNode) {
|
|
24616
|
+
return await this.refreshTimelockNodesInternal(node, parentNode);
|
|
24617
|
+
}
|
|
23753
24618
|
async extendTimelock(node) {
|
|
23754
24619
|
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
23755
24620
|
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
@@ -23758,7 +24623,10 @@ var TransferService = class extends BaseTransferService {
|
|
|
23758
24623
|
txid: hexToBytes6(getTxId(nodeTx)),
|
|
23759
24624
|
index: 0
|
|
23760
24625
|
};
|
|
23761
|
-
const {
|
|
24626
|
+
const {
|
|
24627
|
+
nextSequence: newNodeSequence,
|
|
24628
|
+
nextDirectSequence: newDirectNodeSequence
|
|
24629
|
+
} = getNextTransactionSequence(refundSequence);
|
|
23762
24630
|
const newNodeTx = new Transaction4({
|
|
23763
24631
|
version: 3,
|
|
23764
24632
|
allowUnknownOutputs: true
|
|
@@ -23771,81 +24639,122 @@ var TransferService = class extends BaseTransferService {
|
|
|
23771
24639
|
newNodeTx.addOutput({
|
|
23772
24640
|
script: originalOutput.script,
|
|
23773
24641
|
amount: originalOutput.amount
|
|
23774
|
-
// feeReducedAmount,
|
|
23775
24642
|
});
|
|
23776
24643
|
newNodeTx.addOutput(getEphemeralAnchorOutput());
|
|
23777
|
-
|
|
24644
|
+
let newDirectNodeTx;
|
|
24645
|
+
if (node.directTx.length > 0) {
|
|
24646
|
+
newDirectNodeTx = new Transaction4({
|
|
24647
|
+
version: 3,
|
|
24648
|
+
allowUnknownOutputs: true
|
|
24649
|
+
});
|
|
24650
|
+
newDirectNodeTx.addInput({
|
|
24651
|
+
...newNodeOutPoint,
|
|
24652
|
+
sequence: newDirectNodeSequence
|
|
24653
|
+
});
|
|
24654
|
+
newDirectNodeTx.addOutput({
|
|
24655
|
+
script: originalOutput.script,
|
|
24656
|
+
amount: maybeApplyFee(originalOutput.amount)
|
|
24657
|
+
});
|
|
24658
|
+
}
|
|
24659
|
+
const newCpfpRefundOutPoint = {
|
|
23778
24660
|
txid: hexToBytes6(getTxId(newNodeTx)),
|
|
23779
24661
|
index: 0
|
|
23780
24662
|
};
|
|
24663
|
+
let newDirectRefundOutPoint;
|
|
24664
|
+
if (newDirectNodeTx) {
|
|
24665
|
+
newDirectRefundOutPoint = {
|
|
24666
|
+
txid: hexToBytes6(getTxId(newDirectNodeTx)),
|
|
24667
|
+
index: 0
|
|
24668
|
+
};
|
|
24669
|
+
}
|
|
23781
24670
|
const amountSats = refundTx.getOutput(0).amount;
|
|
23782
24671
|
if (amountSats === void 0) {
|
|
23783
24672
|
throw new Error("Amount not found in extendTimelock");
|
|
23784
24673
|
}
|
|
23785
|
-
const
|
|
24674
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation({
|
|
23786
24675
|
type: "leaf" /* LEAF */,
|
|
23787
24676
|
path: node.id
|
|
23788
24677
|
});
|
|
23789
|
-
const
|
|
23790
|
-
|
|
23791
|
-
|
|
24678
|
+
const {
|
|
24679
|
+
cpfpRefundTx: newCpfpRefundTx,
|
|
24680
|
+
directRefundTx: newDirectRefundTx,
|
|
24681
|
+
directFromCpfpRefundTx: newDirectFromCpfpRefundTx
|
|
24682
|
+
} = createRefundTxs({
|
|
24683
|
+
sequence: INITIAL_SEQUENCE,
|
|
24684
|
+
directSequence: INITIAL_DIRECT_SEQUENCE,
|
|
24685
|
+
input: newCpfpRefundOutPoint,
|
|
24686
|
+
directInput: newDirectRefundOutPoint,
|
|
23792
24687
|
amountSats,
|
|
23793
|
-
|
|
23794
|
-
|
|
23795
|
-
|
|
23796
|
-
)
|
|
24688
|
+
receivingPubkey: signingPublicKey,
|
|
24689
|
+
network: this.config.getNetwork()
|
|
24690
|
+
});
|
|
24691
|
+
if (!newCpfpRefundTx) {
|
|
24692
|
+
throw new ValidationError(
|
|
24693
|
+
"Failed to create refund transactions in extendTimelock"
|
|
24694
|
+
);
|
|
24695
|
+
}
|
|
23797
24696
|
const nodeSighash = getSigHashFromTx(newNodeTx, 0, nodeTx.getOutput(0));
|
|
23798
|
-
const
|
|
23799
|
-
|
|
24697
|
+
const directNodeSighash = newDirectNodeTx ? getSigHashFromTx(newDirectNodeTx, 0, nodeTx.getOutput(0)) : void 0;
|
|
24698
|
+
const cpfpRefundSighash = getSigHashFromTx(
|
|
24699
|
+
newCpfpRefundTx,
|
|
23800
24700
|
0,
|
|
23801
24701
|
newNodeTx.getOutput(0)
|
|
23802
24702
|
);
|
|
24703
|
+
const directRefundSighash = newDirectNodeTx && newDirectRefundTx ? getSigHashFromTx(newDirectRefundTx, 0, newDirectNodeTx.getOutput(0)) : void 0;
|
|
24704
|
+
const directFromCpfpRefundSighash = newDirectFromCpfpRefundTx ? getSigHashFromTx(newDirectFromCpfpRefundTx, 0, newNodeTx.getOutput(0)) : void 0;
|
|
23803
24705
|
const newNodeSigningJob = {
|
|
23804
|
-
signingPublicKey
|
|
24706
|
+
signingPublicKey,
|
|
23805
24707
|
rawTx: newNodeTx.toBytes(),
|
|
23806
24708
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
23807
24709
|
};
|
|
23808
|
-
const
|
|
23809
|
-
signingPublicKey
|
|
23810
|
-
rawTx:
|
|
24710
|
+
const newDirectNodeSigningJob = newDirectNodeTx ? {
|
|
24711
|
+
signingPublicKey,
|
|
24712
|
+
rawTx: newDirectNodeTx.toBytes(),
|
|
24713
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
24714
|
+
} : void 0;
|
|
24715
|
+
const newCpfpRefundSigningJob = {
|
|
24716
|
+
signingPublicKey,
|
|
24717
|
+
rawTx: newCpfpRefundTx.toBytes(),
|
|
23811
24718
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
23812
24719
|
};
|
|
24720
|
+
const newDirectRefundSigningJob = newDirectRefundTx ? {
|
|
24721
|
+
signingPublicKey,
|
|
24722
|
+
rawTx: newDirectRefundTx.toBytes(),
|
|
24723
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
24724
|
+
} : void 0;
|
|
24725
|
+
const newDirectFromCpfpRefundSigningJob = newDirectFromCpfpRefundTx ? {
|
|
24726
|
+
signingPublicKey,
|
|
24727
|
+
rawTx: newDirectFromCpfpRefundTx.toBytes(),
|
|
24728
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
24729
|
+
} : void 0;
|
|
23813
24730
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
23814
24731
|
this.config.getCoordinatorAddress()
|
|
23815
24732
|
);
|
|
23816
|
-
const response = await sparkClient.
|
|
24733
|
+
const response = await sparkClient.extend_leaf_v2({
|
|
23817
24734
|
leafId: node.id,
|
|
23818
24735
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
23819
24736
|
nodeTxSigningJob: getSigningJobProto(newNodeSigningJob),
|
|
23820
|
-
|
|
24737
|
+
directNodeTxSigningJob: newDirectNodeSigningJob ? getSigningJobProto(newDirectNodeSigningJob) : void 0,
|
|
24738
|
+
refundTxSigningJob: getSigningJobProto(newCpfpRefundSigningJob),
|
|
24739
|
+
directRefundTxSigningJob: newDirectRefundSigningJob ? getSigningJobProto(newDirectRefundSigningJob) : void 0,
|
|
24740
|
+
directFromCpfpRefundTxSigningJob: newDirectFromCpfpRefundSigningJob ? getSigningJobProto(newDirectFromCpfpRefundSigningJob) : void 0
|
|
23821
24741
|
});
|
|
23822
24742
|
if (!response.nodeTxSigningResult || !response.refundTxSigningResult) {
|
|
23823
24743
|
throw new Error("Signing result does not exist");
|
|
23824
24744
|
}
|
|
24745
|
+
const keyDerivation = {
|
|
24746
|
+
type: "leaf" /* LEAF */,
|
|
24747
|
+
path: node.id
|
|
24748
|
+
};
|
|
23825
24749
|
const nodeUserSig = await this.config.signer.signFrost({
|
|
23826
24750
|
message: nodeSighash,
|
|
23827
|
-
keyDerivation
|
|
23828
|
-
|
|
23829
|
-
path: node.id
|
|
23830
|
-
},
|
|
23831
|
-
publicKey: signingPubKey,
|
|
24751
|
+
keyDerivation,
|
|
24752
|
+
publicKey: signingPublicKey,
|
|
23832
24753
|
verifyingKey: response.nodeTxSigningResult.verifyingKey,
|
|
23833
24754
|
selfCommitment: newNodeSigningJob.signingNonceCommitment,
|
|
23834
24755
|
statechainCommitments: response.nodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
23835
24756
|
adaptorPubKey: new Uint8Array()
|
|
23836
24757
|
});
|
|
23837
|
-
const refundUserSig = await this.config.signer.signFrost({
|
|
23838
|
-
message: refundSighash,
|
|
23839
|
-
keyDerivation: {
|
|
23840
|
-
type: "leaf" /* LEAF */,
|
|
23841
|
-
path: node.id
|
|
23842
|
-
},
|
|
23843
|
-
publicKey: signingPubKey,
|
|
23844
|
-
verifyingKey: response.refundTxSigningResult.verifyingKey,
|
|
23845
|
-
selfCommitment: newRefundSigningJob.signingNonceCommitment,
|
|
23846
|
-
statechainCommitments: response.refundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
23847
|
-
adaptorPubKey: new Uint8Array()
|
|
23848
|
-
});
|
|
23849
24758
|
const nodeSig = await this.config.signer.aggregateFrost({
|
|
23850
24759
|
message: nodeSighash,
|
|
23851
24760
|
statechainSignatures: response.nodeTxSigningResult.signingResult?.signatureShares,
|
|
@@ -23853,122 +24762,253 @@ var TransferService = class extends BaseTransferService {
|
|
|
23853
24762
|
verifyingKey: response.nodeTxSigningResult.verifyingKey,
|
|
23854
24763
|
statechainCommitments: response.nodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
23855
24764
|
selfCommitment: newNodeSigningJob.signingNonceCommitment,
|
|
23856
|
-
publicKey:
|
|
24765
|
+
publicKey: signingPublicKey,
|
|
23857
24766
|
selfSignature: nodeUserSig,
|
|
23858
24767
|
adaptorPubKey: new Uint8Array()
|
|
23859
24768
|
});
|
|
23860
|
-
|
|
23861
|
-
|
|
24769
|
+
let directNodeSig;
|
|
24770
|
+
if (directNodeSighash && newDirectNodeSigningJob && response.directNodeTxSigningResult) {
|
|
24771
|
+
const directNodeUserSig = await this.config.signer.signFrost({
|
|
24772
|
+
message: directNodeSighash,
|
|
24773
|
+
keyDerivation,
|
|
24774
|
+
publicKey: signingPublicKey,
|
|
24775
|
+
verifyingKey: response.directNodeTxSigningResult.verifyingKey,
|
|
24776
|
+
selfCommitment: newDirectNodeSigningJob.signingNonceCommitment,
|
|
24777
|
+
statechainCommitments: response.directNodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
24778
|
+
adaptorPubKey: new Uint8Array()
|
|
24779
|
+
});
|
|
24780
|
+
directNodeSig = await this.config.signer.aggregateFrost({
|
|
24781
|
+
message: directNodeSighash,
|
|
24782
|
+
statechainSignatures: response.directNodeTxSigningResult.signingResult?.signatureShares,
|
|
24783
|
+
statechainPublicKeys: response.directNodeTxSigningResult.signingResult?.publicKeys,
|
|
24784
|
+
verifyingKey: response.directNodeTxSigningResult.verifyingKey,
|
|
24785
|
+
statechainCommitments: response.directNodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
24786
|
+
selfCommitment: newDirectNodeSigningJob.signingNonceCommitment,
|
|
24787
|
+
publicKey: signingPublicKey,
|
|
24788
|
+
selfSignature: directNodeUserSig,
|
|
24789
|
+
adaptorPubKey: new Uint8Array()
|
|
24790
|
+
});
|
|
24791
|
+
}
|
|
24792
|
+
const cpfpRefundUserSig = await this.config.signer.signFrost({
|
|
24793
|
+
message: cpfpRefundSighash,
|
|
24794
|
+
keyDerivation,
|
|
24795
|
+
publicKey: signingPublicKey,
|
|
24796
|
+
verifyingKey: response.refundTxSigningResult.verifyingKey,
|
|
24797
|
+
selfCommitment: newCpfpRefundSigningJob.signingNonceCommitment,
|
|
24798
|
+
statechainCommitments: response.refundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
24799
|
+
adaptorPubKey: new Uint8Array()
|
|
24800
|
+
});
|
|
24801
|
+
const cpfpRefundSig = await this.config.signer.aggregateFrost({
|
|
24802
|
+
message: cpfpRefundSighash,
|
|
23862
24803
|
statechainSignatures: response.refundTxSigningResult.signingResult?.signatureShares,
|
|
23863
24804
|
statechainPublicKeys: response.refundTxSigningResult.signingResult?.publicKeys,
|
|
23864
24805
|
verifyingKey: response.refundTxSigningResult.verifyingKey,
|
|
23865
24806
|
statechainCommitments: response.refundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
23866
|
-
selfCommitment:
|
|
23867
|
-
publicKey:
|
|
23868
|
-
selfSignature:
|
|
24807
|
+
selfCommitment: newCpfpRefundSigningJob.signingNonceCommitment,
|
|
24808
|
+
publicKey: signingPublicKey,
|
|
24809
|
+
selfSignature: cpfpRefundUserSig,
|
|
23869
24810
|
adaptorPubKey: new Uint8Array()
|
|
23870
24811
|
});
|
|
23871
|
-
|
|
24812
|
+
let directRefundSig;
|
|
24813
|
+
if (directRefundSighash && newDirectRefundSigningJob && response.directRefundTxSigningResult) {
|
|
24814
|
+
const directRefundUserSig = await this.config.signer.signFrost({
|
|
24815
|
+
message: directRefundSighash,
|
|
24816
|
+
keyDerivation,
|
|
24817
|
+
publicKey: signingPublicKey,
|
|
24818
|
+
verifyingKey: response.directRefundTxSigningResult.verifyingKey,
|
|
24819
|
+
selfCommitment: newDirectRefundSigningJob.signingNonceCommitment,
|
|
24820
|
+
statechainCommitments: response.directRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
24821
|
+
adaptorPubKey: new Uint8Array()
|
|
24822
|
+
});
|
|
24823
|
+
directRefundSig = await this.config.signer.aggregateFrost({
|
|
24824
|
+
message: directRefundSighash,
|
|
24825
|
+
statechainSignatures: response.directRefundTxSigningResult.signingResult?.signatureShares,
|
|
24826
|
+
statechainPublicKeys: response.directRefundTxSigningResult.signingResult?.publicKeys,
|
|
24827
|
+
verifyingKey: response.directRefundTxSigningResult.verifyingKey,
|
|
24828
|
+
statechainCommitments: response.directRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
24829
|
+
selfCommitment: newDirectRefundSigningJob.signingNonceCommitment,
|
|
24830
|
+
publicKey: signingPublicKey,
|
|
24831
|
+
selfSignature: directRefundUserSig,
|
|
24832
|
+
adaptorPubKey: new Uint8Array()
|
|
24833
|
+
});
|
|
24834
|
+
}
|
|
24835
|
+
let directFromCpfpRefundSig;
|
|
24836
|
+
if (directFromCpfpRefundSighash && newDirectFromCpfpRefundSigningJob && response.directFromCpfpRefundTxSigningResult) {
|
|
24837
|
+
const directFromCpfpRefundUserSig = await this.config.signer.signFrost({
|
|
24838
|
+
message: directFromCpfpRefundSighash,
|
|
24839
|
+
keyDerivation,
|
|
24840
|
+
publicKey: signingPublicKey,
|
|
24841
|
+
verifyingKey: response.directFromCpfpRefundTxSigningResult.verifyingKey,
|
|
24842
|
+
selfCommitment: newDirectFromCpfpRefundSigningJob.signingNonceCommitment,
|
|
24843
|
+
statechainCommitments: response.directFromCpfpRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
24844
|
+
adaptorPubKey: new Uint8Array()
|
|
24845
|
+
});
|
|
24846
|
+
directFromCpfpRefundSig = await this.config.signer.aggregateFrost({
|
|
24847
|
+
message: directFromCpfpRefundSighash,
|
|
24848
|
+
statechainSignatures: response.directFromCpfpRefundTxSigningResult.signingResult?.signatureShares,
|
|
24849
|
+
statechainPublicKeys: response.directFromCpfpRefundTxSigningResult.signingResult?.publicKeys,
|
|
24850
|
+
verifyingKey: response.directFromCpfpRefundTxSigningResult.verifyingKey,
|
|
24851
|
+
statechainCommitments: response.directFromCpfpRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
24852
|
+
selfCommitment: newDirectFromCpfpRefundSigningJob.signingNonceCommitment,
|
|
24853
|
+
publicKey: signingPublicKey,
|
|
24854
|
+
selfSignature: directFromCpfpRefundUserSig,
|
|
24855
|
+
adaptorPubKey: new Uint8Array()
|
|
24856
|
+
});
|
|
24857
|
+
}
|
|
24858
|
+
return await sparkClient.finalize_node_signatures_v2({
|
|
23872
24859
|
intent: 4 /* EXTEND */,
|
|
23873
24860
|
nodeSignatures: [
|
|
23874
24861
|
{
|
|
23875
24862
|
nodeId: response.leafId,
|
|
23876
24863
|
nodeTxSignature: nodeSig,
|
|
23877
|
-
|
|
24864
|
+
directNodeTxSignature: directNodeSig,
|
|
24865
|
+
refundTxSignature: cpfpRefundSig,
|
|
24866
|
+
directRefundTxSignature: directRefundSig,
|
|
24867
|
+
directFromCpfpRefundTxSignature: directFromCpfpRefundSig
|
|
23878
24868
|
}
|
|
23879
24869
|
]
|
|
23880
24870
|
});
|
|
23881
24871
|
}
|
|
23882
|
-
async
|
|
24872
|
+
async testonly_expireTimeLockNodeTx(node, parentNode) {
|
|
24873
|
+
return await this.refreshTimelockNodesInternal(node, parentNode, true);
|
|
24874
|
+
}
|
|
24875
|
+
async testonly_expireTimeLockRefundtx(node) {
|
|
23883
24876
|
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
23884
|
-
const
|
|
23885
|
-
const
|
|
23886
|
-
const
|
|
23887
|
-
const
|
|
24877
|
+
const directNodeTx = node.directTx.length > 0 ? getTxFromRawTxBytes(node.directTx) : void 0;
|
|
24878
|
+
const cpfpRefundTx = getTxFromRawTxBytes(node.refundTx);
|
|
24879
|
+
const currSequence = cpfpRefundTx.getInput(0).sequence || 0;
|
|
24880
|
+
const currTimelock = getCurrentTimelock(currSequence);
|
|
24881
|
+
if (currTimelock <= 100) {
|
|
24882
|
+
throw new ValidationError("Cannot expire timelock below 100", {
|
|
24883
|
+
field: "currTimelock",
|
|
24884
|
+
value: currTimelock,
|
|
24885
|
+
expected: "Timelock greater than 100"
|
|
24886
|
+
});
|
|
24887
|
+
}
|
|
24888
|
+
const nextSequence = TEST_UNILATERAL_SEQUENCE;
|
|
24889
|
+
const nextDirectSequence = TEST_UNILATERAL_SEQUENCE + DIRECT_TIMELOCK_OFFSET;
|
|
24890
|
+
const nodeOutput = nodeTx.getOutput(0);
|
|
24891
|
+
if (!nodeOutput) {
|
|
24892
|
+
throw Error("Could not get node output");
|
|
24893
|
+
}
|
|
24894
|
+
const keyDerivation = {
|
|
23888
24895
|
type: "leaf" /* LEAF */,
|
|
23889
24896
|
path: node.id
|
|
23890
|
-
}
|
|
23891
|
-
const
|
|
23892
|
-
|
|
23893
|
-
|
|
23894
|
-
|
|
23895
|
-
|
|
23896
|
-
|
|
23897
|
-
|
|
24897
|
+
};
|
|
24898
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
24899
|
+
const cpfpRefundOutPoint = {
|
|
24900
|
+
txid: hexToBytes6(getTxId(nodeTx)),
|
|
24901
|
+
index: 0
|
|
24902
|
+
};
|
|
24903
|
+
let directRefundOutPoint;
|
|
24904
|
+
if (directNodeTx) {
|
|
24905
|
+
directRefundOutPoint = {
|
|
24906
|
+
txid: hexToBytes6(getTxId(directNodeTx)),
|
|
24907
|
+
index: 0
|
|
24908
|
+
};
|
|
23898
24909
|
}
|
|
23899
|
-
|
|
23900
|
-
|
|
23901
|
-
|
|
24910
|
+
const {
|
|
24911
|
+
cpfpRefundTx: newCpfpRefundTx,
|
|
24912
|
+
directRefundTx: newDirectRefundTx,
|
|
24913
|
+
directFromCpfpRefundTx: newDirectFromCpfpRefundTx
|
|
24914
|
+
} = createRefundTxs({
|
|
24915
|
+
sequence: nextSequence,
|
|
24916
|
+
directSequence: nextDirectSequence,
|
|
24917
|
+
input: cpfpRefundOutPoint,
|
|
24918
|
+
directInput: directRefundOutPoint,
|
|
24919
|
+
amountSats: nodeOutput.amount,
|
|
24920
|
+
receivingPubkey: signingPublicKey,
|
|
24921
|
+
network: this.config.getNetwork()
|
|
23902
24922
|
});
|
|
23903
|
-
|
|
23904
|
-
|
|
23905
|
-
|
|
23906
|
-
|
|
23907
|
-
|
|
24923
|
+
const signingJobs = [];
|
|
24924
|
+
signingJobs.push({
|
|
24925
|
+
signingPublicKey,
|
|
24926
|
+
rawTx: newCpfpRefundTx.toBytes(),
|
|
24927
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24928
|
+
type: "cpfp",
|
|
24929
|
+
parentTxOut: nodeOutput
|
|
24930
|
+
});
|
|
24931
|
+
const directNodeTxOut = directNodeTx?.getOutput(0);
|
|
24932
|
+
if (newDirectRefundTx && directNodeTxOut) {
|
|
24933
|
+
signingJobs.push({
|
|
24934
|
+
signingPublicKey,
|
|
24935
|
+
rawTx: newDirectRefundTx.toBytes(),
|
|
24936
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24937
|
+
type: "direct",
|
|
24938
|
+
parentTxOut: directNodeTxOut
|
|
24939
|
+
});
|
|
23908
24940
|
}
|
|
23909
|
-
|
|
23910
|
-
|
|
23911
|
-
|
|
24941
|
+
if (newDirectFromCpfpRefundTx) {
|
|
24942
|
+
signingJobs.push({
|
|
24943
|
+
signingPublicKey,
|
|
24944
|
+
rawTx: newDirectFromCpfpRefundTx.toBytes(),
|
|
24945
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
24946
|
+
type: "directFromCpfp",
|
|
24947
|
+
parentTxOut: nodeOutput
|
|
24948
|
+
});
|
|
23912
24949
|
}
|
|
23913
|
-
newRefundTx.addInput({
|
|
23914
|
-
...refundTxInput,
|
|
23915
|
-
sequence: nextSequence
|
|
23916
|
-
});
|
|
23917
|
-
const refundSigningJob = {
|
|
23918
|
-
signingPublicKey: signingPubKey,
|
|
23919
|
-
rawTx: newRefundTx.toBytes(),
|
|
23920
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
23921
|
-
};
|
|
23922
24950
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
23923
24951
|
this.config.getCoordinatorAddress()
|
|
23924
24952
|
);
|
|
23925
|
-
const response = await sparkClient.
|
|
24953
|
+
const response = await sparkClient.refresh_timelock_v2({
|
|
23926
24954
|
leafId: node.id,
|
|
23927
24955
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
23928
|
-
signingJobs:
|
|
24956
|
+
signingJobs: signingJobs.map(getSigningJobProto)
|
|
23929
24957
|
});
|
|
23930
|
-
if (response.signingResults.length !==
|
|
24958
|
+
if (response.signingResults.length !== signingJobs.length) {
|
|
23931
24959
|
throw Error(
|
|
23932
|
-
`Expected
|
|
24960
|
+
`Expected ${signingJobs.length} signing results, got ${response.signingResults.length}`
|
|
23933
24961
|
);
|
|
23934
24962
|
}
|
|
23935
|
-
|
|
23936
|
-
|
|
23937
|
-
|
|
24963
|
+
let cpfpRefundSignature;
|
|
24964
|
+
let directRefundSignature;
|
|
24965
|
+
let directFromCpfpRefundSignature;
|
|
24966
|
+
for (const [i, signingJob] of signingJobs.entries()) {
|
|
24967
|
+
const signingResult = response.signingResults[i];
|
|
24968
|
+
if (!signingResult) {
|
|
24969
|
+
throw Error("Signing result does not exist");
|
|
24970
|
+
}
|
|
24971
|
+
const rawTx = getTxFromRawTxBytes(signingJob.rawTx);
|
|
24972
|
+
const txOut = signingJob.parentTxOut;
|
|
24973
|
+
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
24974
|
+
const userSignature = await this.config.signer.signFrost({
|
|
24975
|
+
message: rawTxSighash,
|
|
24976
|
+
keyDerivation,
|
|
24977
|
+
publicKey: signingPublicKey,
|
|
24978
|
+
verifyingKey: signingResult.verifyingKey,
|
|
24979
|
+
selfCommitment: signingJob.signingNonceCommitment,
|
|
24980
|
+
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
24981
|
+
adaptorPubKey: new Uint8Array()
|
|
24982
|
+
});
|
|
24983
|
+
const signature = await this.config.signer.aggregateFrost({
|
|
24984
|
+
message: rawTxSighash,
|
|
24985
|
+
statechainSignatures: signingResult.signingResult?.signatureShares,
|
|
24986
|
+
statechainPublicKeys: signingResult.signingResult?.publicKeys,
|
|
24987
|
+
verifyingKey: signingResult.verifyingKey,
|
|
24988
|
+
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
24989
|
+
selfCommitment: signingJob.signingNonceCommitment,
|
|
24990
|
+
publicKey: signingPublicKey,
|
|
24991
|
+
selfSignature: userSignature,
|
|
24992
|
+
adaptorPubKey: new Uint8Array()
|
|
24993
|
+
});
|
|
24994
|
+
if (signingJob.type === "cpfp") {
|
|
24995
|
+
cpfpRefundSignature = signature;
|
|
24996
|
+
} else if (signingJob.type === "direct") {
|
|
24997
|
+
directRefundSignature = signature;
|
|
24998
|
+
} else if (signingJob.type === "directFromCpfp") {
|
|
24999
|
+
directFromCpfpRefundSignature = signature;
|
|
25000
|
+
}
|
|
23938
25001
|
}
|
|
23939
|
-
const
|
|
23940
|
-
const txOut = nodeTx.getOutput(0);
|
|
23941
|
-
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
23942
|
-
const userSignature = await this.config.signer.signFrost({
|
|
23943
|
-
message: rawTxSighash,
|
|
23944
|
-
keyDerivation: {
|
|
23945
|
-
type: "leaf" /* LEAF */,
|
|
23946
|
-
path: node.id
|
|
23947
|
-
},
|
|
23948
|
-
publicKey: signingPubKey,
|
|
23949
|
-
verifyingKey: signingResult.verifyingKey,
|
|
23950
|
-
selfCommitment: refundSigningJob.signingNonceCommitment,
|
|
23951
|
-
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
23952
|
-
adaptorPubKey: new Uint8Array()
|
|
23953
|
-
});
|
|
23954
|
-
const signature = await this.config.signer.aggregateFrost({
|
|
23955
|
-
message: rawTxSighash,
|
|
23956
|
-
statechainSignatures: signingResult.signingResult?.signatureShares,
|
|
23957
|
-
statechainPublicKeys: signingResult.signingResult?.publicKeys,
|
|
23958
|
-
verifyingKey: signingResult.verifyingKey,
|
|
23959
|
-
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
23960
|
-
selfCommitment: refundSigningJob.signingNonceCommitment,
|
|
23961
|
-
publicKey: signingPubKey,
|
|
23962
|
-
selfSignature: userSignature,
|
|
23963
|
-
adaptorPubKey: new Uint8Array()
|
|
23964
|
-
});
|
|
23965
|
-
const result = await sparkClient.finalize_node_signatures({
|
|
25002
|
+
const result = await sparkClient.finalize_node_signatures_v2({
|
|
23966
25003
|
intent: 3 /* REFRESH */,
|
|
23967
25004
|
nodeSignatures: [
|
|
23968
25005
|
{
|
|
23969
25006
|
nodeId: node.id,
|
|
23970
25007
|
nodeTxSignature: new Uint8Array(),
|
|
23971
|
-
|
|
25008
|
+
directNodeTxSignature: new Uint8Array(),
|
|
25009
|
+
refundTxSignature: cpfpRefundSignature,
|
|
25010
|
+
directRefundTxSignature: directRefundSignature,
|
|
25011
|
+
directFromCpfpRefundTxSignature: directFromCpfpRefundSignature
|
|
23972
25012
|
}
|
|
23973
25013
|
]
|
|
23974
25014
|
});
|
|
@@ -23987,7 +25027,12 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
23987
25027
|
connectorOutputs,
|
|
23988
25028
|
receiverPubKey
|
|
23989
25029
|
}) {
|
|
23990
|
-
const {
|
|
25030
|
+
const {
|
|
25031
|
+
transfer,
|
|
25032
|
+
signaturesMap,
|
|
25033
|
+
directSignaturesMap,
|
|
25034
|
+
directFromCpfpSignaturesMap
|
|
25035
|
+
} = await this.signCoopExitRefunds(
|
|
23991
25036
|
leaves,
|
|
23992
25037
|
exitTxId,
|
|
23993
25038
|
connectorOutputs,
|
|
@@ -23996,34 +25041,81 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
23996
25041
|
const transferTweak = await this.deliverTransferPackage(
|
|
23997
25042
|
transfer,
|
|
23998
25043
|
leaves,
|
|
23999
|
-
signaturesMap
|
|
25044
|
+
signaturesMap,
|
|
25045
|
+
directSignaturesMap,
|
|
25046
|
+
directFromCpfpSignaturesMap
|
|
24000
25047
|
);
|
|
24001
|
-
return {
|
|
24002
|
-
|
|
24003
|
-
|
|
24004
|
-
|
|
24005
|
-
|
|
24006
|
-
|
|
24007
|
-
|
|
24008
|
-
|
|
25048
|
+
return {
|
|
25049
|
+
transfer: transferTweak,
|
|
25050
|
+
signaturesMap,
|
|
25051
|
+
directSignaturesMap,
|
|
25052
|
+
directFromCpfpSignaturesMap
|
|
25053
|
+
};
|
|
25054
|
+
}
|
|
25055
|
+
createConnectorRefundTransactions(sequence, directSequence, cpfpNodeOutPoint, directNodeOutPoint, connectorOutput, amountSats, receiverPubKey) {
|
|
25056
|
+
const cpfpRefundTx = new Transaction5();
|
|
25057
|
+
if (!cpfpNodeOutPoint.txid || cpfpNodeOutPoint.index === void 0) {
|
|
25058
|
+
throw new ValidationError("Invalid CPFP node outpoint", {
|
|
25059
|
+
field: "cpfpNodeOutPoint",
|
|
25060
|
+
value: { txid: cpfpNodeOutPoint.txid, index: cpfpNodeOutPoint.index },
|
|
24009
25061
|
expected: "Both txid and index must be defined"
|
|
24010
25062
|
});
|
|
24011
25063
|
}
|
|
24012
|
-
|
|
24013
|
-
txid:
|
|
24014
|
-
index:
|
|
25064
|
+
cpfpRefundTx.addInput({
|
|
25065
|
+
txid: cpfpNodeOutPoint.txid,
|
|
25066
|
+
index: cpfpNodeOutPoint.index,
|
|
24015
25067
|
sequence
|
|
24016
25068
|
});
|
|
24017
|
-
|
|
25069
|
+
cpfpRefundTx.addInput(connectorOutput);
|
|
24018
25070
|
const receiverScript = getP2TRScriptFromPublicKey(
|
|
24019
25071
|
receiverPubKey,
|
|
24020
25072
|
this.config.getNetwork()
|
|
24021
25073
|
);
|
|
24022
|
-
|
|
25074
|
+
cpfpRefundTx.addOutput({
|
|
24023
25075
|
script: receiverScript,
|
|
24024
25076
|
amount: amountSats
|
|
24025
25077
|
});
|
|
24026
|
-
|
|
25078
|
+
let directRefundTx;
|
|
25079
|
+
let directFromCpfpRefundTx;
|
|
25080
|
+
if (directNodeOutPoint) {
|
|
25081
|
+
if (!directNodeOutPoint.txid || directNodeOutPoint.index === void 0) {
|
|
25082
|
+
throw new ValidationError("Invalid direct node outpoint", {
|
|
25083
|
+
field: "directNodeOutPoint",
|
|
25084
|
+
value: {
|
|
25085
|
+
txid: directNodeOutPoint.txid,
|
|
25086
|
+
index: directNodeOutPoint.index
|
|
25087
|
+
},
|
|
25088
|
+
expected: "Both txid and index must be defined"
|
|
25089
|
+
});
|
|
25090
|
+
}
|
|
25091
|
+
directRefundTx = new Transaction5();
|
|
25092
|
+
directRefundTx.addInput({
|
|
25093
|
+
txid: directNodeOutPoint.txid,
|
|
25094
|
+
index: directNodeOutPoint.index,
|
|
25095
|
+
sequence: directSequence
|
|
25096
|
+
});
|
|
25097
|
+
directRefundTx.addInput(connectorOutput);
|
|
25098
|
+
directRefundTx.addOutput({
|
|
25099
|
+
script: receiverScript,
|
|
25100
|
+
amount: maybeApplyFee(amountSats)
|
|
25101
|
+
});
|
|
25102
|
+
directFromCpfpRefundTx = new Transaction5();
|
|
25103
|
+
directFromCpfpRefundTx.addInput({
|
|
25104
|
+
txid: cpfpNodeOutPoint.txid,
|
|
25105
|
+
index: cpfpNodeOutPoint.index,
|
|
25106
|
+
sequence: directSequence
|
|
25107
|
+
});
|
|
25108
|
+
directFromCpfpRefundTx.addInput(connectorOutput);
|
|
25109
|
+
directFromCpfpRefundTx.addOutput({
|
|
25110
|
+
script: receiverScript,
|
|
25111
|
+
amount: maybeApplyFee(amountSats)
|
|
25112
|
+
});
|
|
25113
|
+
}
|
|
25114
|
+
return {
|
|
25115
|
+
cpfpRefundTx,
|
|
25116
|
+
directRefundTx,
|
|
25117
|
+
directFromCpfpRefundTx
|
|
25118
|
+
};
|
|
24027
25119
|
}
|
|
24028
25120
|
async signCoopExitRefunds(leaves, exitTxId, connectorOutputs, receiverPubKey) {
|
|
24029
25121
|
if (leaves.length !== connectorOutputs.length) {
|
|
@@ -24059,39 +25151,67 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
24059
25151
|
});
|
|
24060
25152
|
}
|
|
24061
25153
|
const currentRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
24062
|
-
const
|
|
24063
|
-
|
|
24064
|
-
|
|
24065
|
-
|
|
25154
|
+
const sequence = currentRefundTx.getInput(0).sequence;
|
|
25155
|
+
if (!sequence) {
|
|
25156
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
25157
|
+
field: "sequence",
|
|
25158
|
+
value: currentRefundTx.getInput(0),
|
|
25159
|
+
expected: "Non-null sequence"
|
|
25160
|
+
});
|
|
25161
|
+
}
|
|
25162
|
+
const { nextSequence, nextDirectSequence } = getNextTransactionSequence(sequence);
|
|
25163
|
+
let currentDirectRefundTx;
|
|
25164
|
+
if (leaf.leaf.directRefundTx.length > 0) {
|
|
25165
|
+
currentDirectRefundTx = getTxFromRawTxBytes(leaf.leaf.directRefundTx);
|
|
25166
|
+
}
|
|
25167
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = this.createConnectorRefundTransactions(
|
|
24066
25168
|
nextSequence,
|
|
25169
|
+
nextDirectSequence,
|
|
24067
25170
|
currentRefundTx.getInput(0),
|
|
25171
|
+
currentDirectRefundTx?.getInput(0),
|
|
24068
25172
|
connectorOutput,
|
|
24069
25173
|
BigInt(leaf.leaf.value),
|
|
24070
25174
|
receiverPubKey
|
|
24071
25175
|
);
|
|
24072
25176
|
const signingNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
25177
|
+
const directSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
25178
|
+
const directFromCpfpSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
25179
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(leaf.keyDerivation);
|
|
24073
25180
|
const signingJob = {
|
|
24074
25181
|
leafId: leaf.leaf.id,
|
|
24075
25182
|
refundTxSigningJob: {
|
|
24076
25183
|
signingPublicKey: await this.config.signer.getPublicKeyFromDerivation(
|
|
24077
25184
|
leaf.keyDerivation
|
|
24078
25185
|
),
|
|
24079
|
-
rawTx:
|
|
25186
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
24080
25187
|
signingNonceCommitment: signingNonceCommitment.commitment
|
|
24081
25188
|
},
|
|
24082
|
-
|
|
24083
|
-
|
|
24084
|
-
|
|
25189
|
+
directRefundTxSigningJob: directRefundTx ? {
|
|
25190
|
+
signingPublicKey,
|
|
25191
|
+
rawTx: directRefundTx.toBytes(),
|
|
25192
|
+
signingNonceCommitment: directSigningNonceCommitment.commitment
|
|
25193
|
+
} : void 0,
|
|
25194
|
+
directFromCpfpRefundTxSigningJob: directFromCpfpRefundTx ? {
|
|
25195
|
+
signingPublicKey,
|
|
25196
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
25197
|
+
signingNonceCommitment: directFromCpfpSigningNonceCommitment.commitment
|
|
25198
|
+
} : void 0
|
|
24085
25199
|
};
|
|
24086
25200
|
signingJobs.push(signingJob);
|
|
24087
25201
|
const tx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
25202
|
+
const directTx = leaf.leaf.directTx.length > 0 ? getTxFromRawTxBytes(leaf.leaf.directTx) : void 0;
|
|
24088
25203
|
leafDataMap.set(leaf.leaf.id, {
|
|
24089
25204
|
keyDerivation: leaf.keyDerivation,
|
|
24090
|
-
|
|
25205
|
+
receivingPubkey: receiverPubKey,
|
|
24091
25206
|
signingNonceCommitment,
|
|
25207
|
+
directSigningNonceCommitment,
|
|
24092
25208
|
tx,
|
|
24093
|
-
|
|
24094
|
-
|
|
25209
|
+
directTx,
|
|
25210
|
+
refundTx: cpfpRefundTx,
|
|
25211
|
+
directRefundTx,
|
|
25212
|
+
directFromCpfpRefundTx,
|
|
25213
|
+
directFromCpfpRefundSigningNonceCommitment: directFromCpfpSigningNonceCommitment,
|
|
25214
|
+
vout: leaf.leaf.vout
|
|
24095
25215
|
});
|
|
24096
25216
|
}
|
|
24097
25217
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
@@ -24099,7 +25219,7 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
24099
25219
|
);
|
|
24100
25220
|
let response;
|
|
24101
25221
|
try {
|
|
24102
|
-
response = await sparkClient.
|
|
25222
|
+
response = await sparkClient.cooperative_exit_v2({
|
|
24103
25223
|
transfer: {
|
|
24104
25224
|
transferId: uuidv73(),
|
|
24105
25225
|
leavesToSend: signingJobs,
|
|
@@ -24133,10 +25253,25 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
24133
25253
|
response.signingResults
|
|
24134
25254
|
);
|
|
24135
25255
|
const signaturesMap = /* @__PURE__ */ new Map();
|
|
25256
|
+
const directSignaturesMap = /* @__PURE__ */ new Map();
|
|
25257
|
+
const directFromCpfpSignaturesMap = /* @__PURE__ */ new Map();
|
|
24136
25258
|
for (const signature of signatures) {
|
|
24137
25259
|
signaturesMap.set(signature.nodeId, signature.refundTxSignature);
|
|
25260
|
+
directSignaturesMap.set(
|
|
25261
|
+
signature.nodeId,
|
|
25262
|
+
signature.directRefundTxSignature
|
|
25263
|
+
);
|
|
25264
|
+
directFromCpfpSignaturesMap.set(
|
|
25265
|
+
signature.nodeId,
|
|
25266
|
+
signature.directFromCpfpRefundTxSignature
|
|
25267
|
+
);
|
|
24138
25268
|
}
|
|
24139
|
-
return {
|
|
25269
|
+
return {
|
|
25270
|
+
transfer: response.transfer,
|
|
25271
|
+
signaturesMap,
|
|
25272
|
+
directSignaturesMap,
|
|
25273
|
+
directFromCpfpSignaturesMap
|
|
25274
|
+
};
|
|
24140
25275
|
}
|
|
24141
25276
|
};
|
|
24142
25277
|
|
|
@@ -24144,10 +25279,8 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
24144
25279
|
import { schnorr as schnorr4, secp256k1 as secp256k19 } from "@noble/curves/secp256k1";
|
|
24145
25280
|
import { sha256 as sha2569 } from "@noble/hashes/sha2";
|
|
24146
25281
|
import { hexToBytes as hexToBytes7 } from "@noble/hashes/utils";
|
|
24147
|
-
import
|
|
24148
|
-
import { p2tr as p2tr2, Transaction as Transaction6 } from "@scure/btc-signer";
|
|
25282
|
+
import { p2tr as p2tr2 } from "@scure/btc-signer";
|
|
24149
25283
|
import { equalBytes as equalBytes4 } from "@scure/btc-signer/utils";
|
|
24150
|
-
var INITIAL_TIME_LOCK2 = 2e3;
|
|
24151
25284
|
var DepositService = class {
|
|
24152
25285
|
config;
|
|
24153
25286
|
connectionManager;
|
|
@@ -24215,57 +25348,370 @@ var DepositService = class {
|
|
|
24215
25348
|
});
|
|
24216
25349
|
}
|
|
24217
25350
|
}
|
|
24218
|
-
}
|
|
24219
|
-
async generateDepositAddress({
|
|
24220
|
-
signingPubkey,
|
|
24221
|
-
leafId,
|
|
24222
|
-
isStatic = false
|
|
24223
|
-
}) {
|
|
25351
|
+
}
|
|
25352
|
+
async generateDepositAddress({
|
|
25353
|
+
signingPubkey,
|
|
25354
|
+
leafId,
|
|
25355
|
+
isStatic = false
|
|
25356
|
+
}) {
|
|
25357
|
+
const sparkClient = await this.connectionManager.createSparkClient(
|
|
25358
|
+
this.config.getCoordinatorAddress()
|
|
25359
|
+
);
|
|
25360
|
+
let depositResp;
|
|
25361
|
+
try {
|
|
25362
|
+
depositResp = await sparkClient.generate_deposit_address({
|
|
25363
|
+
signingPublicKey: signingPubkey,
|
|
25364
|
+
identityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
25365
|
+
network: this.config.getNetworkProto(),
|
|
25366
|
+
leafId,
|
|
25367
|
+
isStatic
|
|
25368
|
+
});
|
|
25369
|
+
} catch (error) {
|
|
25370
|
+
throw new NetworkError(
|
|
25371
|
+
"Failed to generate deposit address",
|
|
25372
|
+
{
|
|
25373
|
+
operation: "generate_deposit_address",
|
|
25374
|
+
errorCount: 1,
|
|
25375
|
+
errors: error instanceof Error ? error.message : String(error)
|
|
25376
|
+
},
|
|
25377
|
+
error
|
|
25378
|
+
);
|
|
25379
|
+
}
|
|
25380
|
+
if (!depositResp.depositAddress) {
|
|
25381
|
+
throw new ValidationError(
|
|
25382
|
+
"No deposit address response from coordinator",
|
|
25383
|
+
{
|
|
25384
|
+
field: "depositAddress",
|
|
25385
|
+
value: depositResp
|
|
25386
|
+
}
|
|
25387
|
+
);
|
|
25388
|
+
}
|
|
25389
|
+
await this.validateDepositAddress({
|
|
25390
|
+
address: depositResp.depositAddress,
|
|
25391
|
+
userPubkey: signingPubkey
|
|
25392
|
+
});
|
|
25393
|
+
return depositResp;
|
|
25394
|
+
}
|
|
25395
|
+
async createTreeRoot({
|
|
25396
|
+
keyDerivation,
|
|
25397
|
+
verifyingKey,
|
|
25398
|
+
depositTx,
|
|
25399
|
+
vout
|
|
25400
|
+
}) {
|
|
25401
|
+
const output = depositTx.getOutput(vout);
|
|
25402
|
+
if (!output) {
|
|
25403
|
+
throw new ValidationError("Invalid deposit transaction output", {
|
|
25404
|
+
field: "vout",
|
|
25405
|
+
value: vout,
|
|
25406
|
+
expected: "Valid output index"
|
|
25407
|
+
});
|
|
25408
|
+
}
|
|
25409
|
+
const script = output.script;
|
|
25410
|
+
const amount = output.amount;
|
|
25411
|
+
if (!script || !amount) {
|
|
25412
|
+
throw new ValidationError("No script or amount found in deposit tx", {
|
|
25413
|
+
field: "output",
|
|
25414
|
+
value: output,
|
|
25415
|
+
expected: "Output with script and amount"
|
|
25416
|
+
});
|
|
25417
|
+
}
|
|
25418
|
+
const depositOutPoint = {
|
|
25419
|
+
txid: hexToBytes7(getTxId(depositTx)),
|
|
25420
|
+
index: vout
|
|
25421
|
+
};
|
|
25422
|
+
const depositTxOut = {
|
|
25423
|
+
script,
|
|
25424
|
+
amount
|
|
25425
|
+
};
|
|
25426
|
+
const [cpfpRootTx, directRootTx] = createRootTx(
|
|
25427
|
+
depositOutPoint,
|
|
25428
|
+
depositTxOut
|
|
25429
|
+
);
|
|
25430
|
+
const cpfpRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
25431
|
+
const directRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
25432
|
+
const cpfpRootTxSighash = getSigHashFromTx(cpfpRootTx, 0, output);
|
|
25433
|
+
const directRootTxSighash = getSigHashFromTx(directRootTx, 0, output);
|
|
25434
|
+
const signingPubKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
25435
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
25436
|
+
sequence: INITIAL_SEQUENCE,
|
|
25437
|
+
directSequence: INITIAL_DIRECT_SEQUENCE,
|
|
25438
|
+
input: { txid: hexToBytes7(getTxId(cpfpRootTx)), index: 0 },
|
|
25439
|
+
directInput: { txid: hexToBytes7(getTxId(directRootTx)), index: 0 },
|
|
25440
|
+
amountSats: amount,
|
|
25441
|
+
receivingPubkey: signingPubKey,
|
|
25442
|
+
network: this.config.getNetwork()
|
|
25443
|
+
});
|
|
25444
|
+
const cpfpRefundNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
25445
|
+
const directRefundNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
25446
|
+
const directFromCpfpRefundNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
25447
|
+
const cpfpRefundTxSighash = getSigHashFromTx(
|
|
25448
|
+
cpfpRefundTx,
|
|
25449
|
+
0,
|
|
25450
|
+
cpfpRootTx.getOutput(0)
|
|
25451
|
+
);
|
|
25452
|
+
if (!directRefundTx || !directFromCpfpRefundTx) {
|
|
25453
|
+
throw new ValidationError(
|
|
25454
|
+
"Expected direct refund transactions for tree creation",
|
|
25455
|
+
{
|
|
25456
|
+
field: "directRefundTx",
|
|
25457
|
+
value: directRefundTx
|
|
25458
|
+
}
|
|
25459
|
+
);
|
|
25460
|
+
}
|
|
25461
|
+
const directRefundTxSighash = getSigHashFromTx(
|
|
25462
|
+
directRefundTx,
|
|
25463
|
+
0,
|
|
25464
|
+
directRootTx.getOutput(0)
|
|
25465
|
+
);
|
|
25466
|
+
const directFromCpfpRefundTxSighash = getSigHashFromTx(
|
|
25467
|
+
directFromCpfpRefundTx,
|
|
25468
|
+
0,
|
|
25469
|
+
cpfpRootTx.getOutput(0)
|
|
25470
|
+
);
|
|
24224
25471
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
24225
25472
|
this.config.getCoordinatorAddress()
|
|
24226
25473
|
);
|
|
24227
|
-
let
|
|
25474
|
+
let treeResp;
|
|
24228
25475
|
try {
|
|
24229
|
-
|
|
24230
|
-
signingPublicKey: signingPubkey,
|
|
25476
|
+
treeResp = await sparkClient.start_deposit_tree_creation({
|
|
24231
25477
|
identityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
24232
|
-
|
|
24233
|
-
|
|
24234
|
-
|
|
25478
|
+
onChainUtxo: {
|
|
25479
|
+
vout,
|
|
25480
|
+
rawTx: depositTx.toBytes(true),
|
|
25481
|
+
network: this.config.getNetworkProto()
|
|
25482
|
+
},
|
|
25483
|
+
rootTxSigningJob: {
|
|
25484
|
+
rawTx: cpfpRootTx.toBytes(),
|
|
25485
|
+
signingPublicKey: signingPubKey,
|
|
25486
|
+
signingNonceCommitment: cpfpRootNonceCommitment.commitment
|
|
25487
|
+
},
|
|
25488
|
+
refundTxSigningJob: {
|
|
25489
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
25490
|
+
signingPublicKey: signingPubKey,
|
|
25491
|
+
signingNonceCommitment: cpfpRefundNonceCommitment.commitment
|
|
25492
|
+
},
|
|
25493
|
+
directRootTxSigningJob: {
|
|
25494
|
+
rawTx: directRootTx.toBytes(),
|
|
25495
|
+
signingPublicKey: signingPubKey,
|
|
25496
|
+
signingNonceCommitment: directRootNonceCommitment.commitment
|
|
25497
|
+
},
|
|
25498
|
+
directRefundTxSigningJob: {
|
|
25499
|
+
rawTx: directRefundTx.toBytes(),
|
|
25500
|
+
signingPublicKey: signingPubKey,
|
|
25501
|
+
signingNonceCommitment: directRefundNonceCommitment.commitment
|
|
25502
|
+
},
|
|
25503
|
+
directFromCpfpRefundTxSigningJob: {
|
|
25504
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
25505
|
+
signingPublicKey: signingPubKey,
|
|
25506
|
+
signingNonceCommitment: directFromCpfpRefundNonceCommitment.commitment
|
|
25507
|
+
}
|
|
24235
25508
|
});
|
|
24236
25509
|
} catch (error) {
|
|
24237
25510
|
throw new NetworkError(
|
|
24238
|
-
"Failed to
|
|
25511
|
+
"Failed to start deposit tree creation",
|
|
24239
25512
|
{
|
|
24240
|
-
operation: "
|
|
25513
|
+
operation: "start_deposit_tree_creation",
|
|
24241
25514
|
errorCount: 1,
|
|
24242
25515
|
errors: error instanceof Error ? error.message : String(error)
|
|
24243
25516
|
},
|
|
24244
25517
|
error
|
|
24245
25518
|
);
|
|
24246
25519
|
}
|
|
24247
|
-
if (!
|
|
25520
|
+
if (!treeResp.rootNodeSignatureShares?.verifyingKey) {
|
|
25521
|
+
throw new ValidationError("No verifying key found in tree response", {
|
|
25522
|
+
field: "verifyingKey",
|
|
25523
|
+
value: treeResp.rootNodeSignatureShares,
|
|
25524
|
+
expected: "Non-null verifying key"
|
|
25525
|
+
});
|
|
25526
|
+
}
|
|
25527
|
+
if (!treeResp.rootNodeSignatureShares.nodeTxSigningResult?.signingNonceCommitments) {
|
|
24248
25528
|
throw new ValidationError(
|
|
24249
|
-
"No
|
|
25529
|
+
"No signing nonce commitments found in tree response",
|
|
24250
25530
|
{
|
|
24251
|
-
field: "
|
|
24252
|
-
value:
|
|
25531
|
+
field: "nodeTxSigningResult.signingNonceCommitments",
|
|
25532
|
+
value: treeResp.rootNodeSignatureShares.nodeTxSigningResult,
|
|
25533
|
+
expected: "Non-null signing nonce commitments"
|
|
24253
25534
|
}
|
|
24254
25535
|
);
|
|
24255
25536
|
}
|
|
24256
|
-
|
|
24257
|
-
|
|
24258
|
-
|
|
25537
|
+
if (!treeResp.rootNodeSignatureShares.refundTxSigningResult?.signingNonceCommitments) {
|
|
25538
|
+
throw new ValidationError(
|
|
25539
|
+
"No signing nonce commitments found in tree response",
|
|
25540
|
+
{
|
|
25541
|
+
field: "refundTxSigningResult.signingNonceCommitments"
|
|
25542
|
+
}
|
|
25543
|
+
);
|
|
25544
|
+
}
|
|
25545
|
+
if (!treeResp.rootNodeSignatureShares.directNodeTxSigningResult?.signingNonceCommitments) {
|
|
25546
|
+
throw new ValidationError(
|
|
25547
|
+
"No direct node signing nonce commitments found in tree response",
|
|
25548
|
+
{
|
|
25549
|
+
field: "directNodeTxSigningResult.signingNonceCommitments"
|
|
25550
|
+
}
|
|
25551
|
+
);
|
|
25552
|
+
}
|
|
25553
|
+
if (!treeResp.rootNodeSignatureShares.directRefundTxSigningResult?.signingNonceCommitments) {
|
|
25554
|
+
throw new ValidationError(
|
|
25555
|
+
"No direct refund signing nonce commitments found in tree response",
|
|
25556
|
+
{
|
|
25557
|
+
field: "directRefundTxSigningResult.signingNonceCommitments"
|
|
25558
|
+
}
|
|
25559
|
+
);
|
|
25560
|
+
}
|
|
25561
|
+
if (!treeResp.rootNodeSignatureShares.directFromCpfpRefundTxSigningResult?.signingNonceCommitments) {
|
|
25562
|
+
throw new ValidationError(
|
|
25563
|
+
"No direct from CPFP refund signing nonce commitments found in tree response",
|
|
25564
|
+
{
|
|
25565
|
+
field: "directFromCpfpRefundTxSigningResult.signingNonceCommitments"
|
|
25566
|
+
}
|
|
25567
|
+
);
|
|
25568
|
+
}
|
|
25569
|
+
if (!equalBytes4(treeResp.rootNodeSignatureShares.verifyingKey, verifyingKey)) {
|
|
25570
|
+
throw new ValidationError("Verifying key mismatch", {
|
|
25571
|
+
field: "verifyingKey",
|
|
25572
|
+
value: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
25573
|
+
expected: verifyingKey
|
|
25574
|
+
});
|
|
25575
|
+
}
|
|
25576
|
+
const cpfpRootSignature = await this.config.signer.signFrost({
|
|
25577
|
+
message: cpfpRootTxSighash,
|
|
25578
|
+
publicKey: signingPubKey,
|
|
25579
|
+
keyDerivation,
|
|
25580
|
+
verifyingKey,
|
|
25581
|
+
selfCommitment: cpfpRootNonceCommitment,
|
|
25582
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signingNonceCommitments,
|
|
25583
|
+
adaptorPubKey: new Uint8Array()
|
|
24259
25584
|
});
|
|
24260
|
-
|
|
25585
|
+
const directRootSignature = await this.config.signer.signFrost({
|
|
25586
|
+
message: directRootTxSighash,
|
|
25587
|
+
publicKey: signingPubKey,
|
|
25588
|
+
keyDerivation,
|
|
25589
|
+
verifyingKey,
|
|
25590
|
+
selfCommitment: directRootNonceCommitment,
|
|
25591
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directNodeTxSigningResult.signingNonceCommitments,
|
|
25592
|
+
adaptorPubKey: new Uint8Array()
|
|
25593
|
+
});
|
|
25594
|
+
const cpfpRefundSignature = await this.config.signer.signFrost({
|
|
25595
|
+
message: cpfpRefundTxSighash,
|
|
25596
|
+
publicKey: signingPubKey,
|
|
25597
|
+
keyDerivation,
|
|
25598
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
25599
|
+
selfCommitment: cpfpRefundNonceCommitment,
|
|
25600
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.refundTxSigningResult.signingNonceCommitments,
|
|
25601
|
+
adaptorPubKey: new Uint8Array()
|
|
25602
|
+
});
|
|
25603
|
+
const directRefundSignature = await this.config.signer.signFrost({
|
|
25604
|
+
message: directRefundTxSighash,
|
|
25605
|
+
publicKey: signingPubKey,
|
|
25606
|
+
keyDerivation,
|
|
25607
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
25608
|
+
selfCommitment: directRefundNonceCommitment,
|
|
25609
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directRefundTxSigningResult.signingNonceCommitments,
|
|
25610
|
+
adaptorPubKey: new Uint8Array()
|
|
25611
|
+
});
|
|
25612
|
+
const directFromCpfpRefundSignature = await this.config.signer.signFrost({
|
|
25613
|
+
message: directFromCpfpRefundTxSighash,
|
|
25614
|
+
publicKey: signingPubKey,
|
|
25615
|
+
keyDerivation,
|
|
25616
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
25617
|
+
selfCommitment: directFromCpfpRefundNonceCommitment,
|
|
25618
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directFromCpfpRefundTxSigningResult.signingNonceCommitments,
|
|
25619
|
+
adaptorPubKey: new Uint8Array()
|
|
25620
|
+
});
|
|
25621
|
+
const cpfpRootAggregate = await this.config.signer.aggregateFrost({
|
|
25622
|
+
message: cpfpRootTxSighash,
|
|
25623
|
+
statechainSignatures: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signatureShares,
|
|
25624
|
+
statechainPublicKeys: treeResp.rootNodeSignatureShares.nodeTxSigningResult.publicKeys,
|
|
25625
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
25626
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signingNonceCommitments,
|
|
25627
|
+
selfCommitment: cpfpRootNonceCommitment,
|
|
25628
|
+
publicKey: signingPubKey,
|
|
25629
|
+
selfSignature: cpfpRootSignature,
|
|
25630
|
+
adaptorPubKey: new Uint8Array()
|
|
25631
|
+
});
|
|
25632
|
+
const directRootAggregate = await this.config.signer.aggregateFrost({
|
|
25633
|
+
message: directRootTxSighash,
|
|
25634
|
+
statechainSignatures: treeResp.rootNodeSignatureShares.directNodeTxSigningResult.signatureShares,
|
|
25635
|
+
statechainPublicKeys: treeResp.rootNodeSignatureShares.directNodeTxSigningResult.publicKeys,
|
|
25636
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
25637
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directNodeTxSigningResult.signingNonceCommitments,
|
|
25638
|
+
selfCommitment: directRootNonceCommitment,
|
|
25639
|
+
publicKey: signingPubKey,
|
|
25640
|
+
selfSignature: directRootSignature,
|
|
25641
|
+
adaptorPubKey: new Uint8Array()
|
|
25642
|
+
});
|
|
25643
|
+
const cpfpRefundAggregate = await this.config.signer.aggregateFrost({
|
|
25644
|
+
message: cpfpRefundTxSighash,
|
|
25645
|
+
statechainSignatures: treeResp.rootNodeSignatureShares.refundTxSigningResult.signatureShares,
|
|
25646
|
+
statechainPublicKeys: treeResp.rootNodeSignatureShares.refundTxSigningResult.publicKeys,
|
|
25647
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
25648
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.refundTxSigningResult.signingNonceCommitments,
|
|
25649
|
+
selfCommitment: cpfpRefundNonceCommitment,
|
|
25650
|
+
publicKey: signingPubKey,
|
|
25651
|
+
selfSignature: cpfpRefundSignature,
|
|
25652
|
+
adaptorPubKey: new Uint8Array()
|
|
25653
|
+
});
|
|
25654
|
+
const directRefundAggregate = await this.config.signer.aggregateFrost({
|
|
25655
|
+
message: directRefundTxSighash,
|
|
25656
|
+
statechainSignatures: treeResp.rootNodeSignatureShares.directRefundTxSigningResult.signatureShares,
|
|
25657
|
+
statechainPublicKeys: treeResp.rootNodeSignatureShares.directRefundTxSigningResult.publicKeys,
|
|
25658
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
25659
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directRefundTxSigningResult.signingNonceCommitments,
|
|
25660
|
+
selfCommitment: directRefundNonceCommitment,
|
|
25661
|
+
publicKey: signingPubKey,
|
|
25662
|
+
selfSignature: directRefundSignature,
|
|
25663
|
+
adaptorPubKey: new Uint8Array()
|
|
25664
|
+
});
|
|
25665
|
+
const directFromCpfpRefundAggregate = await this.config.signer.aggregateFrost({
|
|
25666
|
+
message: directFromCpfpRefundTxSighash,
|
|
25667
|
+
statechainSignatures: treeResp.rootNodeSignatureShares.directFromCpfpRefundTxSigningResult.signatureShares,
|
|
25668
|
+
statechainPublicKeys: treeResp.rootNodeSignatureShares.directFromCpfpRefundTxSigningResult.publicKeys,
|
|
25669
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
25670
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directFromCpfpRefundTxSigningResult.signingNonceCommitments,
|
|
25671
|
+
selfCommitment: directFromCpfpRefundNonceCommitment,
|
|
25672
|
+
publicKey: signingPubKey,
|
|
25673
|
+
selfSignature: directFromCpfpRefundSignature,
|
|
25674
|
+
adaptorPubKey: new Uint8Array()
|
|
25675
|
+
});
|
|
25676
|
+
let finalizeResp;
|
|
25677
|
+
try {
|
|
25678
|
+
finalizeResp = await sparkClient.finalize_node_signatures_v2({
|
|
25679
|
+
intent: 0 /* CREATION */,
|
|
25680
|
+
nodeSignatures: [
|
|
25681
|
+
{
|
|
25682
|
+
nodeId: treeResp.rootNodeSignatureShares.nodeId,
|
|
25683
|
+
nodeTxSignature: cpfpRootAggregate,
|
|
25684
|
+
refundTxSignature: cpfpRefundAggregate,
|
|
25685
|
+
directNodeTxSignature: directRootAggregate,
|
|
25686
|
+
directRefundTxSignature: directRefundAggregate,
|
|
25687
|
+
directFromCpfpRefundTxSignature: directFromCpfpRefundAggregate
|
|
25688
|
+
}
|
|
25689
|
+
]
|
|
25690
|
+
});
|
|
25691
|
+
} catch (error) {
|
|
25692
|
+
throw new NetworkError(
|
|
25693
|
+
"Failed to finalize node signatures",
|
|
25694
|
+
{
|
|
25695
|
+
operation: "finalize_node_signatures",
|
|
25696
|
+
errorCount: 1,
|
|
25697
|
+
errors: error instanceof Error ? error.message : String(error)
|
|
25698
|
+
},
|
|
25699
|
+
error
|
|
25700
|
+
);
|
|
25701
|
+
}
|
|
25702
|
+
return finalizeResp;
|
|
24261
25703
|
}
|
|
24262
|
-
|
|
25704
|
+
/**
|
|
25705
|
+
* @deprecated
|
|
25706
|
+
* Use createTreeRoot instead.
|
|
25707
|
+
* This is currently only used to test backwards compatibility.
|
|
25708
|
+
*/
|
|
25709
|
+
async createTreeWithoutDirectTx({
|
|
24263
25710
|
keyDerivation,
|
|
24264
25711
|
verifyingKey,
|
|
24265
25712
|
depositTx,
|
|
24266
25713
|
vout
|
|
24267
25714
|
}) {
|
|
24268
|
-
const rootTx = new Transaction6({ version: 3 });
|
|
24269
25715
|
const output = depositTx.getOutput(vout);
|
|
24270
25716
|
if (!output) {
|
|
24271
25717
|
throw new ValidationError("Invalid deposit transaction output", {
|
|
@@ -24283,39 +25729,31 @@ var DepositService = class {
|
|
|
24283
25729
|
expected: "Output with script and amount"
|
|
24284
25730
|
});
|
|
24285
25731
|
}
|
|
24286
|
-
|
|
24287
|
-
|
|
24288
|
-
txid: getTxId(depositTx),
|
|
25732
|
+
const depositOutPoint = {
|
|
25733
|
+
txid: hexToBytes7(getTxId(depositTx)),
|
|
24289
25734
|
index: vout
|
|
24290
|
-
}
|
|
24291
|
-
|
|
25735
|
+
};
|
|
25736
|
+
const depositTxOut = {
|
|
24292
25737
|
script,
|
|
24293
|
-
amount
|
|
24294
|
-
}
|
|
24295
|
-
|
|
24296
|
-
const
|
|
24297
|
-
const
|
|
24298
|
-
const refundTx = new Transaction6({ version: 3 });
|
|
24299
|
-
const sequence = 1 << 30 | INITIAL_TIME_LOCK2;
|
|
24300
|
-
refundTx.addInput({
|
|
24301
|
-
txid: getTxId(rootTx),
|
|
24302
|
-
index: 0,
|
|
24303
|
-
sequence
|
|
24304
|
-
});
|
|
25738
|
+
amount
|
|
25739
|
+
};
|
|
25740
|
+
const [cpfpRootTx, _] = createRootTx(depositOutPoint, depositTxOut);
|
|
25741
|
+
const cpfpRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
25742
|
+
const cpfpRootTxSighash = getSigHashFromTx(cpfpRootTx, 0, output);
|
|
24305
25743
|
const signingPubKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
24306
|
-
const
|
|
24307
|
-
|
|
24308
|
-
|
|
24309
|
-
|
|
24310
|
-
|
|
24311
|
-
|
|
24312
|
-
refundTx.addOutput({
|
|
24313
|
-
script: refundPkScript,
|
|
24314
|
-
amount: outputAmount
|
|
25744
|
+
const { cpfpRefundTx } = createRefundTxs({
|
|
25745
|
+
sequence: INITIAL_SEQUENCE,
|
|
25746
|
+
input: { txid: hexToBytes7(getTxId(cpfpRootTx)), index: 0 },
|
|
25747
|
+
amountSats: amount,
|
|
25748
|
+
receivingPubkey: signingPubKey,
|
|
25749
|
+
network: this.config.getNetwork()
|
|
24315
25750
|
});
|
|
24316
|
-
|
|
24317
|
-
const
|
|
24318
|
-
|
|
25751
|
+
const cpfpRefundNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
25752
|
+
const cpfpRefundTxSighash = getSigHashFromTx(
|
|
25753
|
+
cpfpRefundTx,
|
|
25754
|
+
0,
|
|
25755
|
+
cpfpRootTx.getOutput(0)
|
|
25756
|
+
);
|
|
24319
25757
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
24320
25758
|
this.config.getCoordinatorAddress()
|
|
24321
25759
|
);
|
|
@@ -24329,14 +25767,14 @@ var DepositService = class {
|
|
|
24329
25767
|
network: this.config.getNetworkProto()
|
|
24330
25768
|
},
|
|
24331
25769
|
rootTxSigningJob: {
|
|
24332
|
-
rawTx:
|
|
25770
|
+
rawTx: cpfpRootTx.toBytes(),
|
|
24333
25771
|
signingPublicKey: signingPubKey,
|
|
24334
|
-
signingNonceCommitment:
|
|
25772
|
+
signingNonceCommitment: cpfpRootNonceCommitment.commitment
|
|
24335
25773
|
},
|
|
24336
25774
|
refundTxSigningJob: {
|
|
24337
|
-
rawTx:
|
|
25775
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
24338
25776
|
signingPublicKey: signingPubKey,
|
|
24339
|
-
signingNonceCommitment:
|
|
25777
|
+
signingNonceCommitment: cpfpRefundNonceCommitment.commitment
|
|
24340
25778
|
}
|
|
24341
25779
|
});
|
|
24342
25780
|
} catch (error) {
|
|
@@ -24382,55 +25820,55 @@ var DepositService = class {
|
|
|
24382
25820
|
expected: verifyingKey
|
|
24383
25821
|
});
|
|
24384
25822
|
}
|
|
24385
|
-
const
|
|
24386
|
-
message:
|
|
25823
|
+
const cpfpRootSignature = await this.config.signer.signFrost({
|
|
25824
|
+
message: cpfpRootTxSighash,
|
|
24387
25825
|
publicKey: signingPubKey,
|
|
24388
25826
|
keyDerivation,
|
|
24389
25827
|
verifyingKey,
|
|
24390
|
-
selfCommitment:
|
|
25828
|
+
selfCommitment: cpfpRootNonceCommitment,
|
|
24391
25829
|
statechainCommitments: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signingNonceCommitments,
|
|
24392
25830
|
adaptorPubKey: new Uint8Array()
|
|
24393
25831
|
});
|
|
24394
|
-
const
|
|
24395
|
-
message:
|
|
25832
|
+
const cpfpRefundSignature = await this.config.signer.signFrost({
|
|
25833
|
+
message: cpfpRefundTxSighash,
|
|
24396
25834
|
publicKey: signingPubKey,
|
|
24397
25835
|
keyDerivation,
|
|
24398
|
-
verifyingKey,
|
|
24399
|
-
selfCommitment:
|
|
25836
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
25837
|
+
selfCommitment: cpfpRefundNonceCommitment,
|
|
24400
25838
|
statechainCommitments: treeResp.rootNodeSignatureShares.refundTxSigningResult.signingNonceCommitments,
|
|
24401
25839
|
adaptorPubKey: new Uint8Array()
|
|
24402
25840
|
});
|
|
24403
|
-
const
|
|
24404
|
-
message:
|
|
25841
|
+
const cpfpRootAggregate = await this.config.signer.aggregateFrost({
|
|
25842
|
+
message: cpfpRootTxSighash,
|
|
24405
25843
|
statechainSignatures: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signatureShares,
|
|
24406
25844
|
statechainPublicKeys: treeResp.rootNodeSignatureShares.nodeTxSigningResult.publicKeys,
|
|
24407
25845
|
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
24408
25846
|
statechainCommitments: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signingNonceCommitments,
|
|
24409
|
-
selfCommitment:
|
|
25847
|
+
selfCommitment: cpfpRootNonceCommitment,
|
|
24410
25848
|
publicKey: signingPubKey,
|
|
24411
|
-
selfSignature:
|
|
25849
|
+
selfSignature: cpfpRootSignature,
|
|
24412
25850
|
adaptorPubKey: new Uint8Array()
|
|
24413
25851
|
});
|
|
24414
|
-
const
|
|
24415
|
-
message:
|
|
25852
|
+
const cpfpRefundAggregate = await this.config.signer.aggregateFrost({
|
|
25853
|
+
message: cpfpRefundTxSighash,
|
|
24416
25854
|
statechainSignatures: treeResp.rootNodeSignatureShares.refundTxSigningResult.signatureShares,
|
|
24417
25855
|
statechainPublicKeys: treeResp.rootNodeSignatureShares.refundTxSigningResult.publicKeys,
|
|
24418
25856
|
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
24419
25857
|
statechainCommitments: treeResp.rootNodeSignatureShares.refundTxSigningResult.signingNonceCommitments,
|
|
24420
|
-
selfCommitment:
|
|
25858
|
+
selfCommitment: cpfpRefundNonceCommitment,
|
|
24421
25859
|
publicKey: signingPubKey,
|
|
24422
|
-
selfSignature:
|
|
25860
|
+
selfSignature: cpfpRefundSignature,
|
|
24423
25861
|
adaptorPubKey: new Uint8Array()
|
|
24424
25862
|
});
|
|
24425
25863
|
let finalizeResp;
|
|
24426
25864
|
try {
|
|
24427
|
-
finalizeResp = await sparkClient.
|
|
25865
|
+
finalizeResp = await sparkClient.finalize_node_signatures_v2({
|
|
24428
25866
|
intent: 0 /* CREATION */,
|
|
24429
25867
|
nodeSignatures: [
|
|
24430
25868
|
{
|
|
24431
25869
|
nodeId: treeResp.rootNodeSignatureShares.nodeId,
|
|
24432
|
-
nodeTxSignature:
|
|
24433
|
-
refundTxSignature:
|
|
25870
|
+
nodeTxSignature: cpfpRootAggregate,
|
|
25871
|
+
refundTxSignature: cpfpRefundAggregate
|
|
24434
25872
|
}
|
|
24435
25873
|
]
|
|
24436
25874
|
});
|
|
@@ -24642,7 +26080,8 @@ var LightningService = class {
|
|
|
24642
26080
|
let signingCommitments;
|
|
24643
26081
|
try {
|
|
24644
26082
|
signingCommitments = await sparkClient.get_signing_commitments({
|
|
24645
|
-
nodeIds: leaves.map((leaf) => leaf.leaf.id)
|
|
26083
|
+
nodeIds: leaves.map((leaf) => leaf.leaf.id),
|
|
26084
|
+
count: 3
|
|
24646
26085
|
});
|
|
24647
26086
|
} catch (error) {
|
|
24648
26087
|
throw new NetworkError(
|
|
@@ -24655,10 +26094,19 @@ var LightningService = class {
|
|
|
24655
26094
|
error
|
|
24656
26095
|
);
|
|
24657
26096
|
}
|
|
24658
|
-
const
|
|
26097
|
+
const {
|
|
26098
|
+
cpfpLeafSigningJobs,
|
|
26099
|
+
directLeafSigningJobs,
|
|
26100
|
+
directFromCpfpLeafSigningJobs
|
|
26101
|
+
} = await this.signingService.signRefunds(
|
|
24659
26102
|
leaves,
|
|
24660
|
-
|
|
24661
|
-
|
|
26103
|
+
receiverIdentityPubkey,
|
|
26104
|
+
signingCommitments.signingCommitments.slice(0, leaves.length),
|
|
26105
|
+
signingCommitments.signingCommitments.slice(
|
|
26106
|
+
leaves.length,
|
|
26107
|
+
2 * leaves.length
|
|
26108
|
+
),
|
|
26109
|
+
signingCommitments.signingCommitments.slice(2 * leaves.length)
|
|
24662
26110
|
);
|
|
24663
26111
|
const transferId = uuidv74();
|
|
24664
26112
|
let bolt11String = "";
|
|
@@ -24695,7 +26143,7 @@ var LightningService = class {
|
|
|
24695
26143
|
const reason = isInboundPayment ? 1 /* REASON_RECEIVE */ : 0 /* REASON_SEND */;
|
|
24696
26144
|
let response;
|
|
24697
26145
|
try {
|
|
24698
|
-
response = await sparkClient.
|
|
26146
|
+
response = await sparkClient.initiate_preimage_swap_v2({
|
|
24699
26147
|
paymentHash,
|
|
24700
26148
|
invoiceAmount: {
|
|
24701
26149
|
invoiceAmountProof: {
|
|
@@ -24707,7 +26155,9 @@ var LightningService = class {
|
|
|
24707
26155
|
transfer: {
|
|
24708
26156
|
transferId,
|
|
24709
26157
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
24710
|
-
leavesToSend:
|
|
26158
|
+
leavesToSend: cpfpLeafSigningJobs,
|
|
26159
|
+
directLeavesToSend: directLeafSigningJobs,
|
|
26160
|
+
directFromCpfpLeavesToSend: directFromCpfpLeafSigningJobs,
|
|
24711
26161
|
receiverIdentityPublicKey: receiverIdentityPubkey,
|
|
24712
26162
|
expiryTime: new Date(Date.now() + 2 * 60 * 1e3)
|
|
24713
26163
|
},
|
|
@@ -26961,7 +28411,9 @@ var TokenTransactionService = class {
|
|
|
26961
28411
|
issuerPublicKeys,
|
|
26962
28412
|
tokenTransactionHashes,
|
|
26963
28413
|
tokenIdentifiers,
|
|
26964
|
-
outputIds
|
|
28414
|
+
outputIds,
|
|
28415
|
+
pageSize,
|
|
28416
|
+
offset
|
|
26965
28417
|
} = params;
|
|
26966
28418
|
const tokenClient = await this.connectionManager.createSparkTokenClient(
|
|
26967
28419
|
this.config.getCoordinatorAddress()
|
|
@@ -26972,8 +28424,8 @@ var TokenTransactionService = class {
|
|
|
26972
28424
|
tokenIdentifiers: tokenIdentifiers?.map(hexToBytes9),
|
|
26973
28425
|
tokenTransactionHashes: tokenTransactionHashes?.map(hexToBytes9),
|
|
26974
28426
|
outputIds: outputIds || [],
|
|
26975
|
-
limit:
|
|
26976
|
-
offset
|
|
28427
|
+
limit: pageSize,
|
|
28428
|
+
offset
|
|
26977
28429
|
};
|
|
26978
28430
|
try {
|
|
26979
28431
|
const response = await tokenClient.query_token_transactions(queryParams);
|
|
@@ -27180,14 +28632,7 @@ function isTokenTransaction(tokenTransaction) {
|
|
|
27180
28632
|
|
|
27181
28633
|
// src/services/tree-creation.ts
|
|
27182
28634
|
import { hexToBytes as hexToBytes10 } from "@noble/curves/abstract/utils";
|
|
27183
|
-
import { Address as
|
|
27184
|
-
var INITIAL_TIME_LOCK3 = 2e3;
|
|
27185
|
-
function maybeApplyFee2(amount) {
|
|
27186
|
-
if (amount > BigInt(DEFAULT_FEE_SATS)) {
|
|
27187
|
-
return amount - BigInt(DEFAULT_FEE_SATS);
|
|
27188
|
-
}
|
|
27189
|
-
return amount;
|
|
27190
|
-
}
|
|
28635
|
+
import { Address as Address4, OutScript as OutScript2 } from "@scure/btc-signer";
|
|
27191
28636
|
var TreeCreationService = class {
|
|
27192
28637
|
config;
|
|
27193
28638
|
connectionManager;
|
|
@@ -27302,7 +28747,7 @@ var TreeCreationService = class {
|
|
|
27302
28747
|
);
|
|
27303
28748
|
let response;
|
|
27304
28749
|
try {
|
|
27305
|
-
response = await sparkClient.
|
|
28750
|
+
response = await sparkClient.create_tree_v2(request);
|
|
27306
28751
|
} catch (error) {
|
|
27307
28752
|
throw new Error(`Error creating tree: ${error}`);
|
|
27308
28753
|
}
|
|
@@ -27319,7 +28764,7 @@ var TreeCreationService = class {
|
|
|
27319
28764
|
);
|
|
27320
28765
|
let finalizeResp;
|
|
27321
28766
|
try {
|
|
27322
|
-
finalizeResp = await sparkClient.
|
|
28767
|
+
finalizeResp = await sparkClient.finalize_node_signatures_v2({
|
|
27323
28768
|
nodeSignatures
|
|
27324
28769
|
});
|
|
27325
28770
|
} catch (error) {
|
|
@@ -27384,91 +28829,111 @@ var TreeCreationService = class {
|
|
|
27384
28829
|
async buildChildCreationNode(node, parentTx, vout, network) {
|
|
27385
28830
|
const internalCreationNode = {
|
|
27386
28831
|
nodeTxSigningJob: void 0,
|
|
27387
|
-
refundTxSigningJob: void 0,
|
|
27388
|
-
children: [],
|
|
27389
28832
|
directNodeTxSigningJob: void 0,
|
|
28833
|
+
refundTxSigningJob: void 0,
|
|
27390
28834
|
directRefundTxSigningJob: void 0,
|
|
27391
|
-
directFromCpfpRefundTxSigningJob: void 0
|
|
28835
|
+
directFromCpfpRefundTxSigningJob: void 0,
|
|
28836
|
+
children: []
|
|
27392
28837
|
};
|
|
27393
|
-
const tx = new Transaction7({ version: 3 });
|
|
27394
|
-
tx.addInput({
|
|
27395
|
-
txid: getTxId(parentTx),
|
|
27396
|
-
index: vout
|
|
27397
|
-
});
|
|
27398
28838
|
const parentTxOut = parentTx.getOutput(vout);
|
|
27399
28839
|
if (!parentTxOut?.script || !parentTxOut?.amount) {
|
|
27400
28840
|
throw new Error("parentTxOut is undefined");
|
|
27401
28841
|
}
|
|
27402
|
-
|
|
28842
|
+
const parentOutPoint = {
|
|
28843
|
+
txid: hexToBytes10(getTxId(parentTx)),
|
|
28844
|
+
index: vout
|
|
28845
|
+
};
|
|
28846
|
+
const parentTxOutObj = {
|
|
27403
28847
|
script: parentTxOut.script,
|
|
27404
28848
|
amount: parentTxOut.amount
|
|
27405
|
-
|
|
27406
|
-
}
|
|
27407
|
-
|
|
27408
|
-
|
|
27409
|
-
|
|
28849
|
+
};
|
|
28850
|
+
const { cpfpNodeTx, directNodeTx } = createNodeTxs(
|
|
28851
|
+
parentTxOutObj,
|
|
28852
|
+
parentOutPoint
|
|
28853
|
+
);
|
|
28854
|
+
const cpfpNodeSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
28855
|
+
const directNodeSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
28856
|
+
const cpfpNodeSigningJob = {
|
|
27410
28857
|
signingPublicKey: node.signingPublicKey,
|
|
27411
|
-
rawTx:
|
|
27412
|
-
signingNonceCommitment:
|
|
28858
|
+
rawTx: cpfpNodeTx.toBytes(),
|
|
28859
|
+
signingNonceCommitment: cpfpNodeSigningCommitment.commitment
|
|
27413
28860
|
};
|
|
27414
|
-
|
|
27415
|
-
|
|
27416
|
-
|
|
28861
|
+
const directNodeSigningJob = directNodeTx ? {
|
|
28862
|
+
signingPublicKey: node.signingPublicKey,
|
|
28863
|
+
rawTx: directNodeTx.toBytes(),
|
|
28864
|
+
signingNonceCommitment: directNodeSigningCommitment.commitment
|
|
28865
|
+
} : void 0;
|
|
28866
|
+
internalCreationNode.nodeTxSigningCommitment = cpfpNodeSigningCommitment;
|
|
28867
|
+
internalCreationNode.directNodeTxSigningCommitment = directNodeSigningCommitment;
|
|
28868
|
+
internalCreationNode.nodeTxSigningJob = cpfpNodeSigningJob;
|
|
28869
|
+
internalCreationNode.directNodeTxSigningJob = directNodeSigningJob;
|
|
28870
|
+
const sequence = INITIAL_SEQUENCE;
|
|
28871
|
+
const directSequence = INITIAL_DIRECT_SEQUENCE;
|
|
27417
28872
|
const childCreationNode = {
|
|
27418
28873
|
nodeTxSigningJob: void 0,
|
|
27419
|
-
refundTxSigningJob: void 0,
|
|
27420
|
-
children: [],
|
|
27421
28874
|
directNodeTxSigningJob: void 0,
|
|
28875
|
+
refundTxSigningJob: void 0,
|
|
27422
28876
|
directRefundTxSigningJob: void 0,
|
|
27423
|
-
directFromCpfpRefundTxSigningJob: void 0
|
|
28877
|
+
directFromCpfpRefundTxSigningJob: void 0,
|
|
28878
|
+
children: []
|
|
27424
28879
|
};
|
|
27425
|
-
const
|
|
27426
|
-
|
|
27427
|
-
|
|
27428
|
-
index: 0,
|
|
27429
|
-
|
|
27430
|
-
|
|
27431
|
-
|
|
27432
|
-
|
|
27433
|
-
|
|
27434
|
-
|
|
27435
|
-
|
|
27436
|
-
childTx.addOutput(getEphemeralAnchorOutput());
|
|
27437
|
-
const childSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
27438
|
-
const childSigningJob = {
|
|
28880
|
+
const [cpfpLeafTx, directLeafTx] = createLeafNodeTx(
|
|
28881
|
+
sequence,
|
|
28882
|
+
directSequence,
|
|
28883
|
+
{ txid: hexToBytes10(getTxId(cpfpNodeTx)), index: 0 },
|
|
28884
|
+
parentTxOutObj,
|
|
28885
|
+
true
|
|
28886
|
+
// shouldCalculateFee
|
|
28887
|
+
);
|
|
28888
|
+
const cpfpLeafSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
28889
|
+
const directLeafSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
28890
|
+
const cpfpLeafSigningJob = {
|
|
27439
28891
|
signingPublicKey: node.signingPublicKey,
|
|
27440
|
-
rawTx:
|
|
27441
|
-
signingNonceCommitment:
|
|
28892
|
+
rawTx: cpfpLeafTx.toBytes(),
|
|
28893
|
+
signingNonceCommitment: cpfpLeafSigningCommitment.commitment
|
|
27442
28894
|
};
|
|
27443
|
-
|
|
27444
|
-
|
|
27445
|
-
|
|
27446
|
-
|
|
27447
|
-
|
|
27448
|
-
|
|
27449
|
-
|
|
27450
|
-
|
|
27451
|
-
|
|
27452
|
-
|
|
28895
|
+
const directLeafSigningJob = {
|
|
28896
|
+
signingPublicKey: node.signingPublicKey,
|
|
28897
|
+
rawTx: directLeafTx.toBytes(),
|
|
28898
|
+
signingNonceCommitment: directLeafSigningCommitment.commitment
|
|
28899
|
+
};
|
|
28900
|
+
childCreationNode.nodeTxSigningCommitment = cpfpLeafSigningCommitment;
|
|
28901
|
+
childCreationNode.directNodeTxSigningCommitment = directLeafSigningCommitment;
|
|
28902
|
+
childCreationNode.nodeTxSigningJob = cpfpLeafSigningJob;
|
|
28903
|
+
childCreationNode.directNodeTxSigningJob = directLeafSigningJob;
|
|
28904
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
28905
|
+
sequence,
|
|
28906
|
+
directSequence,
|
|
28907
|
+
input: { txid: hexToBytes10(getTxId(cpfpLeafTx)), index: 0 },
|
|
28908
|
+
directInput: { txid: hexToBytes10(getTxId(directLeafTx)), index: 0 },
|
|
28909
|
+
amountSats: parentTxOut.amount,
|
|
28910
|
+
receivingPubkey: node.signingPublicKey,
|
|
27453
28911
|
network
|
|
27454
|
-
);
|
|
27455
|
-
const refundAddress = Address5(getNetwork(network)).decode(
|
|
27456
|
-
refundP2trAddress
|
|
27457
|
-
);
|
|
27458
|
-
const refundPkScript = OutScript3.encode(refundAddress);
|
|
27459
|
-
refundTx.addOutput({
|
|
27460
|
-
script: refundPkScript,
|
|
27461
|
-
amount: maybeApplyFee2(parentTxOut.amount)
|
|
27462
28912
|
});
|
|
27463
|
-
|
|
27464
|
-
const
|
|
27465
|
-
const
|
|
28913
|
+
const cpfpRefundSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
28914
|
+
const directRefundSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
28915
|
+
const directFromCpfpRefundSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
28916
|
+
const cpfpRefundSigningJob = {
|
|
27466
28917
|
signingPublicKey: node.signingPublicKey,
|
|
27467
|
-
rawTx:
|
|
27468
|
-
signingNonceCommitment:
|
|
28918
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
28919
|
+
signingNonceCommitment: cpfpRefundSigningCommitment.commitment
|
|
27469
28920
|
};
|
|
27470
|
-
|
|
27471
|
-
|
|
28921
|
+
const directRefundSigningJob = directRefundTx ? {
|
|
28922
|
+
signingPublicKey: node.signingPublicKey,
|
|
28923
|
+
rawTx: directRefundTx.toBytes(),
|
|
28924
|
+
signingNonceCommitment: directRefundSigningCommitment.commitment
|
|
28925
|
+
} : void 0;
|
|
28926
|
+
const directFromCpfpRefundSigningJob = directFromCpfpRefundTx ? {
|
|
28927
|
+
signingPublicKey: node.signingPublicKey,
|
|
28928
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
28929
|
+
signingNonceCommitment: directFromCpfpRefundSigningCommitment.commitment
|
|
28930
|
+
} : void 0;
|
|
28931
|
+
childCreationNode.refundTxSigningCommitment = cpfpRefundSigningCommitment;
|
|
28932
|
+
childCreationNode.directRefundTxSigningCommitment = directRefundSigningCommitment;
|
|
28933
|
+
childCreationNode.directFromCpfpRefundTxSigningCommitment = directFromCpfpRefundSigningCommitment;
|
|
28934
|
+
childCreationNode.refundTxSigningJob = cpfpRefundSigningJob;
|
|
28935
|
+
childCreationNode.directRefundTxSigningJob = directRefundSigningJob;
|
|
28936
|
+
childCreationNode.directFromCpfpRefundTxSigningJob = directFromCpfpRefundSigningJob;
|
|
27472
28937
|
internalCreationNode.children.push(childCreationNode);
|
|
27473
28938
|
return internalCreationNode;
|
|
27474
28939
|
}
|
|
@@ -27477,40 +28942,49 @@ var TreeCreationService = class {
|
|
|
27477
28942
|
if (!parentTxOutput?.script || !parentTxOutput?.amount) {
|
|
27478
28943
|
throw new Error("parentTxOutput is undefined");
|
|
27479
28944
|
}
|
|
27480
|
-
const
|
|
27481
|
-
rootNodeTx.addInput({
|
|
27482
|
-
txid: getTxId(parentTx),
|
|
27483
|
-
index: vout
|
|
27484
|
-
});
|
|
28945
|
+
const childTxOuts = [];
|
|
27485
28946
|
for (let i = 0; i < root.children.length; i++) {
|
|
27486
28947
|
const child = root.children[i];
|
|
27487
28948
|
if (!child || !child.address) {
|
|
27488
28949
|
throw new Error("child address is undefined");
|
|
27489
28950
|
}
|
|
27490
|
-
const childAddress =
|
|
27491
|
-
const childPkScript =
|
|
27492
|
-
|
|
28951
|
+
const childAddress = Address4(getNetwork(network)).decode(child.address);
|
|
28952
|
+
const childPkScript = OutScript2.encode(childAddress);
|
|
28953
|
+
childTxOuts.push({
|
|
27493
28954
|
script: childPkScript,
|
|
27494
28955
|
amount: parentTxOutput.amount / 2n
|
|
27495
|
-
// feeAdjustedAmount / 2n,
|
|
27496
28956
|
});
|
|
27497
28957
|
}
|
|
27498
|
-
|
|
27499
|
-
|
|
27500
|
-
|
|
28958
|
+
const parentOutPoint = {
|
|
28959
|
+
txid: hexToBytes10(getTxId(parentTx)),
|
|
28960
|
+
index: vout
|
|
28961
|
+
};
|
|
28962
|
+
const [cpfpSplitTx, directSplitTx] = createSplitTx(
|
|
28963
|
+
parentOutPoint,
|
|
28964
|
+
childTxOuts
|
|
28965
|
+
);
|
|
28966
|
+
const cpfpSplitSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
28967
|
+
const directSplitSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
28968
|
+
const cpfpSplitSigningJob = {
|
|
28969
|
+
signingPublicKey: root.signingPublicKey,
|
|
28970
|
+
rawTx: cpfpSplitTx.toBytes(),
|
|
28971
|
+
signingNonceCommitment: cpfpSplitSigningCommitment.commitment
|
|
28972
|
+
};
|
|
28973
|
+
const directSplitSigningJob = {
|
|
27501
28974
|
signingPublicKey: root.signingPublicKey,
|
|
27502
|
-
rawTx:
|
|
27503
|
-
signingNonceCommitment:
|
|
28975
|
+
rawTx: directSplitTx.toBytes(),
|
|
28976
|
+
signingNonceCommitment: directSplitSigningCommitment.commitment
|
|
27504
28977
|
};
|
|
27505
28978
|
const rootCreationNode = {
|
|
27506
|
-
nodeTxSigningJob:
|
|
28979
|
+
nodeTxSigningJob: cpfpSplitSigningJob,
|
|
28980
|
+
directNodeTxSigningJob: directSplitSigningJob,
|
|
27507
28981
|
refundTxSigningJob: void 0,
|
|
27508
|
-
children: [],
|
|
27509
|
-
directNodeTxSigningJob: void 0,
|
|
27510
28982
|
directRefundTxSigningJob: void 0,
|
|
27511
|
-
directFromCpfpRefundTxSigningJob: void 0
|
|
28983
|
+
directFromCpfpRefundTxSigningJob: void 0,
|
|
28984
|
+
children: []
|
|
27512
28985
|
};
|
|
27513
|
-
rootCreationNode.nodeTxSigningCommitment =
|
|
28986
|
+
rootCreationNode.nodeTxSigningCommitment = cpfpSplitSigningCommitment;
|
|
28987
|
+
rootCreationNode.directNodeTxSigningCommitment = directSplitSigningCommitment;
|
|
27514
28988
|
const leftChild = root.children[0];
|
|
27515
28989
|
const rightChild = root.children[1];
|
|
27516
28990
|
if (!leftChild || !rightChild) {
|
|
@@ -27518,13 +28992,15 @@ var TreeCreationService = class {
|
|
|
27518
28992
|
}
|
|
27519
28993
|
const leftChildCreationNode = await this.buildChildCreationNode(
|
|
27520
28994
|
leftChild,
|
|
27521
|
-
|
|
28995
|
+
cpfpSplitTx,
|
|
28996
|
+
// Use CPFP version for children
|
|
27522
28997
|
0,
|
|
27523
28998
|
network
|
|
27524
28999
|
);
|
|
27525
29000
|
const rightChildCreationNode = await this.buildChildCreationNode(
|
|
27526
29001
|
rightChild,
|
|
27527
|
-
|
|
29002
|
+
cpfpSplitTx,
|
|
29003
|
+
// Use CPFP version for children
|
|
27528
29004
|
1,
|
|
27529
29005
|
network
|
|
27530
29006
|
);
|
|
@@ -27533,19 +29009,19 @@ var TreeCreationService = class {
|
|
|
27533
29009
|
return rootCreationNode;
|
|
27534
29010
|
}
|
|
27535
29011
|
async signNodeCreation(parentTx, vout, internalNode, creationNode, creationResponseNode) {
|
|
27536
|
-
if (!creationNode.nodeTxSigningJob?.signingPublicKey || !internalNode.verificationKey) {
|
|
29012
|
+
if (!creationNode.nodeTxSigningJob?.signingPublicKey || !creationNode.directNodeTxSigningJob?.signingPublicKey || !internalNode.verificationKey) {
|
|
27537
29013
|
throw new Error("signingPublicKey or verificationKey is undefined");
|
|
27538
29014
|
}
|
|
27539
29015
|
const parentTxOutput = parentTx.getOutput(vout);
|
|
27540
29016
|
if (!parentTxOutput) {
|
|
27541
29017
|
throw new Error("parentTxOutput is undefined");
|
|
27542
29018
|
}
|
|
27543
|
-
const
|
|
27544
|
-
const
|
|
27545
|
-
let
|
|
29019
|
+
const cpfpNodeTx = getTxFromRawTxBytes(creationNode.nodeTxSigningJob.rawTx);
|
|
29020
|
+
const cpfpNodeTxSighash = getSigHashFromTx(cpfpNodeTx, 0, parentTxOutput);
|
|
29021
|
+
let cpfpNodeTxSignature = new Uint8Array();
|
|
27546
29022
|
if (creationNode.nodeTxSigningCommitment) {
|
|
27547
|
-
const
|
|
27548
|
-
message:
|
|
29023
|
+
const cpfpUserSignature = await this.config.signer.signFrost({
|
|
29024
|
+
message: cpfpNodeTxSighash,
|
|
27549
29025
|
publicKey: creationNode.nodeTxSigningJob.signingPublicKey,
|
|
27550
29026
|
keyDerivation: {
|
|
27551
29027
|
type: "leaf" /* LEAF */,
|
|
@@ -27555,30 +29031,84 @@ var TreeCreationService = class {
|
|
|
27555
29031
|
statechainCommitments: creationResponseNode.nodeTxSigningResult?.signingNonceCommitments,
|
|
27556
29032
|
verifyingKey: internalNode.verificationKey
|
|
27557
29033
|
});
|
|
27558
|
-
|
|
27559
|
-
message:
|
|
29034
|
+
cpfpNodeTxSignature = await this.config.signer.aggregateFrost({
|
|
29035
|
+
message: cpfpNodeTxSighash,
|
|
27560
29036
|
statechainSignatures: creationResponseNode.nodeTxSigningResult?.signatureShares,
|
|
27561
29037
|
statechainPublicKeys: creationResponseNode.nodeTxSigningResult?.publicKeys,
|
|
27562
29038
|
verifyingKey: internalNode.verificationKey,
|
|
27563
29039
|
statechainCommitments: creationResponseNode.nodeTxSigningResult?.signingNonceCommitments,
|
|
27564
29040
|
selfCommitment: creationNode.nodeTxSigningCommitment,
|
|
27565
|
-
selfSignature:
|
|
29041
|
+
selfSignature: cpfpUserSignature,
|
|
29042
|
+
publicKey: internalNode.signingPublicKey
|
|
29043
|
+
});
|
|
29044
|
+
}
|
|
29045
|
+
const directNodeTx = getTxFromRawTxBytes(
|
|
29046
|
+
creationNode.directNodeTxSigningJob.rawTx
|
|
29047
|
+
);
|
|
29048
|
+
const directNodeTxSighash = getSigHashFromTx(
|
|
29049
|
+
directNodeTx,
|
|
29050
|
+
0,
|
|
29051
|
+
parentTxOutput
|
|
29052
|
+
);
|
|
29053
|
+
let directNodeTxSignature = new Uint8Array();
|
|
29054
|
+
if (creationNode.directNodeTxSigningCommitment) {
|
|
29055
|
+
const directUserSignature = await this.config.signer.signFrost({
|
|
29056
|
+
message: directNodeTxSighash,
|
|
29057
|
+
publicKey: creationNode.directNodeTxSigningJob.signingPublicKey,
|
|
29058
|
+
keyDerivation: {
|
|
29059
|
+
type: "leaf" /* LEAF */,
|
|
29060
|
+
path: creationResponseNode.nodeId
|
|
29061
|
+
},
|
|
29062
|
+
selfCommitment: creationNode.directNodeTxSigningCommitment,
|
|
29063
|
+
statechainCommitments: creationResponseNode.directNodeTxSigningResult?.signingNonceCommitments,
|
|
29064
|
+
verifyingKey: internalNode.verificationKey
|
|
29065
|
+
});
|
|
29066
|
+
directNodeTxSignature = await this.config.signer.aggregateFrost({
|
|
29067
|
+
message: directNodeTxSighash,
|
|
29068
|
+
statechainSignatures: creationResponseNode.directNodeTxSigningResult?.signatureShares,
|
|
29069
|
+
statechainPublicKeys: creationResponseNode.directNodeTxSigningResult?.publicKeys,
|
|
29070
|
+
verifyingKey: internalNode.verificationKey,
|
|
29071
|
+
statechainCommitments: creationResponseNode.directNodeTxSigningResult?.signingNonceCommitments,
|
|
29072
|
+
selfCommitment: creationNode.directNodeTxSigningCommitment,
|
|
29073
|
+
selfSignature: directUserSignature,
|
|
27566
29074
|
publicKey: internalNode.signingPublicKey
|
|
27567
29075
|
});
|
|
27568
29076
|
}
|
|
27569
|
-
let
|
|
27570
|
-
|
|
27571
|
-
|
|
27572
|
-
|
|
27573
|
-
|
|
27574
|
-
|
|
27575
|
-
|
|
27576
|
-
|
|
27577
|
-
|
|
27578
|
-
|
|
27579
|
-
|
|
27580
|
-
|
|
27581
|
-
|
|
29077
|
+
let cpfpRefundTxSignature = new Uint8Array();
|
|
29078
|
+
let directRefundTxSignature = new Uint8Array();
|
|
29079
|
+
let directFromCpfpRefundTxSignature = new Uint8Array();
|
|
29080
|
+
if (creationNode.refundTxSigningCommitment && creationNode.directRefundTxSigningCommitment && creationNode.directFromCpfpRefundTxSigningCommitment) {
|
|
29081
|
+
const rawCpfpRefundTx = creationNode.refundTxSigningJob?.rawTx;
|
|
29082
|
+
const rawDirectRefundTx = creationNode.directRefundTxSigningJob?.rawTx;
|
|
29083
|
+
const rawDirectFromCpfpRefundTx = creationNode.directFromCpfpRefundTxSigningJob?.rawTx;
|
|
29084
|
+
if (!rawCpfpRefundTx || !rawDirectRefundTx || !rawDirectFromCpfpRefundTx) {
|
|
29085
|
+
throw new Error("refund transaction rawTx is undefined");
|
|
29086
|
+
}
|
|
29087
|
+
if (!creationNode.refundTxSigningJob?.signingPublicKey || !creationNode.directRefundTxSigningJob?.signingPublicKey || !creationNode.directFromCpfpRefundTxSigningJob?.signingPublicKey) {
|
|
29088
|
+
throw new Error("refund transaction signingPublicKey is undefined");
|
|
29089
|
+
}
|
|
29090
|
+
const cpfpRefundTx = getTxFromRawTxBytes(rawCpfpRefundTx);
|
|
29091
|
+
const directRefundTx = getTxFromRawTxBytes(rawDirectRefundTx);
|
|
29092
|
+
const directFromCpfpRefundTx = getTxFromRawTxBytes(
|
|
29093
|
+
rawDirectFromCpfpRefundTx
|
|
29094
|
+
);
|
|
29095
|
+
const cpfpRefundTxSighash = getSigHashFromTx(
|
|
29096
|
+
cpfpRefundTx,
|
|
29097
|
+
0,
|
|
29098
|
+
cpfpNodeTx.getOutput(0)
|
|
29099
|
+
);
|
|
29100
|
+
const directRefundTxSighash = getSigHashFromTx(
|
|
29101
|
+
directRefundTx,
|
|
29102
|
+
0,
|
|
29103
|
+
directNodeTx.getOutput(0)
|
|
29104
|
+
);
|
|
29105
|
+
const directFromCpfpRefundTxSighash = getSigHashFromTx(
|
|
29106
|
+
directFromCpfpRefundTx,
|
|
29107
|
+
0,
|
|
29108
|
+
cpfpNodeTx.getOutput(0)
|
|
29109
|
+
);
|
|
29110
|
+
const cpfpRefundUserSignature = await this.config.signer.signFrost({
|
|
29111
|
+
message: cpfpRefundTxSighash,
|
|
27582
29112
|
publicKey: creationNode.refundTxSigningJob.signingPublicKey,
|
|
27583
29113
|
keyDerivation: {
|
|
27584
29114
|
type: "leaf" /* LEAF */,
|
|
@@ -27588,27 +29118,69 @@ var TreeCreationService = class {
|
|
|
27588
29118
|
statechainCommitments: creationResponseNode.refundTxSigningResult?.signingNonceCommitments,
|
|
27589
29119
|
verifyingKey: internalNode.verificationKey
|
|
27590
29120
|
});
|
|
27591
|
-
|
|
27592
|
-
message:
|
|
29121
|
+
cpfpRefundTxSignature = await this.config.signer.aggregateFrost({
|
|
29122
|
+
message: cpfpRefundTxSighash,
|
|
27593
29123
|
statechainSignatures: creationResponseNode.refundTxSigningResult?.signatureShares,
|
|
27594
29124
|
statechainPublicKeys: creationResponseNode.refundTxSigningResult?.publicKeys,
|
|
27595
29125
|
verifyingKey: internalNode.verificationKey,
|
|
27596
29126
|
statechainCommitments: creationResponseNode.refundTxSigningResult?.signingNonceCommitments,
|
|
27597
29127
|
selfCommitment: creationNode.refundTxSigningCommitment,
|
|
27598
|
-
selfSignature:
|
|
29128
|
+
selfSignature: cpfpRefundUserSignature,
|
|
29129
|
+
publicKey: internalNode.signingPublicKey
|
|
29130
|
+
});
|
|
29131
|
+
const keyDerivation = {
|
|
29132
|
+
type: "leaf" /* LEAF */,
|
|
29133
|
+
path: creationResponseNode.nodeId
|
|
29134
|
+
};
|
|
29135
|
+
const directRefundUserSignature = await this.config.signer.signFrost({
|
|
29136
|
+
message: directRefundTxSighash,
|
|
29137
|
+
publicKey: creationNode.directRefundTxSigningJob.signingPublicKey,
|
|
29138
|
+
keyDerivation,
|
|
29139
|
+
selfCommitment: creationNode.directRefundTxSigningCommitment,
|
|
29140
|
+
statechainCommitments: creationResponseNode.directRefundTxSigningResult?.signingNonceCommitments,
|
|
29141
|
+
verifyingKey: internalNode.verificationKey
|
|
29142
|
+
});
|
|
29143
|
+
directRefundTxSignature = await this.config.signer.aggregateFrost({
|
|
29144
|
+
message: directRefundTxSighash,
|
|
29145
|
+
statechainSignatures: creationResponseNode.directRefundTxSigningResult?.signatureShares,
|
|
29146
|
+
statechainPublicKeys: creationResponseNode.directRefundTxSigningResult?.publicKeys,
|
|
29147
|
+
verifyingKey: internalNode.verificationKey,
|
|
29148
|
+
statechainCommitments: creationResponseNode.directRefundTxSigningResult?.signingNonceCommitments,
|
|
29149
|
+
selfCommitment: creationNode.directRefundTxSigningCommitment,
|
|
29150
|
+
selfSignature: directRefundUserSignature,
|
|
27599
29151
|
publicKey: internalNode.signingPublicKey
|
|
27600
29152
|
});
|
|
29153
|
+
const directFromCpfpRefundUserSignature = await this.config.signer.signFrost({
|
|
29154
|
+
message: directFromCpfpRefundTxSighash,
|
|
29155
|
+
publicKey: creationNode.directFromCpfpRefundTxSigningJob.signingPublicKey,
|
|
29156
|
+
keyDerivation,
|
|
29157
|
+
selfCommitment: creationNode.directFromCpfpRefundTxSigningCommitment,
|
|
29158
|
+
statechainCommitments: creationResponseNode.directFromCpfpRefundTxSigningResult?.signingNonceCommitments,
|
|
29159
|
+
verifyingKey: internalNode.verificationKey
|
|
29160
|
+
});
|
|
29161
|
+
directFromCpfpRefundTxSignature = await this.config.signer.aggregateFrost(
|
|
29162
|
+
{
|
|
29163
|
+
message: directFromCpfpRefundTxSighash,
|
|
29164
|
+
statechainSignatures: creationResponseNode.directFromCpfpRefundTxSigningResult?.signatureShares,
|
|
29165
|
+
statechainPublicKeys: creationResponseNode.directFromCpfpRefundTxSigningResult?.publicKeys,
|
|
29166
|
+
verifyingKey: internalNode.verificationKey,
|
|
29167
|
+
statechainCommitments: creationResponseNode.directFromCpfpRefundTxSigningResult?.signingNonceCommitments,
|
|
29168
|
+
selfCommitment: creationNode.directFromCpfpRefundTxSigningCommitment,
|
|
29169
|
+
selfSignature: directFromCpfpRefundUserSignature,
|
|
29170
|
+
publicKey: internalNode.signingPublicKey
|
|
29171
|
+
}
|
|
29172
|
+
);
|
|
27601
29173
|
}
|
|
27602
29174
|
return {
|
|
27603
|
-
tx,
|
|
29175
|
+
tx: cpfpNodeTx,
|
|
29176
|
+
// Return CPFP version for children
|
|
27604
29177
|
signature: {
|
|
27605
29178
|
nodeId: creationResponseNode.nodeId,
|
|
27606
|
-
nodeTxSignature,
|
|
27607
|
-
|
|
27608
|
-
|
|
27609
|
-
|
|
27610
|
-
|
|
27611
|
-
directFromCpfpRefundTxSignature: new Uint8Array()
|
|
29179
|
+
nodeTxSignature: cpfpNodeTxSignature,
|
|
29180
|
+
directNodeTxSignature,
|
|
29181
|
+
refundTxSignature: cpfpRefundTxSignature,
|
|
29182
|
+
directRefundTxSignature,
|
|
29183
|
+
directFromCpfpRefundTxSignature
|
|
27612
29184
|
}
|
|
27613
29185
|
};
|
|
27614
29186
|
}
|
|
@@ -27670,8 +29242,45 @@ var SigningService = class {
|
|
|
27670
29242
|
constructor(config) {
|
|
27671
29243
|
this.config = config;
|
|
27672
29244
|
}
|
|
27673
|
-
async
|
|
29245
|
+
async signRefundsInternal(refundTx, sighash, leaf, signingCommitments) {
|
|
27674
29246
|
const leafSigningJobs = [];
|
|
29247
|
+
const signingCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
29248
|
+
if (!signingCommitments) {
|
|
29249
|
+
throw new ValidationError("Invalid signing commitments", {
|
|
29250
|
+
field: "signingNonceCommitments",
|
|
29251
|
+
value: signingCommitments,
|
|
29252
|
+
expected: "Non-null signing commitments"
|
|
29253
|
+
});
|
|
29254
|
+
}
|
|
29255
|
+
const signingResult = await this.config.signer.signFrost({
|
|
29256
|
+
message: sighash,
|
|
29257
|
+
keyDerivation: leaf.keyDerivation,
|
|
29258
|
+
publicKey: await this.config.signer.getPublicKeyFromDerivation(
|
|
29259
|
+
leaf.keyDerivation
|
|
29260
|
+
),
|
|
29261
|
+
selfCommitment: signingCommitment,
|
|
29262
|
+
statechainCommitments: signingCommitments,
|
|
29263
|
+
adaptorPubKey: new Uint8Array(),
|
|
29264
|
+
verifyingKey: leaf.leaf.verifyingPublicKey
|
|
29265
|
+
});
|
|
29266
|
+
leafSigningJobs.push({
|
|
29267
|
+
leafId: leaf.leaf.id,
|
|
29268
|
+
signingPublicKey: await this.config.signer.getPublicKeyFromDerivation(
|
|
29269
|
+
leaf.keyDerivation
|
|
29270
|
+
),
|
|
29271
|
+
rawTx: refundTx.toBytes(),
|
|
29272
|
+
signingNonceCommitment: signingCommitment.commitment,
|
|
29273
|
+
userSignature: signingResult,
|
|
29274
|
+
signingCommitments: {
|
|
29275
|
+
signingCommitments
|
|
29276
|
+
}
|
|
29277
|
+
});
|
|
29278
|
+
return leafSigningJobs;
|
|
29279
|
+
}
|
|
29280
|
+
async signRefunds(leaves, receiverIdentityPubkey, cpfpSigningCommitments, directSigningCommitments, directFromCpfpSigningCommitments) {
|
|
29281
|
+
const cpfpLeafSigningJobs = [];
|
|
29282
|
+
const directLeafSigningJobs = [];
|
|
29283
|
+
const directFromCpfpLeafSigningJobs = [];
|
|
27675
29284
|
for (let i = 0; i < leaves.length; i++) {
|
|
27676
29285
|
const leaf = leaves[i];
|
|
27677
29286
|
if (!leaf?.leaf) {
|
|
@@ -27682,14 +29291,20 @@ var SigningService = class {
|
|
|
27682
29291
|
});
|
|
27683
29292
|
}
|
|
27684
29293
|
const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
27685
|
-
const
|
|
29294
|
+
const cpfpNodeOutPoint = {
|
|
27686
29295
|
txid: hexToBytes11(getTxId(nodeTx)),
|
|
27687
29296
|
index: 0
|
|
27688
29297
|
};
|
|
27689
29298
|
const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
27690
|
-
const
|
|
27691
|
-
|
|
27692
|
-
|
|
29299
|
+
const sequence = currRefundTx.getInput(0).sequence;
|
|
29300
|
+
if (!sequence) {
|
|
29301
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
29302
|
+
field: "sequence",
|
|
29303
|
+
value: currRefundTx.getInput(0),
|
|
29304
|
+
expected: "Non-null sequence"
|
|
29305
|
+
});
|
|
29306
|
+
}
|
|
29307
|
+
const { nextSequence, nextDirectSequence } = getNextTransactionSequence(sequence);
|
|
27693
29308
|
const amountSats = currRefundTx.getOutput(0).amount;
|
|
27694
29309
|
if (amountSats === void 0) {
|
|
27695
29310
|
throw new ValidationError("Invalid refund transaction", {
|
|
@@ -27698,56 +29313,98 @@ var SigningService = class {
|
|
|
27698
29313
|
expected: "Non-null amount"
|
|
27699
29314
|
});
|
|
27700
29315
|
}
|
|
27701
|
-
|
|
27702
|
-
|
|
27703
|
-
|
|
29316
|
+
let directNodeTx;
|
|
29317
|
+
let directNodeOutPoint;
|
|
29318
|
+
if (leaf.leaf.directTx.length > 0) {
|
|
29319
|
+
directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
|
|
29320
|
+
directNodeOutPoint = {
|
|
29321
|
+
txid: hexToBytes11(getTxId(directNodeTx)),
|
|
29322
|
+
index: 0
|
|
29323
|
+
};
|
|
29324
|
+
}
|
|
29325
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
29326
|
+
sequence: nextSequence,
|
|
29327
|
+
directSequence: nextDirectSequence,
|
|
29328
|
+
input: cpfpNodeOutPoint,
|
|
29329
|
+
directInput: directNodeOutPoint,
|
|
27704
29330
|
amountSats,
|
|
27705
|
-
receiverIdentityPubkey,
|
|
27706
|
-
this.config.getNetwork()
|
|
29331
|
+
receivingPubkey: receiverIdentityPubkey,
|
|
29332
|
+
network: this.config.getNetwork()
|
|
29333
|
+
});
|
|
29334
|
+
const refundSighash = getSigHashFromTx(
|
|
29335
|
+
cpfpRefundTx,
|
|
29336
|
+
0,
|
|
29337
|
+
nodeTx.getOutput(0)
|
|
27707
29338
|
);
|
|
27708
|
-
const
|
|
27709
|
-
|
|
27710
|
-
|
|
27711
|
-
|
|
27712
|
-
|
|
27713
|
-
|
|
27714
|
-
|
|
27715
|
-
|
|
27716
|
-
|
|
29339
|
+
const signingJobs = await this.signRefundsInternal(
|
|
29340
|
+
cpfpRefundTx,
|
|
29341
|
+
refundSighash,
|
|
29342
|
+
leaf,
|
|
29343
|
+
cpfpSigningCommitments[i]?.signingNonceCommitments
|
|
29344
|
+
);
|
|
29345
|
+
cpfpLeafSigningJobs.push(...signingJobs);
|
|
29346
|
+
if (directRefundTx) {
|
|
29347
|
+
if (!directNodeTx) {
|
|
29348
|
+
throw new ValidationError(
|
|
29349
|
+
"Direct node transaction undefined while direct refund transaction is defined",
|
|
29350
|
+
{
|
|
29351
|
+
field: "directNodeTx",
|
|
29352
|
+
value: directNodeTx,
|
|
29353
|
+
expected: "Non-null direct node transaction"
|
|
29354
|
+
}
|
|
29355
|
+
);
|
|
29356
|
+
}
|
|
29357
|
+
const refundSighash2 = getSigHashFromTx(
|
|
29358
|
+
directRefundTx,
|
|
29359
|
+
0,
|
|
29360
|
+
directNodeTx.getOutput(0)
|
|
29361
|
+
);
|
|
29362
|
+
const signingJobs2 = await this.signRefundsInternal(
|
|
29363
|
+
directRefundTx,
|
|
29364
|
+
refundSighash2,
|
|
29365
|
+
leaf,
|
|
29366
|
+
directSigningCommitments[i]?.signingNonceCommitments
|
|
29367
|
+
);
|
|
29368
|
+
directLeafSigningJobs.push(...signingJobs2);
|
|
27717
29369
|
}
|
|
27718
|
-
|
|
27719
|
-
|
|
27720
|
-
|
|
27721
|
-
|
|
27722
|
-
|
|
27723
|
-
|
|
27724
|
-
|
|
27725
|
-
|
|
27726
|
-
|
|
27727
|
-
|
|
27728
|
-
});
|
|
27729
|
-
leafSigningJobs.push({
|
|
27730
|
-
leafId: leaf.leaf.id,
|
|
27731
|
-
signingPublicKey: await this.config.signer.getPublicKeyFromDerivation(
|
|
27732
|
-
leaf.keyDerivation
|
|
27733
|
-
),
|
|
27734
|
-
rawTx: refundTx.toBytes(),
|
|
27735
|
-
signingNonceCommitment: signingCommitment.commitment,
|
|
27736
|
-
userSignature: signingResult,
|
|
27737
|
-
signingCommitments: {
|
|
27738
|
-
signingCommitments: signingNonceCommitments
|
|
29370
|
+
if (directFromCpfpRefundTx) {
|
|
29371
|
+
if (!directNodeTx) {
|
|
29372
|
+
throw new ValidationError(
|
|
29373
|
+
"Direct node transaction undefined while direct from CPFP refund transaction is defined",
|
|
29374
|
+
{
|
|
29375
|
+
field: "directNodeTx",
|
|
29376
|
+
value: directNodeTx,
|
|
29377
|
+
expected: "Non-null direct node transaction"
|
|
29378
|
+
}
|
|
29379
|
+
);
|
|
27739
29380
|
}
|
|
27740
|
-
|
|
29381
|
+
const refundSighash2 = getSigHashFromTx(
|
|
29382
|
+
directFromCpfpRefundTx,
|
|
29383
|
+
0,
|
|
29384
|
+
nodeTx.getOutput(0)
|
|
29385
|
+
);
|
|
29386
|
+
const signingJobs2 = await this.signRefundsInternal(
|
|
29387
|
+
directFromCpfpRefundTx,
|
|
29388
|
+
refundSighash2,
|
|
29389
|
+
leaf,
|
|
29390
|
+
directFromCpfpSigningCommitments[i]?.signingNonceCommitments
|
|
29391
|
+
);
|
|
29392
|
+
directFromCpfpLeafSigningJobs.push(...signingJobs2);
|
|
29393
|
+
}
|
|
27741
29394
|
}
|
|
27742
|
-
return
|
|
29395
|
+
return {
|
|
29396
|
+
cpfpLeafSigningJobs,
|
|
29397
|
+
directLeafSigningJobs,
|
|
29398
|
+
directFromCpfpLeafSigningJobs
|
|
29399
|
+
};
|
|
27743
29400
|
}
|
|
27744
29401
|
};
|
|
27745
29402
|
|
|
27746
29403
|
// src/tests/utils/test-faucet.ts
|
|
27747
29404
|
import { bytesToHex as bytesToHex12, hexToBytes as hexToBytes12 } from "@noble/curves/abstract/utils";
|
|
27748
29405
|
import { schnorr as schnorr5, secp256k1 as secp256k113 } from "@noble/curves/secp256k1";
|
|
27749
|
-
import * as
|
|
27750
|
-
import { Address as
|
|
29406
|
+
import * as btc5 from "@scure/btc-signer";
|
|
29407
|
+
import { Address as Address5, OutScript as OutScript3, SigHash as SigHash2, Transaction as Transaction8 } from "@scure/btc-signer";
|
|
27751
29408
|
import { taprootTweakPrivKey as taprootTweakPrivKey2 } from "@scure/btc-signer/utils";
|
|
27752
29409
|
var STATIC_FAUCET_KEY = hexToBytes12(
|
|
27753
29410
|
"deadbeef1337cafe4242424242424242deadbeef1337cafe4242424242424242"
|
|
@@ -27892,7 +29549,7 @@ var BitcoinFaucet = class _BitcoinFaucet {
|
|
|
27892
29549
|
}
|
|
27893
29550
|
async sendFaucetCoinToP2WPKHAddress(pubKey) {
|
|
27894
29551
|
const sendToPubKeyTx = new Transaction8();
|
|
27895
|
-
const p2wpkhAddress =
|
|
29552
|
+
const p2wpkhAddress = btc5.p2wpkh(pubKey, getNetwork(4 /* LOCAL */)).address;
|
|
27896
29553
|
if (!p2wpkhAddress) {
|
|
27897
29554
|
throw new Error("Invalid P2WPKH address");
|
|
27898
29555
|
}
|
|
@@ -27948,12 +29605,13 @@ var BitcoinFaucet = class _BitcoinFaucet {
|
|
|
27948
29605
|
}
|
|
27949
29606
|
async call(method, params) {
|
|
27950
29607
|
try {
|
|
27951
|
-
const
|
|
29608
|
+
const { fetch: fetch2, Headers: Headers2 } = getFetch();
|
|
29609
|
+
const response = await fetch2(this.url, {
|
|
27952
29610
|
method: "POST",
|
|
27953
|
-
headers: {
|
|
29611
|
+
headers: new Headers2({
|
|
27954
29612
|
"Content-Type": "application/json",
|
|
27955
29613
|
Authorization: "Basic " + btoa(`${this.username}:${this.password}`)
|
|
27956
|
-
},
|
|
29614
|
+
}),
|
|
27957
29615
|
body: JSON.stringify({
|
|
27958
29616
|
jsonrpc: "1.0",
|
|
27959
29617
|
id: "spark-js",
|
|
@@ -28008,10 +29666,10 @@ var BitcoinFaucet = class _BitcoinFaucet {
|
|
|
28008
29666
|
const tx = new Transaction8();
|
|
28009
29667
|
tx.addInput(coin.outpoint);
|
|
28010
29668
|
const availableAmount = COIN_AMOUNT - FEE_AMOUNT;
|
|
28011
|
-
const destinationAddress =
|
|
29669
|
+
const destinationAddress = Address5(getNetwork(4 /* LOCAL */)).decode(
|
|
28012
29670
|
address2
|
|
28013
29671
|
);
|
|
28014
|
-
const destinationScript =
|
|
29672
|
+
const destinationScript = OutScript3.encode(destinationAddress);
|
|
28015
29673
|
tx.addOutput({
|
|
28016
29674
|
script: destinationScript,
|
|
28017
29675
|
amount
|
|
@@ -28282,31 +29940,37 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
28282
29940
|
}
|
|
28283
29941
|
}
|
|
28284
29942
|
async getLeaves(isBalanceCheck = false) {
|
|
28285
|
-
const
|
|
28286
|
-
|
|
28287
|
-
|
|
28288
|
-
|
|
28289
|
-
|
|
28290
|
-
|
|
28291
|
-
|
|
28292
|
-
}
|
|
29943
|
+
const operatorToLeaves = /* @__PURE__ */ new Map();
|
|
29944
|
+
const ownerIdentityPubkey = await this.config.signer.getIdentityPublicKey();
|
|
29945
|
+
let signingOperators = Object.entries(this.config.getSigningOperators());
|
|
29946
|
+
if (isBalanceCheck) {
|
|
29947
|
+
signingOperators = signingOperators.filter(
|
|
29948
|
+
([id, _]) => id === this.config.getCoordinatorIdentifier()
|
|
29949
|
+
);
|
|
29950
|
+
}
|
|
29951
|
+
await Promise.all(
|
|
29952
|
+
signingOperators.map(async ([id, operator]) => {
|
|
29953
|
+
const leaves2 = await this.queryNodes(
|
|
29954
|
+
{
|
|
29955
|
+
source: {
|
|
29956
|
+
$case: "ownerIdentityPubkey",
|
|
29957
|
+
ownerIdentityPubkey
|
|
29958
|
+
},
|
|
29959
|
+
includeParents: false,
|
|
29960
|
+
network: NetworkToProto[this.config.getNetwork()]
|
|
29961
|
+
},
|
|
29962
|
+
operator.address
|
|
29963
|
+
);
|
|
29964
|
+
operatorToLeaves.set(id, leaves2);
|
|
29965
|
+
})
|
|
29966
|
+
);
|
|
29967
|
+
const leaves = operatorToLeaves.get(
|
|
29968
|
+
this.config.getCoordinatorIdentifier()
|
|
29969
|
+
);
|
|
28293
29970
|
const leavesToIgnore = /* @__PURE__ */ new Set();
|
|
28294
29971
|
if (!isBalanceCheck) {
|
|
28295
|
-
for (const [id,
|
|
28296
|
-
this.config.getSigningOperators()
|
|
28297
|
-
)) {
|
|
29972
|
+
for (const [id, operatorLeaves] of operatorToLeaves) {
|
|
28298
29973
|
if (id !== this.config.getCoordinatorIdentifier()) {
|
|
28299
|
-
const operatorLeaves = await this.queryNodes(
|
|
28300
|
-
{
|
|
28301
|
-
source: {
|
|
28302
|
-
$case: "ownerIdentityPubkey",
|
|
28303
|
-
ownerIdentityPubkey: await this.config.signer.getIdentityPublicKey()
|
|
28304
|
-
},
|
|
28305
|
-
includeParents: false,
|
|
28306
|
-
network: NetworkToProto[this.config.getNetwork()]
|
|
28307
|
-
},
|
|
28308
|
-
operator.address
|
|
28309
|
-
);
|
|
28310
29974
|
for (const [nodeId, leaf] of Object.entries(leaves.nodes)) {
|
|
28311
29975
|
const operatorLeaf = operatorLeaves.nodes[nodeId];
|
|
28312
29976
|
if (!operatorLeaf) {
|
|
@@ -28323,11 +29987,24 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
28323
29987
|
}
|
|
28324
29988
|
}
|
|
28325
29989
|
}
|
|
28326
|
-
const
|
|
28327
|
-
|
|
28328
|
-
|
|
28329
|
-
for (const [id, leaf] of
|
|
28330
|
-
if (
|
|
29990
|
+
const availableLeaves = Object.entries(leaves.nodes).filter(
|
|
29991
|
+
([_, node]) => node.status === "AVAILABLE"
|
|
29992
|
+
);
|
|
29993
|
+
for (const [id, leaf] of availableLeaves) {
|
|
29994
|
+
if (leaf.parentNodeId && leaf.status === "AVAILABLE" && this.verifyKey(
|
|
29995
|
+
await this.config.signer.getPublicKeyFromDerivation({
|
|
29996
|
+
type: "leaf" /* LEAF */,
|
|
29997
|
+
path: leaf.parentNodeId
|
|
29998
|
+
}),
|
|
29999
|
+
leaf.signingKeyshare?.publicKey ?? new Uint8Array(),
|
|
30000
|
+
leaf.verifyingPublicKey
|
|
30001
|
+
)) {
|
|
30002
|
+
this.transferLeavesToSelf([leaf], {
|
|
30003
|
+
type: "leaf" /* LEAF */,
|
|
30004
|
+
path: leaf.parentNodeId
|
|
30005
|
+
});
|
|
30006
|
+
leavesToIgnore.add(id);
|
|
30007
|
+
} else if (!this.verifyKey(
|
|
28331
30008
|
await this.config.signer.getPublicKeyFromDerivation({
|
|
28332
30009
|
type: "leaf" /* LEAF */,
|
|
28333
30010
|
path: leaf.id
|
|
@@ -28338,9 +30015,23 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
28338
30015
|
leavesToIgnore.add(id);
|
|
28339
30016
|
}
|
|
28340
30017
|
}
|
|
28341
|
-
return
|
|
28342
|
-
|
|
28343
|
-
|
|
30018
|
+
return availableLeaves.filter(([_, node]) => !leavesToIgnore.has(node.id)).map(([_, node]) => node);
|
|
30019
|
+
}
|
|
30020
|
+
async checkExtendLeaves(leaves) {
|
|
30021
|
+
await this.withLeaves(async () => {
|
|
30022
|
+
for (const leaf of leaves) {
|
|
30023
|
+
if (!leaf.parentNodeId && leaf.status === "AVAILABLE") {
|
|
30024
|
+
const res = await this.transferService.extendTimelock(leaf);
|
|
30025
|
+
await this.transferLeavesToSelf(res.nodes, {
|
|
30026
|
+
type: "leaf" /* LEAF */,
|
|
30027
|
+
path: leaf.id
|
|
30028
|
+
});
|
|
30029
|
+
}
|
|
30030
|
+
}
|
|
30031
|
+
});
|
|
30032
|
+
}
|
|
30033
|
+
verifyKey(pubkey1, pubkey2, verifyingKey) {
|
|
30034
|
+
return equalBytes5(addPublicKeys(pubkey1, pubkey2), verifyingKey);
|
|
28344
30035
|
}
|
|
28345
30036
|
async selectLeaves(targetAmounts) {
|
|
28346
30037
|
if (targetAmounts.length === 0) {
|
|
@@ -28479,6 +30170,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
28479
30170
|
leaves = await this.checkRefreshTimelockNodes(leaves);
|
|
28480
30171
|
leaves = await this.checkExtendTimeLockNodes(leaves);
|
|
28481
30172
|
this.leaves = leaves;
|
|
30173
|
+
this.checkExtendLeaves(leaves);
|
|
28482
30174
|
this.optimizeLeaves().catch((e) => {
|
|
28483
30175
|
console.error("Failed to optimize leaves", e);
|
|
28484
30176
|
});
|
|
@@ -28719,21 +30411,68 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
28719
30411
|
}
|
|
28720
30412
|
}))
|
|
28721
30413
|
);
|
|
28722
|
-
const {
|
|
30414
|
+
const {
|
|
30415
|
+
transfer,
|
|
30416
|
+
signatureMap,
|
|
30417
|
+
directSignatureMap,
|
|
30418
|
+
directFromCpfpSignatureMap
|
|
30419
|
+
} = await this.transferService.startSwapSignRefund(
|
|
28723
30420
|
leafKeyTweaks,
|
|
28724
30421
|
hexToBytes13(this.config.getSspIdentityPublicKey()),
|
|
28725
30422
|
new Date(Date.now() + 2 * 60 * 1e3)
|
|
28726
30423
|
);
|
|
28727
30424
|
try {
|
|
28728
30425
|
if (!transfer.leaves[0]?.leaf) {
|
|
30426
|
+
console.error("[processSwapBatch] First leaf is missing");
|
|
28729
30427
|
throw new Error("Failed to get leaf");
|
|
28730
30428
|
}
|
|
28731
|
-
const
|
|
28732
|
-
if (!
|
|
28733
|
-
|
|
30429
|
+
const cpfpRefundSignature = signatureMap.get(transfer.leaves[0].leaf.id);
|
|
30430
|
+
if (!cpfpRefundSignature) {
|
|
30431
|
+
console.error(
|
|
30432
|
+
"[processSwapBatch] Missing CPFP refund signature for first leaf"
|
|
30433
|
+
);
|
|
30434
|
+
throw new Error("Failed to get CPFP refund signature");
|
|
30435
|
+
}
|
|
30436
|
+
const directRefundSignature = directSignatureMap.get(
|
|
30437
|
+
transfer.leaves[0].leaf.id
|
|
30438
|
+
);
|
|
30439
|
+
if (!directRefundSignature) {
|
|
30440
|
+
console.error(
|
|
30441
|
+
"[processSwapBatch] Missing direct refund signature for first leaf"
|
|
30442
|
+
);
|
|
30443
|
+
throw new Error("Failed to get direct refund signature");
|
|
30444
|
+
}
|
|
30445
|
+
const directFromCpfpRefundSignature = directFromCpfpSignatureMap.get(
|
|
30446
|
+
transfer.leaves[0].leaf.id
|
|
30447
|
+
);
|
|
30448
|
+
if (!directFromCpfpRefundSignature) {
|
|
30449
|
+
console.error(
|
|
30450
|
+
"[processSwapBatch] Missing direct from CPFP refund signature for first leaf"
|
|
30451
|
+
);
|
|
30452
|
+
throw new Error("Failed to get direct from CPFP refund signature");
|
|
30453
|
+
}
|
|
30454
|
+
const {
|
|
30455
|
+
adaptorPrivateKey: cpfpAdaptorPrivateKey,
|
|
30456
|
+
adaptorSignature: cpfpAdaptorSignature
|
|
30457
|
+
} = generateAdaptorFromSignature(cpfpRefundSignature);
|
|
30458
|
+
let directAdaptorPrivateKey = new Uint8Array();
|
|
30459
|
+
let directAdaptorSignature = new Uint8Array();
|
|
30460
|
+
let directFromCpfpAdaptorPrivateKey = new Uint8Array();
|
|
30461
|
+
let directFromCpfpAdaptorSignature = new Uint8Array();
|
|
30462
|
+
if (directRefundSignature.length > 0) {
|
|
30463
|
+
const { adaptorPrivateKey, adaptorSignature } = generateAdaptorFromSignature(directRefundSignature);
|
|
30464
|
+
directAdaptorPrivateKey = adaptorPrivateKey;
|
|
30465
|
+
directAdaptorSignature = adaptorSignature;
|
|
30466
|
+
}
|
|
30467
|
+
if (directFromCpfpRefundSignature.length > 0) {
|
|
30468
|
+
const { adaptorPrivateKey, adaptorSignature } = generateAdaptorFromSignature(directFromCpfpRefundSignature);
|
|
30469
|
+
directFromCpfpAdaptorPrivateKey = adaptorPrivateKey;
|
|
30470
|
+
directFromCpfpAdaptorSignature = adaptorSignature;
|
|
28734
30471
|
}
|
|
28735
|
-
const { adaptorPrivateKey, adaptorSignature } = generateAdaptorFromSignature(refundSignature);
|
|
28736
30472
|
if (!transfer.leaves[0].leaf) {
|
|
30473
|
+
console.error(
|
|
30474
|
+
"[processSwapBatch] First leaf missing when preparing user leaves"
|
|
30475
|
+
);
|
|
28737
30476
|
throw new Error("Failed to get leaf");
|
|
28738
30477
|
}
|
|
28739
30478
|
const userLeaves = [];
|
|
@@ -28742,37 +30481,113 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
28742
30481
|
raw_unsigned_refund_transaction: bytesToHex13(
|
|
28743
30482
|
transfer.leaves[0].intermediateRefundTx
|
|
28744
30483
|
),
|
|
28745
|
-
|
|
30484
|
+
direct_raw_unsigned_refund_transaction: bytesToHex13(
|
|
30485
|
+
transfer.leaves[0].intermediateDirectRefundTx
|
|
30486
|
+
),
|
|
30487
|
+
direct_from_cpfp_raw_unsigned_refund_transaction: bytesToHex13(
|
|
30488
|
+
transfer.leaves[0].intermediateDirectFromCpfpRefundTx
|
|
30489
|
+
),
|
|
30490
|
+
adaptor_added_signature: bytesToHex13(cpfpAdaptorSignature),
|
|
30491
|
+
direct_adaptor_added_signature: bytesToHex13(directAdaptorSignature),
|
|
30492
|
+
direct_from_cpfp_adaptor_added_signature: bytesToHex13(
|
|
30493
|
+
directFromCpfpAdaptorSignature
|
|
30494
|
+
)
|
|
28746
30495
|
});
|
|
28747
30496
|
for (let i = 1; i < transfer.leaves.length; i++) {
|
|
28748
30497
|
const leaf = transfer.leaves[i];
|
|
28749
30498
|
if (!leaf?.leaf) {
|
|
30499
|
+
console.error(`[processSwapBatch] Leaf ${i + 1} is missing`);
|
|
28750
30500
|
throw new Error("Failed to get leaf");
|
|
28751
30501
|
}
|
|
28752
|
-
const
|
|
28753
|
-
if (!
|
|
28754
|
-
|
|
30502
|
+
const cpfpRefundSignature2 = signatureMap.get(leaf.leaf.id);
|
|
30503
|
+
if (!cpfpRefundSignature2) {
|
|
30504
|
+
console.error(
|
|
30505
|
+
`[processSwapBatch] Missing CPFP refund signature for leaf ${i + 1}`
|
|
30506
|
+
);
|
|
30507
|
+
throw new Error("Failed to get CPFP refund signature");
|
|
30508
|
+
}
|
|
30509
|
+
const directRefundSignature2 = directSignatureMap.get(leaf.leaf.id);
|
|
30510
|
+
if (!directRefundSignature2) {
|
|
30511
|
+
console.error(
|
|
30512
|
+
`[processSwapBatch] Missing direct refund signature for leaf ${i + 1}`
|
|
30513
|
+
);
|
|
30514
|
+
throw new Error("Failed to get direct refund signature");
|
|
30515
|
+
}
|
|
30516
|
+
const directFromCpfpRefundSignature2 = directFromCpfpSignatureMap.get(
|
|
30517
|
+
leaf.leaf.id
|
|
30518
|
+
);
|
|
30519
|
+
if (!directFromCpfpRefundSignature2) {
|
|
30520
|
+
console.error(
|
|
30521
|
+
`[processSwapBatch] Missing direct from CPFP refund signature for leaf ${i + 1}`
|
|
30522
|
+
);
|
|
30523
|
+
throw new Error("Failed to get direct from CPFP refund signature");
|
|
28755
30524
|
}
|
|
28756
|
-
const
|
|
28757
|
-
|
|
28758
|
-
|
|
30525
|
+
const cpfpSignature = generateSignatureFromExistingAdaptor(
|
|
30526
|
+
cpfpRefundSignature2,
|
|
30527
|
+
cpfpAdaptorPrivateKey
|
|
28759
30528
|
);
|
|
30529
|
+
let directSignature = new Uint8Array();
|
|
30530
|
+
if (directRefundSignature2.length > 0) {
|
|
30531
|
+
directSignature = generateSignatureFromExistingAdaptor(
|
|
30532
|
+
directRefundSignature2,
|
|
30533
|
+
directAdaptorPrivateKey
|
|
30534
|
+
);
|
|
30535
|
+
}
|
|
30536
|
+
let directFromCpfpSignature = new Uint8Array();
|
|
30537
|
+
if (directFromCpfpRefundSignature2.length > 0) {
|
|
30538
|
+
directFromCpfpSignature = generateSignatureFromExistingAdaptor(
|
|
30539
|
+
directFromCpfpRefundSignature2,
|
|
30540
|
+
directFromCpfpAdaptorPrivateKey
|
|
30541
|
+
);
|
|
30542
|
+
}
|
|
28760
30543
|
userLeaves.push({
|
|
28761
30544
|
leaf_id: leaf.leaf.id,
|
|
28762
30545
|
raw_unsigned_refund_transaction: bytesToHex13(
|
|
28763
30546
|
leaf.intermediateRefundTx
|
|
28764
30547
|
),
|
|
28765
|
-
|
|
30548
|
+
direct_raw_unsigned_refund_transaction: bytesToHex13(
|
|
30549
|
+
leaf.intermediateDirectRefundTx
|
|
30550
|
+
),
|
|
30551
|
+
direct_from_cpfp_raw_unsigned_refund_transaction: bytesToHex13(
|
|
30552
|
+
leaf.intermediateDirectFromCpfpRefundTx
|
|
30553
|
+
),
|
|
30554
|
+
adaptor_added_signature: bytesToHex13(cpfpSignature),
|
|
30555
|
+
direct_adaptor_added_signature: bytesToHex13(directSignature),
|
|
30556
|
+
direct_from_cpfp_adaptor_added_signature: bytesToHex13(
|
|
30557
|
+
directFromCpfpSignature
|
|
30558
|
+
)
|
|
28766
30559
|
});
|
|
28767
30560
|
}
|
|
28768
30561
|
const sspClient = this.getSspClient();
|
|
28769
|
-
const
|
|
28770
|
-
secp256k114.getPublicKey(
|
|
30562
|
+
const cpfpAdaptorPubkey = bytesToHex13(
|
|
30563
|
+
secp256k114.getPublicKey(cpfpAdaptorPrivateKey)
|
|
28771
30564
|
);
|
|
30565
|
+
if (!cpfpAdaptorPubkey) {
|
|
30566
|
+
throw new Error("Failed to generate CPFP adaptor pubkey");
|
|
30567
|
+
}
|
|
30568
|
+
let directAdaptorPubkey;
|
|
30569
|
+
if (directAdaptorPrivateKey.length > 0) {
|
|
30570
|
+
directAdaptorPubkey = bytesToHex13(
|
|
30571
|
+
secp256k114.getPublicKey(directAdaptorPrivateKey)
|
|
30572
|
+
);
|
|
30573
|
+
}
|
|
30574
|
+
let directFromCpfpAdaptorPubkey;
|
|
30575
|
+
if (directFromCpfpAdaptorPrivateKey.length > 0) {
|
|
30576
|
+
directFromCpfpAdaptorPubkey = bytesToHex13(
|
|
30577
|
+
secp256k114.getPublicKey(directFromCpfpAdaptorPrivateKey)
|
|
30578
|
+
);
|
|
30579
|
+
}
|
|
28772
30580
|
let request = null;
|
|
30581
|
+
const targetAmountSats = targetAmounts?.reduce((acc, amount) => acc + amount, 0) || leavesBatch.reduce((acc, leaf) => acc + leaf.value, 0);
|
|
30582
|
+
const totalAmountSats = leavesBatch.reduce(
|
|
30583
|
+
(acc, leaf) => acc + leaf.value,
|
|
30584
|
+
0
|
|
30585
|
+
);
|
|
28773
30586
|
request = await sspClient.requestLeaveSwap({
|
|
28774
30587
|
userLeaves,
|
|
28775
|
-
adaptorPubkey,
|
|
30588
|
+
adaptorPubkey: cpfpAdaptorPubkey,
|
|
30589
|
+
directAdaptorPubkey,
|
|
30590
|
+
directFromCpfpAdaptorPubkey,
|
|
28776
30591
|
targetAmountSats: targetAmounts?.reduce((acc, amount) => acc + amount, 0) || leavesBatch.reduce((acc, leaf) => acc + leaf.value, 0),
|
|
28777
30592
|
totalAmountSats: leavesBatch.reduce((acc, leaf) => acc + leaf.value, 0),
|
|
28778
30593
|
targetAmountSatsList: targetAmounts,
|
|
@@ -28781,6 +30596,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
28781
30596
|
idempotencyKey: uuidv75()
|
|
28782
30597
|
});
|
|
28783
30598
|
if (!request) {
|
|
30599
|
+
console.error("[processSwapBatch] Leave swap request returned null");
|
|
28784
30600
|
throw new Error("Failed to request leaves swap. No response returned.");
|
|
28785
30601
|
}
|
|
28786
30602
|
const nodes = await this.queryNodes({
|
|
@@ -28794,50 +30610,140 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
28794
30610
|
network: NetworkToProto[this.config.getNetwork()]
|
|
28795
30611
|
});
|
|
28796
30612
|
if (Object.values(nodes.nodes).length !== request.swapLeaves.length) {
|
|
30613
|
+
console.error("[processSwapBatch] Node count mismatch:", {
|
|
30614
|
+
actual: Object.values(nodes.nodes).length,
|
|
30615
|
+
expected: request.swapLeaves.length
|
|
30616
|
+
});
|
|
28797
30617
|
throw new Error("Expected same number of nodes as swapLeaves");
|
|
28798
30618
|
}
|
|
28799
30619
|
for (const [nodeId, node] of Object.entries(nodes.nodes)) {
|
|
28800
30620
|
if (!node.nodeTx) {
|
|
30621
|
+
console.error(`[processSwapBatch] Node tx missing for ${nodeId}`);
|
|
28801
30622
|
throw new Error(`Node tx not found for leaf ${nodeId}`);
|
|
28802
30623
|
}
|
|
28803
30624
|
if (!node.verifyingPublicKey) {
|
|
30625
|
+
console.error(
|
|
30626
|
+
`[processSwapBatch] Verifying public key missing for ${nodeId}`
|
|
30627
|
+
);
|
|
28804
30628
|
throw new Error(`Node public key not found for leaf ${nodeId}`);
|
|
28805
30629
|
}
|
|
28806
30630
|
const leaf = request.swapLeaves.find((leaf2) => leaf2.leafId === nodeId);
|
|
28807
30631
|
if (!leaf) {
|
|
30632
|
+
console.error(`[processSwapBatch] Leaf not found for node ${nodeId}`);
|
|
28808
30633
|
throw new Error(`Leaf not found for node ${nodeId}`);
|
|
28809
30634
|
}
|
|
28810
|
-
const
|
|
28811
|
-
const
|
|
28812
|
-
const
|
|
28813
|
-
const
|
|
30635
|
+
const cpfpNodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
30636
|
+
const cpfpRefundTxBytes = hexToBytes13(leaf.rawUnsignedRefundTransaction);
|
|
30637
|
+
const cpfpRefundTx = getTxFromRawTxBytes(cpfpRefundTxBytes);
|
|
30638
|
+
const cpfpSighash = getSigHashFromTx(
|
|
30639
|
+
cpfpRefundTx,
|
|
30640
|
+
0,
|
|
30641
|
+
cpfpNodeTx.getOutput(0)
|
|
30642
|
+
);
|
|
28814
30643
|
const nodePublicKey = node.verifyingPublicKey;
|
|
28815
30644
|
const taprootKey = computeTaprootKeyNoScript(nodePublicKey.slice(1));
|
|
28816
|
-
const
|
|
30645
|
+
const cpfpAdaptorSignatureBytes = hexToBytes13(
|
|
30646
|
+
leaf.adaptorSignedSignature
|
|
30647
|
+
);
|
|
30648
|
+
applyAdaptorToSignature(
|
|
30649
|
+
taprootKey.slice(1),
|
|
30650
|
+
cpfpSighash,
|
|
30651
|
+
cpfpAdaptorSignatureBytes,
|
|
30652
|
+
cpfpAdaptorPrivateKey
|
|
30653
|
+
);
|
|
30654
|
+
if (!leaf.directRawUnsignedRefundTransaction) {
|
|
30655
|
+
throw new Error(
|
|
30656
|
+
`Direct raw unsigned refund transaction missing for node ${nodeId}`
|
|
30657
|
+
);
|
|
30658
|
+
}
|
|
30659
|
+
if (!leaf.directAdaptorSignedSignature) {
|
|
30660
|
+
throw new Error(
|
|
30661
|
+
`Direct adaptor signed signature missing for node ${nodeId}`
|
|
30662
|
+
);
|
|
30663
|
+
}
|
|
30664
|
+
const directNodeTx = getTxFromRawTxBytes(node.directTx);
|
|
30665
|
+
const directRefundTxBytes = hexToBytes13(
|
|
30666
|
+
leaf.directRawUnsignedRefundTransaction
|
|
30667
|
+
);
|
|
30668
|
+
const directRefundTx = getTxFromRawTxBytes(directRefundTxBytes);
|
|
30669
|
+
const directSighash = getSigHashFromTx(
|
|
30670
|
+
directRefundTx,
|
|
30671
|
+
0,
|
|
30672
|
+
directNodeTx.getOutput(0)
|
|
30673
|
+
);
|
|
30674
|
+
if (!leaf.directFromCpfpAdaptorSignedSignature) {
|
|
30675
|
+
throw new Error(
|
|
30676
|
+
`Direct adaptor signed signature missing for node ${nodeId}`
|
|
30677
|
+
);
|
|
30678
|
+
}
|
|
30679
|
+
const directAdaptorSignatureBytes = hexToBytes13(
|
|
30680
|
+
leaf.directAdaptorSignedSignature
|
|
30681
|
+
);
|
|
30682
|
+
applyAdaptorToSignature(
|
|
30683
|
+
taprootKey.slice(1),
|
|
30684
|
+
directSighash,
|
|
30685
|
+
directAdaptorSignatureBytes,
|
|
30686
|
+
directAdaptorPrivateKey
|
|
30687
|
+
);
|
|
30688
|
+
if (!leaf.directRawUnsignedRefundTransaction) {
|
|
30689
|
+
throw new Error(
|
|
30690
|
+
`Direct raw unsigned refund transaction missing for node ${nodeId}`
|
|
30691
|
+
);
|
|
30692
|
+
}
|
|
30693
|
+
if (!leaf.directFromCpfpRawUnsignedRefundTransaction) {
|
|
30694
|
+
throw new Error(
|
|
30695
|
+
`Direct raw unsigned refund transaction missing for node ${nodeId}`
|
|
30696
|
+
);
|
|
30697
|
+
}
|
|
30698
|
+
const directFromCpfpRefundTxBytes = hexToBytes13(
|
|
30699
|
+
leaf.directFromCpfpRawUnsignedRefundTransaction
|
|
30700
|
+
);
|
|
30701
|
+
const directFromCpfpRefundTx = getTxFromRawTxBytes(
|
|
30702
|
+
directFromCpfpRefundTxBytes
|
|
30703
|
+
);
|
|
30704
|
+
const directFromCpfpSighash = getSigHashFromTx(
|
|
30705
|
+
directFromCpfpRefundTx,
|
|
30706
|
+
0,
|
|
30707
|
+
cpfpNodeTx.getOutput(0)
|
|
30708
|
+
);
|
|
30709
|
+
const directFromCpfpAdaptorSignatureBytes = hexToBytes13(
|
|
30710
|
+
leaf.directFromCpfpAdaptorSignedSignature
|
|
30711
|
+
);
|
|
28817
30712
|
applyAdaptorToSignature(
|
|
28818
30713
|
taprootKey.slice(1),
|
|
28819
|
-
|
|
28820
|
-
|
|
28821
|
-
|
|
30714
|
+
directFromCpfpSighash,
|
|
30715
|
+
directFromCpfpAdaptorSignatureBytes,
|
|
30716
|
+
directFromCpfpAdaptorPrivateKey
|
|
28822
30717
|
);
|
|
28823
30718
|
}
|
|
28824
30719
|
await this.transferService.deliverTransferPackage(
|
|
28825
30720
|
transfer,
|
|
28826
30721
|
leafKeyTweaks,
|
|
28827
|
-
signatureMap
|
|
30722
|
+
signatureMap,
|
|
30723
|
+
directSignatureMap,
|
|
30724
|
+
directFromCpfpSignatureMap
|
|
28828
30725
|
);
|
|
28829
30726
|
const completeResponse = await sspClient.completeLeaveSwap({
|
|
28830
|
-
adaptorSecretKey: bytesToHex13(
|
|
30727
|
+
adaptorSecretKey: bytesToHex13(cpfpAdaptorPrivateKey),
|
|
30728
|
+
directAdaptorSecretKey: bytesToHex13(directAdaptorPrivateKey),
|
|
30729
|
+
directFromCpfpAdaptorSecretKey: bytesToHex13(
|
|
30730
|
+
directFromCpfpAdaptorPrivateKey
|
|
30731
|
+
),
|
|
28831
30732
|
userOutboundTransferExternalId: transfer.id,
|
|
28832
30733
|
leavesSwapRequestId: request.id
|
|
28833
30734
|
});
|
|
28834
30735
|
if (!completeResponse || !completeResponse.inboundTransfer?.sparkId) {
|
|
30736
|
+
console.error(
|
|
30737
|
+
"[processSwapBatch] Invalid complete response:",
|
|
30738
|
+
completeResponse
|
|
30739
|
+
);
|
|
28835
30740
|
throw new Error("Failed to complete leaves swap");
|
|
28836
30741
|
}
|
|
28837
30742
|
const incomingTransfer = await this.transferService.queryTransfer(
|
|
28838
30743
|
completeResponse.inboundTransfer.sparkId
|
|
28839
30744
|
);
|
|
28840
30745
|
if (!incomingTransfer) {
|
|
30746
|
+
console.error("[processSwapBatch] No incoming transfer found");
|
|
28841
30747
|
throw new Error("Failed to get incoming transfer");
|
|
28842
30748
|
}
|
|
28843
30749
|
return await this.claimTransfer({
|
|
@@ -28847,6 +30753,11 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
28847
30753
|
optimize: false
|
|
28848
30754
|
});
|
|
28849
30755
|
} catch (e) {
|
|
30756
|
+
console.error("[processSwapBatch] Error details:", {
|
|
30757
|
+
error: e,
|
|
30758
|
+
message: e.message,
|
|
30759
|
+
stack: e.stack
|
|
30760
|
+
});
|
|
28850
30761
|
await this.cancelAllSenderInitiatedTransfers();
|
|
28851
30762
|
throw new Error(`Failed to request leaves swap: ${e}`);
|
|
28852
30763
|
}
|
|
@@ -29161,10 +31072,10 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
29161
31072
|
index: outputIndex,
|
|
29162
31073
|
witnessScript: new Uint8Array()
|
|
29163
31074
|
});
|
|
29164
|
-
const addressDecoded =
|
|
31075
|
+
const addressDecoded = Address6(getNetwork(network)).decode(
|
|
29165
31076
|
destinationAddress
|
|
29166
31077
|
);
|
|
29167
|
-
const outputScript =
|
|
31078
|
+
const outputScript = OutScript4.encode(addressDecoded);
|
|
29168
31079
|
tx.addOutput({
|
|
29169
31080
|
script: outputScript,
|
|
29170
31081
|
amount: BigInt(creditAmountSats)
|
|
@@ -29297,8 +31208,8 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
29297
31208
|
if (!output) {
|
|
29298
31209
|
continue;
|
|
29299
31210
|
}
|
|
29300
|
-
const parsedScript =
|
|
29301
|
-
const address2 =
|
|
31211
|
+
const parsedScript = OutScript4.decode(output.script);
|
|
31212
|
+
const address2 = Address6(getNetwork(this.config.getNetwork())).encode(
|
|
29302
31213
|
parsedScript
|
|
29303
31214
|
);
|
|
29304
31215
|
if (staticDepositAddresses.has(address2)) {
|
|
@@ -29317,8 +31228,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
29317
31228
|
field: "txid"
|
|
29318
31229
|
});
|
|
29319
31230
|
}
|
|
31231
|
+
const { fetch: fetch2, Headers: Headers2 } = getFetch();
|
|
29320
31232
|
const baseUrl = this.config.getElectrsUrl();
|
|
29321
|
-
const headers =
|
|
31233
|
+
const headers = new Headers2();
|
|
29322
31234
|
let txHex;
|
|
29323
31235
|
if (this.config.getNetwork() === 4 /* LOCAL */) {
|
|
29324
31236
|
const localFaucet = BitcoinFaucet.getInstance();
|
|
@@ -29329,9 +31241,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
29329
31241
|
const auth = btoa(
|
|
29330
31242
|
`${ELECTRS_CREDENTIALS.username}:${ELECTRS_CREDENTIALS.password}`
|
|
29331
31243
|
);
|
|
29332
|
-
headers
|
|
31244
|
+
headers.set("Authorization", `Basic ${auth}`);
|
|
29333
31245
|
}
|
|
29334
|
-
const response = await
|
|
31246
|
+
const response = await fetch2(`${baseUrl}/tx/${txid}/hex`, {
|
|
29335
31247
|
headers
|
|
29336
31248
|
});
|
|
29337
31249
|
txHex = await response.text();
|
|
@@ -29459,8 +31371,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
29459
31371
|
this.mutexes.set(txid, mutex);
|
|
29460
31372
|
}
|
|
29461
31373
|
const nodes = await mutex.runExclusive(async () => {
|
|
31374
|
+
const { fetch: fetch2, Headers: Headers2 } = getFetch();
|
|
29462
31375
|
const baseUrl = this.config.getElectrsUrl();
|
|
29463
|
-
const headers =
|
|
31376
|
+
const headers = new Headers2();
|
|
29464
31377
|
let txHex;
|
|
29465
31378
|
if (this.config.getNetwork() === 4 /* LOCAL */) {
|
|
29466
31379
|
const localFaucet = BitcoinFaucet.getInstance();
|
|
@@ -29471,9 +31384,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
29471
31384
|
const auth = btoa(
|
|
29472
31385
|
`${ELECTRS_CREDENTIALS.username}:${ELECTRS_CREDENTIALS.password}`
|
|
29473
31386
|
);
|
|
29474
|
-
headers
|
|
31387
|
+
headers.set("Authorization", `Basic ${auth}`);
|
|
29475
31388
|
}
|
|
29476
|
-
const response = await
|
|
31389
|
+
const response = await fetch2(`${baseUrl}/tx/${txid}/hex`, {
|
|
29477
31390
|
headers
|
|
29478
31391
|
});
|
|
29479
31392
|
txHex = await response.text();
|
|
@@ -29501,8 +31414,8 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
29501
31414
|
if (!output) {
|
|
29502
31415
|
continue;
|
|
29503
31416
|
}
|
|
29504
|
-
const parsedScript =
|
|
29505
|
-
const address2 =
|
|
31417
|
+
const parsedScript = OutScript4.decode(output.script);
|
|
31418
|
+
const address2 = Address6(getNetwork(this.config.getNetwork())).encode(
|
|
29506
31419
|
parsedScript
|
|
29507
31420
|
);
|
|
29508
31421
|
if (unusedDepositAddresses.has(address2)) {
|
|
@@ -29562,8 +31475,8 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
29562
31475
|
if (!output) {
|
|
29563
31476
|
continue;
|
|
29564
31477
|
}
|
|
29565
|
-
const parsedScript =
|
|
29566
|
-
const address2 =
|
|
31478
|
+
const parsedScript = OutScript4.decode(output.script);
|
|
31479
|
+
const address2 = Address6(getNetwork(this.config.getNetwork())).encode(
|
|
29567
31480
|
parsedScript
|
|
29568
31481
|
);
|
|
29569
31482
|
const unusedDepositAddress = unusedDepositAddresses.get(address2);
|
|
@@ -29715,10 +31628,16 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
29715
31628
|
const validNodes = [];
|
|
29716
31629
|
for (const node of nodes) {
|
|
29717
31630
|
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
29718
|
-
const
|
|
29719
|
-
|
|
29720
|
-
|
|
29721
|
-
|
|
31631
|
+
const sequence = nodeTx.getInput(0).sequence;
|
|
31632
|
+
if (!sequence) {
|
|
31633
|
+
throw new ValidationError("Invalid node transaction", {
|
|
31634
|
+
field: "sequence",
|
|
31635
|
+
value: nodeTx.getInput(0),
|
|
31636
|
+
expected: "Non-null sequence"
|
|
31637
|
+
});
|
|
31638
|
+
}
|
|
31639
|
+
const needsRefresh = doesLeafNeedRefresh(sequence, true);
|
|
31640
|
+
if (needsRefresh) {
|
|
29722
31641
|
nodesToExtend.push(node);
|
|
29723
31642
|
nodeIds.push(node.id);
|
|
29724
31643
|
} else {
|
|
@@ -29755,11 +31674,16 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
29755
31674
|
const validNodes = [];
|
|
29756
31675
|
for (const node of nodes) {
|
|
29757
31676
|
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
29758
|
-
const
|
|
29759
|
-
|
|
29760
|
-
|
|
29761
|
-
|
|
29762
|
-
|
|
31677
|
+
const sequence = refundTx.getInput(0).sequence;
|
|
31678
|
+
if (!sequence) {
|
|
31679
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
31680
|
+
field: "sequence",
|
|
31681
|
+
value: refundTx.getInput(0),
|
|
31682
|
+
expected: "Non-null sequence"
|
|
31683
|
+
});
|
|
31684
|
+
}
|
|
31685
|
+
const needsRefresh = doesLeafNeedRefresh(sequence);
|
|
31686
|
+
if (needsRefresh) {
|
|
29763
31687
|
nodesToRefresh.push(node);
|
|
29764
31688
|
nodeIds.push(node.id);
|
|
29765
31689
|
} else {
|
|
@@ -29793,7 +31717,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
29793
31717
|
throw new Error(`parent node ${node.parentNodeId} not found`);
|
|
29794
31718
|
}
|
|
29795
31719
|
const { nodes: nodes2 } = await this.transferService.refreshTimelockNodes(
|
|
29796
|
-
|
|
31720
|
+
node,
|
|
29797
31721
|
parentNode
|
|
29798
31722
|
);
|
|
29799
31723
|
if (nodes2.length !== 1) {
|
|
@@ -29842,7 +31766,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
29842
31766
|
leavesToClaim.push({
|
|
29843
31767
|
leaf: {
|
|
29844
31768
|
...leaf.leaf,
|
|
29845
|
-
refundTx: leaf.intermediateRefundTx
|
|
31769
|
+
refundTx: leaf.intermediateRefundTx,
|
|
31770
|
+
directRefundTx: leaf.intermediateDirectRefundTx,
|
|
31771
|
+
directFromCpfpRefundTx: leaf.intermediateDirectFromCpfpRefundTx
|
|
29846
31772
|
},
|
|
29847
31773
|
keyDerivation: {
|
|
29848
31774
|
type: "ecies" /* ECIES */,
|
|
@@ -29918,7 +31844,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
29918
31844
|
if (type && transfer.type !== type) {
|
|
29919
31845
|
continue;
|
|
29920
31846
|
}
|
|
29921
|
-
if (transfer.status !== 2 /* TRANSFER_STATUS_SENDER_KEY_TWEAKED */ && transfer.status !== 3 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAKED */ && transfer.status !== 4 /* TRANSFER_STATUS_RECEIVER_REFUND_SIGNED */ && transfer.status !== 10 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAK_APPLIED */) {
|
|
31847
|
+
if (transfer.status !== 2 /* TRANSFER_STATUS_SENDER_KEY_TWEAKED */ && transfer.status !== 3 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAKED */ && transfer.status !== 4 /* TRANSFER_STATUS_RECEIVER_REFUND_SIGNED */ && transfer.status !== 10 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAK_APPLIED */ && transfer.status !== 9 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAK_LOCKED */) {
|
|
29922
31848
|
continue;
|
|
29923
31849
|
}
|
|
29924
31850
|
promises.push(
|
|
@@ -30206,6 +32132,8 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
30206
32132
|
await this.transferService.deliverTransferPackage(
|
|
30207
32133
|
swapResponse.transfer,
|
|
30208
32134
|
leavesToSend,
|
|
32135
|
+
/* @__PURE__ */ new Map(),
|
|
32136
|
+
/* @__PURE__ */ new Map(),
|
|
30209
32137
|
/* @__PURE__ */ new Map()
|
|
30210
32138
|
);
|
|
30211
32139
|
const sspResponse = await sspClient.requestLightningSend({
|
|
@@ -30639,14 +32567,18 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
30639
32567
|
issuerPublicKeys,
|
|
30640
32568
|
tokenTransactionHashes,
|
|
30641
32569
|
tokenIdentifiers,
|
|
30642
|
-
outputIds
|
|
32570
|
+
outputIds,
|
|
32571
|
+
pageSize = 100,
|
|
32572
|
+
offset = 0
|
|
30643
32573
|
}) {
|
|
30644
32574
|
return this.tokenTransactionService.queryTokenTransactions({
|
|
30645
32575
|
ownerPublicKeys,
|
|
30646
32576
|
issuerPublicKeys,
|
|
30647
32577
|
tokenTransactionHashes,
|
|
30648
32578
|
tokenIdentifiers,
|
|
30649
|
-
outputIds
|
|
32579
|
+
outputIds,
|
|
32580
|
+
pageSize,
|
|
32581
|
+
offset
|
|
30650
32582
|
});
|
|
30651
32583
|
}
|
|
30652
32584
|
async getTokenL1Address() {
|
|
@@ -30964,87 +32896,64 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
|
|
|
30964
32896
|
},
|
|
30965
32897
|
includeParents: true
|
|
30966
32898
|
});
|
|
30967
|
-
|
|
30968
|
-
if (!
|
|
32899
|
+
let leaf = response.nodes[nodeId];
|
|
32900
|
+
if (!leaf) {
|
|
30969
32901
|
throw new ValidationError("Node not found", {
|
|
30970
32902
|
field: "nodeId",
|
|
30971
32903
|
value: nodeId
|
|
30972
32904
|
});
|
|
30973
32905
|
}
|
|
30974
|
-
|
|
30975
|
-
|
|
30976
|
-
|
|
30977
|
-
|
|
30978
|
-
|
|
30979
|
-
|
|
30980
|
-
|
|
30981
|
-
|
|
30982
|
-
|
|
30983
|
-
|
|
30984
|
-
|
|
30985
|
-
});
|
|
30986
|
-
}
|
|
30987
|
-
const result = await this.transferService.refreshTimelockNodes(
|
|
30988
|
-
[node],
|
|
30989
|
-
parentNode
|
|
30990
|
-
);
|
|
30991
|
-
const leafIndex = this.leaves.findIndex((leaf) => leaf.id === node.id);
|
|
30992
|
-
if (leafIndex !== -1 && result.nodes.length > 0) {
|
|
30993
|
-
const newNode = result.nodes[0];
|
|
30994
|
-
if (newNode) {
|
|
30995
|
-
this.leaves[leafIndex] = newNode;
|
|
32906
|
+
let parentNode;
|
|
32907
|
+
let hasParentNode = false;
|
|
32908
|
+
if (!leaf.parentNodeId) {
|
|
32909
|
+
} else {
|
|
32910
|
+
hasParentNode = true;
|
|
32911
|
+
parentNode = response.nodes[leaf.parentNodeId];
|
|
32912
|
+
if (!parentNode) {
|
|
32913
|
+
throw new ValidationError("Parent node not found", {
|
|
32914
|
+
field: "parentNodeId",
|
|
32915
|
+
value: leaf.parentNodeId
|
|
32916
|
+
});
|
|
30996
32917
|
}
|
|
30997
32918
|
}
|
|
30998
|
-
|
|
30999
|
-
|
|
31000
|
-
|
|
31001
|
-
|
|
31002
|
-
|
|
31003
|
-
|
|
31004
|
-
|
|
31005
|
-
|
|
31006
|
-
|
|
31007
|
-
|
|
31008
|
-
|
|
31009
|
-
|
|
31010
|
-
|
|
31011
|
-
|
|
31012
|
-
* @returns {Promise<void>} Promise that resolves when the refund timelock is refreshed
|
|
31013
|
-
*/
|
|
31014
|
-
async testOnly_expireTimelockRefundTx(nodeId) {
|
|
31015
|
-
const sparkClient = await this.connectionManager.createSparkClient(
|
|
31016
|
-
this.config.getCoordinatorAddress()
|
|
31017
|
-
);
|
|
31018
|
-
try {
|
|
31019
|
-
const response = await sparkClient.query_nodes({
|
|
31020
|
-
source: {
|
|
31021
|
-
$case: "nodeIds",
|
|
31022
|
-
nodeIds: {
|
|
31023
|
-
nodeIds: [nodeId]
|
|
32919
|
+
const nodeTx = getTxFromRawTxBytes(leaf.nodeTx);
|
|
32920
|
+
const refundTx = getTxFromRawTxBytes(leaf.refundTx);
|
|
32921
|
+
if (hasParentNode) {
|
|
32922
|
+
const nodeTimelock = getCurrentTimelock(nodeTx.getInput(0).sequence);
|
|
32923
|
+
if (nodeTimelock > 100) {
|
|
32924
|
+
const expiredNodeTxLeaf = await this.transferService.testonly_expireTimeLockNodeTx(
|
|
32925
|
+
leaf,
|
|
32926
|
+
parentNode
|
|
32927
|
+
);
|
|
32928
|
+
if (!expiredNodeTxLeaf.nodes[0]) {
|
|
32929
|
+
throw new ValidationError("No expired node tx leaf", {
|
|
32930
|
+
field: "expiredNodeTxLeaf",
|
|
32931
|
+
value: expiredNodeTxLeaf
|
|
32932
|
+
});
|
|
31024
32933
|
}
|
|
31025
|
-
|
|
31026
|
-
|
|
31027
|
-
});
|
|
31028
|
-
const node = response.nodes[nodeId];
|
|
31029
|
-
if (!node) {
|
|
31030
|
-
throw new ValidationError("Node not found", {
|
|
31031
|
-
field: "nodeId",
|
|
31032
|
-
value: nodeId
|
|
31033
|
-
});
|
|
32934
|
+
leaf = expiredNodeTxLeaf.nodes[0];
|
|
32935
|
+
}
|
|
31034
32936
|
}
|
|
31035
|
-
const
|
|
31036
|
-
|
|
31037
|
-
|
|
31038
|
-
|
|
31039
|
-
|
|
31040
|
-
|
|
32937
|
+
const refundTimelock = getCurrentTimelock(refundTx.getInput(0).sequence);
|
|
32938
|
+
if (refundTimelock > 100) {
|
|
32939
|
+
const expiredTxLeaf = await this.transferService.testonly_expireTimeLockRefundtx(leaf);
|
|
32940
|
+
if (!expiredTxLeaf.nodes[0]) {
|
|
32941
|
+
throw new ValidationError("No expired tx leaf", {
|
|
32942
|
+
field: "expiredTxLeaf",
|
|
32943
|
+
value: expiredTxLeaf
|
|
32944
|
+
});
|
|
31041
32945
|
}
|
|
32946
|
+
leaf = expiredTxLeaf.nodes[0];
|
|
32947
|
+
}
|
|
32948
|
+
const leafIndex = this.leaves.findIndex((leaf2) => leaf2.id === leaf2.id);
|
|
32949
|
+
if (leafIndex !== -1) {
|
|
32950
|
+
this.leaves[leafIndex] = leaf;
|
|
31042
32951
|
}
|
|
31043
32952
|
} catch (error) {
|
|
31044
32953
|
throw new NetworkError(
|
|
31045
|
-
"Failed to refresh
|
|
32954
|
+
"Failed to refresh timelock",
|
|
31046
32955
|
{
|
|
31047
|
-
method: "
|
|
32956
|
+
method: "refresh_timelock"
|
|
31048
32957
|
},
|
|
31049
32958
|
error
|
|
31050
32959
|
);
|
|
@@ -31110,7 +33019,10 @@ export {
|
|
|
31110
33019
|
AuthenticationError,
|
|
31111
33020
|
ConfigurationError,
|
|
31112
33021
|
DEFAULT_FEE_SATS,
|
|
33022
|
+
DIRECT_TIMELOCK_OFFSET,
|
|
31113
33023
|
ReactNativeSparkSigner as DefaultSparkSigner,
|
|
33024
|
+
INITIAL_DIRECT_SEQUENCE,
|
|
33025
|
+
INITIAL_SEQUENCE,
|
|
31114
33026
|
InternalValidationError,
|
|
31115
33027
|
LRC_WALLET_NETWORK,
|
|
31116
33028
|
LRC_WALLET_NETWORK_TYPE,
|
|
@@ -31122,6 +33034,8 @@ export {
|
|
|
31122
33034
|
ReactNativeSparkSigner,
|
|
31123
33035
|
SparkSDKError,
|
|
31124
33036
|
SparkWallet,
|
|
33037
|
+
TEST_UNILATERAL_DIRECT_SEQUENCE,
|
|
33038
|
+
TEST_UNILATERAL_SEQUENCE,
|
|
31125
33039
|
TokenTransactionService,
|
|
31126
33040
|
ValidationError,
|
|
31127
33041
|
WalletConfig,
|
|
@@ -31138,13 +33052,21 @@ export {
|
|
|
31138
33052
|
constructFeeBumpTx,
|
|
31139
33053
|
constructUnilateralExitFeeBumpPackages,
|
|
31140
33054
|
constructUnilateralExitTxs,
|
|
33055
|
+
createConnectorRefundTransactions,
|
|
33056
|
+
createLeafNodeTx,
|
|
33057
|
+
createNodeTx,
|
|
33058
|
+
createNodeTxs,
|
|
31141
33059
|
createRefundTx,
|
|
33060
|
+
createRefundTxs,
|
|
33061
|
+
createRootTx,
|
|
31142
33062
|
createSigningCommitment,
|
|
31143
33063
|
createSigningNonce,
|
|
33064
|
+
createSplitTx,
|
|
31144
33065
|
decodeBech32mTokenIdentifier,
|
|
31145
33066
|
decodeBytesToSigningCommitment,
|
|
31146
33067
|
decodeBytesToSigningNonce,
|
|
31147
33068
|
decodeSparkAddress,
|
|
33069
|
+
doesLeafNeedRefresh,
|
|
31148
33070
|
encodeBech32mTokenIdentifier,
|
|
31149
33071
|
encodeSigningCommitmentToBytes,
|
|
31150
33072
|
encodeSigningNonceToBytes,
|