@buildonspark/spark-sdk 0.3.2 → 0.3.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.
Files changed (75) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/bare/index.cjs +953 -1567
  3. package/dist/bare/index.d.cts +132 -29
  4. package/dist/bare/index.d.ts +132 -29
  5. package/dist/bare/index.js +948 -1565
  6. package/dist/{chunk-MGCUXELA.js → chunk-IC4IUEOS.js} +931 -125
  7. package/dist/{chunk-MH7BMOLL.js → chunk-J2P3KTQP.js} +1 -1
  8. package/dist/{chunk-JDQKNT7G.js → chunk-KIQTO4FX.js} +403 -1808
  9. package/dist/{chunk-73GJOG5R.js → chunk-XWLR6G5C.js} +1 -1
  10. package/dist/{chunk-4KGN75J4.js → chunk-YH7MDVTT.js} +1 -1
  11. package/dist/{client-DrjQwET9.d.ts → client-DBZ43pJT.d.ts} +1 -1
  12. package/dist/{client-DUFejFfn.d.cts → client-DWml6sjL.d.cts} +1 -1
  13. package/dist/debug.cjs +957 -1569
  14. package/dist/debug.d.cts +8 -5
  15. package/dist/debug.d.ts +8 -5
  16. package/dist/debug.js +4 -4
  17. package/dist/graphql/objects/index.d.cts +3 -3
  18. package/dist/graphql/objects/index.d.ts +3 -3
  19. package/dist/index.cjs +913 -1528
  20. package/dist/index.d.cts +6 -6
  21. package/dist/index.d.ts +6 -6
  22. package/dist/index.js +9 -5
  23. package/dist/index.node.cjs +913 -1528
  24. package/dist/index.node.d.cts +6 -6
  25. package/dist/index.node.d.ts +6 -6
  26. package/dist/index.node.js +8 -4
  27. package/dist/{logging-IsaT3wjW.d.ts → logging-BUpzk4Z6.d.cts} +5 -5
  28. package/dist/{logging-Bt2FNHFR.d.cts → logging-Dt2ooQiP.d.ts} +5 -5
  29. package/dist/native/index.cjs +913 -1528
  30. package/dist/native/index.d.cts +133 -44
  31. package/dist/native/index.d.ts +133 -44
  32. package/dist/native/index.js +912 -1529
  33. package/dist/proto/spark.cjs +931 -125
  34. package/dist/proto/spark.d.cts +1 -1
  35. package/dist/proto/spark.d.ts +1 -1
  36. package/dist/proto/spark.js +17 -1
  37. package/dist/proto/spark_token.d.cts +1 -1
  38. package/dist/proto/spark_token.d.ts +1 -1
  39. package/dist/proto/spark_token.js +2 -2
  40. package/dist/{spark-CLz4-Ln8.d.cts → spark-DasxuVfm.d.cts} +150 -5
  41. package/dist/{spark-CLz4-Ln8.d.ts → spark-DasxuVfm.d.ts} +150 -5
  42. package/dist/{spark-wallet-V03V4Tgm.d.cts → spark-wallet-BoMIOPWW.d.cts} +15 -26
  43. package/dist/{spark-wallet-KI68-_jO.d.ts → spark-wallet-jlC0XN5f.d.ts} +15 -26
  44. package/dist/{spark-wallet.node-Cuvw8Kvq.d.ts → spark-wallet.node-07PksUHH.d.cts} +1 -1
  45. package/dist/{spark-wallet.node-BtkqW5vn.d.cts → spark-wallet.node-CdWkKMSq.d.ts} +1 -1
  46. package/dist/tests/test-utils.cjs +951 -147
  47. package/dist/tests/test-utils.d.cts +4 -4
  48. package/dist/tests/test-utils.d.ts +4 -4
  49. package/dist/tests/test-utils.js +5 -5
  50. package/dist/{token-transactions-5XxBewhV.d.ts → token-transactions-BDzCrQSk.d.cts} +5 -19
  51. package/dist/{token-transactions-fTnCtBpp.d.cts → token-transactions-DscJaJOE.d.ts} +5 -19
  52. package/dist/types/index.cjs +923 -125
  53. package/dist/types/index.d.cts +2 -2
  54. package/dist/types/index.d.ts +2 -2
  55. package/dist/types/index.js +2 -2
  56. package/package.json +1 -1
  57. package/src/proto/spark.ts +1167 -103
  58. package/src/services/config.ts +0 -4
  59. package/src/services/token-transactions.ts +11 -703
  60. package/src/services/transfer.ts +2 -213
  61. package/src/services/wallet-config.ts +0 -2
  62. package/src/spark-wallet/proto-descriptors.ts +1 -1
  63. package/src/spark-wallet/spark-wallet.ts +47 -215
  64. package/src/spark_descriptors.pb +0 -0
  65. package/src/tests/address.test.ts +141 -0
  66. package/src/tests/integration/address.test.ts +4 -0
  67. package/src/tests/integration/lightning.test.ts +14 -9
  68. package/src/tests/integration/token-output.test.ts +0 -1
  69. package/src/tests/integration/transfer.test.ts +108 -2
  70. package/src/tests/token-hashing.test.ts +0 -247
  71. package/src/utils/address.ts +58 -35
  72. package/src/utils/token-hashing.ts +1 -420
  73. package/src/utils/token-transaction-validation.ts +0 -330
  74. package/src/utils/transaction.ts +8 -8
  75. package/src/tests/integration/swap.test.ts +0 -780
