@buildonspark/spark-sdk 0.1.45 → 0.1.47

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 (146) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/{chunk-I54FARY2.js → chunk-EAP3U3CW.js} +14 -14
  3. package/dist/chunk-GWFQ7EBA.js +3773 -0
  4. package/dist/{chunk-J2IE4Z7Y.js → chunk-NNX4OK44.js} +3487 -934
  5. package/dist/{RequestLightningSendInput-Du0z7Om7.d.cts → client-CvpTRpcw.d.cts} +422 -212
  6. package/dist/{RequestLightningSendInput-DEPd_fPO.d.ts → client-D7KgLN44.d.ts} +422 -212
  7. package/dist/graphql/objects/index.d.cts +5 -9
  8. package/dist/graphql/objects/index.d.ts +5 -9
  9. package/dist/graphql/objects/index.js +1 -1
  10. package/dist/index.cjs +20461 -23377
  11. package/dist/index.d.cts +15 -769
  12. package/dist/index.d.ts +15 -769
  13. package/dist/index.js +81 -71
  14. package/dist/index.node.cjs +21994 -25018
  15. package/dist/index.node.d.cts +312 -34
  16. package/dist/index.node.d.ts +312 -34
  17. package/dist/index.node.js +82 -176
  18. package/dist/native/index.cjs +22847 -25841
  19. package/dist/native/index.d.cts +974 -1138
  20. package/dist/native/index.d.ts +974 -1138
  21. package/dist/native/index.js +10604 -13592
  22. package/dist/proto/lrc20.d.cts +2 -2
  23. package/dist/proto/lrc20.d.ts +2 -2
  24. package/dist/proto/lrc20.js +3098 -46
  25. package/dist/proto/spark.d.cts +1 -1
  26. package/dist/proto/spark.d.ts +1 -1
  27. package/dist/proto/spark_token.d.cts +1 -1
  28. package/dist/proto/spark_token.d.ts +1 -1
  29. package/dist/{sdk-types-Cc4l4kb1.d.ts → sdk-types-BGCeea0G.d.ts} +1 -1
  30. package/dist/{sdk-types-B0SwjolI.d.cts → sdk-types-XUeQMLFP.d.cts} +1 -1
  31. package/dist/{spark-dM7EYXYQ.d.cts → spark-BbUrbvZz.d.cts} +1 -1
  32. package/dist/{spark-dM7EYXYQ.d.ts → spark-BbUrbvZz.d.ts} +1 -1
  33. package/dist/spark-wallet-BAFPpPtY.d.cts +923 -0
  34. package/dist/spark-wallet-CJkQW8pK.d.ts +923 -0
  35. package/dist/spark_bindings/native/index.d.cts +1 -1
  36. package/dist/spark_bindings/native/index.d.ts +1 -1
  37. package/dist/spark_bindings/wasm/index.d.cts +1 -1
  38. package/dist/spark_bindings/wasm/index.d.ts +1 -1
  39. package/dist/{services/index.cjs → tests/test-utils.cjs} +2512 -4380
  40. package/dist/tests/test-utils.d.cts +79 -0
  41. package/dist/tests/test-utils.d.ts +79 -0
  42. package/dist/tests/test-utils.js +85 -0
  43. package/dist/types/index.d.cts +5 -9
  44. package/dist/types/index.d.ts +5 -9
  45. package/dist/types/index.js +5 -5
  46. package/dist/{types-C-Rp0Oo7.d.cts → types-BADxR3bm.d.cts} +1 -1
  47. package/dist/{types-C-Rp0Oo7.d.ts → types-BADxR3bm.d.ts} +1 -1
  48. package/package.json +7 -35
  49. package/src/graphql/client.ts +59 -20
  50. package/src/index.node.ts +28 -2
  51. package/src/index.ts +31 -1
  52. package/src/native/index.ts +16 -2
  53. package/src/services/config.ts +4 -6
  54. package/src/services/connection.ts +131 -64
  55. package/src/services/lightning.ts +1 -2
  56. package/src/services/token-transactions.ts +7 -7
  57. package/src/services/transfer.ts +1 -1
  58. package/src/services/tree-creation.ts +1 -1
  59. package/src/services/wallet-config.ts +18 -10
  60. package/src/signer/signer.react-native.ts +2 -5
  61. package/src/signer/signer.ts +138 -64
  62. package/src/signer/types.ts +52 -0
  63. package/src/spark-wallet/spark-wallet.ts +79 -36
  64. package/src/spark-wallet/types.ts +4 -4
  65. package/src/tests/integration/coop-exit.test.ts +2 -1
  66. package/src/tests/integration/lightning.test.ts +2 -2
  67. package/src/tests/integration/swap.test.ts +1 -1
  68. package/src/tests/integration/transfer.test.ts +5 -5
  69. package/src/tests/integration/tree-creation.test.ts +1 -1
  70. package/src/tests/integration/wallet.test.ts +1 -0
  71. package/src/tests/isHermeticTest.ts +3 -24
  72. package/src/tests/{test-util.ts → test-utils.ts} +3 -7
  73. package/src/tests/wrapWithOtelSpan.test.ts +1 -1
  74. package/src/{address → utils}/address.ts +1 -1
  75. package/src/utils/crypto.ts +19 -9
  76. package/src/utils/index.ts +2 -0
  77. package/src/utils/network.ts +17 -0
  78. package/src/utils/secret-sharing.ts +1 -2
  79. package/src/utils/signing.ts +1 -1
  80. package/src/utils/token-transactions.ts +3 -3
  81. package/src/utils/unilateral-exit.ts +32 -0
  82. package/src/utils/xchain-address.ts +1 -1
  83. package/dist/BitcoinNetwork-TnABML0T.d.cts +0 -18
  84. package/dist/BitcoinNetwork-TnABML0T.d.ts +0 -18
  85. package/dist/LightningSendFeeEstimateInput-BgOhEAI-.d.cts +0 -10
  86. package/dist/LightningSendFeeEstimateInput-BgOhEAI-.d.ts +0 -10
  87. package/dist/address/index.cjs +0 -458
  88. package/dist/address/index.d.cts +0 -32
  89. package/dist/address/index.d.ts +0 -32
  90. package/dist/address/index.js +0 -17
  91. package/dist/chunk-5FUB65LX.js +0 -838
  92. package/dist/chunk-6264CGDM.js +0 -113
  93. package/dist/chunk-7V6N75CC.js +0 -24
  94. package/dist/chunk-C2S227QR.js +0 -2336
  95. package/dist/chunk-GSI4OLXZ.js +0 -117
  96. package/dist/chunk-GZ5IPPJ2.js +0 -170
  97. package/dist/chunk-HWJWKEIU.js +0 -75
  98. package/dist/chunk-KMUMFYFX.js +0 -137
  99. package/dist/chunk-L3EHBOUX.js +0 -0
  100. package/dist/chunk-NSJF5F5O.js +0 -325
  101. package/dist/chunk-NTFKFRQ2.js +0 -3146
  102. package/dist/chunk-PQN3C2MF.js +0 -1122
  103. package/dist/chunk-QNNSEJ4P.js +0 -232
  104. package/dist/chunk-R5PXJZQS.js +0 -277
  105. package/dist/chunk-VTUGIIWI.js +0 -0
  106. package/dist/chunk-YUPMXTCJ.js +0 -622
  107. package/dist/chunk-Z5HIAYFT.js +0 -84
  108. package/dist/index-B2AwKW5J.d.cts +0 -214
  109. package/dist/index-CJDi1HWc.d.ts +0 -214
  110. package/dist/network-BTJl-Sul.d.ts +0 -46
  111. package/dist/network-CqgsdUF2.d.cts +0 -46
  112. package/dist/services/config.cjs +0 -2354
  113. package/dist/services/config.d.cts +0 -42
  114. package/dist/services/config.d.ts +0 -42
  115. package/dist/services/config.js +0 -17
  116. package/dist/services/connection.cjs +0 -17691
  117. package/dist/services/connection.d.cts +0 -95
  118. package/dist/services/connection.d.ts +0 -95
  119. package/dist/services/connection.js +0 -11
  120. package/dist/services/index.d.cts +0 -21
  121. package/dist/services/index.d.ts +0 -21
  122. package/dist/services/index.js +0 -58
  123. package/dist/services/lrc-connection.cjs +0 -4713
  124. package/dist/services/lrc-connection.d.cts +0 -34
  125. package/dist/services/lrc-connection.d.ts +0 -34
  126. package/dist/services/lrc-connection.js +0 -11
  127. package/dist/services/token-transactions.cjs +0 -2877
  128. package/dist/services/token-transactions.d.cts +0 -75
  129. package/dist/services/token-transactions.d.ts +0 -75
  130. package/dist/services/token-transactions.js +0 -15
  131. package/dist/services/wallet-config.cjs +0 -340
  132. package/dist/services/wallet-config.d.cts +0 -56
  133. package/dist/services/wallet-config.d.ts +0 -56
  134. package/dist/services/wallet-config.js +0 -33
  135. package/dist/signer/signer.cjs +0 -2004
  136. package/dist/signer/signer.d.cts +0 -10
  137. package/dist/signer/signer.d.ts +0 -10
  138. package/dist/signer/signer.js +0 -24
  139. package/dist/signer-BocS_J6B.d.ts +0 -187
  140. package/dist/signer-DKS0AJkw.d.cts +0 -187
  141. package/dist/utils/index.cjs +0 -2947
  142. package/dist/utils/index.d.cts +0 -18
  143. package/dist/utils/index.d.ts +0 -18
  144. package/dist/utils/index.js +0 -157
  145. package/src/address/index.ts +0 -1
  146. package/src/services/lrc-connection.ts +0 -215
