@buildonspark/spark-sdk 0.1.46 → 0.2.0

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 (171) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/{chunk-BGGEVUJK.js → chunk-2ENZX6LT.js} +241 -7
  3. package/dist/{chunk-LHRD2WT6.js → chunk-4JD4HIAN.js} +23 -3
  4. package/dist/{chunk-I54FARY2.js → chunk-CDLETEDT.js} +11 -3
  5. package/dist/{chunk-OBFKIEMP.js → chunk-TM6CHQXC.js} +1 -1
  6. package/dist/chunk-UDK3EBE5.js +13514 -0
  7. package/dist/chunk-XYTKKLCV.js +7 -0
  8. package/dist/{RequestLightningSendInput-2cSh_In4.d.cts → client-DKbwpcnl.d.ts} +434 -212
  9. package/dist/{RequestLightningSendInput-CN6BNg_g.d.ts → client-Drs5Lapg.d.cts} +434 -212
  10. package/dist/{services/config.cjs → debug.cjs} +31007 -1003
  11. package/dist/debug.d.cts +126 -0
  12. package/dist/debug.d.ts +126 -0
  13. package/dist/debug.js +21 -0
  14. package/dist/graphql/objects/index.d.cts +4 -11
  15. package/dist/graphql/objects/index.d.ts +4 -11
  16. package/dist/graphql/objects/index.js +2 -4
  17. package/dist/index.cjs +18219 -20818
  18. package/dist/index.d.cts +15 -768
  19. package/dist/index.d.ts +15 -768
  20. package/dist/index.js +82 -76
  21. package/dist/index.node.cjs +23831 -26538
  22. package/dist/index.node.d.cts +191 -33
  23. package/dist/index.node.d.ts +191 -33
  24. package/dist/index.node.js +87 -181
  25. package/dist/native/index.cjs +17835 -20519
  26. package/dist/native/index.d.cts +1466 -1546
  27. package/dist/native/index.d.ts +1466 -1546
  28. package/dist/native/index.js +22605 -25286
  29. package/dist/proto/lrc20.d.cts +2 -2
  30. package/dist/proto/lrc20.d.ts +2 -2
  31. package/dist/proto/lrc20.js +3098 -46
  32. package/dist/proto/spark.cjs +241 -7
  33. package/dist/proto/spark.d.cts +1 -1
  34. package/dist/proto/spark.d.ts +1 -1
  35. package/dist/proto/spark.js +5 -1
  36. package/dist/proto/spark_token.cjs +22 -2
  37. package/dist/proto/spark_token.d.cts +8 -1
  38. package/dist/proto/spark_token.d.ts +8 -1
  39. package/dist/proto/spark_token.js +2 -2
  40. package/dist/{sdk-types-CKBsylfW.d.ts → sdk-types-DCIVdKUT.d.ts} +1 -1
  41. package/dist/{sdk-types-Ct8xmN7l.d.cts → sdk-types-DJ2ve9YY.d.cts} +1 -1
  42. package/dist/{spark-DbzGfse6.d.ts → spark-BUOx3U7Q.d.cts} +103 -5
  43. package/dist/{spark-DbzGfse6.d.cts → spark-BUOx3U7Q.d.ts} +103 -5
  44. package/dist/spark-wallet-CF8Oxjqs.d.ts +935 -0
  45. package/dist/spark-wallet-DOLSa3oF.d.cts +935 -0
  46. package/dist/spark_bindings/native/index.d.cts +1 -1
  47. package/dist/spark_bindings/native/index.d.ts +1 -1
  48. package/dist/spark_bindings/wasm/index.d.cts +1 -1
  49. package/dist/spark_bindings/wasm/index.d.ts +1 -1
  50. package/dist/{services/index.cjs → tests/test-utils.cjs} +9788 -10263
  51. package/dist/tests/test-utils.d.cts +79 -0
  52. package/dist/tests/test-utils.d.ts +79 -0
  53. package/dist/tests/test-utils.js +93 -0
  54. package/dist/types/index.cjs +239 -7
  55. package/dist/types/index.d.cts +5 -9
  56. package/dist/types/index.d.ts +5 -9
  57. package/dist/types/index.js +4 -6
  58. package/dist/{types-C-Rp0Oo7.d.ts → types-BADxR3bm.d.cts} +1 -1
  59. package/dist/{types-C-Rp0Oo7.d.cts → types-BADxR3bm.d.ts} +1 -1
  60. package/dist/{index-COm59SPw.d.ts → xchain-address-C2xMs9nz.d.cts} +6 -94
  61. package/dist/{index-CKL5DodV.d.cts → xchain-address-Ckto9oEz.d.ts} +6 -94
  62. package/package.json +9 -33
  63. package/src/debug.ts +13 -0
  64. package/src/graphql/client.ts +59 -20
  65. package/src/index.node.ts +28 -2
  66. package/src/index.ts +31 -1
  67. package/src/native/index.ts +16 -2
  68. package/src/proto/mock.ts +76 -0
  69. package/src/proto/spark.ts +354 -6
  70. package/src/proto/spark_token.ts +34 -2
  71. package/src/services/config.ts +4 -6
  72. package/src/services/connection.ts +131 -64
  73. package/src/services/coop-exit.ts +6 -3
  74. package/src/services/deposit.ts +9 -8
  75. package/src/services/lightning.ts +4 -3
  76. package/src/services/signing.ts +10 -6
  77. package/src/services/token-transactions.ts +100 -85
  78. package/src/services/transfer.ts +88 -60
  79. package/src/services/tree-creation.ts +17 -9
  80. package/src/services/wallet-config.ts +17 -9
  81. package/src/signer/signer.react-native.ts +5 -10
  82. package/src/signer/signer.ts +269 -339
  83. package/src/signer/types.ts +63 -0
  84. package/src/spark-wallet/spark-wallet.ts +226 -149
  85. package/src/spark-wallet/types.ts +22 -8
  86. package/src/tests/integration/adaptor-signature.test.ts +8 -9
  87. package/src/tests/integration/coop-exit.test.ts +214 -202
  88. package/src/tests/integration/lightning.test.ts +128 -103
  89. package/src/tests/integration/swap.test.ts +116 -84
  90. package/src/tests/integration/transfer.test.ts +291 -214
  91. package/src/tests/integration/tree-creation.test.ts +0 -5
  92. package/src/tests/integration/wallet.test.ts +1 -0
  93. package/src/tests/isHermeticTest.ts +3 -24
  94. package/src/tests/{test-util.ts → test-utils.ts} +13 -11
  95. package/src/tests/token-identifier.test.ts +6 -6
  96. package/src/tests/wrapWithOtelSpan.test.ts +1 -1
  97. package/src/{address → utils}/address.ts +1 -1
  98. package/src/utils/crypto.ts +19 -9
  99. package/src/utils/index.ts +2 -0
  100. package/src/utils/network.ts +17 -0
  101. package/src/utils/secret-sharing.ts +1 -2
  102. package/src/utils/signing.ts +1 -1
  103. package/src/utils/token-identifier.ts +27 -21
  104. package/src/utils/token-transaction-validation.ts +34 -0
  105. package/src/utils/token-transactions.ts +12 -8
  106. package/src/utils/unilateral-exit.ts +32 -0
  107. package/src/utils/xchain-address.ts +1 -1
  108. package/dist/BitcoinNetwork-TnABML0T.d.cts +0 -18
  109. package/dist/BitcoinNetwork-TnABML0T.d.ts +0 -18
  110. package/dist/LightningSendFeeEstimateInput-BgOhEAI-.d.cts +0 -10
  111. package/dist/LightningSendFeeEstimateInput-BgOhEAI-.d.ts +0 -10
  112. package/dist/address/index.cjs +0 -458
  113. package/dist/address/index.d.cts +0 -32
  114. package/dist/address/index.d.ts +0 -32
  115. package/dist/address/index.js +0 -17
  116. package/dist/chunk-4EMV7HHW.js +0 -277
  117. package/dist/chunk-C2S227QR.js +0 -2336
  118. package/dist/chunk-DXR2PXJU.js +0 -1122
  119. package/dist/chunk-GSI4OLXZ.js +0 -117
  120. package/dist/chunk-HHNQ3ZHC.js +0 -170
  121. package/dist/chunk-HMLOC6TE.js +0 -14
  122. package/dist/chunk-HSCLBJEL.js +0 -113
  123. package/dist/chunk-HWJWKEIU.js +0 -75
  124. package/dist/chunk-JB64OQES.js +0 -7095
  125. package/dist/chunk-KMUMFYFX.js +0 -137
  126. package/dist/chunk-N5VZVCGJ.js +0 -622
  127. package/dist/chunk-NSJF5F5O.js +0 -325
  128. package/dist/chunk-NTFKFRQ2.js +0 -3146
  129. package/dist/chunk-OFCJFZ4I.js +0 -24
  130. package/dist/chunk-QNNSEJ4P.js +0 -232
  131. package/dist/chunk-UXDODSDT.js +0 -838
  132. package/dist/chunk-VTUGIIWI.js +0 -0
  133. package/dist/chunk-Z5HIAYFT.js +0 -84
  134. package/dist/network-Css46DAz.d.cts +0 -46
  135. package/dist/network-hynb7iTZ.d.ts +0 -46
  136. package/dist/services/config.d.cts +0 -42
  137. package/dist/services/config.d.ts +0 -42
  138. package/dist/services/config.js +0 -17
  139. package/dist/services/connection.cjs +0 -17691
  140. package/dist/services/connection.d.cts +0 -95
  141. package/dist/services/connection.d.ts +0 -95
  142. package/dist/services/connection.js +0 -11
  143. package/dist/services/index.d.cts +0 -21
  144. package/dist/services/index.d.ts +0 -21
  145. package/dist/services/index.js +0 -58
  146. package/dist/services/lrc-connection.cjs +0 -4713
  147. package/dist/services/lrc-connection.d.cts +0 -34
  148. package/dist/services/lrc-connection.d.ts +0 -34
  149. package/dist/services/lrc-connection.js +0 -11
  150. package/dist/services/token-transactions.cjs +0 -2877
  151. package/dist/services/token-transactions.d.cts +0 -75
  152. package/dist/services/token-transactions.d.ts +0 -75
  153. package/dist/services/token-transactions.js +0 -15
  154. package/dist/services/wallet-config.cjs +0 -340
  155. package/dist/services/wallet-config.d.cts +0 -56
  156. package/dist/services/wallet-config.d.ts +0 -56
  157. package/dist/services/wallet-config.js +0 -33
  158. package/dist/signer/signer.cjs +0 -2004
  159. package/dist/signer/signer.d.cts +0 -10
  160. package/dist/signer/signer.d.ts +0 -10
  161. package/dist/signer/signer.js +0 -24
  162. package/dist/signer-BP6F__oR.d.cts +0 -187
  163. package/dist/signer-BVZJXcq7.d.ts +0 -187
  164. package/dist/utils/index.cjs +0 -2947
  165. package/dist/utils/index.d.cts +0 -18
  166. package/dist/utils/index.d.ts +0 -18
  167. package/dist/utils/index.js +0 -157
  168. package/ios/spark_frost.kt +0 -1900
  169. package/src/address/index.ts +0 -1
  170. package/src/services/lrc-connection.ts +0 -215
  171. /package/dist/{chunk-L3EHBOUX.js → chunk-BYXBJQAS.js} +0 -0
