@buildonspark/spark-sdk 0.2.4 → 0.2.6

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 (82) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/{chunk-3SEOTO43.js → chunk-3SPMJMUX.js} +3 -2
  3. package/dist/chunk-AVI5E5VT.js +66 -0
  4. package/dist/{chunk-WAQKYSDI.js → chunk-CQY5ML2A.js} +3 -2
  5. package/dist/{chunk-W4ZRBSWM.js → chunk-GUZ3WCB4.js} +466 -167
  6. package/dist/{client-KhNkrXz4.d.cts → client-CusuvuCe.d.cts} +199 -104
  7. package/dist/{client-BF4cn8F4.d.ts → client-Dn4Ld8pD.d.ts} +199 -104
  8. package/dist/debug.cjs +662 -336
  9. package/dist/debug.d.cts +9 -7
  10. package/dist/debug.d.ts +9 -7
  11. package/dist/debug.js +3 -3
  12. package/dist/graphql/objects/index.d.cts +6 -51
  13. package/dist/graphql/objects/index.d.ts +6 -51
  14. package/dist/graphql/objects/index.js +1 -1
  15. package/dist/index.cjs +713 -327
  16. package/dist/index.d.cts +19 -188
  17. package/dist/index.d.ts +19 -188
  18. package/dist/index.js +15 -8
  19. package/dist/index.node.cjs +638 -352
  20. package/dist/index.node.d.cts +7 -7
  21. package/dist/index.node.d.ts +7 -7
  22. package/dist/index.node.js +59 -100
  23. package/dist/native/index.cjs +655 -325
  24. package/dist/native/index.d.cts +253 -164
  25. package/dist/native/index.d.ts +253 -164
  26. package/dist/native/index.js +505 -172
  27. package/dist/proto/lrc20.d.cts +1 -1
  28. package/dist/proto/lrc20.d.ts +1 -1
  29. package/dist/proto/spark.d.cts +1 -1
  30. package/dist/proto/spark.d.ts +1 -1
  31. package/dist/proto/spark_token.d.cts +1 -1
  32. package/dist/proto/spark_token.d.ts +1 -1
  33. package/dist/{spark-B_7nZx6T.d.cts → spark-Cj4brrP5.d.cts} +1 -1
  34. package/dist/{spark-B_7nZx6T.d.ts → spark-Cj4brrP5.d.ts} +1 -1
  35. package/dist/{spark-wallet-C1Tr_VKI.d.ts → spark-wallet-B6YthxDI.d.ts} +61 -26
  36. package/dist/{spark-wallet-DG3x2obf.d.cts → spark-wallet-BbOf2P2l.d.cts} +61 -26
  37. package/dist/spark-wallet.node-BBk1sGS2.d.cts +12 -0
  38. package/dist/spark-wallet.node-Bffethig.d.ts +12 -0
  39. package/dist/tests/test-utils.cjs +86 -54
  40. package/dist/tests/test-utils.d.cts +24 -24
  41. package/dist/tests/test-utils.d.ts +24 -24
  42. package/dist/tests/test-utils.js +4 -4
  43. package/dist/token-transactions-0_5XMWjs.d.ts +184 -0
  44. package/dist/token-transactions-CD-Adb5y.d.cts +184 -0
  45. package/dist/types/index.cjs +3 -2
  46. package/dist/types/index.d.cts +3 -4
  47. package/dist/types/index.d.ts +3 -4
  48. package/dist/types/index.js +2 -2
  49. package/dist/{xchain-address-HBr6isnc.d.cts → xchain-address-BnKZ0-dY.d.cts} +6 -5
  50. package/dist/{xchain-address-BHu6CpZC.d.ts → xchain-address-Di3lu4Wy.d.ts} +6 -5
  51. package/package.json +7 -2
  52. package/src/graphql/client.ts +49 -8
  53. package/src/graphql/objects/SparkWalletUser.ts +1 -1
  54. package/src/graphql/queries/Transfers.ts +15 -0
  55. package/src/index.node.ts +5 -1
  56. package/src/index.ts +4 -1
  57. package/src/services/config.ts +13 -2
  58. package/src/services/token-transactions.ts +22 -8
  59. package/src/services/wallet-config.ts +22 -13
  60. package/src/spark-wallet/spark-wallet.browser.ts +72 -0
  61. package/src/spark-wallet/spark-wallet.node.ts +60 -118
  62. package/src/spark-wallet/spark-wallet.ts +400 -156
  63. package/src/tests/integration/ssp/coop-exit-validation.test.ts +233 -0
  64. package/src/tests/integration/ssp/coop-exit.test.ts +112 -93
  65. package/src/tests/integration/ssp/static-deposit-validation.test.ts +145 -0
  66. package/src/tests/integration/ssp/static_deposit.test.ts +453 -64
  67. package/src/tests/integration/ssp/transfers.test.ts +102 -0
  68. package/src/tests/integration/static_deposit.test.ts +92 -0
  69. package/src/tests/integration/transfer.test.ts +1 -1
  70. package/src/tests/utils/regtest-test-faucet.ts +8 -0
  71. package/src/tests/utils/spark-testing-wallet.ts +42 -0
  72. package/src/tests/utils/test-faucet.ts +6 -2
  73. package/src/types/sdk-types.ts +15 -0
  74. package/src/utils/bitcoin.ts +13 -0
  75. package/src/utils/token-identifier.ts +47 -4
  76. package/src/utils/token-transactions.ts +13 -9
  77. package/dist/chunk-TVUMSHWA.js +0 -7
  78. package/dist/sdk-types-CB9HrW5O.d.cts +0 -44
  79. package/dist/sdk-types-CkRNraXT.d.ts +0 -44
  80. package/dist/spark-wallet.node-CGxoeCpH.d.ts +0 -13
  81. package/dist/spark-wallet.node-CN9LoB_O.d.cts +0 -13
  82. package/src/graphql/queries/Transfer.ts +0 -10