@@ -0,0 +1,52 @@
1
+ import type { HDKey } from "@scure/bip32";
2
+ import type {
3
+ IKeyPackage,
4
+ ISigningCommitment,
5
+ } from "../spark_bindings/types.js";
6
+
7
+ export { MultisigReceiptInput } from "@buildonspark/lrc20-sdk/lrc/types";
8
+
9
+ export type SigningNonce = {
10
+ binding: Uint8Array;
11
+ hiding: Uint8Array;
12
+ };
13
+
14
+ export type SigningCommitment = {
15
+ binding: Uint8Array;
16
+ hiding: Uint8Array;
17
+ };
18
+
19
+ export type SignFrostParams = {
20
+ message: Uint8Array;
21
+ privateAsPubKey: Uint8Array;
22
+ publicKey: Uint8Array;
23
+ verifyingKey: Uint8Array;
24
+ selfCommitment: ISigningCommitment;
25
+ statechainCommitments?: { [key: string]: ISigningCommitment } | undefined;
26
+ adaptorPubKey?: Uint8Array | undefined;
27
+ };
28
+
29
+ export type AggregateFrostParams = Omit<SignFrostParams, "privateAsPubKey"> & {
30
+ selfSignature: Uint8Array;
31
+ statechainSignatures?: { [key: string]: Uint8Array } | undefined;
32
+ statechainPublicKeys?: { [key: string]: Uint8Array } | undefined;
33
+ };
34
+
35
+ export type SplitSecretWithProofsParams = {
36
+ secret: Uint8Array;
37
+ curveOrder: bigint;
38
+ threshold: number;
39
+ numShares: number;
40
+ isSecretPubkey?: boolean;
41
+ };
42
+
43
+ export type DerivedHDKey = {
44
+ hdKey: HDKey;
45
+ privateKey: Uint8Array;
46
+ publicKey: Uint8Array;
47
+ };
48
+
49
+ export type KeyPair = {
50
+ privateKey: Uint8Array;
51
+ publicKey: Uint8Array;
52
+ };
@@ -54,7 +54,6 @@ import { ConnectionManager } from "../services/connection.js";
54
54
  import { CoopExitService } from "../services/coop-exit.js";
