@buildonspark/spark-sdk 0.5.0 → 0.5.1

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 (81) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/bare/index.cjs +1608 -3635
  3. package/dist/bare/index.d.cts +27 -435
  4. package/dist/bare/index.d.ts +27 -435
  5. package/dist/bare/index.js +1608 -3634
  6. package/dist/{chunk-RU434ZAE.js → chunk-F3BFSHVR.js} +357 -391
  7. package/dist/{chunk-UYEB2VPG.js → chunk-IOIEBLMK.js} +7 -1
  8. package/dist/{chunk-EU3I7GFB.js → chunk-STB6WMU7.js} +1 -1
  9. package/dist/{chunk-JE3MXMPW.js → chunk-UTECVGQQ.js} +93 -202
  10. package/dist/{chunk-ZP6Z6DFX.js → chunk-YFVVYZCS.js} +37 -5
  11. package/dist/{client-D1dLzWu0.d.ts → client-C9kc4cog.d.cts} +9 -3
  12. package/dist/{client-CVn0R_eM.d.cts → client-eyjf4knu.d.ts} +9 -3
  13. package/dist/graphql/objects/index.cjs +7 -1
  14. package/dist/graphql/objects/index.d.cts +3 -3
  15. package/dist/graphql/objects/index.d.ts +3 -3
  16. package/dist/graphql/objects/index.js +1 -1
  17. package/dist/index.browser.d.ts +27 -435
  18. package/dist/index.browser.js +1613 -3639
  19. package/dist/index.node.cjs +1613 -3640
  20. package/dist/index.node.d.cts +7 -8
  21. package/dist/index.node.d.ts +7 -8
  22. package/dist/index.node.js +5 -7
  23. package/dist/native/index.react-native.cjs +1613 -3640
  24. package/dist/native/index.react-native.d.cts +27 -435
  25. package/dist/native/index.react-native.d.ts +27 -435
  26. package/dist/native/index.react-native.js +1613 -3639
  27. package/dist/proto/spark.cjs +93 -202
  28. package/dist/proto/spark.d.cts +1 -1
  29. package/dist/proto/spark.d.ts +1 -1
  30. package/dist/proto/spark.js +1 -1
  31. package/dist/proto/spark_token.cjs +36 -4
  32. package/dist/proto/spark_token.d.cts +4 -1
  33. package/dist/proto/spark_token.d.ts +4 -1
  34. package/dist/proto/spark_token.js +2 -2
  35. package/dist/{spark-2Fxnvl8K.d.cts → spark-d6w3BLGZ.d.cts} +10 -328
  36. package/dist/{spark-2Fxnvl8K.d.ts → spark-d6w3BLGZ.d.ts} +10 -328
  37. package/dist/{spark-wallet.node-DlhZiDgY.d.ts → spark-wallet.node-MReThHBY.d.ts} +6 -7
  38. package/dist/{spark-wallet.node-xKJXzAEd.d.cts → spark-wallet.node-eR0svGws.d.cts} +6 -7
  39. package/dist/tests/test-utils.cjs +409 -2429
  40. package/dist/tests/test-utils.d.cts +3 -3
  41. package/dist/tests/test-utils.d.ts +3 -3
  42. package/dist/tests/test-utils.js +5 -5
  43. package/dist/types/index.cjs +100 -203
  44. package/dist/types/index.d.cts +2 -2
  45. package/dist/types/index.d.ts +2 -2
  46. package/dist/types/index.js +3 -3
  47. package/package.json +3 -3
  48. package/src/graphql/client.ts +36 -1
  49. package/src/graphql/objects/LightningSendRequestStatus.ts +25 -13
  50. package/src/proto/common.ts +1 -1
  51. package/src/proto/google/protobuf/descriptor.ts +1 -1
  52. package/src/proto/google/protobuf/duration.ts +1 -1
  53. package/src/proto/google/protobuf/empty.ts +1 -1
  54. package/src/proto/google/protobuf/timestamp.ts +1 -1
  55. package/src/proto/mock.ts +1 -1
  56. package/src/proto/spark.ts +113 -446
  57. package/src/proto/spark_authn.ts +1 -1
  58. package/src/proto/spark_token.ts +41 -2
  59. package/src/proto/validate/validate.ts +1 -1
  60. package/src/services/connection/connection.ts +23 -60
  61. package/src/services/coop-exit.ts +3 -5
  62. package/src/services/deposit.ts +1 -1
  63. package/src/services/lightning.ts +1 -1
  64. package/src/services/signing.ts +5 -6
  65. package/src/services/transfer.ts +250 -240
  66. package/src/services/wallet-config.ts +22 -5
  67. package/src/spark-wallet/proto-descriptors.ts +1 -1
  68. package/src/spark-wallet/proto-reflection.ts +0 -2
  69. package/src/spark-wallet/spark-wallet.ts +2 -2
  70. package/src/spark_descriptors.pb +0 -0
  71. package/src/tests/bufbuild-reflection.test.ts +2 -3
  72. package/src/tests/integration/coop-exit.test.ts +6 -1
  73. package/src/tests/integration/htlc.test.ts +5 -0
  74. package/src/tests/integration/lightning.test.ts +24 -4
  75. package/src/tests/integration/time-sync.test.ts +18 -0
  76. package/src/tests/integration/transfer.test.ts +42 -7
  77. package/src/tests/ssp-client-retry.test.ts +161 -0
  78. package/src/tests/token-hashing.test.ts +92 -0
  79. package/src/utils/token-hashing.ts +4 -51
  80. package/src/utils/transaction.ts +1 -2
  81. package/src/utils/unilateral-exit.ts +139 -142
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.7.7
3
+ // protoc-gen-ts_proto v2.8.3
4
4
  // protoc v5.29.3
