@buildonspark/spark-sdk 0.0.9 → 0.0.10

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 (85) hide show
  1. package/dist/services/config.d.ts +20 -16
  2. package/dist/services/config.js +26 -18
  3. package/dist/services/config.js.map +1 -1
  4. package/dist/services/connection.js +1 -1
  5. package/dist/services/connection.js.map +1 -1
  6. package/dist/services/deposit.js +2 -2
  7. package/dist/services/deposit.js.map +1 -1
  8. package/dist/services/lightning.js +4 -4
  9. package/dist/services/lightning.js.map +1 -1
  10. package/dist/services/token-transactions.js +8 -7
  11. package/dist/services/token-transactions.js.map +1 -1
  12. package/dist/services/transfer.js +12 -10
  13. package/dist/services/transfer.js.map +1 -1
  14. package/dist/spark-sdk.d.ts +2 -3
  15. package/dist/spark-sdk.js +2 -7
  16. package/dist/spark-sdk.js.map +1 -1
  17. package/dist/tests/coop-exit.test.js +8 -5
  18. package/dist/tests/coop-exit.test.js.map +1 -1
  19. package/dist/tests/deposit.test.js +8 -10
  20. package/dist/tests/deposit.test.js.map +1 -1
  21. package/dist/tests/jest.setup.d.ts +1 -0
  22. package/dist/tests/jest.setup.js +8 -0
  23. package/dist/tests/jest.setup.js.map +1 -0
  24. package/dist/tests/keys.test.js +0 -1
  25. package/dist/tests/keys.test.js.map +1 -1
  26. package/dist/tests/lightning.test.js +10 -7
  27. package/dist/tests/lightning.test.js.map +1 -1
  28. package/dist/tests/swap.test.js +8 -5
  29. package/dist/tests/swap.test.js.map +1 -1
  30. package/dist/tests/test-util.d.ts +8 -44
  31. package/dist/tests/test-util.js +10 -7
  32. package/dist/tests/test-util.js.map +1 -1
  33. package/dist/tests/transfer.test.js +30 -19
  34. package/dist/tests/transfer.test.js.map +1 -1
  35. package/package.json +2 -2
  36. package/dist/LightningSendRequest-CNJFhLVc.d.cts +0 -374
  37. package/dist/LightningSendRequest-CNJFhLVc.d.ts +0 -374
  38. package/dist/auto-bind.d.ts +0 -7
  39. package/dist/auto-bind.js +0 -41
  40. package/dist/auto-bind.js.map +0 -1
  41. package/dist/chunk-5SAJ52IV.js +0 -10309
  42. package/dist/chunk-COXVABEU.js +0 -1524
  43. package/dist/chunk-F4JW24C4.js +0 -78
  44. package/dist/chunk-H4A2WXR3.js +0 -331
  45. package/dist/chunk-HTNOFUHX.js +0 -1547
  46. package/dist/chunk-JQFHUW4I.js +0 -21
  47. package/dist/chunk-K3Y7DVLD.js +0 -19
  48. package/dist/chunk-NDKNVHGP.js +0 -127
  49. package/dist/chunk-PMVJGQCP.js +0 -627
  50. package/dist/chunk-QX3ZJH2S.js +0 -527
  51. package/dist/chunk-SL2YOBVM.js +0 -127
  52. package/dist/chunk-SWCOMKD6.js +0 -333
  53. package/dist/chunk-SWFFNBSR.js +0 -1244
  54. package/dist/chunk-WLK5POBV.js +0 -527
  55. package/dist/chunk-WZ74TD7N.js +0 -660
  56. package/dist/chunk-WZYVI3M3.js +0 -1244
  57. package/dist/chunk-ZGU3XW7W.js +0 -78
  58. package/dist/connection-BgWj7Hnd.d.cts +0 -77
  59. package/dist/connection-BgbVJtzh.d.ts +0 -77
  60. package/dist/connection-DX-9yFl8.d.ts +0 -77
  61. package/dist/connection-hITj9Mgk.d.cts +0 -77
  62. package/dist/graphql/objects/index.cjs +0 -626
  63. package/dist/graphql/objects/index.d.cts +0 -140
  64. package/dist/index.cjs +0 -17202
  65. package/dist/index.d.cts +0 -413
  66. package/dist/index.d.ts +0 -413
  67. package/dist/index.js +0 -3390
  68. package/dist/proto/spark.cjs +0 -10451
  69. package/dist/proto/spark.d.cts +0 -3
  70. package/dist/services/index.cjs +0 -12503
  71. package/dist/services/index.d.cts +0 -23
  72. package/dist/services/index.d.ts +0 -23
  73. package/dist/services/index.js +0 -17
  74. package/dist/signer/signer.cjs +0 -894
  75. package/dist/signer/signer.d.cts +0 -5
  76. package/dist/signer-BaC_ZP1g.d.ts +0 -138
  77. package/dist/signer-C6h1OnSQ.d.cts +0 -138
  78. package/dist/signer-CO4owhHI.d.ts +0 -154
  79. package/dist/signer-DDkpXvNZ.d.cts +0 -154
  80. package/dist/spark-BUTdOtMz.d.cts +0 -1170
  81. package/dist/spark-BUTdOtMz.d.ts +0 -1170
  82. package/dist/tests/test-util.cjs +0 -12269
  83. package/dist/tests/test-util.d.cts +0 -90
  84. package/dist/utils/index.cjs +0 -1825
  85. package/dist/utils/index.d.cts +0 -280