55
55
  import { DepositService } from "../services/deposit.js";
56
56
  import { LightningService } from "../services/lightning.js";
57
- import { Lrc20ConnectionManager } from "../services/lrc-connection.js";
58
57
  import { TokenTransactionService } from "../services/token-transactions.js";
59
58
  import type { LeafKeyTweak } from "../services/transfer.js";
60
59
  import { TransferService } from "../services/transfer.js";
@@ -88,7 +87,7 @@ import {
88
87
  NetworkToProto,
89
88
  NetworkType,
90
89
  } from "../utils/network.js";
91
- import { calculateAvailableTokenAmount } from "../utils/token-transactions.js";
90
+ import { sumAvailableTokens } from "../utils/token-transactions.js";
92
91
  import { getNextTransactionSequence } from "../utils/transaction.js";
93
92
 
94
93
  import { LRCWallet } from "@buildonspark/lrc20-sdk";
@@ -99,7 +98,7 @@ import {
99
98
  encodeSparkAddress,
100
99
  isValidPublicKey,
101
100
  SparkAddressFormat,
102
- } from "../address/index.js";
101
+ } from "../utils/address.js";
103
102
  import { isReactNative } from "../constants.js";
104
103
  import { Network as NetworkProto, networkToJSON } from "../proto/spark.js";