@@ -1,24 +1,15 @@
1
- import { secp256k1 } from "@noble/curves/secp256k1";
2
1
  import {
3
2
  bytesToHex,
4
3
  bytesToNumberBE,
5
4
  numberToBytesBE,
6
5
  } from "@noble/curves/utils";
7
6
  import { hexToBytes } from "@noble/hashes/utils";
8
- import {
9
- InternalValidationError,
10
- NetworkError,
11
- ValidationError,
12
- } from "../errors/types.js";
7
+ import { NetworkError, ValidationError } from "../errors/types.js";
13
8
  import {
14
9
  Direction,
15
- OperatorSpecificOwnerSignature,
16
10
  OperatorSpecificTokenTransactionSignablePayload,
17
11
  OutputWithPreviousTransactionData,
18
- QueryTokenTransactionsRequest as QueryTokenTransactionsRequestV0,
19
12
  RevocationSecretWithIndex,
20
- SignTokenTransactionResponse,
21
- TokenTransaction as TokenTransactionV0,
22
13
  } from "../proto/spark.js";
23
14
  import {
24
15
  InputTtxoSignaturesPerOperator,
@@ -39,20 +30,12 @@ import { collectResponses } from "../utils/response-validation.js";
39
30
  import {
40
31
  hashOperatorSpecificTokenTransactionSignablePayload,
41
32
  hashTokenTransaction,
42
- hashTokenTransactionV0,
43
33
  } from "../utils/token-hashing.js";
44
34
  import {
45
35
  Bech32mTokenIdentifier,
46
36
  decodeBech32mTokenIdentifier,
47
37
  } from "../utils/token-identifier.js";
48
- import {
49
- KeyshareWithOperatorIndex,
50
- recoverRevocationSecretFromKeyshares,
51
- } from "../utils/token-keyshares.js";
52
- import {
53
- validateTokenTransaction,
54
- validateTokenTransactionV0,
55
- } from "../utils/token-transaction-validation.js";
38
+ import { validateTokenTransaction } from "../utils/token-transaction-validation.js";
56
39
  import {
57
40
  checkIfSelectedOutputsAreAvailable,
58
41
  sumAvailableTokens,
@@ -177,18 +160,6 @@ export class TokenTransactionService {
177
160
  this.config.getNetworkType(),
178
161
  ).tokenIdentifier;
179
162
 
180
- // remove for full v0 deprecation
181
- let tokenPublicKey: Uint8Array;
182
- if (this.config.getTokenTransactionVersion() === "V0") {
183
- const tokenClient = await this.connectionManager.createSparkTokenClient(
184
- this.config.getCoordinatorAddress(),
185
- );
186
- const tokenMetadata = await tokenClient.query_token_metadata({
187
- tokenIdentifiers: [rawTokenIdentifier],
188
- });
189
- tokenPublicKey = tokenMetadata.tokenMetadata[0]!.issuerPublicKey;
190
- }
191
-
192
163
  let sparkInvoices: SparkAddressFormat[] = [];
193
164
 
194
165
  const tokenOutputData = receiverOutputs.map((transfer) => {
@@ -201,10 +172,7 @@ export class TokenTransactionService {
201
172
  sparkInvoices.push(transfer.receiverSparkAddress as SparkAddressFormat);
202
173
  }
203
174
 
204
- if (
205
- this.config.getTokenTransactionVersion() !== "V0" &&
206
- receiverAddress.sparkInvoiceFields
207
- ) {
175
+ if (receiverAddress.sparkInvoiceFields) {
208
176
  return {
209
177
  receiverPublicKey: hexToBytes(receiverAddress.identityPublicKey),
210
178
  rawTokenIdentifier,
@@ -216,30 +184,16 @@ export class TokenTransactionService {
216
184
  return {
217
185
  receiverPublicKey: hexToBytes(receiverAddress.identityPublicKey),
218
186
  rawTokenIdentifier,
219
- tokenPublicKey, // Remove for full v0 deprecation
220
187
  tokenAmount: transfer.tokenAmount,
221
188
  };
222
189
  });
223
190
 
224
- let tokenTransaction: TokenTransactionV0 | TokenTransaction;
225
-
226
- if (this.config.getTokenTransactionVersion() === "V0") {
227
- // remove for full v0 deprecation
228
- tokenTransaction = await this.constructTransferTokenTransactionV0(
229
- outputsToUse,
230
- tokenOutputData as Array<{
231
- receiverPublicKey: Uint8Array;
232
- tokenPublicKey: Uint8Array;
233
- tokenAmount: bigint;
234
- }>,
235
- );
236
- } else {
237
- tokenTransaction = await this.constructTransferTokenTransaction(
238
- outputsToUse,
239
- tokenOutputData,
240
- sparkInvoices,
241
- );
242
- }
191
+ const tokenTransaction = await this.constructTransferTokenTransaction(
192
+ outputsToUse,
193
+ tokenOutputData,
194
+ sparkInvoices,
195
+ );
196
+
243
197
  const txId = await this.broadcastTokenTransaction(
244
198
  tokenTransaction,
245
199
  outputsToUse.map((output) => output.output!.ownerPublicKey),
@@ -249,60 +203,6 @@ export class TokenTransactionService {
249
203
  return txId;
250
204
  }
251
205
 
252
- public async constructTransferTokenTransactionV0(
253
- selectedOutputs: OutputWithPreviousTransactionData[],
254
- tokenOutputData: Array<{
255
- receiverPublicKey: Uint8Array;
256
- tokenPublicKey: Uint8Array;
257
- tokenAmount: bigint;
258
- }>,
259
- ): Promise<TokenTransactionV0> {
260
- // Ensure outputsToSpend are ordered by vout ascending so that the input indices
261
- // used for owner signatures match the order expected by the SO, which sorts
262
- // inputs by "prevTokenTransactionVout" before validating signatures.
263
- selectedOutputs.sort(
264
- (a, b) => a.previousTransactionVout - b.previousTransactionVout,
265
- );
266
-
267
- const availableTokenAmount = sumAvailableTokens(selectedOutputs);
268
- const totalRequestedAmount = tokenOutputData.reduce(
269
- (sum, output) => sum + output.tokenAmount,
270
- 0n,
271
- );
272
-
273
- const tokenOutputs = tokenOutputData.map((output) => ({
274
- ownerPublicKey: output.receiverPublicKey,
275
- tokenPublicKey: output.tokenPublicKey,
276
- tokenAmount: numberToBytesBE(output.tokenAmount, 16),
277
- }));
278
-
279
- if (availableTokenAmount > totalRequestedAmount) {
280
- const changeAmount = availableTokenAmount - totalRequestedAmount;
281
- const firstTokenPublicKey = tokenOutputData[0]!!.tokenPublicKey;
282
-
283
- tokenOutputs.push({
284
- ownerPublicKey: await this.config.signer.getIdentityPublicKey(),
285
- tokenPublicKey: firstTokenPublicKey,
286
- tokenAmount: numberToBytesBE(changeAmount, 16),
287
- });
288
- }
289
-
290
- return {
291
- network: this.config.getNetworkProto(),
292
- tokenInputs: {
293
- $case: "transferInput",
294
- transferInput: {
295
- outputsToSpend: selectedOutputs.map((output) => ({
296
- prevTokenTransactionHash: output.previousTransactionHash,
297
- prevTokenTransactionVout: output.previousTransactionVout,
298
- })),
299
- },
300
- },
301
- tokenOutputs,
302
- sparkOperatorIdentityPublicKeys: this.collectOperatorIdentityPublicKeys(),
303
- };
304
- }
305
-
306
206
  public async constructTransferTokenTransaction(
307
207
  selectedOutputs: OutputWithPreviousTransactionData[],
308
208
  tokenOutputData: Array<{
@@ -375,156 +275,12 @@ export class TokenTransactionService {
375
275
  }
376
276
 
377
277
  public async broadcastTokenTransaction(
378
- tokenTransaction: TokenTransactionV0 | TokenTransaction,
278
+ tokenTransaction: TokenTransaction,
379
279
  outputsToSpendSigningPublicKeys?: Uint8Array[],
380
280
  outputsToSpendCommitments?: Uint8Array[],
381
281
  ): Promise<string> {
382
282
  const signingOperators = this.config.getSigningOperators();
383
- if (!isTokenTransaction(tokenTransaction)) {
384
- return this.broadcastTokenTransactionV0(
385
- tokenTransaction,
386
- signingOperators,
387
- outputsToSpendSigningPublicKeys,
388
- outputsToSpendCommitments,
389
- );
390
- } else {
391
- return this.broadcastTokenTransactionV1(
392
- tokenTransaction as TokenTransaction,
393
- signingOperators,
394
- outputsToSpendSigningPublicKeys,
395
- outputsToSpendCommitments,
396
- );
397
- }
398
- }
399
283
 
400
- private async broadcastTokenTransactionV0(
401
- tokenTransaction: TokenTransactionV0,
402
- signingOperators: Record<string, SigningOperator>,
403
- outputsToSpendSigningPublicKeys?: Uint8Array[],
404
- outputsToSpendCommitments?: Uint8Array[],
405
- ): Promise<string> {
406
- const { finalTokenTransaction, finalTokenTransactionHash, threshold } =
407
- await this.startTokenTransactionV0(
408
- tokenTransaction,
409
- signingOperators,
410
- outputsToSpendSigningPublicKeys,
411
- outputsToSpendCommitments,
412
- );
413
-
414
- const { successfulSignatures } = await this.signTokenTransactionV0(
415
- finalTokenTransaction,
416
- finalTokenTransactionHash,
417
- signingOperators,
418
- );
419
-
420
- if (finalTokenTransaction.tokenInputs!.$case === "transferInput") {
421
- const outputsToSpend =
422
- finalTokenTransaction.tokenInputs!.transferInput.outputsToSpend;
423
-
424
- const errors: ValidationError[] = [];
425
- const revocationSecrets: RevocationSecretWithIndex[] = [];
426
-
427
- for (
428
- let outputIndex = 0;
429
- outputIndex < outputsToSpend.length;
430
- outputIndex++
431
- ) {
432
- // For each output, collect keyshares from all SOs that responded successfully
433
- const outputKeyshares: KeyshareWithOperatorIndex[] =
434
- successfulSignatures.map(({ identifier, response }) => ({
435
- operatorIndex: parseInt(identifier, 16),
436
- keyshare: response.revocationKeyshares[outputIndex]!,
437
- }));
438
-
439
- if (outputKeyshares.length < threshold) {
440
- errors.push(
441
- new ValidationError("Insufficient keyshares", {
442
- field: "outputKeyshares",
443
- value: outputKeyshares.length,
444
- expected: threshold,
445
- index: outputIndex,
446
- }),
447
- );
448
- }
449
-
450
- // Check for duplicate operator indices
451
- const seenIndices = new Set<number>();
452
- for (const { operatorIndex } of outputKeyshares) {
453
- if (seenIndices.has(operatorIndex)) {
454
- errors.push(
455
- new ValidationError("Duplicate operator index", {
456
- field: "outputKeyshares",
457
- value: operatorIndex,
458
- expected: "Unique operator index",
459
- index: outputIndex,
460
- }),
461
- );
462
- }
463
- seenIndices.add(operatorIndex);
464
- }
465
-
466
- const revocationSecret = recoverRevocationSecretFromKeyshares(
467
- outputKeyshares as KeyshareWithOperatorIndex[],
468
- threshold,
469
- );
470
- const derivedRevocationCommitment = secp256k1.getPublicKey(
471
- revocationSecret,
472
- true,
473
- );
474
-
475
- if (
476
- !outputsToSpendCommitments ||
477
- !outputsToSpendCommitments[outputIndex] ||
478
- !derivedRevocationCommitment.every(
479
- (byte, i) => byte === outputsToSpendCommitments[outputIndex]![i],
480
- )
481
- ) {
482
- errors.push(
483
- new InternalValidationError(
484
- "Revocation commitment verification failed",
485
- {
486
- field: "revocationCommitment",
487
- value: derivedRevocationCommitment,
488
- expected: bytesToHex(outputsToSpendCommitments![outputIndex]!),
489
- outputIndex: outputIndex,
490
- },
491
- ),
492
- );
493
- }
494
-
495
- revocationSecrets.push({
496
- inputIndex: outputIndex,
497
- revocationSecret,
498
- });
499
- }
500
-
501
- if (errors.length > 0) {
502
- throw new ValidationError(
503
- "Multiple validation errors occurred across outputs",
504
- {
505
- field: "outputValidation",
506
- value: errors,
507
- },
508
- );
509
- }
510
-
511
- // Finalize the token transaction with the keyshares
512
- await this.finalizeTokenTransaction(
513
- finalTokenTransaction,
514
- revocationSecrets,
515
- threshold,
516
- );
517
- }
518
-
519
- return bytesToHex(finalTokenTransactionHash);
520
- }
521
-
522
- private async broadcastTokenTransactionV1(
523
- tokenTransaction: TokenTransaction,
524
- signingOperators: Record<string, SigningOperator>,
525
- outputsToSpendSigningPublicKeys?: Uint8Array[],
526
- outputsToSpendCommitments?: Uint8Array[],
527
- ): Promise<string> {
528
284
  const { finalTokenTransaction, finalTokenTransactionHash, threshold } =
529
285
  await this.startTokenTransaction(
530
286
  tokenTransaction,
@@ -542,123 +298,6 @@ export class TokenTransactionService {
542
298
  return bytesToHex(finalTokenTransactionHash);
543
299
  }
544
300
 
545
- private async startTokenTransactionV0(
546
- tokenTransaction: TokenTransactionV0,
547
- signingOperators: Record<string, SigningOperator>,
548
- outputsToSpendSigningPublicKeys?: Uint8Array[],
549
- outputsToSpendCommitments?: Uint8Array[],
550
- ): Promise<{
551
- finalTokenTransaction: TokenTransactionV0;
552
- finalTokenTransactionHash: Uint8Array;
553
- threshold: number;
554
- }> {
555
- const sparkClient = await this.connectionManager.createSparkClient(
556
- this.config.getCoordinatorAddress(),
557
- );
558
-
559
- const partialTokenTransactionHash = hashTokenTransactionV0(
560
- tokenTransaction,
561
- true,
562
- );
563
-
564
- const ownerSignaturesWithIndex: SignatureWithIndex[] = [];
565
- if (tokenTransaction.tokenInputs!.$case === "mintInput") {
566
- const issuerPublicKey =
567
- tokenTransaction.tokenInputs!.mintInput.issuerPublicKey;
568
- if (!issuerPublicKey) {
569
- throw new ValidationError("Invalid mint input", {
570
- field: "issuerPublicKey",
571
- value: null,
572
- expected: "Non-null issuer public key",
573
- });
574
- }
575
-
576
- const ownerSignature = await this.signMessageWithKey(
577
- partialTokenTransactionHash,
578
- issuerPublicKey,
579
- );
580
-
581
- ownerSignaturesWithIndex.push({
582
- signature: ownerSignature,
583
- inputIndex: 0,
584
- });
585
- } else if (tokenTransaction.tokenInputs!.$case === "transferInput") {
586
- if (!outputsToSpendSigningPublicKeys || !outputsToSpendCommitments) {
587
- throw new ValidationError("Invalid transfer input", {
588
- field: "outputsToSpend",
589
- value: {
590
- signingPublicKeys: outputsToSpendSigningPublicKeys,
591
- revocationPublicKeys: outputsToSpendCommitments,
592
- },
593
- expected: "Non-null signing and revocation public keys",
594
- });
595
- }
596
-
597
- for (const [i, key] of outputsToSpendSigningPublicKeys.entries()) {
598
- if (!key) {
599
- throw new ValidationError("Invalid signing key", {
600
- field: "outputsToSpendSigningPublicKeys",
601
- value: i,
602
- expected: "Non-null signing key",
603
- });
604
- }
605
- const ownerSignature = await this.signMessageWithKey(
606
- partialTokenTransactionHash,
607
- key,
608
- );
609
-
610
- ownerSignaturesWithIndex.push({
611
- signature: ownerSignature,
612
- inputIndex: i,
613
- });
614
- }
615
- }
616
-
617
- const startResponse = await sparkClient.start_token_transaction(
618
- {
619
- identityPublicKey: await this.config.signer.getIdentityPublicKey(),
620
- partialTokenTransaction: tokenTransaction,
621
- tokenTransactionSignatures: {
622
- ownerSignatures: ownerSignaturesWithIndex,
623
- },
624
- },
625
- {
626
- retry: true,
627
- retryableStatuses: ["UNKNOWN", "UNAVAILABLE", "CANCELLED", "INTERNAL"],
628
- retryMaxAttempts: 3,
629
- } as SparkCallOptions,
630
- );
631
-
632
- if (!startResponse.finalTokenTransaction) {
633
- throw new Error("Final token transaction missing in start response");
634
- }
635
- if (!startResponse.keyshareInfo) {
636
- throw new Error("Keyshare info missing in start response");
637
- }
638
-
639
- validateTokenTransactionV0(
640
- startResponse.finalTokenTransaction,
641
- tokenTransaction,
642
- signingOperators,
643
- startResponse.keyshareInfo,
644
- this.config.getExpectedWithdrawBondSats(),
645
- this.config.getExpectedWithdrawRelativeBlockLocktime(),
646
- this.config.getThreshold(),
647
- );
648
-
649
- const finalTokenTransaction = startResponse.finalTokenTransaction;
650
- const finalTokenTransactionHash = hashTokenTransactionV0(
651
- finalTokenTransaction,
652
- false,
653
- );
654
-
655
- return {
656
- finalTokenTransaction,
657
- finalTokenTransactionHash,
658
- threshold: startResponse.keyshareInfo!.threshold,
659
- };
660
- }
661
-
662
301
  private async startTokenTransaction(
663
302
  tokenTransaction: TokenTransaction,
664
303
  signingOperators: Record<string, SigningOperator>,
@@ -804,134 +443,6 @@ export class TokenTransactionService {
804
443
  };
805
444
  }
806
445
 
807
- private async signTokenTransactionV0(
808
- finalTokenTransaction: TokenTransactionV0,
809
- finalTokenTransactionHash: Uint8Array,
810
- signingOperators: Record<string, SigningOperator>,
811
- ): Promise<{
812
- successfulSignatures: {
813
- index: number;
814
- identifier: string;
815
- response: SignTokenTransactionResponse;
816
- }[];
817
- }> {
818
- // Submit sign_token_transaction to all SOs in parallel and track their indices
819
- const soSignatures = await Promise.allSettled(
820
- Object.entries(signingOperators).map(
821
- async ([identifier, operator], index) => {
822
- const internalSparkClient =
823
- await this.connectionManager.createSparkClient(operator.address);
824
- const identityPublicKey =
825
- await this.config.signer.getIdentityPublicKey();
826
-
827
- // Create operator-specific payload with operator's identity public key
828
- const payload: OperatorSpecificTokenTransactionSignablePayload = {
829
- finalTokenTransactionHash: finalTokenTransactionHash,
830
- operatorIdentityPublicKey: hexToBytes(operator.identityPublicKey),
831
- };
832
-
833
- const payloadHash =
834
- await hashOperatorSpecificTokenTransactionSignablePayload(payload);
835
-
836
- let operatorSpecificSignatures: OperatorSpecificOwnerSignature[] = [];
837
- if (finalTokenTransaction.tokenInputs!.$case === "mintInput") {
838
- const issuerPublicKey =
839
- finalTokenTransaction.tokenInputs!.mintInput.issuerPublicKey;
840
- if (!issuerPublicKey) {
841
- throw new ValidationError("Invalid mint input", {
842
- field: "issuerPublicKey",
843
- value: null,
844
- expected: "Non-null issuer public key",
845
- });
846
- }
847
-
848
- const ownerSignature = await this.signMessageWithKey(
849
- payloadHash,
850
- issuerPublicKey,
851
- );
852
-
853
- operatorSpecificSignatures.push({
854
- ownerSignature: {
855
- signature: ownerSignature,
856
- inputIndex: 0,
857
- },
858
- payload: payload,
859
- });
860
- }
861
-
862
- if (finalTokenTransaction.tokenInputs!.$case === "transferInput") {
863
- const transferInput =
864
- finalTokenTransaction.tokenInputs!.transferInput;
865
- for (let i = 0; i < transferInput.outputsToSpend.length; i++) {
866
- let ownerSignature: Uint8Array;
867
- if (this.config.getTokenSignatures() === "SCHNORR") {
868
- ownerSignature =
869
- await this.config.signer.signSchnorrWithIdentityKey(
870
- payloadHash,
871
- );
872
- } else {
873
- ownerSignature =
874
- await this.config.signer.signMessageWithIdentityKey(
875
- payloadHash,
876
- );
877
- }
878
-
879
- operatorSpecificSignatures.push({
880
- ownerSignature: {
881
- signature: ownerSignature,
882
- inputIndex: i,
883
- },
884
- payload,
885
- });
886
- }
887
- }
888
-
889
- try {
890
- const response = await internalSparkClient.sign_token_transaction(
891
- {
892
- finalTokenTransaction,
893
- operatorSpecificSignatures,
894
- identityPublicKey,
895
- },
896
- {
897
- retry: true,
898
- retryableStatuses: [
899
- "UNKNOWN",
900
- "UNAVAILABLE",
901
- "CANCELLED",
902
- "INTERNAL",
903
- ],
904
- retryMaxAttempts: 3,
905
- } as SparkCallOptions,
906
- );
907
-
908
- return {
909
- index,
910
- identifier,
911
- response,
912
- };
913
- } catch (error) {
914
- throw new NetworkError(
915
- "Failed to sign token transaction",
916
- {
917
- operation: "sign_token_transaction",
918
- errorCount: 1,
919
- errors: error instanceof Error ? error.message : String(error),
920
- },
921
- error as Error,
922
- );
923
- }
924
- },
925
- ),
926
- );
927
-
928
- const successfulSignatures = collectResponses(soSignatures);
929
-
930
- return {
931
- successfulSignatures,
932
- };
933
- }
934
-
935
446
  private async signTokenTransaction(
936
447
  finalTokenTransaction: TokenTransaction,
937
448
  finalTokenTransactionHash: Uint8Array,
@@ -1017,67 +528,6 @@ export class TokenTransactionService {
1017
528
  }
1018
529
  }
1019
530
 
1020
- if (this.config.getTokenTransactionVersion() === "V0") {
1021
- return this.fetchOwnedTokenOutputsV0(params);
1022
- } else {
1023
- return this.fetchOwnedTokenOutputsV1(params);
1024
- }
1025
- }
1026
-
1027
- public async queryTokenTransactions(
1028
- params: QueryTokenTransactionsParams,
1029
- ): Promise<QueryTokenTransactionsResponse> {
1030
- if (this.config.getTokenTransactionVersion() === "V0") {
1031
- return this.queryTokenTransactionsV0(params);
1032
- } else {
1033
- return this.queryTokenTransactionsV1(params);
1034
- }
1035
- }
1036
-
1037
- private async fetchOwnedTokenOutputsV0(
1038
- params: FetchOwnedTokenOutputsParams,
1039
- ): Promise<OutputWithPreviousTransactionData[]> {
1040
- const {
1041
- ownerPublicKeys,
1042
- issuerPublicKeys: tokenPublicKeys = [],
1043
- tokenIdentifiers = [],
1044
- } = params;
1045
-
1046
- const sparkClient = await this.connectionManager.createSparkClient(
1047
- this.config.getCoordinatorAddress(),
1048
- );
1049
-
1050
- try {
1051
- const result = await sparkClient.query_token_outputs({
1052
- ownerPublicKeys,
1053
- tokenPublicKeys,
1054
- tokenIdentifiers,
1055
- network: this.config.getNetworkProto(),
1056
- });
1057
-
1058
- return result.outputsWithPreviousTransactionData;
1059
- } catch (error) {
1060
- throw new NetworkError(
1061
- "Failed to fetch owned token outputs",
1062
- {
1063
- operation: "spark.query_token_outputs",
1064
- errorCount: 1,
1065
- errors: error instanceof Error ? error.message : String(error),
1066
- },
1067
- error as Error,
1068
- );
1069
- }
1070
- }
1071
-
1072
- private async fetchOwnedTokenOutputsV1(
1073
- params: FetchOwnedTokenOutputsParams,
1074
- ): Promise<OutputWithPreviousTransactionData[]> {
1075
- const {
1076
- ownerPublicKeys,
1077
- issuerPublicKeys = [],
1078
- tokenIdentifiers = [],
1079
- } = params;
1080
-
1081
531
  const tokenClient = await this.connectionManager.createSparkTokenClient(
1082
532
  this.config.getCoordinatorAddress(),
1083
533
  );
@@ -1124,87 +574,7 @@ export class TokenTransactionService {
1124
574
  }
1125
575
  }
1126
576
 
1127
- private async queryTokenTransactionsV0(
1128
- params: QueryTokenTransactionsParams,
1129
- ): Promise<QueryTokenTransactionsResponse> {
1130
- const {
1131
- ownerPublicKeys,
1132
- issuerPublicKeys,
1133
- tokenTransactionHashes,
1134
- tokenIdentifiers,
1135
- outputIds,
1136
- pageSize,
1137
- offset,
1138
- } = params;
1139
-
1140
- const sparkClient = await this.connectionManager.createSparkClient(
1141
- this.config.getCoordinatorAddress(),
1142
- );
1143
-
1144
- let queryParams: QueryTokenTransactionsRequestV0 = {
1145
- tokenPublicKeys: issuerPublicKeys?.map(hexToBytes)!,
1146
- ownerPublicKeys: ownerPublicKeys?.map(hexToBytes)!,
1147
- tokenIdentifiers: tokenIdentifiers?.map((identifier) => {
1148
- const { tokenIdentifier } = decodeBech32mTokenIdentifier(
1149
- identifier as Bech32mTokenIdentifier,
1150
- this.config.getNetworkType(),
1151
- );
1152
- return tokenIdentifier;
1153
- })!,
1154
- tokenTransactionHashes: tokenTransactionHashes?.map(hexToBytes)!,
1155
- outputIds: outputIds || [],
1156
- limit: pageSize!,
1157
- offset: offset!,
1158
- };
1159
-
1160
- try {
1161
- const response = await sparkClient.query_token_transactions(queryParams);
1162
- return {
1163
- tokenTransactionsWithStatus: response.tokenTransactionsWithStatus.map(
1164
- (tx) => {
1165
- // Convert V0 structure to V1 structure
1166
- const v1TokenTransaction: TokenTransaction = {
1167
- version: 1,
1168
- network: tx.tokenTransaction!.network,
1169
- tokenInputs: tx.tokenTransaction!.tokenInputs,
1170
- tokenOutputs: tx.tokenTransaction!.tokenOutputs!,
1171
- sparkOperatorIdentityPublicKeys:
1172
- tx.tokenTransaction!.sparkOperatorIdentityPublicKeys!,
1173
- expiryTime: undefined, // V0 doesn't have expiry time
1174
- clientCreatedTimestamp:
1175
- tx.tokenTransaction?.tokenInputs?.$case === "mintInput"
1176
- ? new Date(
1177
- tx.tokenTransaction.tokenInputs.mintInput
1178
- .issuerProvidedTimestamp * 1000,
1179
- )
1180
- : new Date(),
1181
- invoiceAttachments: [],
1182
- };
1183
-
1184
- return {
1185
- tokenTransaction: v1TokenTransaction,
1186
- status: tx.status,
1187
- confirmationMetadata: tx.confirmationMetadata,
1188
- tokenTransactionHash: tx.tokenTransactionHash,
1189
- };
1190
- },
1191
- ),
1192
- offset: response.offset,
1193
- };
1194
- } catch (error) {
1195
- throw new NetworkError(
1196
- "Failed to query token transactions",
1197
- {
1198
- operation: "spark.query_token_transactions",
1199
- errorCount: 1,
1200
- errors: error instanceof Error ? error.message : String(error),
1201
- },
1202
- error as Error,
1203
- );
1204
- }
1205
- }
1206
-
1207
- private async queryTokenTransactionsV1(
577
+ public async queryTokenTransactions(
1208
578
  params: QueryTokenTransactionsParams,
1209
579
  ): Promise<QueryTokenTransactionsResponse> {
1210
580
  const {
@@ -1354,62 +724,6 @@ export class TokenTransactionService {
1354
724
  }
1355
725
  }
1356
726
 
1357
- private async finalizeTokenTransaction(
1358
- finalTokenTransaction: TokenTransactionV0,
1359
- revocationSecrets: RevocationSecretWithIndex[],
1360
- threshold: number,
1361
- ): Promise<TokenTransactionV0> {
1362
- const signingOperators = this.config.getSigningOperators();
1363
- // Submit finalize_token_transaction to all SOs in parallel
1364
- const soResponses = await Promise.allSettled(
1365
- Object.entries(signingOperators).map(async ([identifier, operator]) => {
1366
- const internalSparkClient =
1367
- await this.connectionManager.createSparkClient(operator.address);
1368
- const identityPublicKey =
1369
- await this.config.signer.getIdentityPublicKey();
1370
-
1371
- try {
1372
- const response = await internalSparkClient.finalize_token_transaction(
1373
- {
1374
- finalTokenTransaction,
1375
- revocationSecrets,
1376
- identityPublicKey,
1377
- },
1378
- {
1379
- retry: true,
1380
- retryableStatuses: [
1381
- "UNKNOWN",
1382
- "UNAVAILABLE",
1383
- "CANCELLED",
1384
- "INTERNAL",
1385
- ],
1386
- retryMaxAttempts: 3,
1387
- } as SparkCallOptions,
1388
- );
1389
-
1390
- return {
1391
- identifier,
1392
- response,
1393
- };
1394
- } catch (error) {
1395
- throw new NetworkError(
1396
- "Failed to finalize token transaction",
1397
- {
1398
- operation: "finalize_token_transaction",
1399
- errorCount: 1,
1400
- errors: error instanceof Error ? error.message : String(error),
1401
- },
1402
- error as Error,
1403
- );
1404
- }
1405
- }),
1406
- );
1407
-
1408
- collectResponses(soResponses);
1409
-
1410
- return finalTokenTransaction;
1411
- }
1412
-
1413
727
  private async createSignaturesForOperators(
1414
728
  finalTokenTransaction: TokenTransaction,
1415
729
  finalTokenTransactionHash: Uint8Array,
@@ -1514,9 +828,3 @@ export class TokenTransactionService {
1514
828
  return inputTtxoSignaturesPerOperator;
1515
829
  }
1516
830
  }
1517
-
1518
- function isTokenTransaction(
1519
- tokenTransaction: TokenTransactionV0 | TokenTransaction,
1520
- ): tokenTransaction is TokenTransaction {
1521
- return "version" in tokenTransaction && "expiryTime" in tokenTransaction;
1522
- }