@@ -10,6 +10,7 @@ import {
10
10
  import { sha256 } from "@noble/hashes/sha2";
11
11
  import { AuthenticationError, NetworkError } from "../errors/index.js";
12
12
  import { SparkSigner } from "../signer/signer.js";
13
+ import { UserRequestType } from "../types/sdk-types.js";
13
14
  import { ClaimStaticDeposit } from "./mutations/ClaimStaticDeposit.js";
14
15
  import { CompleteCoopExit } from "./mutations/CompleteCoopExit.js";
15
16
  import { CompleteLeavesSwap } from "./mutations/CompleteLeavesSwap.js";
@@ -19,6 +20,7 @@ import { RequestLightningReceive } from "./mutations/RequestLightningReceive.js"
19
20
  import { RequestLightningSend } from "./mutations/RequestLightningSend.js";
20
21
  import { RequestSwapLeaves } from "./mutations/RequestSwapLeaves.js";
21
22
  import { VerifyChallenge } from "./mutations/VerifyChallenge.js";
23
+ import { ClaimStaticDepositFromJson } from "./objects/ClaimStaticDeposit.js";
22
24
  import ClaimStaticDepositOutput, {
23
25
  ClaimStaticDepositOutputFromJson,
24
26
  } from "./objects/ClaimStaticDepositOutput.js";
@@ -29,7 +31,7 @@ import CoopExitRequest, {
29
31
  CoopExitRequestFromJson,
30
32
  } from "./objects/CoopExitRequest.js";
31
33
  import { GetChallengeOutputFromJson } from "./objects/GetChallengeOutput.js";
32
- import type {
34
+ import {
33
35
  BitcoinNetwork,
34
36
  CompleteCoopExitInput,
35
37
  CompleteLeavesSwapInput,
@@ -70,7 +72,7 @@ import { GetClaimDepositQuote } from "./queries/GetClaimDepositQuote.js";
70
72
  import { GetCoopExitFeeQuote } from "./queries/GetCoopExitFeeQuote.js";
71
73
  import { LeavesSwapFeeEstimate } from "./queries/LeavesSwapFeeEstimate.js";
72
74
  import { LightningSendFeeEstimate } from "./queries/LightningSendFeeEstimate.js";
73
- import { GetTransfer } from "./queries/Transfer.js";
75
+ import { GetTransfers } from "./queries/Transfers.js";
74
76
  import { UserRequest } from "./queries/UserRequest.js";
75
77
 
76
78
  export interface SspClientOptions {
@@ -79,6 +81,10 @@ export interface SspClientOptions {
79
81
  schemaEndpoint?: string;
80
82
  }
81
83
 
84
+ export interface TransferWithUserRequest extends Transfer {
85
+ userRequest?: UserRequestType;
86
+ }
87
+
82
88
  export interface MayHaveSspClientOptions {
83
89
  readonly sspClientOptions?: SspClientOptions;
84
90
  }
@@ -485,14 +491,49 @@ export default class SspClient {
485
491
  });
486
492
  }
487
493
 
488
- async getTransfer(id: string): Promise<Transfer | null> {
494
+ async getTransfers(ids: string[]): Promise<TransferWithUserRequest[]> {
489
495
  return await this.executeRawQuery({
490
- queryPayload: GetTransfer,
496
+ queryPayload: GetTransfers,
491
497
  variables: {
492
- transfer_spark_id: id,
493
- },
494
- constructObject: (response: { transfer: any }) => {
495
- return TransferFromJson(response.transfer);
498
+ transfer_spark_ids: ids,
499
+ },
500
+ constructObject: (response: { transfers: any }) => {
501
+ return response.transfers.map((transfer: any) => {
502
+ const transferObj: TransferWithUserRequest = TransferFromJson(
503
+ transfer,
504
+ ) as TransferWithUserRequest;
505
+
506
+ switch (transfer.transfer_user_request.__typename) {
507
+ case "ClaimStaticDeposit":
508
+ transferObj.userRequest = ClaimStaticDepositFromJson(
509
+ transfer.transfer_user_request,
510
+ );
511
+ break;
512
+ case "CoopExitRequest":
513
+ transferObj.userRequest = CoopExitRequestFromJson(
514
+ transfer.transfer_user_request,
515
+ );
516
+ break;
517
+ case "LeavesSwapRequest":
518
+ transferObj.userRequest = LeavesSwapRequestFromJson(
519
+ transfer.transfer_user_request,
520
+ );
521
+ break;
522
+ case "LightningReceiveRequest":
523
+ transferObj.userRequest = LightningReceiveRequestFromJson(
524
+ transfer.transfer_user_request,
525
+ );
526
+ break;
527
+ case "LightningSendRequest":
528
+ transferObj.userRequest = LightningSendRequestFromJson(
529
+ transfer.transfer_user_request,
530
+ );
531
+ break;
532
+ }
533
+
534
+ const { userRequestId, ...rest } = transferObj;
535
+ return rest;
536
+ });
496
537
  },
497
538
  });
498
539
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { Query, isObject } from "@lightsparkdev/core";
4
4
  import autoBind from "../../auto-bind.js";
5
- import LightsparkClient from "../client.js";
5
+ import type LightsparkClient from "../client.js";
6
6
  import BitcoinNetwork from "./BitcoinNetwork.js";
7
7
  import Entity from "./Entity.js";
8
8
  import SparkUserRequestStatus from "./SparkUserRequestStatus.js";
@@ -0,0 +1,15 @@
1
+ import { FRAGMENT as TransferFragment } from "../objects/Transfer.js";
2
+ import { FRAGMENT as UserRequestFragment } from "../objects/UserRequest.js";
3
+
4
+ export const GetTransfers = `
5
+ query Transfers($transfer_spark_ids: [UUID!]!) {
6
+ transfers(transfer_spark_ids: $transfer_spark_ids) {
7
+ ...TransferFragment
8
+ transfer_user_request: user_request {
9
+ ...UserRequestFragment
10
+ }
11
+ }
12
+ }
13
+ ${TransferFragment}
14
+ ${UserRequestFragment}
15
+ `;
package/src/index.node.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /* Root Node.js entrypoint */
2
2
 
3
3
  import nodeCrypto from "crypto";
4
+
4
5
  import { setCrypto } from "./utils/crypto.js";
5
6
 
6
7
  const cryptoImpl =
@@ -21,7 +22,10 @@ export {
21
22
  } from "./signer/signer.js";
22
23
  export * from "./signer/types.js";
23
24
 
24
- export { SparkWallet } from "./spark-wallet/spark-wallet.node.js";
25
+ export {
26
+ SparkWalletNodeJS as SparkWallet,
27
+ initializeTracerEnvNodeJS as initializeTracerEnv,
28
+ } from "./spark-wallet/spark-wallet.node.js";
25
29
  export * from "./spark-wallet/types.js";
26
30
 
27
31
  export { type WalletConfigService } from "./services/config.js";
package/src/index.ts CHANGED
@@ -24,7 +24,10 @@ export {
24
24
  } from "./signer/signer.js";
25
25
  export * from "./signer/types.js";
26
26
 
27
- export { SparkWallet } from "./spark-wallet/spark-wallet.js";
27
+ export {
28
+ SparkWalletBrowser as SparkWallet,
29
+ initializeTracerEnvBrowser as initializeTracerEnv,
30
+ } from "./spark-wallet/spark-wallet.browser.js";
28
31
  export * from "./spark-wallet/types.js";
29
32
 
30
33
  export { type WalletConfigService } from "./services/config.js";
@@ -10,6 +10,7 @@ import {
10
10
  ConfigOptions,
11
11
  WalletConfig,
12
12
  SigningOperator,
13
+ ConsoleOptions,
13
14
  } from "./wallet-config.js";
14
15
  import { ConfigurationError } from "../errors/types.js";
15
16
 
@@ -47,7 +48,7 @@ export class WalletConfigService
47
48
 
48
49
  public getCoordinatorAddress(): string {
49
50
  const coordinator =
50
- this.config.signingOperators[this.config.coodinatorIdentifier];
51
+ this.config.signingOperators[this.config.coordinatorIdentifier];
51
52
  if (!coordinator) {
52
53
  throw new ConfigurationError(
53
54
  "Coordinator not found in signing operators",
@@ -72,7 +73,7 @@ export class WalletConfigService
72
73
  }
73
74
 
74
75
  public getCoordinatorIdentifier(): string {
75
- return this.config.coodinatorIdentifier;
76
+ return this.config.coordinatorIdentifier;
76
77
  }
77
78
 
78
79
  public getExpectedWithdrawBondSats(): number {
@@ -124,7 +125,17 @@ export class WalletConfigService
124
125
  return this.config.electrsUrl;
125
126
  }
126
127
 
128
+ public getSspBaseUrl(): string {
129
+ return this.config.sspClientOptions.baseUrl;
130
+ }
131
+
127
132
  public getSspIdentityPublicKey(): string {
128
133
  return this.config.sspClientOptions.identityPublicKey;
129
134
  }
135
+
136
+ public getConsoleOptions(): ConsoleOptions {
137
+ return {
138
+ ...this.config.console,
139
+ };
140
+ }
130
141
  }
@@ -71,8 +71,8 @@ export interface QueryTokenTransactionsParams {
71
71
  tokenTransactionHashes?: string[];
72
72
  tokenIdentifiers?: string[];
73
73
  outputIds?: string[];
74
- pageSize: number;
75
- offset: number;
74
+ pageSize?: number;
75
+ offset?: number;
76
76
  }
77
77
 
78
78
  export class TokenTransactionService {
@@ -1043,6 +1043,8 @@ export class TokenTransactionService {
1043
1043
  tokenTransactionHashes,
1044
1044
  tokenIdentifiers,
1045
1045
  outputIds,
1046
+ pageSize,
1047
+ offset,
1046
1048
  } = params;
1047
1049
 
1048
1050
  const sparkClient = await this.connectionManager.createSparkClient(
@@ -1052,11 +1054,17 @@ export class TokenTransactionService {
1052
1054
  let queryParams: QueryTokenTransactionsRequestV0 = {
1053
1055
  tokenPublicKeys: issuerPublicKeys?.map(hexToBytes)!,
1054
1056
  ownerPublicKeys: ownerPublicKeys?.map(hexToBytes)!,
1055
- tokenIdentifiers: tokenIdentifiers?.map(hexToBytes)!,
1057
+ tokenIdentifiers: tokenIdentifiers?.map((identifier) => {
1058
+ const { tokenIdentifier } = decodeBech32mTokenIdentifier(
1059
+ identifier as Bech32mTokenIdentifier,
1060
+ this.config.getNetworkType(),
1061
+ );
1062
+ return tokenIdentifier;
1063
+ })!,
1056
1064
  tokenTransactionHashes: tokenTransactionHashes?.map(hexToBytes)!,
1057
1065
  outputIds: outputIds || [],
1058
- limit: 100,
1059
- offset: 0,
1066
+ limit: pageSize!,
1067
+ offset: offset!,
1060
1068
  };
1061
1069
 
1062
1070
  try {
@@ -1120,11 +1128,17 @@ export class TokenTransactionService {
1120
1128
  let queryParams: QueryTokenTransactionsRequestV1 = {
1121
1129
  issuerPublicKeys: issuerPublicKeys?.map(hexToBytes)!,
1122
1130
  ownerPublicKeys: ownerPublicKeys?.map(hexToBytes)!,
1123
- tokenIdentifiers: tokenIdentifiers?.map(hexToBytes)!,
1131
+ tokenIdentifiers: tokenIdentifiers?.map((identifier) => {
1132
+ const { tokenIdentifier } = decodeBech32mTokenIdentifier(
1133
+ identifier as Bech32mTokenIdentifier,
1134
+ this.config.getNetworkType(),
1135
+ );
1136
+ return tokenIdentifier;
1137
+ })!,
1124
1138
  tokenTransactionHashes: tokenTransactionHashes?.map(hexToBytes)!,
1125
1139
  outputIds: outputIds || [],
1126
- limit: pageSize,
1127
- offset: offset,
1140
+ limit: pageSize!,
1141
+ offset: offset!,
1128
1142
  };
1129
1143
 
1130
1144
  try {
@@ -132,11 +132,16 @@ export type SigningOperator = {
132
132
  readonly identityPublicKey: string;
133
133
  };
134
134
 
135
+ /* Console logging and debug tool options */
136
+ export type ConsoleOptions = {
137
+ otel?: boolean;
138
+ };
139
+
135
140
  export type ConfigOptions = MayHaveLrc20WalletApiConfig &
136
141
  MayHaveSspClientOptions & {
137
142
  readonly network?: NetworkType;
138
143
  readonly signingOperators?: Readonly<Record<string, SigningOperator>>;
139
- readonly coodinatorIdentifier?: string;
144
+ readonly coordinatorIdentifier?: string;
140
145
  readonly frostSignerAddress?: string;
141
146
  readonly lrc20Address?: string;
142
147
  readonly threshold?: number;
@@ -148,14 +153,9 @@ export type ConfigOptions = MayHaveLrc20WalletApiConfig &
148
153
  readonly sspClientOptions?: SspClientOptions;
149
154
  readonly expectedWithdrawBondSats?: number;
150
155
  readonly expectedWithdrawRelativeBlockLocktime?: number;
156
+ readonly console?: ConsoleOptions;
151
157
  };
152
158
 
153
- const DEV_PUBKEYS = [
154
- "03acd9a5a88db102730ff83dee69d69088cc4c9d93bbee893e90fd5051b7da9651",
155
- "02d2d103cacb1d6355efeab27637c74484e2a7459e49110c3fe885210369782e23",
156
- "0350f07ffc21bfd59d31e0a7a600e2995273938444447cb9bc4c75b8a895dbb853",
157
- ];
158
-
159
159
  const PROD_PUBKEYS = [
160
160
  "03dfbdff4b6332c220f8fa2ba8ed496c698ceada563fa01b67d9983bfc5c95e763",
161
161
  "03e625e9768651c9be268e287245cc33f96a68ce9141b0b4769205db027ee8ed77",
@@ -169,7 +169,7 @@ function getLocalFrostSignerAddress(): string {
169
169
  const BASE_CONFIG: Required<ConfigOptions> = {
170
170
  network: "LOCAL",
171
171
  lrc20Address: getLrc20Url("LOCAL"),
172
- coodinatorIdentifier:
172
+ coordinatorIdentifier:
173
173
  "0000000000000000000000000000000000000000000000000000000000000001",
174
174
  frostSignerAddress: getLocalFrostSignerAddress(),
175
175
  threshold: 2,
@@ -190,6 +190,9 @@ const BASE_CONFIG: Required<ConfigOptions> = {
190
190
  identityPublicKey: getSspIdentityPublicKey("LOCAL"),
191
191
  schemaEndpoint: getSspSchemaEndpoint("LOCAL"),
192
192
  },
193
+ console: {
194
+ otel: false,
195
+ },
193
196
  };
194
197
 
195
198
  const LOCAL_WALLET_CONFIG: Required<ConfigOptions> = {
@@ -280,6 +283,12 @@ function getSigningOperators(): Record<string, SigningOperator> {
280
283
  }
281
284
 
282
285
  export function getLocalSigningOperators(): Record<string, SigningOperator> {
286
+ const addresses = Array.from({ length: 5 }, (_, i) =>
287
+ isHermeticTest
288
+ ? `https://${i}.spark.minikube.local`
289
+ : `https://localhost:${i + 8535}`,
290
+ );
291
+
283
292
  const pubkeys = [
284
293
  "0322ca18fc489ae25418a0e768273c2c61cabb823edfb14feb891e9bec62016510",
285
294
  "0341727a6c41b168f07eb50865ab8c397a53c7eef628ac1020956b705e43b6cb27",
@@ -293,35 +302,35 @@ export function getLocalSigningOperators(): Record<string, SigningOperator> {
293
302
  id: 0,
294
303
  identifier:
295
304
  "0000000000000000000000000000000000000000000000000000000000000001",
296
- address: "https://localhost:8535",
305
+ address: addresses[0]!,
297
306
  identityPublicKey: pubkeys[0]!,
298
307
  },
299
308
  "0000000000000000000000000000000000000000000000000000000000000002": {
300
309
  id: 1,
301
310
  identifier:
302
311
  "0000000000000000000000000000000000000000000000000000000000000002",
303
- address: "https://localhost:8536",
312
+ address: addresses[1]!,
304
313
  identityPublicKey: pubkeys[1]!,
305
314
  },
306
315
  "0000000000000000000000000000000000000000000000000000000000000003": {
307
316
  id: 2,
308
317
  identifier:
309
318
  "0000000000000000000000000000000000000000000000000000000000000003",
310
- address: "https://localhost:8537",
319
+ address: addresses[2]!,
311
320
  identityPublicKey: pubkeys[2]!,
312
321
  },
313
322
  "0000000000000000000000000000000000000000000000000000000000000004": {
314
323
  id: 3,
315
324
  identifier:
316
325
  "0000000000000000000000000000000000000000000000000000000000000004",
317
- address: "https://localhost:8538",
326
+ address: addresses[3]!,
318
327
  identityPublicKey: pubkeys[3]!,
319
328
  },
320
329
  "0000000000000000000000000000000000000000000000000000000000000005": {
321
330
  id: 4,
322
331
  identifier:
323
332
  "0000000000000000000000000000000000000000000000000000000000000005",
324
- address: "https://localhost:8539",
333
+ address: addresses[4]!,
325
334
  identityPublicKey: pubkeys[4]!,
326
335
  },
327
336
  };
@@ -0,0 +1,72 @@
1
+ import { SparkWallet as BaseSparkWallet } from "./spark-wallet.js";
2
+ import {
3
+ ConsoleSpanExporter,
4
+ SimpleSpanProcessor,
5
+ SpanProcessor,
6
+ WebTracerProvider,
7
+ } from "@opentelemetry/sdk-trace-web";
8
+ import { registerInstrumentations } from "@opentelemetry/instrumentation";
9
+ import { FetchInstrumentation } from "@opentelemetry/instrumentation-fetch";
10
+ import { W3CTraceContextPropagator } from "@opentelemetry/core";
11
+ import { propagation } from "@opentelemetry/api";
12
+ import { SparkWalletProps } from "../spark-wallet/types.js";
13
+ import type { ConfigOptions } from "../services/wallet-config.js";
14
+ import type { SparkSigner } from "../signer/signer.js";
15
+
16
+ export class SparkWalletBrowser extends BaseSparkWallet {
17
+ public static async initialize({
18
+ mnemonicOrSeed,
19
+ accountNumber,
20
+ signer,
21
+ options,
22
+ }: SparkWalletProps) {
23
+ const wallet = new SparkWalletBrowser(options, signer);
24
+ wallet.initializeTracer(wallet);
25
+
26
+ const initResponse = await wallet.initWallet(mnemonicOrSeed, accountNumber);
27
+
28
+ return {
29
+ wallet,
30
+ ...initResponse,
31
+ };
32
+ }
33
+
34
+ protected initializeTracerEnv({
35
+ spanProcessors,
36
+ traceUrls,
37
+ }: Parameters<BaseSparkWallet["initializeTracerEnv"]>[0]) {
38
+ initializeTracerEnvBrowser({ spanProcessors, traceUrls });
39
+ }
40
+ }
41
+
42
+ export function initializeTracerEnvBrowser({
43
+ spanProcessors,
44
+ traceUrls,
45
+ }: Parameters<BaseSparkWallet["initializeTracerEnv"]>[0]) {
46
+ const provider = new WebTracerProvider({ spanProcessors });
47
+ provider.register();
48
+
49
+ propagation.setGlobalPropagator(new W3CTraceContextPropagator());
50
+
51
+ registerInstrumentations({
52
+ instrumentations: [
53
+ new FetchInstrumentation({
54
+ ignoreUrls: [
55
+ /* Since we're wrapping global fetch we should be careful to avoid
56
+ adding headers for unrelated requests */
57
+ new RegExp(
58
+ `^(?!(${traceUrls
59
+ .map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
60
+ .join("|")}))`,
61
+ ),
62
+ ],
63
+ propagateTraceHeaderCorsUrls: /.*/,
64
+ }),
65
+ ],
66
+ });
67
+ }
68
+
69
+ export {
70
+ SparkWalletBrowser as SparkWallet,
71
+ initializeTracerEnvBrowser as initializeTracerEnv,
72
+ };
@@ -1,129 +1,71 @@
1
- import { Tracer } from "@opentelemetry/api";
2
1
  import { SparkWallet as BaseSparkWallet } from "./spark-wallet.js";
3
- import type { InitWalletResponse } from "./types.js";
4
- import { isObject } from "@lightsparkdev/core";
2
+ import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
3
+ import { AsyncLocalStorageContextManager } from "@opentelemetry/context-async-hooks";
4
+ import { W3CTraceContextPropagator } from "@opentelemetry/core";
5
+ import { registerInstrumentations } from "@opentelemetry/instrumentation";
6
+ import { UndiciInstrumentation } from "@opentelemetry/instrumentation-undici";
7
+ import {
8
+ ConsoleSpanExporter,
9
+ SimpleSpanProcessor,
10
+ } from "@opentelemetry/sdk-trace-base";
11
+ import { SparkWalletProps } from "./types.js";
5
12
 
6
- export class SparkWallet extends BaseSparkWallet {
7
- private tracer: Tracer | null = null;
13
+ export class SparkWalletNodeJS extends BaseSparkWallet {
14
+ public static async initialize({
15
+ mnemonicOrSeed,
16
+ accountNumber,
17
+ signer,
18
+ options,
19
+ }: SparkWalletProps) {
20
+ const wallet = new SparkWalletNodeJS(options, signer);
21
+ wallet.initializeTracer(wallet);
8
22
 
9
- protected wrapWithOtelSpan<A extends unknown[], R>(
10
- name: string,
11
- fn: (...args: A) => Promise<R>,
12
- ) {
13
- return async (...args: A) => {
14
- if (!this.tracer) {
15
- throw new Error("Tracer not initialized");
16
- }
23
+ const initResponse = await wallet.initWallet(mnemonicOrSeed, accountNumber);
17
24
 
18
- return await this.tracer.startActiveSpan(name, async (span) => {
19
- const traceId = span.spanContext().traceId;
20
- try {
21
- const result = await fn(...args);
22
- return result;
23
- } catch (error) {
24
- if (error instanceof Error) {
25
- error.message += ` [traceId: ${traceId}]`;
26
- } else if (isObject(error)) {
27
- error["traceId"] = traceId;
28
- }
29
- throw error;
30
- } finally {
31
- span.end();
32
- }
33
- });
25
+ return {
26
+ wallet,
27
+ ...initResponse,
34
28
  };
35
29
  }
36
30
 
37
- protected async initializeTracer(tracerName: string) {
38
- const { trace, propagation, context } = await import("@opentelemetry/api");
39
- const { W3CTraceContextPropagator } = await import("@opentelemetry/core");
40
- const { AsyncLocalStorageContextManager } = await import(
41
- "@opentelemetry/context-async-hooks"
42
- );
43
- const { BasicTracerProvider } = await import(
44
- "@opentelemetry/sdk-trace-base"
45
- );
46
-
47
- trace.setGlobalTracerProvider(new BasicTracerProvider());
48
- propagation.setGlobalPropagator(new W3CTraceContextPropagator());
49
- context.setGlobalContextManager(new AsyncLocalStorageContextManager());
50
-
51
- this.tracer = trace.getTracer(tracerName);
52
- }
53
-
54
- private getTraceName(methodName: string) {
55
- return `SparkWallet.${methodName}`;
31
+ protected initializeTracerEnv({
32
+ spanProcessors,
33
+ traceUrls,
34
+ }: Parameters<BaseSparkWallet["initializeTracerEnv"]>[0]) {
35
+ initializeTracerEnvNodeJS({ spanProcessors, traceUrls });
56
36
  }
37
+ }
57
38
 
58
- private wrapPublicMethodsWithOtelSpan<M extends keyof SparkWallet>(
59
- methodName: M,
60
- ) {
61
- const original = this[methodName];
62
-
63
- if (typeof original !== "function") {
64
- throw new Error(`Method ${methodName} is not a function on SparkWallet.`);
65
- }
66
-
67
- const wrapped = this.wrapWithOtelSpan(
68
- this.getTraceName(methodName),
69
- original.bind(this) as (...args: unknown[]) => Promise<unknown>,
70
- ) as SparkWallet[M];
71
-
72
- (this as SparkWallet)[methodName] = wrapped;
73
- }
74
-
75
- private wrapSparkWalletWithTracing() {
76
- const methods = [
77
- "getLeaves",
78
- "getIdentityPublicKey",
79
- "getSparkAddress",
80
- "createSparkPaymentIntent",
81
- "getSwapFeeEstimate",
82
- "getTransfers",
83
- "getBalance",
84
- "getSingleUseDepositAddress",
85
- "getStaticDepositAddress",
86
- "queryStaticDepositAddresses",
87
- "getClaimStaticDepositQuote",
88
- "claimStaticDeposit",
89
- "refundStaticDeposit",
90
- "getUnusedDepositAddresses",
91
- "claimDeposit",
92
- "advancedDeposit",
93
- "transfer",
94
- "createLightningInvoice",
95
- "payLightningInvoice",
96
- "getLightningSendFeeEstimate",
97
- "withdraw",
98
- "getWithdrawalFeeQuote",
99
- "getTransferFromSsp",
100
- "getTransfer",
101
- "transferTokens",
102
- "batchTransferTokens",
103
- "queryTokenTransactions",
104
- "getLightningReceiveRequest",
105
- "getLightningSendRequest",
106
- "getCoopExitRequest",
107
- "checkTimelock",
108
- "testOnly_expireTimelock",
109
- ] as const;
110
-
111
- methods.forEach((m) => this.wrapPublicMethodsWithOtelSpan(m));
112
-
113
- /* Private methods can't be indexed on `this` and need to be wrapped individually: */
114
- this.initWallet = this.wrapWithOtelSpan(
115
- this.getTraceName("initWallet"),
116
- this.initWallet.bind(this),
117
- );
118
- }
39
+ export function initializeTracerEnvNodeJS({
40
+ spanProcessors,
41
+ traceUrls,
42
+ }: Parameters<BaseSparkWallet["initializeTracerEnv"]>[0]) {
43
+ const provider = new NodeTracerProvider({ spanProcessors });
44
+ provider.register({
45
+ contextManager: new AsyncLocalStorageContextManager(),
46
+ propagator: new W3CTraceContextPropagator(),
47
+ });
119
48
 
120
- protected async initWallet(
121
- mnemonicOrSeed?: Uint8Array | string,
122
- accountNumber?: number,
123
- ): Promise<InitWalletResponse | undefined> {
124
- const res = super.initWallet(mnemonicOrSeed, accountNumber);
125
- await this.initializeTracer(this.tracerId);
126
- this.wrapSparkWalletWithTracing();
127
- return res;
128
- }
49
+ registerInstrumentations({
50
+ instrumentations: [
51
+ new UndiciInstrumentation({
52
+ ignoreRequestHook: (request) => {
53
+ /* Since we're wrapping global fetch we should be careful to avoid
54
+ adding headers or causing errors for unrelated requests */
55
+ try {
56
+ return !traceUrls.some((prefix) =>
57
+ request.origin.startsWith(prefix),
58
+ );
59
+ } catch {
60
+ return true;
61
+ }
62
+ },
63
+ }),
64
+ ],
65
+ });
129
66
  }
67
+
68
+ export {
69
+ SparkWalletNodeJS as SparkWallet,
70
+ initializeTracerEnvNodeJS as initializeTracerEnv,
71
+ };