105
104
  import {
@@ -124,12 +123,15 @@ import type {
124
123
  InitWalletResponse,
125
124
  PayLightningInvoiceParams,
126
125
  SparkWalletProps,
127
- TokenMetadata,
126
+ UserTokenMetadata,
128
127
  TransferParams,
129
128
  TokenBalanceMap,
130
129
  } from "./types.js";
131
130
  import { encodeHumanReadableTokenIdentifier } from "../utils/token-identifier.js";
132
- import { TokenTransactionWithStatus } from "../proto/spark_token.js";
131
+ import {
132
+ TokenTransactionWithStatus,
133
+ TokenMetadata,
134
+ } from "../proto/spark_token.js";
133
135
 
134
136
  /**
135
137
  * The SparkWallet class is the primary interface for interacting with the Spark network.
@@ -140,7 +142,6 @@ export class SparkWallet extends EventEmitter {
140
142
  protected config: WalletConfigService;
141
143
 
142
144
  protected connectionManager: ConnectionManager;
143
- protected lrc20ConnectionManager: Lrc20ConnectionManager;
144
145
  protected lrc20Wallet: LRCWallet | undefined;
145
146
  protected transferService: TransferService;
146
147
  protected tracerId = "spark-sdk";
@@ -169,6 +170,7 @@ export class SparkWallet extends EventEmitter {
169
170
 
170
171
  protected tokenOutputs: Map<string, OutputWithPreviousTransactionData[]> =
171
172
  new Map();
173
+ protected tokenMetadata: Map<string, TokenMetadata> = new Map();
172
174
 
173
175
  // Add this property near the top of the class with other private properties
174
176
  private claimTransfersInterval: NodeJS.Timeout | null = null;
@@ -188,7 +190,6 @@ export class SparkWallet extends EventEmitter {
188
190
  this.config = new WalletConfigService(options, signer);
189
191
  this.connectionManager = new ConnectionManager(this.config);
190
192
  this.signingService = new SigningService(this.config);
191
- this.lrc20ConnectionManager = new Lrc20ConnectionManager(this.config);
192
193
  this.depositService = new DepositService(
193
194
  this.config,
194
195
  this.connectionManager,
@@ -1214,34 +1215,70 @@ export class SparkWallet extends EventEmitter {
1214
1215
  };
1215
1216
  }
1216
1217
 
1218
+ private async getTokenMetadata(): Promise<Map<string, UserTokenMetadata>> {
1219
+ let metadataToFetch = new Array<string>();
1220
+ for (const issuerPublicKey of this.tokenOutputs.keys()) {
1221
+ if (!this.tokenMetadata.has(issuerPublicKey)) {
1222
+ metadataToFetch.push(issuerPublicKey);
1223
+ }
1224
+ }
1225
+
1226
+ if (metadataToFetch.length > 0) {
1227
+ const sparkTokenClient =
1228
+ await this.connectionManager.createSparkTokenClient(
1229
+ this.config.getCoordinatorAddress(),
1230
+ );
1231
+
1232
+ try {
1233
+ const response = await sparkTokenClient.query_token_metadata({
1234
+ issuerPublicKeys: metadataToFetch.map(hexToBytes),
1235
+ });
1236
+
1237
+ for (const metadata of response.tokenMetadata) {
1238
+ this.tokenMetadata.set(
1239
+ bytesToHex(metadata.issuerPublicKey),
1240
+ metadata,
1241
+ );
1242
+ }
1243
+ } catch (error) {
1244
+ throw new NetworkError("Failed to fetch token metadata", {
1245
+ errorCount: 1,
1246
+ errors: error instanceof Error ? error.message : String(error),
1247
+ });
1248
+ }
1249
+ }
1250
+
1251
+ let tokenMetadataMap = new Map<string, UserTokenMetadata>();
1252
+
1253
+ for (const [issuerPublicKey, metadata] of this.tokenMetadata) {
1254
+ tokenMetadataMap.set(issuerPublicKey, {
1255
+ tokenPublicKey: bytesToHex(metadata.issuerPublicKey),
1256
+ rawTokenIdentifier: metadata.tokenIdentifier,
1257
+ tokenName: metadata.tokenName,
1258
+ tokenTicker: metadata.tokenTicker,
1259
+ decimals: metadata.decimals,
1260
+ maxSupply: bytesToNumberBE(metadata.maxSupply),
1261
+ });
1262
+ }
1263
+
1264
+ return tokenMetadataMap;
1265
+ }
1266
+
1217
1267
  private async getTokenBalance(): Promise<TokenBalanceMap> {
1218
- const sparkTokenClient =
1219
- await this.connectionManager.createSparkTokenClient(
1220
- this.config.getCoordinatorAddress(),
1221
- );
1268
+ const tokenMetadataMap = await this.getTokenMetadata();
1222
1269
 
1223
- const tokenMetadata = await sparkTokenClient.query_token_metadata({
1224
- issuerPublicKeys: Array.from(this.tokenOutputs.keys()).map(hexToBytes),
1225
- });
1226
1270
  const result: TokenBalanceMap = new Map();
1271
+ for (const [issuerPublicKey, tokenMetadata] of tokenMetadataMap) {
1272
+ const outputs = this.tokenOutputs.get(issuerPublicKey);
1227
1273
 
1228
- for (const metadata of tokenMetadata.tokenMetadata) {
1229
- const tokenPublicKey = bytesToHex(metadata.issuerPublicKey);
1230
- const leaves = this.tokenOutputs.get(tokenPublicKey);
1231
1274
  const humanReadableTokenIdentifier = encodeHumanReadableTokenIdentifier({
1232
- tokenIdentifier: metadata.tokenIdentifier,
1275
+ tokenIdentifier: tokenMetadata.rawTokenIdentifier,
1233
1276
  network: this.config.getNetworkType(),
1234
1277
  });
1278
+
1235
1279
  result.set(humanReadableTokenIdentifier, {
1236
- balance: leaves ? calculateAvailableTokenAmount(leaves) : BigInt(0),
1237
- tokenMetadata: {
1238
- tokenPublicKey,
1239
- rawTokenIdentifier: metadata.tokenIdentifier,
1240
- tokenName: metadata.tokenName,
1241
- tokenTicker: metadata.tokenTicker,
1242
- decimals: metadata.decimals,
1243
- maxSupply: bytesToNumberBE(metadata.maxSupply),
1244
- },
1280
+ balance: outputs ? sumAvailableTokens(outputs) : BigInt(0),
1281
+ tokenMetadata: tokenMetadata,
1245
1282
  });
1246
1283
  }
1247
1284
 
@@ -3303,7 +3340,7 @@ export class SparkWallet extends EventEmitter {
3303
3340
  }
3304
3341
 
3305
3342
  /**
3306
- * Retrieves token transaction history for specified tokens owned by the wallet.
3343
+ * Retrieves token transaction history for specified tokens
3307
3344
  * Can optionally filter by specific transaction hashes.
3308
3345
  *
3309
3346
  * @param ownerPublicKeys - Optional array of owner public keys to query transactions for
@@ -3313,13 +3350,20 @@ export class SparkWallet extends EventEmitter {
3313
3350
  * @param outputIds - Optional array of output IDs to filter by
3314
3351
  * @returns Promise resolving to array of token transactions with their current status
3315
3352
  */
3316
- public async queryTokenTransactions(
3317
- ownerPublicKeys?: string[],
3318
- issuerPublicKeys?: string[],
3319
- tokenTransactionHashes?: string[],
3320
- tokenIdentifiers?: string[],
3321
- outputIds?: string[],
3322
- ): Promise<TokenTransactionWithStatus[]> {
3353
+
3354
+ public async queryTokenTransactions({
3355
+ ownerPublicKeys,
3356
+ issuerPublicKeys,
3357
+ tokenTransactionHashes,
3358
+ tokenIdentifiers,
3359
+ outputIds,
3360
+ }: {
3361
+ ownerPublicKeys?: string[];
3362
+ issuerPublicKeys?: string[];
3363
+ tokenTransactionHashes?: string[];
3364
+ tokenIdentifiers?: string[];
3365
+ outputIds?: string[];
3366
+ }): Promise<TokenTransactionWithStatus[]> {
3323
3367
  return this.tokenTransactionService.queryTokenTransactions({
3324
3368
  ownerPublicKeys,
3325
3369
  issuerPublicKeys,
@@ -3849,7 +3893,6 @@ export class SparkWallet extends EventEmitter {
3849
3893
  public async cleanupConnections() {
3850
3894
  this.cleanup();
3851
3895
  await this.connectionManager.closeConnections();
3852
- await this.lrc20ConnectionManager.closeConnection();
3853
3896
  }
3854
3897
 
3855
3898
  // Add this new method to start periodic claiming
@@ -41,7 +41,7 @@ export type DepositParams = {
41
41
  *
42
42
  * @example
43
43
  * ```typescript
44
- * const tokenMetadata: TokenMetadata = {
44
+ * const tokenMetadata: UserTokenMetadata = {
45
45
  * rawTokenIdentifier: new Uint8Array([1, 2, 3]),
46
46
  * tokenPublicKey: "0348fbb...",
47
47
  * tokenName: "SparkToken",
@@ -51,10 +51,10 @@ export type DepositParams = {
51
51
  * };
52
52
  * ```
53
53
  */
54
- export type TokenMetadata = {
54
+ export type UserTokenMetadata = {
55
55
  /** Raw binary token identifier - This is used to encode the human readable token identifier */
56
56
  rawTokenIdentifier: Uint8Array;
57
- /** Hex-encoded public key of the token issuer - Same as issuerPublicKey */
57
+ /** Public key of the token issuer - Same as issuerPublicKey */
58
58
  tokenPublicKey: string;
59
59
  /** Human-readable name of the token (e.g., SparkToken)*/
60
60
  tokenName: string;
@@ -70,7 +70,7 @@ export type TokenBalanceMap = Map<
70
70
  HumanReadableTokenIdentifier,
71
71
  {
72
72
  balance: bigint;
73
- tokenMetadata: TokenMetadata;
73
+ tokenMetadata: UserTokenMetadata;
74
74
  }
75
75
  >;
76
76
 
@@ -19,9 +19,10 @@ import {
19
19
  getTxIdNoReverse,
20
20
  } from "../../utils/bitcoin.js";
21
21
  import { getNetwork, Network } from "../../utils/network.js";
22
- import { createNewTree } from "../test-util.js";
22
+ import { createNewTree } from "../test-utils.js";
23
23
  import { SparkWalletTesting } from "../utils/spark-testing-wallet.js";
24
24
  import { BitcoinFaucet } from "../utils/test-faucet.js";
25
+
25
26
  describe("coop exit", () => {
26
27
  const brokenTestFn = process.env.GITHUB_ACTIONS ? it.skip : it;
27
28
 
@@ -15,7 +15,7 @@ import {
15
15
  CurrencyUnit,
16
16
  LightningReceiveRequestStatus,
17
17
  } from "../../types/index.js";
18
- import { createNewTree, getTestWalletConfig } from "../test-util.js";
18
+ import { createNewTree, getTestWalletConfig } from "../test-utils.js";
19
19
  import { SparkWalletTesting } from "../utils/spark-testing-wallet.js";
20
20
  import { BitcoinFaucet } from "../utils/test-faucet.js";
21
21
 
@@ -476,7 +476,7 @@ describe("LightningService", () => {
476
476
  );
477
477
 
478
478
  expect(transfer.status).toEqual(
479
- TransferStatus.TRANSFER_STATUS_SENDER_INITIATED_COORDINATOR,
479
+ TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAK_PENDING,
480
480
  );
481
481
 
482
482
  const refunds =
@@ -16,7 +16,7 @@ import {
16
16
  computeTaprootKeyNoScript,
17
17
  getSigHashFromTx,
18
18
  } from "../../utils/bitcoin.js";
19
- import { createNewTree } from "../test-util.js";
19
+ import { createNewTree } from "../test-utils.js";
20
20
  import { SparkWalletTesting } from "../utils/spark-testing-wallet.js";
21
21
  import { BitcoinFaucet } from "../utils/test-faucet.js";
22
22
 
@@ -16,9 +16,9 @@ import { TransferService } from "../../services/transfer.js";
16
16
  import {
17
17
  ConfigOptions,
18
18
  getLocalSigningOperators,
19
- LOCAL_WALLET_CONFIG,
19
+ WalletConfig,
20
20
  } from "../../services/wallet-config.js";
21
- import { createNewTree } from "../../tests/test-util.js";
21
+ import { createNewTree } from "../test-utils.js";
22
22
  import { NetworkType } from "../../utils/network.js";
23
23
  import { SparkWalletTesting } from "../utils/spark-testing-wallet.js";
24
24
  import { BitcoinFaucet } from "../utils/test-faucet.js";
@@ -423,7 +423,7 @@ describe("Transfer", () => {
423
423
  ),
424
424
  );
425
425
  const missingOperatorOptions = {
426
- ...LOCAL_WALLET_CONFIG,
426
+ ...WalletConfig.LOCAL,
427
427
  signingOperators,
428
428
  };
429
429
  const mnemonic = generateMnemonic(wordlist);
@@ -493,7 +493,7 @@ describe("Transfer", () => {
493
493
  ]);
494
494
 
495
495
  const receiverOptions = {
496
- ...LOCAL_WALLET_CONFIG,
496
+ ...WalletConfig.LOCAL,
497
497
  };
498
498
 
499
499
  const { wallet: receiverWalletWithAllOperators } =
@@ -521,7 +521,7 @@ describe("Transfer", () => {
521
521
  const { wallet: receiverWalletWithMissingOperatorAsCoordinator } =
522
522
  await SparkWalletTesting.initialize({
523
523
  options: {
524
- ...LOCAL_WALLET_CONFIG,
524
+ ...WalletConfig.LOCAL,
525
525
  coodinatorIdentifier: soToRemove,
526
526
  },
527
527
  mnemonicOrSeed: mnemonic,
@@ -6,7 +6,7 @@ import { ValidationError } from "../../errors/types.js";
6
6
  import { getTxFromRawTxBytes, getTxId } from "../../utils/bitcoin.js";
7
7
  import { Network } from "../../utils/network.js";
8
8
  import { DEFAULT_FEE_SATS } from "../../utils/transaction.js";
9
- import { createNewTreeWithLevels } from "../test-util.js";
9
+ import { createNewTreeWithLevels } from "../test-utils.js";
10
10
  import { SparkWalletTesting } from "../utils/spark-testing-wallet.js";
11
11
  import { BitcoinFaucet } from "../utils/test-faucet.js";
12
12
 
@@ -2,6 +2,7 @@ import { describe, expect, it } from "@jest/globals";
2
2
  import { ConfigOptions } from "../../services/wallet-config.js";
3
3
  import { NetworkType } from "../../utils/network.js";
4
4
  import { SparkWalletTesting } from "../utils/spark-testing-wallet.js";
5
+
5
6
  describe("wallet", () => {
6
7
  it("should initialize a wallet", async () => {
7
8
  const seedOrMnemonics = [
@@ -1,24 +1,3 @@
1
- import { isNode } from "@lightsparkdev/core";
2
- import fs from "fs";
3
-
4
- /**
5
- * Checks if the current environment is a hermetic test environment.
6
- * A hermetic test environment is identified by either:
7
- * 1. The existence of a marker file at /tmp/spark_hermetic (Node.js only)
8
- * 2. The HERMETIC_TEST environment variable being set to "true"
9
- *
10
- * @returns {boolean} True if running in a hermetic test environment, false otherwise
11
- */
12
- export function isHermeticTest() {
13
- if (isNode) {
14
- return (
15
- (fs?.existsSync?.("/tmp/spark_hermetic") ?? false) ||
16
- process.env.HERMETIC_TEST === "true"
17
- );
18
- }
19
-
20
- return (
21
- (typeof process !== "undefined" && process.env?.HERMETIC_TEST === "true") ||
22
- false
23
- );
24
- }
1
+ export const isHermeticTest = Boolean(
2
+ typeof process !== "undefined" && process?.env?.HERMETIC_TEST === "true",
3
+ );
@@ -6,17 +6,13 @@ import { TreeNode } from "../proto/spark.js";
6
6
  import { WalletConfigService } from "../services/config.js";
7
7
  import { ConnectionManager } from "../services/connection.js";
8
8
  import { DepositService } from "../services/deposit.js";
9
- import {
10
- ConfigOptions,
11
- LOCAL_WALLET_CONFIG,
12
- } from "../services/wallet-config.js";
9
+ import { ConfigOptions, WalletConfig } from "../services/wallet-config.js";
13
10
  import { getP2TRAddressFromPublicKey } from "../utils/bitcoin.js";
14
- import { getCrypto } from "../utils/crypto.js";
15
11
  import { getNetwork, Network } from "../utils/network.js";
16
12
  import { SparkWalletTesting } from "./utils/spark-testing-wallet.js";
17
13
  import { BitcoinFaucet } from "./utils/test-faucet.js";
18
14
 
19
- const crypto = getCrypto();
15
+ export { BitcoinFaucet };
20
16
 
21
17
  export function getTestWalletConfig() {
22
18
  const identityPrivateKey = secp256k1.utils.randomPrivateKey();
@@ -27,7 +23,7 @@ export function getTestWalletConfigWithIdentityKey(
27
23
  identityPrivateKey: Uint8Array,
28
24
  ) {
29
25
  return {
30
- ...LOCAL_WALLET_CONFIG,
26
+ ...WalletConfig.LOCAL,
31
27
  identityPrivateKey,
32
28
  } as ConfigOptions;
33
29
  }
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect } from "@jest/globals";
2
2
  import { SparkWalletTesting } from "./utils/spark-testing-wallet.js";
3
- import { getTestWalletConfig } from "./test-util.js";
3
+ import { getTestWalletConfig } from "./test-utils.js";
4
4
  import { BasicTracerProvider } from "@opentelemetry/sdk-trace-base";
5
5
  import { trace } from "@opentelemetry/api";
6
6
 
@@ -2,7 +2,7 @@ import { secp256k1 } from "@noble/curves/secp256k1";
2
2
  import { bytesToHex, hexToBytes } from "@noble/hashes/utils";
3
3
  import { bech32m } from "@scure/base";
4
4
  import { PaymentIntentFields, SparkAddress } from "../proto/spark.js";
5
- import { NetworkType } from "../utils/network.js";
5
+ import { NetworkType } from "./network.js";
6
6
  import { ValidationError } from "../errors/index.js";
7
7
 
8
8
  import { UUID, uuidv7 } from "uuidv7";
@@ -1,12 +1,22 @@
1
- import nodeCrypto from "crypto";
1
+ export interface SparkCrypto {
2
+ // Browser
3
+ getRandomValues<T extends ArrayBufferView | null>(array: T): T;
4
+ // Node.js
5
+ getRandomValues<T extends ArrayBuffer | ArrayBufferView>(array: T): T;
6
+ }
2
7
 
3
- export const getCrypto = (): Crypto => {
4
- let cryptoImpl: any =
5
- typeof window !== "undefined"
6
- ? window.crypto
7
- : typeof global !== "undefined" && global.crypto
8
- ? global.crypto
9
- : nodeCrypto;
8
+ let cryptoImpl: SparkCrypto | null = globalThis.crypto ?? null;
10
9
 
11
- return cryptoImpl as Crypto;
10
+ export const getCrypto = () => {
11
+ if (!cryptoImpl) {
12
+ throw new Error(
13
+ "Crypto implementation is not set. Please set it using setCrypto().",
14
+ );
15
+ }
16
+
17
+ return cryptoImpl;
18
+ };
19
+
20
+ export const setCrypto = (cryptoImplParam: SparkCrypto | null): void => {
21
+ cryptoImpl = cryptoImplParam;
12
22
  };
@@ -1,3 +1,4 @@
1
+ export * from "./address.js";
1
2
  export * from "./adaptor-signature.js";
2
3
  export * from "./bitcoin.js";
3
4
  export * from "./keys.js";
@@ -7,6 +8,7 @@ export * from "./proof.js";
7
8
  export * from "./response-validation.js";
8
9
  export * from "./secret-sharing.js";
9
10
  export * from "./signing.js";
11
+ export * from "./token-identifier.js";
10
12
  export * from "./token-transactions.js";
11
13
  export * from "./transfer_package.js";
12
14
  export * from "./transaction.js";
@@ -23,6 +23,23 @@ export const NetworkToProto: Record<Network, NetworkProto> = {
23
23
  [Network.LOCAL]: NetworkProto.REGTEST,
24
24
  };
25
25
 
26
+ export const protoToNetwork = (
27
+ protoNetwork: NetworkProto,
28
+ ): Network | undefined => {
29
+ switch (protoNetwork) {
30
+ case NetworkProto.MAINNET:
31
+ return Network.MAINNET;
32
+ case NetworkProto.TESTNET:
33
+ return Network.TESTNET;
34
+ case NetworkProto.SIGNET:
35
+ return Network.SIGNET;
36
+ case NetworkProto.REGTEST:
37
+ return Network.REGTEST;
38
+ default:
39
+ return undefined;
40
+ }
41
+ };
42
+
26
43
  const NetworkConfig: Record<Network, typeof btc.NETWORK> = {
27
44
  [Network.MAINNET]: btc.NETWORK,
28
45
  [Network.TESTNET]: btc.TEST_NETWORK,
@@ -3,8 +3,6 @@ import { secp256k1 } from "@noble/curves/secp256k1";
3
3
  import { getCrypto } from "./crypto.js";
4
4
  import { ValidationError } from "../errors/index.js";
5
5
 
6
- const crypto = getCrypto();
7
-
8
6
  type Polynomial = {
9
7
  fieldModulus: bigint;
10
8
  coefficients: bigint[];
@@ -28,6 +26,7 @@ export function getRandomBigInt(max: bigint): bigint {
28
26
 
29
27
  const mask = (1n << BigInt(max.toString(2).length)) - 1n;
30
28
  while (true) {
29
+ const crypto = getCrypto();
31
30
  const randBytes = crypto.getRandomValues(new Uint8Array(byteLength + 1));
32
31
 
33
32
  const randValue = BigInt("0x" + bytesToHex(randBytes)) & mask;
@@ -1,6 +1,6 @@
1
1
  import { secp256k1 } from "@noble/curves/secp256k1";
2
2
  import { ValidationError } from "../errors/index.js";
3
- import type { SigningCommitment, SigningNonce } from "../signer/signer.js";
3
+ import type { SigningCommitment, SigningNonce } from "../signer/types.js";
4
4
 
5
5
  export function getRandomSigningNonce(): SigningNonce {
6
6
  const binding = secp256k1.utils.randomPrivateKey();
@@ -2,10 +2,10 @@ import { bytesToHex, bytesToNumberBE } from "@noble/curves/abstract/utils";
2
2
  import { OutputWithPreviousTransactionData } from "../proto/spark.js";
3
3
  import { TokenBalanceMap } from "../spark-wallet/types.js";
4
4
 
5
- export function calculateAvailableTokenAmount(
6
- outputLeaves: OutputWithPreviousTransactionData[],
5
+ export function sumAvailableTokens(
6
+ outputs: OutputWithPreviousTransactionData[],
7
7
  ): bigint {
8
- return outputLeaves.reduce(
8
+ return outputs.reduce(
9
9
  (sum, output) => sum + BigInt(bytesToNumberBE(output.output!.tokenAmount!)),
10
10
  BigInt(0),
11
11
  );
@@ -493,6 +493,38 @@ export async function constructUnilateralExitFeeBumpPackages(
493
493
  undefined,
494
494
  );
495
495
 
496
+ const feeBumpTx = btc.Transaction.fromPSBT(
497
+ hexToBytes(refundFeeBump.feeBumpPsbt),
498
+ );
499
+
500
+ var feeBumpOut: psbt.TransactionOutput | null =
501
+ feeBumpTx.outputsLength === 1 ? feeBumpTx.getOutput(0) : null;
502
+ var feeBumpOutPubKey: string | null = null;
503
+
504
+ // Remove used UTXOs from the available list
505
+ for (const usedUtxo of usedUtxos) {
506
+ if (feeBumpOut && bytesToHex(feeBumpOut.script!) == usedUtxo.script) {
507
+ feeBumpOutPubKey = usedUtxo.publicKey;
508
+ }
509
+ const index = availableUtxos.findIndex(
510
+ (u) => u.txid === usedUtxo.txid && u.vout === usedUtxo.vout,
511
+ );
512
+ if (index !== -1) {
513
+ availableUtxos.splice(index, 1);
514
+ }
515
+ }
516
+
517
+ if (feeBumpOut)
518
+ // Add to end instead of the beginning in case there are other available UTXOs we can use first
519
+ // We don't want to wait on leaf 1 to be broadcasted to broadcast leaf 2 if we can use a different available UTXO
520
+ availableUtxos.push({
521
+ txid: getTxId(feeBumpTx),
522
+ vout: 0,
523
+ value: feeBumpOut.amount!,
524
+ script: bytesToHex(feeBumpOut.script!),
525
+ publicKey: feeBumpOutPubKey!,
526
+ });
527
+
496
528
  txPackages.push({
497
529
  tx: refundTxHex,
498
530
  feeBumpPsbt: refundFeeBump.feeBumpPsbt,
@@ -1,4 +1,4 @@
1
- import { encodeSparkAddress, SparkAddressFormat } from "../address/address.js";
1
+ import { encodeSparkAddress, SparkAddressFormat } from "./address.js";
2
2
  import * as btc from "@scure/btc-signer";
3
3
  import { ValidationError } from "../errors/index.js";
4
4
 
@@ -1,18 +0,0 @@
1
- /** This is an enum identifying a particular Bitcoin Network. **/
2
- declare enum BitcoinNetwork {
3
- /**
4
- * This is an enum value that represents values that could be added in the future.
5
- * Clients should support unknown values as more of them could be added without notice.
6
- */
7
- FUTURE_VALUE = "FUTURE_VALUE",
8
- /** The production version of the Bitcoin Blockchain. **/
9
- MAINNET = "MAINNET",
10
- /** A test version of the Bitcoin Blockchain, maintained by Lightspark. **/
11
- REGTEST = "REGTEST",
12
- /** A test version of the Bitcoin Blockchain, maintained by a centralized organization. Not in use at Lightspark. **/
13
- SIGNET = "SIGNET",
14
- /** A test version of the Bitcoin Blockchain, publicly available. **/
15
- TESTNET = "TESTNET"
16
- }
17
-
18
- export { BitcoinNetwork as B };
@@ -1,18 +0,0 @@
1
- /** This is an enum identifying a particular Bitcoin Network. **/
2
- declare enum BitcoinNetwork {
3
- /**
4
- * This is an enum value that represents values that could be added in the future.
5
- * Clients should support unknown values as more of them could be added without notice.
6
- */
7
- FUTURE_VALUE = "FUTURE_VALUE",
8
- /** The production version of the Bitcoin Blockchain. **/
9
- MAINNET = "MAINNET",
10
- /** A test version of the Bitcoin Blockchain, maintained by Lightspark. **/
11
- REGTEST = "REGTEST",
12
- /** A test version of the Bitcoin Blockchain, maintained by a centralized organization. Not in use at Lightspark. **/
13
- SIGNET = "SIGNET",
14
- /** A test version of the Bitcoin Blockchain, publicly available. **/
15
- TESTNET = "TESTNET"
16
- }
17
-
18
- export { BitcoinNetwork as B };