nexa-wallet-sdk 0.1.2

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 (48) hide show
  1. package/.parcel-cache/3e09f086f3c4d605-AssetGraph +0 -0
  2. package/.parcel-cache/5eac57ec674cdae8-AssetGraph +0 -0
  3. package/.parcel-cache/data.mdb +0 -0
  4. package/.parcel-cache/e43547b6c9167b58-RequestGraph +0 -0
  5. package/.parcel-cache/ecfe15d74834bbfd-BundleGraph +0 -0
  6. package/.parcel-cache/lock.mdb +0 -0
  7. package/.parcel-cache/snapshot-e43547b6c9167b58.txt +2 -0
  8. package/README.md +445 -0
  9. package/dist/browser/index.js +2456 -0
  10. package/dist/browser/index.js.map +1 -0
  11. package/dist/index.d.ts +918 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +2915 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/index.mjs +2456 -0
  16. package/dist/index.mjs.map +1 -0
  17. package/package.json +90 -0
  18. package/spec.md +257 -0
  19. package/src/index.ts +93 -0
  20. package/src/models/rostrum.entities.ts +159 -0
  21. package/src/models/transaction.entities.ts +46 -0
  22. package/src/models/wallet.entities.ts +42 -0
  23. package/src/network/RostrumProvider.ts +137 -0
  24. package/src/types.ts +0 -0
  25. package/src/utils/CommonUtils.ts +123 -0
  26. package/src/utils/TXUtils.ts +445 -0
  27. package/src/utils/TokenUtils.ts +75 -0
  28. package/src/utils/ValidationUtils.ts +86 -0
  29. package/src/utils/WalletUtils.ts +522 -0
  30. package/src/utils/WatchOnlyTXUtils.ts +275 -0
  31. package/src/wallet/Wallet.ts +397 -0
  32. package/src/wallet/WatchOnlyWallet.ts +169 -0
  33. package/src/wallet/accounts/AccountStore.ts +173 -0
  34. package/src/wallet/accounts/interfaces/BaseAccountInterface.ts +56 -0
  35. package/src/wallet/accounts/models/DappAccount.ts +80 -0
  36. package/src/wallet/accounts/models/DefaultAccount.ts +96 -0
  37. package/src/wallet/accounts/models/VaultAccount.ts +81 -0
  38. package/src/wallet/transactions/WalletTransactionCreator.ts +145 -0
  39. package/src/wallet/transactions/WatchOnlyTransactionCreator.ts +189 -0
  40. package/src/wallet/transactions/interfaces/TransactionCreator.ts +438 -0
  41. package/tests/core/tx/transactioncreator.test.ts +455 -0
  42. package/tests/core/tx/wallettransactioncreator.test.ts +362 -0
  43. package/tests/core/tx/watchonlytransactioncreator.test.ts +258 -0
  44. package/tests/core/wallet/accountstore.test.ts +341 -0
  45. package/tests/core/wallet/wallet.test.ts +69 -0
  46. package/tests/core/watchonlywallet/watchonlywallet.test.ts +251 -0
  47. package/tests/index.test.ts +12 -0
  48. package/tsconfig.json +113 -0