5
5
  // source: spark_authn.proto
6
6
 
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.7.7
3
+ // protoc-gen-ts_proto v2.8.3
4
4
  // protoc v5.29.3
5
5
  // source: spark_token.proto
6
6
 
@@ -197,7 +197,11 @@ export interface TokenCreateInput {
197
197
  /** Decoded uint128 */
198
198
  maxSupply: Uint8Array;
199
199
  isFreezable: boolean;
200
- creationEntityPublicKey?: Uint8Array | undefined;
200
+ creationEntityPublicKey?:
201
+ | Uint8Array
202
+ | undefined;
203
+ /** If any of the fields below are provided, use protohash to generate the token_identifier */
204
+ extraMetadata?: Uint8Array | undefined;
201
205
  }
202
206
 
203
207
  /**
@@ -422,6 +426,7 @@ export interface TokenMetadata {
422
426
  isFreezable: boolean;
423
427
  creationEntityPublicKey?: Uint8Array | undefined;
424
428
  tokenIdentifier: Uint8Array;
429
+ extraMetadata?: Uint8Array | undefined;
425
430
  }
426
431
 
427
432
  export interface QueryTokenMetadataResponse {
@@ -748,6 +753,7 @@ function createBaseTokenCreateInput(): TokenCreateInput {
748
753
  maxSupply: new Uint8Array(0),
749
754
  isFreezable: false,
750
755
  creationEntityPublicKey: undefined,
756
+ extraMetadata: undefined,
751
757
  };
752
758
  }
753
759
 
@@ -774,6 +780,9 @@ export const TokenCreateInput: MessageFns<TokenCreateInput> = {
774
780
  if (message.creationEntityPublicKey !== undefined) {
775
781
  writer.uint32(58).bytes(message.creationEntityPublicKey);
776
782
  }
783
+ if (message.extraMetadata !== undefined) {
784
+ writer.uint32(66).bytes(message.extraMetadata);
785
+ }
777
786
  return writer;
778
787
  },
779
788
 
@@ -840,6 +849,14 @@ export const TokenCreateInput: MessageFns<TokenCreateInput> = {
840
849
  message.creationEntityPublicKey = reader.bytes();
841
850
  continue;
842
851
  }
852
+ case 8: {
853
+ if (tag !== 66) {
854
+ break;
855
+ }
856
+
857
+ message.extraMetadata = reader.bytes();
858
+ continue;
859
+ }
843
860
  }
844
861
  if ((tag & 7) === 4 || tag === 0) {
845
862
  break;
@@ -860,6 +877,7 @@ export const TokenCreateInput: MessageFns<TokenCreateInput> = {
860
877
  creationEntityPublicKey: isSet(object.creationEntityPublicKey)
861
878
  ? bytesFromBase64(object.creationEntityPublicKey)
862
879
  : undefined,
880
+ extraMetadata: isSet(object.extraMetadata) ? bytesFromBase64(object.extraMetadata) : undefined,
863
881
  };
864
882
  },
865
883
 
@@ -886,6 +904,9 @@ export const TokenCreateInput: MessageFns<TokenCreateInput> = {
886
904
  if (message.creationEntityPublicKey !== undefined) {
887
905
  obj.creationEntityPublicKey = base64FromBytes(message.creationEntityPublicKey);
888
906
  }
907
+ if (message.extraMetadata !== undefined) {
908
+ obj.extraMetadata = base64FromBytes(message.extraMetadata);
909
+ }
889
910
  return obj;
890
911
  },
891
912
 
@@ -901,6 +922,7 @@ export const TokenCreateInput: MessageFns<TokenCreateInput> = {
901
922
  message.maxSupply = object.maxSupply ?? new Uint8Array(0);
902
923
  message.isFreezable = object.isFreezable ?? false;
903
924
  message.creationEntityPublicKey = object.creationEntityPublicKey ?? undefined;
925
+ message.extraMetadata = object.extraMetadata ?? undefined;
904
926
  return message;
905
927
  },
906
928
  };
@@ -3081,6 +3103,7 @@ function createBaseTokenMetadata(): TokenMetadata {
3081
3103
  isFreezable: false,
3082
3104
  creationEntityPublicKey: undefined,
3083
3105
  tokenIdentifier: new Uint8Array(0),
3106
+ extraMetadata: undefined,
3084
3107
  };
3085
3108
  }
3086
3109
 
@@ -3110,6 +3133,9 @@ export const TokenMetadata: MessageFns<TokenMetadata> = {
3110
3133
  if (message.tokenIdentifier.length !== 0) {
3111
3134
  writer.uint32(66).bytes(message.tokenIdentifier);
3112
3135
  }
3136
+ if (message.extraMetadata !== undefined) {
3137
+ writer.uint32(74).bytes(message.extraMetadata);
3138
+ }
3113
3139
  return writer;
3114
3140
  },
3115
3141
 
@@ -3184,6 +3210,14 @@ export const TokenMetadata: MessageFns<TokenMetadata> = {
3184
3210
  message.tokenIdentifier = reader.bytes();
3185
3211
  continue;
3186
3212
  }
3213
+ case 9: {
3214
+ if (tag !== 74) {
3215
+ break;
3216
+ }
3217
+
3218
+ message.extraMetadata = reader.bytes();
3219
+ continue;
3220
+ }
3187
3221
  }
3188
3222
  if ((tag & 7) === 4 || tag === 0) {
3189
3223
  break;
@@ -3205,6 +3239,7 @@ export const TokenMetadata: MessageFns<TokenMetadata> = {
3205
3239
  ? bytesFromBase64(object.creationEntityPublicKey)
3206
3240
  : undefined,
3207
3241
  tokenIdentifier: isSet(object.tokenIdentifier) ? bytesFromBase64(object.tokenIdentifier) : new Uint8Array(0),
3242
+ extraMetadata: isSet(object.extraMetadata) ? bytesFromBase64(object.extraMetadata) : undefined,
3208
3243
  };
3209
3244
  },
3210
3245
 
@@ -3234,6 +3269,9 @@ export const TokenMetadata: MessageFns<TokenMetadata> = {
3234
3269
  if (message.tokenIdentifier.length !== 0) {
3235
3270
  obj.tokenIdentifier = base64FromBytes(message.tokenIdentifier);
3236
3271
  }
3272
+ if (message.extraMetadata !== undefined) {
3273
+ obj.extraMetadata = base64FromBytes(message.extraMetadata);
3274
+ }
3237
3275
  return obj;
3238
3276
  },
3239
3277
 
@@ -3250,6 +3288,7 @@ export const TokenMetadata: MessageFns<TokenMetadata> = {
3250
3288
  message.isFreezable = object.isFreezable ?? false;
3251
3289
  message.creationEntityPublicKey = object.creationEntityPublicKey ?? undefined;
3252
3290
  message.tokenIdentifier = object.tokenIdentifier ?? new Uint8Array(0);
3291
+ message.extraMetadata = object.extraMetadata ?? undefined;
3253
3292
  return message;
3254
3293
  },
3255
3294
  };
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.7.7
3
+ // protoc-gen-ts_proto v2.8.3
4
4
  // protoc v5.29.3
5
5
  // source: validate/validate.proto
6
6
 
@@ -215,6 +215,10 @@ export abstract class ConnectionManager {
215
215
  return serverTime;
216
216
  }
217
217
 
218
+ public isTimeSynced(): boolean {
219
+ return this.timeSync.isSynced();
220
+ }
221
+
218
222
  protected getMonotonicTime(): number {
219
223
  return getMonotonicTime();
220
224
  }
@@ -438,54 +442,6 @@ export abstract class ConnectionManager {
438
442
  return metadata;
439
443
  }
440
444
 
441
- protected recordTimeSync(
442
- dateHeader: string,
443
- serverProcessingTimeMs: number,
444
- sendTime: number,
445
- receiveTime: number,
446
- ) {
447
- this.timeSync.recordSync(
448
- dateHeader,
449
- serverProcessingTimeMs,
450
- sendTime,
451
- receiveTime,
452
- );
453
- }
454
-
455
- private processResponseForTimeSync(
456
- result: IteratorResult<any, any>,
457
- firstResponse: boolean,
458
- sendTime: number,
459
- ): boolean {
460
- if (!firstResponse) return false;
461
-
462
- const receiveTime = this.getMonotonicTime();
463
-
464
- if (typeof result.value === "object" && result.value !== null) {
465
- const responseObj = result.value as any;
466
- if (responseObj.header && responseObj.header instanceof Metadata) {
467
- const dateHeader = responseObj.header.get(
468
- ConnectionManager.DATE_HEADER,
469
- )?.[0];
470
- const processingTimeHeader = responseObj.header.get(
471
- ConnectionManager.PROCESSING_TIME_HEADER,
472
- )?.[0];
473
-
474
- if (dateHeader && processingTimeHeader) {
475
- const serverProcessingTimeMs = parseFloat(processingTimeHeader);
476
- this.recordTimeSync(
477
- dateHeader,
478
- serverProcessingTimeMs,
479
- sendTime,
480
- receiveTime,
481
- );
482
- }
483
- }
484
- }
485
-
486
- return true;
487
- }
488
-
489
445
  protected createAuthnMiddleware() {
490
446
  return async function* <Req, Res>(
491
447
  this: ConnectionManager,
@@ -512,33 +468,40 @@ export abstract class ConnectionManager {
512
468
  const metadata = this.prepareMetadata(Metadata(options.metadata));
513
469
  const authToken = await this.authenticate(address);
514
470
  const sendTime = this.getMonotonicTime();
471
+ const receiveTime = { value: 0 };
515
472
 
516
473
  try {
517
474
  const generator = call.next(call.request as Req, {
518
475
  ...options,
519
476
  metadata: metadata.set("Authorization", `Bearer ${authToken}`),
477
+ onHeader: (header: Metadata) => {
478
+ receiveTime.value = this.getMonotonicTime();
479
+
480
+ const dateHeader = header.get(ConnectionManager.DATE_HEADER);
481
+ const processingTimeHeader = header.get(
482
+ ConnectionManager.PROCESSING_TIME_HEADER,
483
+ );
484
+
485
+ if (dateHeader && processingTimeHeader) {
486
+ const serverProcessingTimeMs = parseFloat(processingTimeHeader);
487
+ this.timeSync.recordSync(
488
+ dateHeader,
489
+ serverProcessingTimeMs,
490
+ sendTime,
491
+ receiveTime.value,
492
+ );
493
+ }
494
+ },
520
495
  });
521
496
 
522
- let firstResponse = true;
523
497
  let result = await generator.next();
524
498
 
525
499
  while (!result.done) {
526
- if (firstResponse) {
527
- firstResponse = this.processResponseForTimeSync(
528
- result,
529
- firstResponse,
530
- sendTime,
531
- );
532
- }
533
-
534
500
  yield result.value;
535
501
  result = await generator.next();
536
502
  }
537
503
 
538
504
  if (result.value !== undefined) {
539
- if (firstResponse) {
540
- this.processResponseForTimeSync(result, firstResponse, sendTime);
541
- }
542
505
  return result.value;
543
506
  }
544
507
  } catch (error: unknown) {
@@ -173,9 +173,7 @@ export class CoopExitService extends BaseTransferService {
173
173
  const signingJob: LeafRefundTxSigningJob = {
174
174
  leafId: leaf.leaf.id,
175
175
  refundTxSigningJob: {
176
- signingPublicKey: await this.config.signer.getPublicKeyFromDerivation(
177
- leaf.keyDerivation,
178
- ),
176
+ signingPublicKey,
179
177
  rawTx: cpfpRefundTx.toBytes(),
180
178
  signingNonceCommitment: signingNonceCommitment.commitment,
181
179
  },
@@ -242,14 +240,14 @@ export class CoopExitService extends BaseTransferService {
242
240
  });
243
241
  } catch (error) {
244
242
  throw new SparkRequestError("Failed to initiate cooperative exit", {
245
- operation: "cooperative_exit",
243
+ operation: "cooperative_exit_v2",
246
244
  error,
247
245
  });
248
246
  }
249
247
 
250
248
  if (!response.transfer) {
251
249
  throw new SparkRequestError("Failed to initiate cooperative exit", {
252
- operation: "cooperative_exit",
250
+ operation: "cooperative_exit_v2",
253
251
  error: new Error("No transfer in response"),
254
252
  });
255
253
  }
@@ -599,7 +599,7 @@ export class DepositService {
599
599
  });
600
600
  } catch (error) {
601
601
  throw new SparkRequestError("Failed to finalize node signatures", {
602
- operation: "finalize_node_signatures",
602
+ operation: "finalize_node_signatures_v2",
603
603
  error,
604
604
  });
605
605
  }
@@ -310,7 +310,7 @@ export class LightningService {
310
310
  });
311
311
  } catch (error) {
312
312
  throw new SparkRequestError("Failed to initiate preimage swap", {
313
- operation: "initiate_preimage_swap",
313
+ operation: "initiate_preimage_swap_v3",
314
314
  error,
315
315
  });
316
316
  }
@@ -49,12 +49,13 @@ export class SigningService {
49
49
  expected: "Non-null signing commitments",
50
50
  });
51
51
  }
52
+ const publicKey = await this.config.signer.getPublicKeyFromDerivation(
53
+ leaf.keyDerivation,
54
+ );
52
55
  const signingResult = await this.config.signer.signFrost({
53
56
  message: sighash,
54
57
  keyDerivation: leaf.keyDerivation,
55
- publicKey: await this.config.signer.getPublicKeyFromDerivation(
56
- leaf.keyDerivation,
57
- ),
58
+ publicKey,
58
59
  selfCommitment: signingCommitment,
59
60
  statechainCommitments: signingCommitments,
60
61
  adaptorPubKey: new Uint8Array(),
@@ -63,9 +64,7 @@ export class SigningService {
63
64
 
64
65
  leafSigningJobs.push({
65
66
  leafId: leaf.leaf.id,
66
- signingPublicKey: await this.config.signer.getPublicKeyFromDerivation(
67
- leaf.keyDerivation,
68
- ),
67
+ signingPublicKey: publicKey,
69
68
  rawTx: refundTx.toBytes(),
70
69
  signingNonceCommitment: signingCommitment.commitment,
71
70
  userSignature: signingResult,