@@ -1,527 +0,0 @@
1
- import {
2
- validateResponses
3
- } from "./chunk-K3Y7DVLD.js";
4
- import {
5
- bigIntToPrivateKey,
6
- recoverSecret
7
- } from "./chunk-HTNOFUHX.js";
8
-
9
- // src/services/token-transactions.ts
10
- import {
11
- bytesToHex as bytesToHex2,
12
- bytesToNumberBE as bytesToNumberBE2,
13
- numberToBytesBE
14
- } from "@noble/curves/abstract/utils";
15
- import { secp256k1 as secp256k12 } from "@noble/curves/secp256k1";
16
-
17
- // src/utils/token-hashing.ts
18
- import { sha256 } from "@scure/btc-signer/utils";
19
- function hashTokenTransaction(tokenTransaction, partialHash = false) {
20
- if (!tokenTransaction) {
21
- throw new Error("token transaction cannot be nil");
22
- }
23
- let allHashes = [];
24
- if (tokenTransaction.tokenInput?.$case === "transferInput") {
25
- for (const leaf of tokenTransaction.tokenInput.transferInput.leavesToSpend || []) {
26
- const hashObj = sha256.create();
27
- if (leaf.prevTokenTransactionHash) {
28
- hashObj.update(leaf.prevTokenTransactionHash);
29
- }
30
- const voutBytes = new Uint8Array(4);
31
- new DataView(voutBytes.buffer).setUint32(
32
- 0,
33
- leaf.prevTokenTransactionLeafVout,
34
- false
35
- );
36
- hashObj.update(voutBytes);
37
- allHashes.push(hashObj.digest());
38
- }
39
- }
40
- if (tokenTransaction.tokenInput?.$case === "mintInput") {
41
- const hashObj = sha256.create();
42
- if (tokenTransaction.tokenInput.mintInput.issuerPublicKey) {
43
- hashObj.update(tokenTransaction.tokenInput.mintInput.issuerPublicKey);
44
- }
45
- if (tokenTransaction.tokenInput.mintInput.issuerProvidedTimestamp) {
46
- const timestampBytes = new Uint8Array(8);
47
- new DataView(timestampBytes.buffer).setBigUint64(
48
- 0,
49
- BigInt(tokenTransaction.tokenInput.mintInput.issuerProvidedTimestamp),
50
- true
51
- // true for little-endian to match Go implementation
52
- );
53
- hashObj.update(timestampBytes);
54
- }
55
- allHashes.push(hashObj.digest());
56
- }
57
- for (const leaf of tokenTransaction.outputLeaves || []) {
58
- const hashObj = sha256.create();
59
- if (leaf.id && !partialHash) {
60
- hashObj.update(new TextEncoder().encode(leaf.id));
61
- }
62
- if (leaf.ownerPublicKey) {
63
- hashObj.update(leaf.ownerPublicKey);
64
- }
65
- if (leaf.revocationPublicKey && !partialHash) {
66
- hashObj.update(leaf.revocationPublicKey);
67
- }
68
- if (leaf.withdrawBondSats && !partialHash) {
69
- const bondBytes = new Uint8Array(8);
70
- new DataView(bondBytes.buffer).setBigUint64(
71
- 0,
72
- BigInt(leaf.withdrawBondSats),
73
- false
74
- );
75
- hashObj.update(bondBytes);
76
- }
77
- if (leaf.withdrawRelativeBlockLocktime && !partialHash) {
78
- const locktimeBytes = new Uint8Array(8);
79
- new DataView(locktimeBytes.buffer).setBigUint64(
80
- 0,
81
- BigInt(leaf.withdrawRelativeBlockLocktime),
82
- false
83
- );
84
- hashObj.update(locktimeBytes);
85
- }
86
- if (leaf.tokenPublicKey) {
87
- hashObj.update(leaf.tokenPublicKey);
88
- }
89
- if (leaf.tokenAmount) {
90
- hashObj.update(leaf.tokenAmount);
91
- }
92
- allHashes.push(hashObj.digest());
93
- }
94
- const sortedPubKeys = [
95
- ...tokenTransaction.sparkOperatorIdentityPublicKeys || []
96
- ].sort((a, b) => {
97
- for (let i = 0; i < a.length && i < b.length; i++) {
98
- if (a[i] !== b[i]) return a[i] - b[i];
99
- }
100
- return a.length - b.length;
101
- });
102
- for (const pubKey of sortedPubKeys) {
103
- const hashObj = sha256.create();
104
- if (pubKey) {
105
- hashObj.update(pubKey);
106
- }
107
- allHashes.push(hashObj.digest());
108
- }
109
- const finalHashObj = sha256.create();
110
- const concatenatedHashes = new Uint8Array(
111
- allHashes.reduce((sum, hash) => sum + hash.length, 0)
112
- );
113
- let offset = 0;
114
- for (const hash of allHashes) {
115
- concatenatedHashes.set(hash, offset);
116
- offset += hash.length;
117
- }
118
- finalHashObj.update(concatenatedHashes);
119
- return finalHashObj.digest();
120
- }
121
- function hashOperatorSpecificTokenTransactionSignablePayload(payload) {
122
- if (!payload) {
123
- throw new Error("revocation keyshare signable payload cannot be nil");
124
- }
125
- let allHashes = new Uint8Array(0);
126
- const hash1 = sha256(payload.finalTokenTransactionHash || new Uint8Array(0));
127
- allHashes = concatenateUint8Arrays(allHashes, hash1);
128
- const hash2 = sha256(payload.operatorIdentityPublicKey || new Uint8Array(0));
129
- allHashes = concatenateUint8Arrays(allHashes, hash2);
130
- return sha256(allHashes);
131
- }
132
- function concatenateUint8Arrays(array1, array2) {
133
- const result = new Uint8Array(array1.length + array2.length);
134
- result.set(array1, 0);
135
- result.set(array2, array1.length);
136
- return result;
137
- }
138
-
139
- // src/utils/token-keyshares.ts
140
- import { secp256k1 } from "@noble/curves/secp256k1";
141
- function recoverPrivateKeyFromKeyshares(keyshares, threshold) {
142
- const shares = keyshares.map((keyshare) => ({
143
- fieldModulus: BigInt("0x" + secp256k1.CURVE.n.toString(16)),
144
- // secp256k1 curve order
145
- threshold,
146
- index: BigInt(keyshare.index),
147
- share: BigInt("0x" + Buffer.from(keyshare.keyshare).toString("hex")),
148
- proofs: []
149
- }));
150
- const recoveredKey = recoverSecret(shares);
151
- return bigIntToPrivateKey(recoveredKey);
152
- }
153
-
154
- // src/utils/token-transactions.ts
155
- import { bytesToHex, bytesToNumberBE } from "@noble/curves/abstract/utils";
156
- function calculateAvailableTokenAmount(outputLeaves) {
157
- return outputLeaves.reduce(
158
- (sum, leaf) => sum + BigInt(bytesToNumberBE(leaf.leaf.tokenAmount)),
159
- BigInt(0)
160
- );
161
- }
162
- function checkIfSelectedLeavesAreAvailable(selectedLeaves, tokenLeaves, tokenPublicKey) {
163
- const tokenPubKeyHex = bytesToHex(tokenPublicKey);
164
- const tokenLeavesAvailable = tokenLeaves.get(tokenPubKeyHex);
165
- if (!tokenLeavesAvailable) {
166
- return false;
167
- }
168
- if (selectedLeaves.length === 0 || tokenLeavesAvailable.length < selectedLeaves.length) {
169
- return false;
170
- }
171
- const availableLeafIds = new Set(
172
- tokenLeavesAvailable.map((leaf) => leaf.leaf.id)
173
- );
174
- for (const selectedLeaf of selectedLeaves) {
175
- if (!selectedLeaf.leaf?.id || !availableLeafIds.has(selectedLeaf.leaf.id)) {
176
- return false;
177
- }
178
- }
179
- return true;
180
- }
181
-
182
- // src/services/token-transactions.ts
183
- var TokenTransactionService = class {
184
- config;
185
- connectionManager;
186
- constructor(config, connectionManager) {
187
- this.config = config;
188
- this.connectionManager = connectionManager;
189
- }
190
- async constructTransferTokenTransaction(selectedLeaves, receiverSparkAddress, tokenPublicKey, tokenAmount) {
191
- let availableTokenAmount = calculateAvailableTokenAmount(selectedLeaves);
192
- if (availableTokenAmount === tokenAmount) {
193
- return {
194
- tokenInput: {
195
- $case: "transferInput",
196
- transferInput: {
197
- leavesToSpend: selectedLeaves.map((leaf) => ({
198
- prevTokenTransactionHash: leaf.previousTransactionHash,
199
- prevTokenTransactionLeafVout: leaf.previousTransactionVout
200
- }))
201
- }
202
- },
203
- outputLeaves: [
204
- {
205
- ownerPublicKey: receiverSparkAddress,
206
- tokenPublicKey,
207
- tokenAmount: numberToBytesBE(tokenAmount, 16)
208
- }
209
- ],
210
- sparkOperatorIdentityPublicKeys: this.collectOperatorIdentityPublicKeys()
211
- };
212
- } else {
213
- const tokenAmountDifference = availableTokenAmount - tokenAmount;
214
- return {
215
- tokenInput: {
216
- $case: "transferInput",
217
- transferInput: {
218
- leavesToSpend: selectedLeaves.map((leaf) => ({
219
- prevTokenTransactionHash: leaf.previousTransactionHash,
220
- prevTokenTransactionLeafVout: leaf.previousTransactionVout
221
- }))
222
- }
223
- },
224
- outputLeaves: [
225
- {
226
- ownerPublicKey: receiverSparkAddress,
227
- tokenPublicKey,
228
- tokenAmount: numberToBytesBE(tokenAmount, 16)
229
- },
230
- {
231
- ownerPublicKey: await this.config.signer.getIdentityPublicKey(),
232
- tokenPublicKey,
233
- tokenAmount: numberToBytesBE(tokenAmountDifference, 16)
234
- }
235
- ],
236
- sparkOperatorIdentityPublicKeys: this.collectOperatorIdentityPublicKeys()
237
- };
238
- }
239
- }
240
- collectOperatorIdentityPublicKeys() {
241
- const operatorKeys = [];
242
- for (const [_, operator] of Object.entries(
243
- this.config.getConfig().signingOperators
244
- )) {
245
- operatorKeys.push(operator.identityPublicKey);
246
- }
247
- return operatorKeys;
248
- }
249
- async broadcastTokenTransaction(tokenTransaction, leafToSpendSigningPublicKeys, leafToSpendRevocationPublicKeys) {
250
- const sparkClient = await this.connectionManager.createSparkClient(
251
- this.config.getCoordinatorAddress()
252
- );
253
- const signingOperators = this.config.getConfig().signingOperators;
254
- const partialTokenTransactionHash = hashTokenTransaction(
255
- tokenTransaction,
256
- true
257
- );
258
- const ownerSignatures = [];
259
- if (tokenTransaction.tokenInput.$case === "mintInput") {
260
- const issuerPublicKey = tokenTransaction.tokenInput.mintInput.issuerPublicKey;
261
- if (!issuerPublicKey) {
262
- throw new Error("issuer public key cannot be nil");
263
- }
264
- const ownerSignature = await this.signMessageWithKey(
265
- partialTokenTransactionHash,
266
- issuerPublicKey
267
- );
268
- ownerSignatures.push(ownerSignature);
269
- } else if (tokenTransaction.tokenInput.$case === "transferInput") {
270
- const transferInput = tokenTransaction.tokenInput.transferInput;
271
- if (!leafToSpendSigningPublicKeys || !leafToSpendRevocationPublicKeys) {
272
- throw new Error(
273
- "leafToSpendSigningPublicKeys and leafToSpendRevocationPublicKeys are required"
274
- );
275
- }
276
- for (let i = 0; i < transferInput.leavesToSpend.length; i++) {
277
- const key = leafToSpendSigningPublicKeys[i];
278
- if (!key) {
279
- throw new Error("key not found");
280
- }
281
- const ownerSignature = await this.signMessageWithKey(
282
- partialTokenTransactionHash,
283
- key
284
- );
285
- ownerSignatures.push(ownerSignature);
286
- }
287
- }
288
- const startResponse = await sparkClient.start_token_transaction({
289
- identityPublicKey: await this.config.signer.getIdentityPublicKey(),
290
- partialTokenTransaction: tokenTransaction,
291
- tokenTransactionSignatures: {
292
- ownerSignatures
293
- }
294
- });
295
- if (startResponse.keyshareInfo?.ownerIdentifiers.length !== Object.keys(signingOperators).length) {
296
- throw new Error(
297
- `Keyshare operator count (${startResponse.keyshareInfo?.ownerIdentifiers.length}) does not match signing operator count (${Object.keys(signingOperators).length})`
298
- );
299
- }
300
- for (const identifier of startResponse.keyshareInfo?.ownerIdentifiers || []) {
301
- if (!signingOperators[identifier]) {
302
- throw new Error(
303
- `Keyshare operator ${identifier} not found in signing operator list`
304
- );
305
- }
306
- }
307
- const finalTokenTransaction = startResponse.finalTokenTransaction;
308
- const finalTokenTransactionHash = hashTokenTransaction(
309
- finalTokenTransaction,
310
- false
311
- );
312
- const payload = {
313
- finalTokenTransactionHash,
314
- operatorIdentityPublicKey: await this.config.signer.getIdentityPublicKey()
315
- };
316
- const payloadHash = await hashOperatorSpecificTokenTransactionSignablePayload(payload);
317
- const operatorSpecificSignatures = [];
318
- if (tokenTransaction.tokenInput.$case === "mintInput") {
319
- const issuerPublicKey = tokenTransaction.tokenInput.mintInput.issuerPublicKey;
320
- if (!issuerPublicKey) {
321
- throw new Error("issuer public key cannot be nil");
322
- }
323
- const ownerSignature = await this.signMessageWithKey(
324
- payloadHash,
325
- issuerPublicKey
326
- );
327
- operatorSpecificSignatures.push({
328
- ownerPublicKey: issuerPublicKey,
329
- ownerSignature,
330
- payload
331
- });
332
- }
333
- if (tokenTransaction.tokenInput.$case === "transferInput") {
334
- const transferInput = tokenTransaction.tokenInput.transferInput;
335
- for (let i = 0; i < transferInput.leavesToSpend.length; i++) {
336
- let ownerSignature;
337
- if (this.config.getConfig().useTokenTransactionSchnorrSignatures) {
338
- ownerSignature = await this.config.signer.signSchnorrWithIdentityKey(payloadHash);
339
- } else {
340
- ownerSignature = await this.config.signer.signMessageWithIdentityKey(payloadHash);
341
- }
342
- operatorSpecificSignatures.push({
343
- ownerPublicKey: await this.config.signer.getIdentityPublicKey(),
344
- ownerSignature,
345
- payload
346
- });
347
- }
348
- }
349
- const soSignatures = await Promise.allSettled(
350
- Object.entries(signingOperators).map(
351
- async ([identifier, operator], index) => {
352
- const internalSparkClient = await this.connectionManager.createSparkClient(operator.address);
353
- const identityPublicKey = await this.config.signer.getIdentityPublicKey();
354
- const response = await internalSparkClient.sign_token_transaction(
355
- {
356
- finalTokenTransaction,
357
- operatorSpecificSignatures,
358
- identityPublicKey
359
- },
360
- {
361
- retry: true,
362
- retryMaxAttempts: 5
363
- }
364
- );
365
- return {
366
- index,
367
- identifier,
368
- response
369
- };
370
- }
371
- )
372
- );
373
- const threshold = startResponse.keyshareInfo.threshold;
374
- const successfulSignatures = validateResponses(soSignatures);
375
- if (tokenTransaction.tokenInput.$case === "transferInput") {
376
- const leavesToSpend = tokenTransaction.tokenInput.transferInput.leavesToSpend;
377
- let revocationKeys = [];
378
- for (let leafIndex = 0; leafIndex < leavesToSpend.length; leafIndex++) {
379
- const leafKeyshares = successfulSignatures.map(
380
- ({ identifier, response }) => ({
381
- index: parseInt(identifier, 16),
382
- keyshare: response.tokenTransactionRevocationKeyshares[leafIndex]
383
- })
384
- );
385
- if (leafKeyshares.length < threshold) {
386
- throw new Error(
387
- `Insufficient keyshares for leaf ${leafIndex}: got ${leafKeyshares.length}, need ${threshold}`
388
- );
389
- }
390
- const seenIndices = /* @__PURE__ */ new Set();
391
- for (const { index } of leafKeyshares) {
392
- if (seenIndices.has(index)) {
393
- throw new Error(
394
- `Duplicate operator index ${index} for leaf ${leafIndex}`
395
- );
396
- }
397
- seenIndices.add(index);
398
- }
399
- const recoveredPrivateKey = recoverPrivateKeyFromKeyshares(
400
- leafKeyshares,
401
- threshold
402
- );
403
- const recoveredPublicKey = secp256k12.getPublicKey(
404
- recoveredPrivateKey,
405
- true
406
- );
407
- if (!leafToSpendRevocationPublicKeys || !leafToSpendRevocationPublicKeys[leafIndex] || !recoveredPublicKey.every(
408
- (byte, i) => byte === leafToSpendRevocationPublicKeys[leafIndex][i]
409
- )) {
410
- throw new Error(
411
- `Recovered public key does not match expected revocation public key for leaf ${leafIndex}`
412
- );
413
- }
414
- revocationKeys.push(recoveredPrivateKey);
415
- }
416
- await this.finalizeTokenTransaction(
417
- finalTokenTransaction,
418
- revocationKeys,
419
- threshold
420
- );
421
- }
422
- return bytesToHex2(
423
- hashTokenTransaction(startResponse.finalTokenTransaction)
424
- );
425
- }
426
- async finalizeTokenTransaction(finalTokenTransaction, leafToSpendRevocationKeys, threshold) {
427
- const signingOperators = this.config.getConfig().signingOperators;
428
- const soResponses = await Promise.allSettled(
429
- Object.entries(signingOperators).map(async ([identifier, operator]) => {
430
- const internalSparkClient = await this.connectionManager.createSparkClient(operator.address);
431
- const identityPublicKey = await this.config.signer.getIdentityPublicKey();
432
- const response = await internalSparkClient.finalize_token_transaction(
433
- {
434
- finalTokenTransaction,
435
- leafToSpendRevocationKeys,
436
- identityPublicKey
437
- },
438
- {
439
- retry: true,
440
- retryMaxAttempts: 5
441
- }
442
- );
443
- return {
444
- identifier,
445
- response
446
- };
447
- })
448
- );
449
- validateResponses(soResponses);
450
- return finalTokenTransaction;
451
- }
452
- async fetchOwnedTokenLeaves(ownerPublicKeys, tokenPublicKeys) {
453
- const sparkClient = await this.connectionManager.createSparkClient(
454
- this.config.getCoordinatorAddress()
455
- );
456
- const result = await sparkClient.get_owned_token_leaves({
457
- ownerPublicKeys,
458
- tokenPublicKeys
459
- });
460
- return result.leavesWithPreviousTransactionData;
461
- }
462
- async syncTokenLeaves(tokenLeaves) {
463
- const unsortedTokenLeaves = await this.fetchOwnedTokenLeaves(
464
- await this.config.signer.getTrackedPublicKeys(),
465
- []
466
- );
467
- unsortedTokenLeaves.forEach((leaf) => {
468
- const tokenKey = bytesToHex2(leaf.leaf.tokenPublicKey);
469
- const index = leaf.previousTransactionVout;
470
- tokenLeaves.set(tokenKey, [{ ...leaf, previousTransactionVout: index }]);
471
- });
472
- }
473
- selectTokenLeaves(tokenLeaves, tokenAmount) {
474
- if (calculateAvailableTokenAmount(tokenLeaves) < tokenAmount) {
475
- throw new Error("Insufficient available token amount");
476
- }
477
- const exactMatch = tokenLeaves.find(
478
- (item) => bytesToNumberBE2(item.leaf.tokenAmount) === tokenAmount
479
- );
480
- if (exactMatch) {
481
- return [exactMatch];
482
- }
483
- tokenLeaves.sort(
484
- (a, b) => Number(
485
- bytesToNumberBE2(a.leaf.tokenAmount) - bytesToNumberBE2(b.leaf.tokenAmount)
486
- )
487
- );
488
- let remainingAmount = tokenAmount;
489
- const selectedLeaves = [];
490
- for (const leafInfo of tokenLeaves) {
491
- if (remainingAmount <= 0n) break;
492
- selectedLeaves.push(leafInfo);
493
- remainingAmount -= bytesToNumberBE2(leafInfo.leaf.tokenAmount);
494
- }
495
- if (remainingAmount > 0n) {
496
- throw new Error(
497
- "You do not have enough funds to complete the specified operation"
498
- );
499
- }
500
- return selectedLeaves;
501
- }
502
- // Helper function for deciding if the signer public key is the identity public key
503
- async signMessageWithKey(message, publicKey) {
504
- if (bytesToHex2(publicKey) === bytesToHex2(await this.config.signer.getIdentityPublicKey())) {
505
- if (this.config.getConfig().useTokenTransactionSchnorrSignatures) {
506
- return await this.config.signer.signSchnorrWithIdentityKey(message);
507
- } else {
508
- return await this.config.signer.signMessageWithIdentityKey(message);
509
- }
510
- } else {
511
- if (this.config.getConfig().useTokenTransactionSchnorrSignatures) {
512
- return await this.config.signer.signSchnorr(message, publicKey);
513
- } else {
514
- return await this.config.signer.signMessageWithPublicKey(
515
- message,
516
- publicKey
517
- );
518
- }
519
- }
520
- }
521
- };
522
-
523
- export {
524
- calculateAvailableTokenAmount,
525
- checkIfSelectedLeavesAreAvailable,
526
- TokenTransactionService
527
- };