@@ -1,3 +1,10 @@
1
+ import { privateAdd, privateNegate } from "@bitcoinerlab/secp256k1";
2
+ import {
3
+ fromPrivateKey,
4
+ PARITY,
5
+ Receipt,
6
+ TokenSigner,
7
+ } from "@buildonspark/lrc20-sdk";
1
8
  import {
2
9
  bytesToHex,
3
10
  bytesToNumberBE,
@@ -5,15 +12,17 @@ import {
5
12
  hexToBytes,
6
13
  } from "@noble/curves/abstract/utils";
7
14
  import { schnorr, secp256k1 } from "@noble/curves/secp256k1";
15
+ import { sha256 } from "@noble/hashes/sha2";
8
16
  import { HDKey } from "@scure/bip32";
9
17
  import { generateMnemonic, mnemonicToSeed } from "@scure/bip39";
10
18
  import { wordlist } from "@scure/bip39/wordlists/english";
19
+ import { Transaction } from "@scure/btc-signer";
20
+ import { taprootTweakPrivKey } from "@scure/btc-signer/utils";
21
+ import type { Psbt } from "bitcoinjs-lib";
11
22
  import * as ecies from "eciesjs";
12
23
  import { isReactNative } from "../constants.js";
13
24
  import { ConfigurationError, ValidationError } from "../errors/types.js";
14
- import { TreeNode } from "../proto/spark.js";
15
- import { IKeyPackage, ISigningCommitment } from "../spark_bindings/types.js";
16
- import { generateAdaptorFromSignature } from "../utils/adaptor-signature.js";
25
+ import { IKeyPackage } from "../spark_bindings/types.js";
17
26
  import { subtractPrivateKeys } from "../utils/keys.js";
18
27
  import {
19
28
  splitSecretWithProofs,
@@ -23,6 +32,17 @@ import {
23
32
  getRandomSigningNonce,
24
33
  getSigningCommitmentFromNonce,
25
34
  } from "../utils/signing.js";
35
+ import {
36
+ KeyDerivationType,
37
+ type AggregateFrostParams,
38
+ type DerivedHDKey,
39
+ type KeyDerivation,
40
+ type KeyPair,
41
+ type SignFrostParams,
42
+ type SigningCommitment,
43
+ type SigningNonce,
44
+ type SplitSecretWithProofsParams,
45
+ } from "./types.js";
26
46
 
27
47
  let sparkFrostModule: any = undefined;
28
48
  const getSparkFrostModule = async () => {
@@ -36,72 +56,11 @@ const getSparkFrostModule = async () => {
36
56
  return sparkFrostModule;
37
57
  };
38
58
 
39
- import { privateAdd, privateNegate } from "@bitcoinerlab/secp256k1";
40
- import {
41
- fromPrivateKey,
42
- PARITY,
43
- Receipt,
44
- TokenSigner,
45
- } from "@buildonspark/lrc20-sdk";
46
- import { sha256 } from "@noble/hashes/sha2";
47
- import { Transaction } from "@scure/btc-signer";
48
- import { taprootTweakPrivKey } from "@scure/btc-signer/utils";
49
- import type { Psbt } from "bitcoinjs-lib";
50
-
51
- export { Receipt, PARITY, fromPrivateKey } from "@buildonspark/lrc20-sdk";
52
- export { MultisigReceiptInput } from "@buildonspark/lrc20-sdk/lrc/types";
53
-
54
- export type SigningNonce = {
55
- binding: Uint8Array;
56
- hiding: Uint8Array;
57
- };
58
-
59
- export type SigningCommitment = {
60
- binding: Uint8Array;
61
- hiding: Uint8Array;
62
- };
63
-
64
- export type SignFrostParams = {
65
- message: Uint8Array;
66
- privateAsPubKey: Uint8Array;
67
- publicKey: Uint8Array;
68
- verifyingKey: Uint8Array;
69
- selfCommitment: ISigningCommitment;
70
- statechainCommitments?: { [key: string]: ISigningCommitment } | undefined;
71
- adaptorPubKey?: Uint8Array | undefined;
72
- };
73
-
74
- export type AggregateFrostParams = Omit<SignFrostParams, "privateAsPubKey"> & {
75
- selfSignature: Uint8Array;
76
- statechainSignatures?: { [key: string]: Uint8Array } | undefined;
77
- statechainPublicKeys?: { [key: string]: Uint8Array } | undefined;
78
- };
79
-
80
- export type SplitSecretWithProofsParams = {
81
- secret: Uint8Array;
82
- curveOrder: bigint;
83
- threshold: number;
84
- numShares: number;
85
- isSecretPubkey?: boolean;
86
- };
87
-
88
- type DerivedHDKey = {
89
- hdKey: HDKey;
90
- privateKey: Uint8Array;
91
- publicKey: Uint8Array;
92
- };
93
-
94
- type KeyPair = {
95
- privateKey: Uint8Array;
96
- publicKey: Uint8Array;
97
- };
98
-
99
59
  interface SparkKeysGenerator {
100
60
  deriveKeysFromSeed(
101
61
  seed: Uint8Array,
102
62
  accountNumber: number,
103
63
  ): Promise<{
104
- masterPublicKey: Uint8Array;
105
64
  identityKey: KeyPair;
106
65
  signingHDKey: DerivedHDKey;
107
66
  depositKey: KeyPair;
@@ -116,7 +75,6 @@ class DefaultSparkKeysGenerator implements SparkKeysGenerator {
116
75
  seed: Uint8Array,
117
76
  accountNumber: number,
118
77
  ): Promise<{
119
- masterPublicKey: Uint8Array;
120
78
  identityKey: KeyPair;
121
79
  signingHDKey: DerivedHDKey;
122
80
  depositKey: KeyPair;
@@ -155,7 +113,78 @@ class DefaultSparkKeysGenerator implements SparkKeysGenerator {
155
113
  }
156
114
 
157
115
  return {
158
- masterPublicKey: hdkey.publicKey,
116
+ identityKey: {
117
+ privateKey: identityKey.privateKey,
118
+ publicKey: identityKey.publicKey,
119
+ },
120
+ signingHDKey: {
121
+ hdKey: signingKey,
122
+ privateKey: signingKey.privateKey,
123
+ publicKey: signingKey.publicKey,
124
+ },
125
+ depositKey: {
126
+ privateKey: depositKey.privateKey,
127
+ publicKey: depositKey.publicKey,
128
+ },
129
+ staticDepositHDKey: {
130
+ hdKey: staticDepositKey,
131
+ privateKey: staticDepositKey.privateKey,
132
+ publicKey: staticDepositKey.publicKey,
133
+ },
134
+ };
135
+ }
136
+ }
137
+
138
+ class DerivationPathKeysGenerator implements SparkKeysGenerator {
139
+ constructor(private readonly derivationPathTemplate: string) {}
140
+
141
+ async deriveKeysFromSeed(
142
+ seed: Uint8Array,
143
+ accountNumber: number,
144
+ ): Promise<{
145
+ identityKey: KeyPair;
146
+ signingHDKey: DerivedHDKey;
147
+ depositKey: KeyPair;
148
+ staticDepositHDKey: DerivedHDKey;
149
+ }> {
150
+ const hdkey = HDKey.fromMasterSeed(seed);
151
+
152
+ if (!hdkey.privateKey || !hdkey.publicKey) {
153
+ throw new ValidationError("Failed to derive keys from seed", {
154
+ field: "hdkey",
155
+ value: seed,
156
+ });
157
+ }
158
+
159
+ const derivationPath = this.derivationPathTemplate.replaceAll(
160
+ "?",
161
+ accountNumber.toString(),
162
+ );
163
+
164
+ const identityKey = hdkey.derive(derivationPath);
165
+ const signingKey = hdkey.derive(`${derivationPath}/1'`);
166
+ const depositKey = hdkey.derive(`${derivationPath}/2'`);
167
+ const staticDepositKey = hdkey.derive(`${derivationPath}/3'`);
168
+
169
+ if (
170
+ !identityKey.privateKey ||
171
+ !identityKey.publicKey ||
172
+ !signingKey.privateKey ||
173
+ !signingKey.publicKey ||
174
+ !depositKey.privateKey ||
175
+ !depositKey.publicKey ||
176
+ !staticDepositKey.privateKey ||
177
+ !staticDepositKey.publicKey
178
+ ) {
179
+ throw new ValidationError(
180
+ "Failed to derive all required keys from seed",
181
+ {
182
+ field: "derivedKeys",
183
+ },
184
+ );
185
+ }
186
+
187
+ return {
159
188
  identityKey: {
160
189
  privateKey: identityKey.privateKey,
161
190
  publicKey: identityKey.publicKey,
@@ -185,7 +214,6 @@ class TaprootOutputKeysGenerator implements SparkKeysGenerator {
185
214
  seed: Uint8Array,
186
215
  accountNumber: number,
187
216
  ): Promise<{
188
- masterPublicKey: Uint8Array;
189
217
  identityKey: KeyPair;
190
218
  signingHDKey: DerivedHDKey;
191
219
  depositKey: KeyPair;
@@ -241,7 +269,6 @@ class TaprootOutputKeysGenerator implements SparkKeysGenerator {
241
269
  }
242
270
 
243
271
  return {
244
- masterPublicKey: hdkey.publicKey,
245
272
  identityKey: {
246
273
  privateKey: identityKey.privateKey,
247
274
  publicKey: identityKey.publicKey,
@@ -264,11 +291,9 @@ class TaprootOutputKeysGenerator implements SparkKeysGenerator {
264
291
  }
265
292
  }
266
293
 
267
- // TODO: Properly clean up keys when they are no longer needed
268
294
  interface SparkSigner extends TokenSigner {
269
295
  getIdentityPublicKey(): Promise<Uint8Array>;
270
296
  getDepositSigningKey(): Promise<Uint8Array>;
271
- generateStaticDepositKey(idx: number): Promise<Uint8Array>;
272
297
  getStaticDepositSigningKey(idx: number): Promise<Uint8Array>;
273
298
  getStaticDepositSecretKey(idx: number): Promise<Uint8Array>;
274
299
 
@@ -280,21 +305,35 @@ interface SparkSigner extends TokenSigner {
280
305
  accountNumber?: number,
281
306
  ): Promise<string>;
282
307
 
283
- restoreSigningKeysFromLeafs(leafs: TreeNode[]): Promise<void>;
284
- getTrackedPublicKeys(): Promise<Uint8Array[]>;
285
- // Generates a new private key, and returns the public key
286
- generatePublicKey(hash?: Uint8Array): Promise<Uint8Array>;
287
- // Called when a public key is no longer needed
288
- removePublicKey(publicKey: Uint8Array): Promise<void>;
289
- getSchnorrPublicKey(publicKey: Uint8Array): Promise<Uint8Array>;
308
+ getPublicKeyFromDerivation(
309
+ keyDerivation?: KeyDerivation,
310
+ ): Promise<Uint8Array>;
290
311
 
291
- signSchnorr(message: Uint8Array, publicKey: Uint8Array): Promise<Uint8Array>;
292
312
  signSchnorrWithIdentityKey(message: Uint8Array): Promise<Uint8Array>;
293
313
 
294
- subtractPrivateKeysGivenPublicKeys(
295
- first: Uint8Array,
296
- second: Uint8Array,
314
+ subtractPrivateKeysGivenDerivationPaths(
315
+ first: string,
316
+ second: string,
297
317
  ): Promise<Uint8Array>;
318
+
319
+ subtractAndSplitSecretWithProofsGivenDerivations(
320
+ params: Omit<SplitSecretWithProofsParams, "secret"> & {
321
+ first: KeyDerivation;
322
+ second?: KeyDerivation | undefined;
323
+ },
324
+ ): Promise<VerifiableSecretShare[]>;
325
+
326
+ subtractSplitAndEncrypt(
327
+ params: Omit<SplitSecretWithProofsParams, "secret"> & {
328
+ first: KeyDerivation;
329
+ second: KeyDerivation;
330
+ receiverPublicKey: Uint8Array;
331
+ },
332
+ ): Promise<{
333
+ shares: VerifiableSecretShare[];
334
+ secretCipher: Uint8Array;
335
+ }>;
336
+
298
337
  splitSecretWithProofs(
299
338
  params: SplitSecretWithProofsParams,
300
339
  ): Promise<VerifiableSecretShare[]>;
@@ -302,11 +341,6 @@ interface SparkSigner extends TokenSigner {
302
341
  signFrost(params: SignFrostParams): Promise<Uint8Array>;
303
342
  aggregateFrost(params: AggregateFrostParams): Promise<Uint8Array>;
304
343
 
305
- signMessageWithPublicKey(
306
- message: Uint8Array,
307
- publicKey: Uint8Array,
308
- compact?: boolean,
309
- ): Promise<Uint8Array>;
310
344
  // If compact is true, the signature should be in ecdsa compact format else it should be in DER format
311
345
  signMessageWithIdentityKey(
312
346
  message: Uint8Array,
@@ -323,34 +357,18 @@ interface SparkSigner extends TokenSigner {
323
357
  publicKey: Uint8Array,
324
358
  ): void;
325
359
 
326
- encryptLeafPrivateKeyEcies(
327
- receiverPublicKey: Uint8Array,
328
- publicKey: Uint8Array,
329
- ): Promise<Uint8Array>;
330
360
  decryptEcies(ciphertext: Uint8Array): Promise<Uint8Array>;
331
361
 
332
362
  getRandomSigningCommitment(): Promise<SigningCommitment>;
333
363
 
334
- hashRandomPrivateKey(): Promise<Uint8Array>;
335
- generateAdaptorFromSignature(signature: Uint8Array): Promise<{
336
- adaptorSignature: Uint8Array;
337
- adaptorPublicKey: Uint8Array;
338
- }>;
339
-
340
364
  getDepositSigningKey(): Promise<Uint8Array>;
341
- getMasterPublicKey(): Promise<Uint8Array>;
342
365
  }
343
366
 
344
367
  class DefaultSparkSigner implements SparkSigner {
345
- private masterPublicKey: Uint8Array | null = null;
346
368
  private identityKey: KeyPair | null = null;
347
369
  private signingKey: HDKey | null = null;
348
370
  private depositKey: KeyPair | null = null;
349
371
  private staticDepositKey: HDKey | null = null;
350
- private staticDepositKeyMap: Map<number, HDKey> = new Map();
351
-
352
- // <hex, hex>
353
- protected publicKeyToPrivateKeyMap: Map<string, string> = new Map();
354
372
 
355
373
  protected commitmentToNonceMap: Map<SigningCommitment, SigningNonce> =
356
374
  new Map();
@@ -385,48 +403,37 @@ class DefaultSparkSigner implements SparkSigner {
385
403
  return newPrivateKey;
386
404
  }
387
405
 
388
- async restoreSigningKeysFromLeafs(leafs: TreeNode[]) {
389
- if (!this.signingKey) {
390
- throw new ValidationError("Signing key is not set", {
391
- field: "signingKey",
392
- });
393
- }
394
-
395
- for (const leaf of leafs) {
396
- const hash = sha256(leaf.id);
397
- const privateKey = this.deriveSigningKey(hash);
398
-
399
- const publicKey = secp256k1.getPublicKey(privateKey);
400
- this.publicKeyToPrivateKeyMap.set(
401
- bytesToHex(publicKey),
402
- bytesToHex(privateKey),
403
- );
404
- }
405
- }
406
-
407
- async getSchnorrPublicKey(publicKey: Uint8Array): Promise<Uint8Array> {
408
- const privateKey = this.publicKeyToPrivateKeyMap.get(bytesToHex(publicKey));
409
- if (!privateKey) {
410
- throw new ValidationError("Private key is not set", {
411
- field: "privateKey",
406
+ private async decryptEciesToPrivateKey(
407
+ ciphertext: Uint8Array,
408
+ ): Promise<Uint8Array> {
409
+ if (!this.identityKey?.privateKey) {
410
+ throw new ConfigurationError("Identity key not initialized", {
411
+ configKey: "identityKey",
412
412
  });
413
413
  }
414
+ const receiverEciesPrivKey = ecies.PrivateKey.fromHex(
415
+ bytesToHex(this.identityKey.privateKey),
416
+ );
417
+ const privateKey = ecies.decrypt(receiverEciesPrivKey.toHex(), ciphertext);
414
418
 
415
- return schnorr.getPublicKey(hexToBytes(privateKey));
419
+ return privateKey;
416
420
  }
417
421
 
418
- async signSchnorr(
419
- message: Uint8Array,
420
- publicKey: Uint8Array,
422
+ protected async getSigningPrivateKeyFromDerivation(
423
+ keyDerivation: KeyDerivation,
421
424
  ): Promise<Uint8Array> {
422
- const privateKey = this.publicKeyToPrivateKeyMap.get(bytesToHex(publicKey));
423
- if (!privateKey) {
424
- throw new ValidationError("Private key is not set", {
425
- field: "privateKey",
426
- });
425
+ switch (keyDerivation.type) {
426
+ case KeyDerivationType.LEAF:
427
+ return this.deriveSigningKey(sha256(keyDerivation.path));
428
+ case KeyDerivationType.DEPOSIT:
429
+ return this.depositKey?.privateKey ?? new Uint8Array();
430
+ case KeyDerivationType.STATIC_DEPOSIT:
431
+ return this.getStaticDepositSecretKey(keyDerivation.path);
432
+ case KeyDerivationType.ECIES:
433
+ return this.decryptEciesToPrivateKey(keyDerivation.path);
434
+ case KeyDerivationType.RANDOM:
435
+ return secp256k1.utils.randomPrivateKey();
427
436
  }
428
-
429
- return schnorr.sign(message, hexToBytes(privateKey));
430
437
  }
431
438
 
432
439
  async signSchnorrWithIdentityKey(message: Uint8Array): Promise<Uint8Array> {
@@ -461,49 +468,9 @@ class DefaultSparkSigner implements SparkSigner {
461
468
  return this.depositKey.publicKey;
462
469
  }
463
470
 
464
- async generateStaticDepositKey(idx: number): Promise<Uint8Array> {
465
- if (!this.staticDepositKey?.privateKey) {
466
- throw new ValidationError("Static deposit key is not set", {
467
- field: "staticDepositKey",
468
- });
469
- }
470
-
471
- if (this.staticDepositKeyMap.has(idx)) {
472
- const staticDepositKey = this.staticDepositKeyMap.get(idx);
473
- return staticDepositKey?.publicKey!;
474
- }
475
-
476
- const staticDepositKey = this.staticDepositKey.deriveChild(
477
- HARDENED_OFFSET + idx,
478
- );
479
- this.staticDepositKeyMap.set(idx, staticDepositKey);
480
- this.publicKeyToPrivateKeyMap.set(
481
- bytesToHex(staticDepositKey.publicKey!),
482
- bytesToHex(staticDepositKey.privateKey!),
483
- );
484
- return staticDepositKey.publicKey!;
485
- }
486
-
487
471
  async getStaticDepositSigningKey(idx: number): Promise<Uint8Array> {
488
- if (!this.staticDepositKey) {
489
- throw new ValidationError("Static deposit key is not set", {
490
- field: "staticDepositKey",
491
- });
492
- }
493
-
494
- if (!this.staticDepositKeyMap.has(idx)) {
495
- await this.generateStaticDepositKey(idx);
496
- }
497
-
498
- const staticDepositKey = this.staticDepositKeyMap.get(idx);
499
-
500
- if (!staticDepositKey?.publicKey) {
501
- throw new ValidationError("Static deposit key is not set", {
502
- field: "staticDepositKey",
503
- });
504
- }
505
-
506
- return staticDepositKey.publicKey;
472
+ const staticDepositKey = await this.getStaticDepositSecretKey(idx);
473
+ return secp256k1.getPublicKey(staticDepositKey);
507
474
  }
508
475
 
509
476
  async getStaticDepositSecretKey(idx: number): Promise<Uint8Array> {
@@ -513,11 +480,9 @@ class DefaultSparkSigner implements SparkSigner {
513
480
  });
514
481
  }
515
482
 
516
- if (!this.staticDepositKeyMap.has(idx)) {
517
- await this.generateStaticDepositKey(idx);
518
- }
519
-
520
- const staticDepositKey = this.staticDepositKeyMap.get(idx);
483
+ const staticDepositKey = this.staticDepositKey.deriveChild(
484
+ HARDENED_OFFSET + idx,
485
+ );
521
486
 
522
487
  if (!staticDepositKey?.privateKey) {
523
488
  throw new ValidationError("Static deposit key is not set", {
@@ -536,72 +501,92 @@ class DefaultSparkSigner implements SparkSigner {
536
501
  return await mnemonicToSeed(mnemonic);
537
502
  }
538
503
 
539
- async getTrackedPublicKeys(): Promise<Uint8Array[]> {
540
- return Array.from(this.publicKeyToPrivateKeyMap.keys()).map(hexToBytes);
504
+ async getPublicKeyFromDerivation(
505
+ keyDerivation: KeyDerivation,
506
+ ): Promise<Uint8Array> {
507
+ const privateKey =
508
+ await this.getSigningPrivateKeyFromDerivation(keyDerivation);
509
+ return secp256k1.getPublicKey(privateKey);
541
510
  }
542
511
 
543
- async generatePublicKey(hash?: Uint8Array): Promise<Uint8Array> {
544
- if (!this.signingKey) {
545
- throw new ValidationError("Private key is not set", {
546
- field: "signingKey",
547
- });
548
- }
549
-
550
- let newPrivateKey: Uint8Array | null = null;
551
- if (hash) {
552
- newPrivateKey = this.deriveSigningKey(hash);
553
- } else {
554
- newPrivateKey = secp256k1.utils.randomPrivateKey();
555
- }
556
-
557
- if (!newPrivateKey) {
558
- throw new ValidationError("Failed to generate new private key", {
559
- field: "privateKey",
560
- });
561
- }
562
-
563
- const publicKey = secp256k1.getPublicKey(newPrivateKey);
564
- const pubKeyHex = bytesToHex(publicKey);
565
-
566
- const privKeyHex = bytesToHex(newPrivateKey);
567
- this.publicKeyToPrivateKeyMap.set(pubKeyHex, privKeyHex);
512
+ async subtractPrivateKeysGivenDerivationPaths(
513
+ first: string,
514
+ second: string,
515
+ ): Promise<Uint8Array> {
516
+ const firstPrivateKey = this.deriveSigningKey(sha256(first));
517
+ const secondPrivateKey = this.deriveSigningKey(sha256(second));
568
518
 
569
- return publicKey;
570
- }
519
+ const resultPrivKey = subtractPrivateKeys(
520
+ firstPrivateKey,
521
+ secondPrivateKey,
522
+ );
523
+ const resultPubKey = secp256k1.getPublicKey(resultPrivKey);
571
524
 
572
- async removePublicKey(publicKey: Uint8Array): Promise<void> {
573
- this.publicKeyToPrivateKeyMap.delete(bytesToHex(publicKey));
525
+ return resultPubKey;
574
526
  }
575
527
 
576
- async subtractPrivateKeysGivenPublicKeys(
577
- first: Uint8Array,
578
- second: Uint8Array,
579
- ): Promise<Uint8Array> {
580
- const firstPubKeyHex = bytesToHex(first);
581
- const secondPubKeyHex = bytesToHex(second);
528
+ async subtractAndSplitSecretWithProofsGivenDerivations({
529
+ first,
530
+ second,
531
+ curveOrder,
532
+ threshold,
533
+ numShares,
534
+ }: Omit<SplitSecretWithProofsParams, "secret"> & {
535
+ first: KeyDerivation;
536
+ second: KeyDerivation;
537
+ }): Promise<VerifiableSecretShare[]> {
538
+ const firstPrivateKey =
539
+ await this.getSigningPrivateKeyFromDerivation(first);
540
+ const secondPrivateKey =
541
+ await this.getSigningPrivateKeyFromDerivation(second);
582
542
 
583
- const firstPrivateKeyHex =
584
- this.publicKeyToPrivateKeyMap.get(firstPubKeyHex);
585
- const secondPrivateKeyHex =
586
- this.publicKeyToPrivateKeyMap.get(secondPubKeyHex);
543
+ const resultPrivKey = subtractPrivateKeys(
544
+ firstPrivateKey,
545
+ secondPrivateKey,
546
+ );
587
547
 
588
- if (!firstPrivateKeyHex || !secondPrivateKeyHex) {
589
- throw new Error("Private key is not set");
590
- }
548
+ return await this.splitSecretWithProofs({
549
+ secret: resultPrivKey,
550
+ curveOrder,
551
+ threshold,
552
+ numShares,
553
+ });
554
+ }
591
555
 
592
- const firstPrivateKey = hexToBytes(firstPrivateKeyHex);
593
- const secondPrivateKey = hexToBytes(secondPrivateKeyHex);
556
+ async subtractSplitAndEncrypt({
557
+ first,
558
+ second,
559
+ curveOrder,
560
+ threshold,
561
+ numShares,
562
+ receiverPublicKey,
563
+ }: Omit<SplitSecretWithProofsParams, "secret"> & {
564
+ first: KeyDerivation;
565
+ second: KeyDerivation;
566
+ receiverPublicKey: Uint8Array;
567
+ }): Promise<{
568
+ shares: VerifiableSecretShare[];
569
+ secretCipher: Uint8Array;
570
+ }> {
571
+ const firstPrivateKey =
572
+ await this.getSigningPrivateKeyFromDerivation(first);
573
+ const secondPrivateKey =
574
+ await this.getSigningPrivateKeyFromDerivation(second);
594
575
 
595
576
  const resultPrivKey = subtractPrivateKeys(
596
577
  firstPrivateKey,
597
578
  secondPrivateKey,
598
579
  );
599
- const resultPubKey = secp256k1.getPublicKey(resultPrivKey);
600
580
 
601
- const resultPrivKeyHex = bytesToHex(resultPrivKey);
602
- const resultPubKeyHex = bytesToHex(resultPubKey);
603
- this.publicKeyToPrivateKeyMap.set(resultPubKeyHex, resultPrivKeyHex);
604
- return resultPubKey;
581
+ return {
582
+ shares: await this.splitSecretWithProofs({
583
+ secret: resultPrivKey,
584
+ curveOrder,
585
+ threshold,
586
+ numShares,
587
+ }),
588
+ secretCipher: ecies.encrypt(receiverPublicKey, secondPrivateKey),
589
+ };
605
590
  }
606
591
 
607
592
  async splitSecretWithProofs({
@@ -609,23 +594,14 @@ class DefaultSparkSigner implements SparkSigner {
609
594
  curveOrder,
610
595
  threshold,
611
596
  numShares,
612
- isSecretPubkey = false,
613
597
  }: SplitSecretWithProofsParams): Promise<VerifiableSecretShare[]> {
614
- if (isSecretPubkey) {
615
- const pubKeyHex = bytesToHex(secret);
616
- const privateKey = this.publicKeyToPrivateKeyMap.get(pubKeyHex);
617
- if (!privateKey) {
618
- throw new Error("Private key is not set");
619
- }
620
- secret = hexToBytes(privateKey);
621
- }
622
598
  const secretAsInt = bytesToNumberBE(secret);
623
599
  return splitSecretWithProofs(secretAsInt, curveOrder, threshold, numShares);
624
600
  }
625
601
 
626
602
  async signFrost({
627
603
  message,
628
- privateAsPubKey,
604
+ keyDerivation,
629
605
  publicKey,
630
606
  verifyingKey,
631
607
  selfCommitment,
@@ -638,9 +614,9 @@ class DefaultSparkSigner implements SparkSigner {
638
614
  field: "SparkFrost",
639
615
  });
640
616
  }
641
- const privateAsPubKeyHex = bytesToHex(privateAsPubKey);
617
+
642
618
  const signingPrivateKey =
643
- this.publicKeyToPrivateKeyMap.get(privateAsPubKeyHex);
619
+ await this.getSigningPrivateKeyFromDerivation(keyDerivation);
644
620
 
645
621
  if (!signingPrivateKey) {
646
622
  throw new ValidationError("Private key not found for public key", {
@@ -656,7 +632,7 @@ class DefaultSparkSigner implements SparkSigner {
656
632
  }
657
633
 
658
634
  const keyPackage: IKeyPackage = {
659
- secretKey: hexToBytes(signingPrivateKey),
635
+ secretKey: signingPrivateKey,
660
636
  publicKey: publicKey,
661
637
  verifyingKey: verifyingKey,
662
638
  };
@@ -710,56 +686,20 @@ class DefaultSparkSigner implements SparkSigner {
710
686
  }
711
687
 
712
688
  const {
713
- masterPublicKey,
714
689
  identityKey,
715
690
  signingHDKey: signingKey,
716
691
  depositKey,
717
692
  staticDepositHDKey: staticDepositKey,
718
693
  } = await this.keysGenerator.deriveKeysFromSeed(seed, accountNumber ?? 0);
719
694
 
720
- this.masterPublicKey = masterPublicKey;
721
695
  this.identityKey = identityKey;
722
696
  this.depositKey = depositKey;
723
697
  this.signingKey = signingKey.hdKey;
724
698
  this.staticDepositKey = staticDepositKey.hdKey;
725
699
 
726
- this.publicKeyToPrivateKeyMap.set(
727
- bytesToHex(identityKey.publicKey),
728
- bytesToHex(identityKey.privateKey),
729
- );
730
- this.publicKeyToPrivateKeyMap.set(
731
- bytesToHex(depositKey.publicKey),
732
- bytesToHex(depositKey.privateKey),
733
- );
734
- this.publicKeyToPrivateKeyMap.set(
735
- bytesToHex(staticDepositKey.publicKey),
736
- bytesToHex(staticDepositKey.privateKey),
737
- );
738
700
  return bytesToHex(identityKey.publicKey);
739
701
  }
740
702
 
741
- async signMessageWithPublicKey(
742
- message: Uint8Array,
743
- publicKey: Uint8Array,
744
- compact?: boolean,
745
- ): Promise<Uint8Array> {
746
- const privateKey = this.publicKeyToPrivateKeyMap.get(bytesToHex(publicKey));
747
- if (!privateKey) {
748
- throw new ValidationError("Private key not found for public key", {
749
- field: "privateKey",
750
- value: bytesToHex(publicKey),
751
- });
752
- }
753
-
754
- const signature = secp256k1.sign(message, hexToBytes(privateKey));
755
-
756
- if (compact) {
757
- return signature.toCompactRawBytes();
758
- }
759
-
760
- return signature.toDERRawBytes();
761
- }
762
-
763
703
  async signMessageWithIdentityKey(
764
704
  message: Uint8Array,
765
705
  compact?: boolean,
@@ -779,19 +719,6 @@ class DefaultSparkSigner implements SparkSigner {
779
719
  return signature.toDERRawBytes();
780
720
  }
781
721
 
782
- async encryptLeafPrivateKeyEcies(
783
- receiverPublicKey: Uint8Array,
784
- publicKey: Uint8Array,
785
- ): Promise<Uint8Array> {
786
- const publicKeyHex = bytesToHex(publicKey);
787
- const privateKey = this.publicKeyToPrivateKeyMap.get(publicKeyHex);
788
- if (!privateKey) {
789
- throw new Error("Private key is not set");
790
- }
791
-
792
- return ecies.encrypt(receiverPublicKey, hexToBytes(privateKey));
793
- }
794
-
795
722
  async decryptEcies(ciphertext: Uint8Array): Promise<Uint8Array> {
796
723
  if (!this.identityKey?.privateKey) {
797
724
  throw new ConfigurationError("Identity key not initialized", {
@@ -803,9 +730,7 @@ class DefaultSparkSigner implements SparkSigner {
803
730
  );
804
731
  const privateKey = ecies.decrypt(receiverEciesPrivKey.toHex(), ciphertext);
805
732
  const publicKey = secp256k1.getPublicKey(privateKey);
806
- const publicKeyHex = bytesToHex(publicKey);
807
- const privateKeyHex = bytesToHex(privateKey);
808
- this.publicKeyToPrivateKeyMap.set(publicKeyHex, privateKeyHex);
733
+
809
734
  return publicKey;
810
735
  }
811
736
 
@@ -816,37 +741,6 @@ class DefaultSparkSigner implements SparkSigner {
816
741
  return commitment;
817
742
  }
818
743
 
819
- async hashRandomPrivateKey(): Promise<Uint8Array> {
820
- return sha256(secp256k1.utils.randomPrivateKey());
821
- }
822
-
823
- async generateAdaptorFromSignature(signature: Uint8Array): Promise<{
824
- adaptorSignature: Uint8Array;
825
- adaptorPublicKey: Uint8Array;
826
- }> {
827
- const adaptor = generateAdaptorFromSignature(signature);
828
-
829
- const adaptorPublicKey = secp256k1.getPublicKey(adaptor.adaptorPrivateKey);
830
-
831
- this.publicKeyToPrivateKeyMap.set(
832
- bytesToHex(adaptorPublicKey),
833
- bytesToHex(adaptor.adaptorPrivateKey),
834
- );
835
-
836
- return {
837
- adaptorSignature: signature,
838
- adaptorPublicKey: adaptorPublicKey,
839
- };
840
- }
841
-
842
- async getMasterPublicKey(): Promise<Uint8Array> {
843
- if (!this.masterPublicKey) {
844
- throw new Error("Private key is not set");
845
- }
846
-
847
- return this.masterPublicKey;
848
- }
849
-
850
744
  async validateMessageWithIdentityKey(
851
745
  message: Uint8Array,
852
746
  signature: Uint8Array,
@@ -913,10 +807,6 @@ class DefaultSparkSigner implements SparkSigner {
913
807
  equalBytes(publicKey, this.depositKey?.publicKey ?? new Uint8Array())
914
808
  ) {
915
809
  privateKey = this.depositKey?.privateKey;
916
- } else {
917
- privateKey = hexToBytes(
918
- this.publicKeyToPrivateKeyMap.get(bytesToHex(publicKey)) ?? "",
919
- );
920
810
  }
921
811
 
922
812
  if (!privateKey) {
@@ -931,10 +821,50 @@ class DefaultSparkSigner implements SparkSigner {
931
821
  }
932
822
 
933
823
  class TaprootSparkSigner extends DefaultSparkSigner {
934
- constructor() {
935
- super({ sparkKeysGenerator: new TaprootOutputKeysGenerator() });
824
+ constructor(useAddressIndex = false) {
825
+ super({
826
+ sparkKeysGenerator: new TaprootOutputKeysGenerator(useAddressIndex),
827
+ });
936
828
  }
937
829
  }
938
830
 
939
- export { DefaultSparkSigner, TaprootSparkSigner, TaprootOutputKeysGenerator };
940
- export type { SparkSigner, TokenSigner };
831
+ class NativeSegwitSparkSigner extends DefaultSparkSigner {
832
+ constructor(useAddressIndex = false) {
833
+ super({
834
+ sparkKeysGenerator: new DerivationPathKeysGenerator(
835
+ useAddressIndex ? "m/84'/0'/0'/0/?" : "m/84'/0'/?'/0/0",
836
+ ),
837
+ });
838
+ }
839
+ }
840
+
841
+ class WrappedSegwitSparkSigner extends DefaultSparkSigner {
842
+ constructor(useAddressIndex = false) {
843
+ super({
844
+ sparkKeysGenerator: new DerivationPathKeysGenerator(
845
+ useAddressIndex ? "m/49'/0'/0'/0/?" : "m/49'/0'/?'/0/0",
846
+ ),
847
+ });
848
+ }
849
+ }
850
+
851
+ class LegacyBitcoinSparkSigner extends DefaultSparkSigner {
852
+ constructor(useAddressIndex = false) {
853
+ super({
854
+ sparkKeysGenerator: new DerivationPathKeysGenerator(
855
+ useAddressIndex ? "m/44'/0'/0'/0/?" : "m/44'/0'/?'/0/0",
856
+ ),
857
+ });
858
+ }
859
+ }
860
+
861
+ export {
862
+ DefaultSparkSigner,
863
+ LegacyBitcoinSparkSigner,
864
+ NativeSegwitSparkSigner,
865
+ TaprootOutputKeysGenerator,
866
+ TaprootSparkSigner,
867
+ WrappedSegwitSparkSigner,
868
+ type SparkSigner,
869
+ type TokenSigner,
870
+ };