@@ -0,0 +1,455 @@
1
+ import { describe, test, expect, beforeEach, vi } from 'vitest'
2
+ import { TransactionBuilder, Networks, Transaction } from 'libnexa-ts'
3
+ import { TransactionCreator } from '../../../src/wallet/transactions/interfaces/TransactionCreator'
4
+ import { PermissionLabel } from '../../../src/models/transaction.entities'
5
+
6
+ // Mock the rostrumProvider
7
+ vi.mock('../../../src/network/RostrumProvider', () => ({
8
+ rostrumProvider: {
9
+ broadcast: vi.fn().mockResolvedValue('txid123')
10
+ }
11
+ }))
12
+
13
+ // Mock the WalletUtils
14
+ vi.mock('../../../src/utils/WalletUtils', () => ({
15
+ isValidNexaAddress: vi.fn().mockReturnValue(true)
16
+ }))
17
+
18
+ // Create a concrete implementation of TransactionCreator for testing
19
+ class TestTransactionCreator extends TransactionCreator {
20
+ constructor(tx?: TransactionBuilder | string | Buffer) {
21
+ super(tx)
22
+ }
23
+
24
+ public parseTxHex(tx: string): this {
25
+ // Mock implementation
26
+ return this
27
+ }
28
+
29
+ public parseTxBuffer(tx: Buffer): this {
30
+ // Mock implementation
31
+ return this
32
+ }
33
+
34
+ public populate(): this {
35
+ // Mock implementation
36
+ return this
37
+ }
38
+ }
39
+
40
+ describe('TransactionCreator', () => {
41
+ let creator: TestTransactionCreator
42
+
43
+ beforeEach(() => {
44
+ creator = new TestTransactionCreator()
45
+ })
46
+
47
+ describe('constructor', () => {
48
+ test('should create instance without transaction builder', () => {
49
+ const creator = new TestTransactionCreator()
50
+ expect(creator).toBeInstanceOf(TransactionCreator)
51
+ expect(creator.network).toBe(Networks.mainnet)
52
+ expect(creator.totalValue).toBe(BigInt(0))
53
+ })
54
+
55
+ test('should create instance with transaction builder', () => {
56
+ const txBuilder = new TransactionBuilder()
57
+ const creator = new TestTransactionCreator(txBuilder)
58
+ expect(creator).toBeInstanceOf(TransactionCreator)
59
+ })
60
+ })
61
+
62
+ describe('onNetwork', () => {
63
+ test('should set network by string', () => {
64
+ const result = creator.onNetwork('testnet')
65
+ expect(result).toBe(creator)
66
+ expect(creator.network).toBe(Networks.testnet)
67
+ })
68
+
69
+ test('should set network by Networkish object', () => {
70
+ const result = creator.onNetwork(Networks.testnet)
71
+ expect(result).toBe(creator)
72
+ expect(creator.network).toBe(Networks.testnet)
73
+ })
74
+
75
+ test('should be chainable', () => {
76
+ const result = creator
77
+ .onNetwork('testnet')
78
+ .onNetwork('mainnet')
79
+ expect(result).toBe(creator)
80
+ expect(creator.network).toBe(Networks.mainnet)
81
+ })
82
+ })
83
+
84
+ describe('property getters and setters', () => {
85
+ test('should get and set txOptions', () => {
86
+ const options = { feeFromAmount: true }
87
+ creator.txOptions = options
88
+ expect(creator.txOptions).toEqual(options)
89
+ })
90
+
91
+ test('should get and set network', () => {
92
+ creator.network = Networks.testnet
93
+ expect(creator.network).toBe(Networks.testnet)
94
+ })
95
+
96
+ test('should get and set totalValue', () => {
97
+ const value = BigInt(1000)
98
+ creator.totalValue = value
99
+ expect(creator.totalValue).toBe(value)
100
+ })
101
+
102
+ test('should get and set builder', () => {
103
+ const mockFn = vi.fn()
104
+ creator.builder = [mockFn]
105
+ expect(creator.builder).toHaveLength(1)
106
+ expect(creator.builder[0]).toBe(mockFn)
107
+ })
108
+
109
+ test('should get and set tokens', () => {
110
+ const tokenAction = {
111
+ token: 'test-token',
112
+ amount: BigInt(100),
113
+ action: 'send'
114
+ }
115
+ creator.tokens.add(tokenAction)
116
+ expect(creator.tokens.size).toBe(1)
117
+ expect(creator.tokens.has(tokenAction)).toBe(true)
118
+ })
119
+ })
120
+
121
+ describe('consolidate', () => {
122
+ test('should add consolidate operation to builder', () => {
123
+ const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
124
+ const result = creator.consolidate(toAddr)
125
+
126
+ expect(result).toBe(creator)
127
+ expect(creator.builder).toHaveLength(1)
128
+ })
129
+
130
+ test('should be chainable', () => {
131
+ const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
132
+ const result = creator
133
+ .consolidate(toAddr)
134
+ .consolidate(toAddr)
135
+
136
+ expect(result).toBe(creator)
137
+ expect(creator.builder).toHaveLength(2)
138
+ })
139
+ })
140
+
141
+ describe('feeFromAmount', () => {
142
+ test('should add feeFromAmount operation to builder', () => {
143
+ const result = creator.feeFromAmount()
144
+
145
+ expect(result).toBe(creator)
146
+ expect(creator.builder).toHaveLength(1)
147
+ })
148
+
149
+ test('should be chainable', () => {
150
+ const result = creator
151
+ .feeFromAmount()
152
+ .feeFromAmount()
153
+
154
+ expect(result).toBe(creator)
155
+ expect(creator.builder).toHaveLength(2)
156
+ })
157
+ })
158
+
159
+ describe('sendToToken', () => {
160
+ test('should add token send operation to builder', () => {
161
+ const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
162
+ const amount = '1000'
163
+ const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
164
+
165
+ const result = creator.sendToToken(toAddr, amount, token)
166
+
167
+ expect(result).toBe(creator)
168
+ expect(creator.builder).toHaveLength(1)
169
+ })
170
+
171
+ test('should be chainable', () => {
172
+ const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
173
+ const amount = '1000'
174
+ const token = 'nexatest:tq8r37lcjlqazz7vuvug84q2ev50573hesrnxkv9y6hvhhl5k5qqqnmyf79mx'
175
+
176
+ const result = creator
177
+ .sendToToken(toAddr, amount, token)
178
+ .sendToToken(toAddr, amount, token)
179
+
180
+ expect(result).toBe(creator)
181
+ expect(creator.builder).toHaveLength(2)
182
+ })
183
+ })
184
+
185
+ describe('sendTo', () => {
186
+ test('should add NEXA send operation to builder', () => {
187
+ const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
188
+ const amount = '1000'
189
+
190
+ const result = creator.sendTo(toAddr, amount)
191
+
192
+ expect(result).toBe(creator)
193
+ expect(creator.builder).toHaveLength(1)
194
+ })
195
+
196
+ test('should be chainable', () => {
197
+ const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
198
+ const amount = '1000'
199
+
200
+ const result = creator
201
+ .sendTo(toAddr, amount)
202
+ .sendTo(toAddr, amount)
203
+
204
+ expect(result).toBe(creator)
205
+ expect(creator.builder).toHaveLength(2)
206
+ })
207
+ })
208
+
209
+ describe('renewAuthority', () => {
210
+ test('should add renew authority operation to builder', () => {
211
+ const token = 'nexatest:tq8r37lcjlqazz7vuvug84q2ev50573hesrnxkv9y6hvhhl5k5qqqnmyf79mx'
212
+ const perms: PermissionLabel[] = ['mint', 'melt']
213
+
214
+ const result = creator.renewAuthority(token, perms)
215
+
216
+ expect(result).toBe(creator)
217
+ expect(creator.builder).toHaveLength(1)
218
+ })
219
+
220
+ test('should add renew authority operation with address', () => {
221
+ const token = 'nexatest:tq8r37lcjlqazz7vuvug84q2ev50573hesrnxkv9y6hvhhl5k5qqqnmyf79mx'
222
+ const perms: PermissionLabel[] = ['mint', 'melt']
223
+ const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
224
+
225
+ const result = creator.renewAuthority(token, perms, toAddr)
226
+
227
+ expect(result).toBe(creator)
228
+ expect(creator.builder).toHaveLength(1)
229
+ })
230
+ })
231
+
232
+ describe('deleteAuthority', () => {
233
+ test('should add delete authority operation to builder', () => {
234
+ const token = 'nexatest:tq8r37lcjlqazz7vuvug84q2ev50573hesrnxkv9y6hvhhl5k5qqqnmyf79mx'
235
+ const outpoint = 'abc123:0'
236
+
237
+ const result = creator.deleteAuthority(token, outpoint)
238
+
239
+ expect(result).toBe(creator)
240
+ expect(creator.builder).toHaveLength(1)
241
+ })
242
+
243
+ test('should be chainable', () => {
244
+ const token = 'nexatest:tq8r37lcjlqazz7vuvug84q2ev50573hesrnxkv9y6hvhhl5k5qqqnmyf79mx'
245
+ const outpoint = 'abc123:0'
246
+
247
+ const result = creator
248
+ .deleteAuthority(token, outpoint)
249
+ .deleteAuthority(token, outpoint)
250
+
251
+ expect(result).toBe(creator)
252
+ expect(creator.builder).toHaveLength(2)
253
+ })
254
+ })
255
+
256
+ describe('legacy methods', () => {
257
+ test('legacyToken should add operation to builder', () => {
258
+ const result = creator.legacyToken('Test Token', 'TEST', 2, 'https://test.com', 'hash123')
259
+ expect(result).toBe(creator)
260
+ expect(creator.builder).toHaveLength(1)
261
+ })
262
+
263
+ test('legacyGroup should add operation to builder', () => {
264
+ const result = creator.legacyGroup('Test Group', 'TGRP', 'https://group.com', 'hash456')
265
+ expect(result).toBe(creator)
266
+ expect(creator.builder).toHaveLength(1)
267
+ })
268
+
269
+ test('should be chainable', () => {
270
+ const result = creator
271
+ .legacyToken('Test Token', 'TEST', 2, 'https://test.com', 'hash123')
272
+ .legacyGroup('Test Group', 'TGRP', 'https://group.com', 'hash456')
273
+ expect(result).toBe(creator)
274
+ expect(creator.builder).toHaveLength(2)
275
+ })
276
+ })
277
+
278
+ describe('token', () => {
279
+ test('should add token creation to builder', () => {
280
+ const result = creator.token('Test Token', 'TEST', 2, 'https://test.com', 'hash123')
281
+
282
+ expect(result).toBe(creator)
283
+ expect(creator.builder).toHaveLength(1)
284
+ })
285
+
286
+ test('should be chainable', () => {
287
+ const result = creator
288
+ .token('Test Token', 'TEST', 2, 'https://test.com', 'hash123')
289
+ .token('Test Token 2', 'TEST2', 4, 'https://test2.com', 'hash456')
290
+
291
+ expect(result).toBe(creator)
292
+ expect(creator.builder).toHaveLength(2)
293
+ })
294
+ })
295
+
296
+ describe('collection', () => {
297
+ test('should add collection creation to builder', () => {
298
+ const result = creator.collection('Test Collection', 'TCOL', 'https://collection.com', 'hash123')
299
+
300
+ expect(result).toBe(creator)
301
+ expect(creator.builder).toHaveLength(1)
302
+ })
303
+
304
+ test('should be chainable', () => {
305
+ const result = creator
306
+ .collection('Test Collection', 'TCOL', 'https://collection.com', 'hash123')
307
+ .collection('Test Collection 2', 'TCOL2', 'https://collection2.com', 'hash456')
308
+
309
+ expect(result).toBe(creator)
310
+ expect(creator.builder).toHaveLength(2)
311
+ })
312
+ })
313
+
314
+ describe('NFT', () => {
315
+ test('should add NFT creation to builder', () => {
316
+ const parent = 'nexatest:tq8r37lcjlqazz7vuvug84q2ev50573hesrnxkv9y6hvhhl5k5qqqnmyf79mx'
317
+ const result = creator.nft(parent, 'https://nft.com/content.zip', 'hash123')
318
+
319
+ expect(result).toBe(creator)
320
+ expect(creator.builder).toHaveLength(1)
321
+ })
322
+
323
+ test('should be chainable', () => {
324
+ const parent = 'nexatest:tq8r37lcjlqazz7vuvug84q2ev50573hesrnxkv9y6hvhhl5k5qqqnmyf79mx'
325
+ const result = creator
326
+ .nft(parent, 'https://nft1.com/content.zip', 'hash123')
327
+ .nft(parent, 'https://nft2.com/content.zip', 'hash456')
328
+
329
+ expect(result).toBe(creator)
330
+ expect(creator.builder).toHaveLength(2)
331
+ })
332
+ })
333
+
334
+ describe('addOpReturn', () => {
335
+ test('should add OP_RETURN with string data', () => {
336
+ const data = 'Hello World'
337
+ const result = creator.addOpReturn(data)
338
+
339
+ expect(result).toBe(creator)
340
+ expect(creator.builder).toHaveLength(1)
341
+ })
342
+
343
+ test('should add OP_RETURN with buffer data', () => {
344
+ const data = Buffer.from('Hello World')
345
+ const result = creator.addOpReturn(data)
346
+
347
+ expect(result).toBe(creator)
348
+ expect(creator.builder).toHaveLength(1)
349
+ })
350
+
351
+ test('should add OP_RETURN with full script', () => {
352
+ const data = 'Hello World'
353
+ const result = creator.addOpReturn(data, true)
354
+
355
+ expect(result).toBe(creator)
356
+ expect(creator.builder).toHaveLength(1)
357
+ })
358
+
359
+ test('should be chainable', () => {
360
+ const result = creator
361
+ .addOpReturn('Hello')
362
+ .addOpReturn('World')
363
+
364
+ expect(result).toBe(creator)
365
+ expect(creator.builder).toHaveLength(2)
366
+ })
367
+ })
368
+
369
+ describe('build', () => {
370
+ test('should execute all builder functions and return serialized transaction', async () => {
371
+ const mockFunction = vi.fn().mockResolvedValue(undefined)
372
+ creator.builder = [mockFunction]
373
+
374
+ const result = await creator.build()
375
+
376
+ expect(mockFunction).toHaveBeenCalledTimes(1)
377
+ expect(typeof result).toBe('string')
378
+ })
379
+
380
+ test('should execute multiple builder functions in order', async () => {
381
+ const mockFunction1 = vi.fn().mockResolvedValue(undefined)
382
+ const mockFunction2 = vi.fn().mockResolvedValue(undefined)
383
+ creator.builder = [mockFunction1, mockFunction2]
384
+
385
+ await creator.build()
386
+
387
+ expect(mockFunction1).toHaveBeenCalledTimes(1)
388
+ expect(mockFunction2).toHaveBeenCalledTimes(1)
389
+ })
390
+ })
391
+
392
+ describe('integration tests', () => {
393
+ test('should handle complete transaction flow', async () => {
394
+ const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
395
+ const amount = '1000'
396
+ const token = 'nexatest:tq8r37lcjlqazz7vuvug84q2ev50573hesrnxkv9y6hvhhl5k5qqqnmyf79mx'
397
+
398
+ const result = creator
399
+ .onNetwork('testnet')
400
+ .sendTo(toAddr, amount)
401
+ .sendToToken(toAddr, amount, token)
402
+ .addOpReturn('Transaction data')
403
+ .feeFromAmount()
404
+ .populate()
405
+ expect(result).toBe(creator)
406
+ expect(creator.builder).toHaveLength(4) // sendTo, sendToToken, addOpReturn, feeFromAmount (populate not called yet)
407
+ expect(creator.network).toBe(Networks.testnet)
408
+
409
+ const tx = await creator.build()
410
+ expect(typeof tx).toBe('string')
411
+ })
412
+
413
+ test('should handle token authority operations', async () => {
414
+ const token = 'nexatest:tq8r37lcjlqazz7vuvug84q2ev50573hesrnxkv9y6hvhhl5k5qqqnmyf79mx'
415
+ const perms: PermissionLabel[] = ['mint', 'melt']
416
+ const outpoint = 'abc123:0'
417
+
418
+ const result = creator
419
+ .renewAuthority(token, perms)
420
+ .deleteAuthority(token, outpoint)
421
+ .populate()
422
+
423
+ expect(result).toBe(creator)
424
+ expect(creator.builder).toHaveLength(2) // renewAuthority, deleteAuthority (populate not called yet)
425
+
426
+ const tx = await creator.build()
427
+ expect(typeof tx).toBe('string')
428
+ })
429
+
430
+ test('should handle token and collection creation', async () => {
431
+ const parent = 'nexatest:tq8r37lcjlqazz7vuvug84q2ev50573hesrnxkv9y6hvhhl5k5qqqnmyf79mx'
432
+
433
+ const result = creator
434
+ .token('Test Token', 'TEST', 2, 'https://test.com', 'hash123')
435
+ .collection('Test Collection', 'TCOL', 'https://collection.com', 'hash456')
436
+ .nft(parent, 'https://nft.com/content.zip', 'hash789')
437
+ .populate()
438
+
439
+ expect(result).toBe(creator)
440
+ expect(creator.builder).toHaveLength(3) // token, collection, NFT (populate not called yet)
441
+
442
+ const tx = await creator.build()
443
+ expect(typeof tx).toBe('string')
444
+ })
445
+ })
446
+
447
+ describe('error handling', () => {
448
+ test('should handle async errors in builder functions', async () => {
449
+ const errorFunction = vi.fn().mockRejectedValue(new Error('Test error'))
450
+ creator.builder = [errorFunction]
451
+
452
+ await expect(creator.build()).rejects.toThrow('Test error')
453
+ })
454
+ })
455
+ })