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,362 @@
1
+ import { describe, test, expect, beforeEach, vi } from 'vitest'
2
+ import { TransactionBuilder, Networks, PrivateKey } from 'libnexa-ts'
3
+ import WalletTransactionCreator from '../../../src/wallet/transactions/WalletTransactionCreator'
4
+ import { BaseAccount } from '../../../src/wallet/accounts/interfaces/BaseAccountInterface'
5
+ import { AddressKey } from '../../../src/models/wallet.entities'
6
+
7
+ // Mock the TXUtils functions
8
+ vi.mock('../../../src/utils/TXUtils', () => ({
9
+ populateTokenAuth: vi.fn().mockResolvedValue([{} as PrivateKey]),
10
+ buildCreateGroupTransaction: vi.fn().mockResolvedValue([{} as PrivateKey]),
11
+ populateAndDuplicateTokenAuths: vi.fn().mockResolvedValue([{} as PrivateKey]),
12
+ prepareDeleteTransaction: vi.fn().mockResolvedValue([{} as PrivateKey]),
13
+ populateTokenInputsAndChange: vi.fn().mockResolvedValue([{} as PrivateKey]),
14
+ populateNexaInputsAndChange: vi.fn().mockResolvedValue([{} as PrivateKey])
15
+ }))
16
+
17
+ // Mock the rostrumProvider
18
+ vi.mock('../../../src/network/RostrumProvider', () => ({
19
+ rostrumProvider: {
20
+ getUtxo: vi.fn().mockResolvedValue({
21
+ tx_hash: 'mock-tx-hash',
22
+ amount: 1000000,
23
+ scriptpubkey: 'mock-scriptpubkey',
24
+ addresses: ['nexatest:address123']
25
+ }),
26
+ getBlockTip: vi.fn().mockResolvedValue({
27
+ height: 100000
28
+ })
29
+ }
30
+ }))
31
+
32
+ describe('WalletTransactionCreator', () => {
33
+ let creator: WalletTransactionCreator
34
+ let mockAccount: BaseAccount
35
+
36
+ beforeEach(() => {
37
+ mockAccount = {
38
+ accountKeys: {
39
+ receiveKeys: [
40
+ {
41
+ key: { privateKey: {} as PrivateKey },
42
+ address: 'nexatest:receive123',
43
+ balance: '1000000',
44
+ tokensBalance: {}
45
+ }
46
+ ],
47
+ changeKeys: [
48
+ {
49
+ key: { privateKey: {} as PrivateKey },
50
+ address: 'nexatest:change123',
51
+ balance: '500000',
52
+ tokensBalance: {}
53
+ }
54
+ ]
55
+ }
56
+ } as BaseAccount
57
+
58
+ creator = new WalletTransactionCreator(mockAccount)
59
+ })
60
+
61
+ describe('constructor', () => {
62
+ test('should create instance with account', () => {
63
+ expect(creator).toBeInstanceOf(WalletTransactionCreator)
64
+ })
65
+
66
+ test('should create instance with account and transaction builder', () => {
67
+ const txBuilder = new TransactionBuilder()
68
+ const creator = new WalletTransactionCreator(mockAccount, txBuilder)
69
+ expect(creator).toBeInstanceOf(WalletTransactionCreator)
70
+ })
71
+
72
+ test('should throw error for account without receive keys', () => {
73
+ const invalidAccount = {
74
+ accountKeys: {
75
+ receiveKeys: [],
76
+ changeKeys: []
77
+ }
78
+ } as unknown as BaseAccount
79
+
80
+ expect(() => {
81
+ new WalletTransactionCreator(invalidAccount)
82
+ }).toThrow('No receive keys available in account')
83
+ })
84
+
85
+ test('should throw error for account without account keys', () => {
86
+ const invalidAccount = {} as BaseAccount
87
+
88
+ expect(() => {
89
+ new WalletTransactionCreator(invalidAccount)
90
+ }).toThrow('Account keys are not initialized')
91
+ })
92
+ })
93
+
94
+ describe('fromAccount', () => {
95
+ test('should set account and return this for chaining', () => {
96
+ const newAccount = {
97
+ accountKeys: {
98
+ receiveKeys: [{
99
+ key: {privateKey: {} as PrivateKey},
100
+ address: 'nexatest:new123',
101
+ balance: '0',
102
+ tokensBalance: {}
103
+ }],
104
+ changeKeys: []
105
+ }
106
+ } as unknown as BaseAccount
107
+
108
+ const result = creator.fromAccount(newAccount)
109
+
110
+ expect(result).toBe(creator)
111
+ expect(creator['_account']).toBe(newAccount)
112
+ })
113
+ })
114
+
115
+ describe('parseTxHex', () => {
116
+ test('should add parse operation to builder', () => {
117
+ const hex = 'deadbeef'
118
+ const result = creator.parseTxHex(hex)
119
+
120
+ expect(result).toBe(creator)
121
+ expect(creator.builder).toHaveLength(1)
122
+ })
123
+ })
124
+
125
+ describe('parseTxBuffer', () => {
126
+ test('should add parse operation to builder', () => {
127
+ const buffer = Buffer.from('deadbeef', 'hex')
128
+ const result = creator.parseTxBuffer(buffer)
129
+
130
+ expect(result).toBe(creator)
131
+ expect(creator.builder).toHaveLength(1)
132
+ })
133
+ })
134
+
135
+ describe('mint', () => {
136
+ test('should add mint operation to builder', () => {
137
+ const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
138
+ const amount = '1000'
139
+
140
+ const result = creator.mint(token, amount)
141
+
142
+ expect(result).toBe(creator)
143
+ expect(creator.builder).toHaveLength(1)
144
+ })
145
+
146
+ test('should be chainable', () => {
147
+ const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
148
+ const amount = '1000'
149
+
150
+ const result = creator
151
+ .mint(token, amount)
152
+ .mint(token, amount)
153
+
154
+ expect(result).toBe(creator)
155
+ expect(creator.builder).toHaveLength(2)
156
+ })
157
+ })
158
+
159
+ describe('melt', () => {
160
+ test('should add melt operation to builder', () => {
161
+ const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
162
+ const amount = '1000'
163
+
164
+ const result = creator.melt(token, amount)
165
+
166
+ expect(result).toBe(creator)
167
+ expect(creator.builder).toHaveLength(1)
168
+ })
169
+
170
+ test('should be chainable', () => {
171
+ const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
172
+ const amount = '1000'
173
+
174
+ const result = creator
175
+ .melt(token, amount)
176
+ .melt(token, amount)
177
+
178
+ expect(result).toBe(creator)
179
+ expect(creator.builder).toHaveLength(2)
180
+ })
181
+ })
182
+
183
+ describe('populate', () => {
184
+ test('should add populate operation to builder', () => {
185
+ const result = creator.populate()
186
+
187
+ expect(result).toBe(creator)
188
+ expect(creator.builder).toHaveLength(1)
189
+ })
190
+
191
+ test('should validate account before populating', () => {
192
+ const invalidCreator = new WalletTransactionCreator(mockAccount)
193
+ invalidCreator['_account'] = null as any
194
+
195
+ expect(() => {
196
+ invalidCreator.populate()
197
+ }).toThrow('Account must be set before performing transactions')
198
+ })
199
+ })
200
+
201
+ describe('sign', () => {
202
+ test('should add sign operation to builder', () => {
203
+ const result = creator.sign()
204
+
205
+ expect(result).toBe(creator)
206
+ expect(creator.builder).toHaveLength(1)
207
+ })
208
+
209
+ test('should be chainable', () => {
210
+ const result = creator
211
+ .populate()
212
+ .sign()
213
+
214
+ expect(result).toBe(creator)
215
+ expect(creator.builder).toHaveLength(2)
216
+ })
217
+ })
218
+
219
+ describe('findPrivateKeyFromAddress', () => {
220
+ test('should find key for existing address', () => {
221
+ const result = creator['findPrivateKeyFromAddress']('nexatest:receive123')
222
+
223
+ expect(result).toBeDefined()
224
+ expect(result?.address).toBe('nexatest:receive123')
225
+ })
226
+
227
+ test('should find key in change addresses', () => {
228
+ const result = creator['findPrivateKeyFromAddress']('nexatest:change123')
229
+
230
+ expect(result).toBeDefined()
231
+ expect(result?.address).toBe('nexatest:change123')
232
+ })
233
+
234
+ test('should return undefined for non-existent address', () => {
235
+ const result = creator['findPrivateKeyFromAddress']('nexatest:nonexistent')
236
+
237
+ expect(result).toBeUndefined()
238
+ })
239
+ })
240
+
241
+ describe('validateAccount', () => {
242
+ test('should not throw for valid account', () => {
243
+ expect(() => {
244
+ creator['validateAccount']()
245
+ }).not.toThrow()
246
+ })
247
+
248
+ test('should throw for null account', () => {
249
+ creator['_account'] = null as any
250
+
251
+ expect(() => {
252
+ creator['validateAccount']()
253
+ }).toThrow('Account must be set before performing transactions')
254
+ })
255
+
256
+ test('should throw for account without keys', () => {
257
+ creator['_account'] = {} as BaseAccount
258
+
259
+ expect(() => {
260
+ creator['validateAccount']()
261
+ }).toThrow('Account keys are not initialized')
262
+ })
263
+
264
+ test('should throw for account without receive keys', () => {
265
+ creator['_account'] = {
266
+ accountKeys: {
267
+ receiveKeys: [],
268
+ changeKeys: []
269
+ }
270
+ } as unknown as BaseAccount
271
+
272
+ expect(() => {
273
+ creator['validateAccount']()
274
+ }).toThrow('No receive keys available in account')
275
+ })
276
+ })
277
+
278
+ describe('integration tests', () => {
279
+ test('should handle complete transaction flow', () => {
280
+ const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
281
+ const amount = '1000'
282
+ const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
283
+
284
+ const result = creator
285
+ .onNetwork('testnet')
286
+ .sendTo(toAddr, amount)
287
+ .mint(token, amount)
288
+ .populate()
289
+ .sign()
290
+
291
+ expect(result).toBe(creator)
292
+ expect(creator.builder).toHaveLength(4) // sendTo, mint, populate, sign
293
+ expect(creator.network).toBe(Networks.testnet)
294
+ })
295
+
296
+ test('should handle token operations', () => {
297
+ const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
298
+ const amount = '1000'
299
+
300
+ const result = creator
301
+ .mint(token, amount)
302
+ .melt(token, amount)
303
+ .populate()
304
+ .sign()
305
+
306
+ expect(result).toBe(creator)
307
+ expect(creator.builder).toHaveLength(4)
308
+ })
309
+
310
+ test('should handle token creation', () => {
311
+ const result = creator
312
+ .token('Test Token', 'TEST', 2, 'https://test.com', 'hash123')
313
+ .populate()
314
+ .sign()
315
+
316
+ expect(result).toBe(creator)
317
+ expect(creator.builder).toHaveLength(3)
318
+ })
319
+
320
+ test('should handle transaction parsing and signing', () => {
321
+ const hexTx = 'deadbeef'
322
+
323
+ const result = creator
324
+ .parseTxHex(hexTx)
325
+ .sign()
326
+
327
+ expect(result).toBe(creator)
328
+ expect(creator.builder).toHaveLength(2)
329
+ })
330
+ })
331
+
332
+ describe('error handling', () => {
333
+ test('should handle async errors in builder functions', async () => {
334
+ const errorFunction = vi.fn().mockRejectedValue(new Error('Test error'))
335
+ creator.builder = [errorFunction]
336
+
337
+ await expect(creator.build()).rejects.toThrow('Test error')
338
+ })
339
+
340
+ test('should handle validation errors during operations', () => {
341
+ const invalidCreator = new WalletTransactionCreator(mockAccount)
342
+ invalidCreator['_account'] = null as any
343
+
344
+ expect(() => {
345
+ invalidCreator.mint('token', '1000')
346
+ }).not.toThrow() // Error should be thrown when builder executes, not when adding to builder
347
+ })
348
+ })
349
+
350
+ describe('network handling', () => {
351
+ test('should set network correctly', () => {
352
+ const result = creator.onNetwork('testnet')
353
+
354
+ expect(result).toBe(creator)
355
+ expect(creator.network).toBe(Networks.testnet)
356
+ })
357
+
358
+ test('should default to mainnet', () => {
359
+ expect(creator.network).toBe(Networks.mainnet)
360
+ })
361
+ })
362
+ })
@@ -0,0 +1,258 @@
1
+ import { describe, test, expect, beforeEach, vi } from 'vitest'
2
+ import { TransactionBuilder, Networks } from 'libnexa-ts'
3
+ import WatchOnlyTransactionCreator from '../../../src/wallet/transactions/WatchOnlyTransactionCreator'
4
+ import { WatchOnlyAddress } from '../../../src/models/wallet.entities'
5
+
6
+ // Mock the WatchOnlyTXUtils functions
7
+ vi.mock('../../../src/utils/WatchOnlyTXUtils', () => ({
8
+ watchOnlyPopulateTokenAuth: vi.fn().mockResolvedValue(['address1']),
9
+ watchOnlyBuildCreateGroupTransaction: vi.fn().mockResolvedValue(['address2']),
10
+ watchOnlyPopulateAndDuplicateTokenAuths: vi.fn().mockResolvedValue(['address3']),
11
+ watchOnlyPrepareDeleteTransaction: vi.fn().mockResolvedValue(['address4']),
12
+ watchOnlyPopulateTokenInputsAndChange: vi.fn().mockResolvedValue(['address5']),
13
+ watchOnlyPopulateNexaInputsAndChange: vi.fn().mockResolvedValue(['address6'])
14
+ }))
15
+
16
+ describe('WatchOnlyTransactionCreator', () => {
17
+ let creator: WatchOnlyTransactionCreator
18
+ let mockAddresses: WatchOnlyAddress[]
19
+
20
+ beforeEach(() => {
21
+ mockAddresses = [
22
+ { address: 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc' },
23
+ { address: 'nexatest:nqtsq5g5dsgh6mwjchqypn8hvdrjue0xpmz293fl7rm926xv' }
24
+ ]
25
+ creator = new WatchOnlyTransactionCreator()
26
+ })
27
+
28
+ describe('constructor', () => {
29
+ test('should create instance without transaction builder', () => {
30
+ const creator = new WatchOnlyTransactionCreator()
31
+ expect(creator).toBeInstanceOf(WatchOnlyTransactionCreator)
32
+ })
33
+
34
+ test('should create instance with transaction builder', () => {
35
+ const txBuilder = new TransactionBuilder()
36
+ const creator = new WatchOnlyTransactionCreator(txBuilder)
37
+ expect(creator).toBeInstanceOf(WatchOnlyTransactionCreator)
38
+ })
39
+ })
40
+
41
+ describe('parseTxBuffer', () => {
42
+ test('should not throw error and return this for chaining', () => {
43
+ const buffer = Buffer.from('test')
44
+ const result = creator.parseTxBuffer(buffer)
45
+ expect(result).toBe(creator)
46
+ expect(creator.builder).toHaveLength(1)
47
+ })
48
+ })
49
+
50
+ describe('parseTxHex', () => {
51
+ test('should not throw error and return this for chaining', () => {
52
+ const hex = 'deadbeef'
53
+ const result = creator.parseTxHex(hex)
54
+ expect(result).toBe(creator)
55
+ expect(creator.builder).toHaveLength(1)
56
+ })
57
+ })
58
+
59
+ describe('from', () => {
60
+ test('should accept single address string', () => {
61
+ const address = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
62
+ const result = creator.onNetwork('testnet').from(address)
63
+
64
+ expect(result).toBe(creator) // Should return this for chaining
65
+ expect(creator['_availableAddresses']).toHaveLength(1)
66
+ expect(creator['_availableAddresses'][0].address).toBe(address)
67
+ })
68
+
69
+ test('should accept array of address strings', () => {
70
+ const addresses = [
71
+ 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc',
72
+ 'nexatest:nqtsq5g5dsgh6mwjchqypn8hvdrjue0xpmz293fl7rm926xv'
73
+ ]
74
+ const result = creator.onNetwork('testnet').from(addresses)
75
+
76
+ expect(result).toBe(creator)
77
+ expect(creator['_availableAddresses']).toHaveLength(2)
78
+ expect(creator['_availableAddresses'][0].address).toBe(addresses[0])
79
+ expect(creator['_availableAddresses'][1].address).toBe(addresses[1])
80
+ })
81
+
82
+ test('should accept array of WatchOnlyAddress objects', () => {
83
+ const result = creator.from(mockAddresses)
84
+
85
+ expect(result).toBe(creator)
86
+ expect(creator['_availableAddresses']).toHaveLength(2)
87
+ expect(creator['_availableAddresses'][0]).toEqual(mockAddresses[0])
88
+ expect(creator['_availableAddresses'][1]).toEqual(mockAddresses[1])
89
+ })
90
+
91
+ test('should accept single WatchOnlyAddress object', () => {
92
+ const address = mockAddresses[0]
93
+ const result = creator.from(address)
94
+
95
+ expect(result).toBe(creator)
96
+ expect(creator['_availableAddresses']).toHaveLength(1)
97
+ expect(creator['_availableAddresses'][0]).toEqual(address)
98
+ })
99
+ })
100
+
101
+ describe('mint', () => {
102
+ test('should add mint operation to builder', () => {
103
+ const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
104
+ const amount = '1000'
105
+ const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
106
+
107
+ const result = creator.mint(token, amount, toAddr)
108
+
109
+ expect(result).toBe(creator)
110
+ expect(creator.builder).toHaveLength(1)
111
+ })
112
+
113
+ test('should be chainable', () => {
114
+ const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
115
+ const amount = '1000'
116
+ const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
117
+
118
+ const result = creator
119
+ .mint(token, amount, toAddr)
120
+ .mint(token, amount, toAddr)
121
+
122
+ expect(result).toBe(creator)
123
+ expect(creator.builder).toHaveLength(2)
124
+ })
125
+ })
126
+
127
+ describe('melt', () => {
128
+ test('should add melt operation to builder', () => {
129
+ const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
130
+ const amount = '1000'
131
+ const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
132
+
133
+ const result = creator.melt(token, amount, toAddr)
134
+
135
+ expect(result).toBe(creator)
136
+ expect(creator.builder).toHaveLength(1)
137
+ })
138
+
139
+ test('should be chainable', () => {
140
+ const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
141
+ const amount = '1000'
142
+ const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
143
+
144
+ const result = creator
145
+ .melt(token, amount, toAddr)
146
+ .melt(token, amount, toAddr)
147
+
148
+ expect(result).toBe(creator)
149
+ expect(creator.builder).toHaveLength(2)
150
+ })
151
+ })
152
+
153
+ describe('populate', () => {
154
+ test('should add populate operation to builder', () => {
155
+ const result = creator.populate()
156
+
157
+ expect(result).toBe(creator)
158
+ expect(creator.builder).toHaveLength(1)
159
+ })
160
+
161
+ test('should be chainable', () => {
162
+ const result = creator
163
+ .from(mockAddresses)
164
+ .populate()
165
+
166
+ expect(result).toBe(creator)
167
+ expect(creator.builder).toHaveLength(1)
168
+ })
169
+ })
170
+
171
+ describe('integration tests', () => {
172
+ test('should handle complete transaction flow', () => {
173
+ const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
174
+ const amount = '1000'
175
+ const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
176
+
177
+ const result = creator
178
+ .onNetwork('testnet')
179
+ .from(mockAddresses)
180
+ .mint(token, amount, toAddr)
181
+ .melt(token, amount, toAddr)
182
+ .populate()
183
+
184
+ expect(result).toBe(creator)
185
+ expect(creator.builder).toHaveLength(3) // mint, melt, populate
186
+ expect(creator.network).toBe(Networks.testnet)
187
+ })
188
+
189
+ test('should handle token operations and populate', () => {
190
+ const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
191
+ const amount = '1000'
192
+ const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
193
+
194
+ const result = creator
195
+ .from(mockAddresses)
196
+ .sendTo(toAddr, amount)
197
+ .sendToToken(toAddr, amount, token)
198
+ .populate()
199
+
200
+ expect(result).toBe(creator)
201
+ expect(creator.builder).toHaveLength(3) // sendTo, sendToToken, populate
202
+ })
203
+
204
+ test('should handle token creation', () => {
205
+ const result = creator
206
+ .from(mockAddresses)
207
+ .token('Test Token', 'TEST', 2, 'https://test.com', 'hash')
208
+ .populate()
209
+
210
+ expect(result).toBe(creator)
211
+ expect(creator.builder).toHaveLength(2) // token, populate
212
+ })
213
+
214
+ test('should handle consolidate transaction', () => {
215
+ const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
216
+
217
+ const result = creator
218
+ .from(mockAddresses)
219
+ .consolidate(toAddr)
220
+ .populate()
221
+
222
+ expect(result).toBe(creator)
223
+ expect(creator.builder).toHaveLength(2) // consolidate, populate
224
+ })
225
+ })
226
+
227
+ describe('network handling', () => {
228
+ test('should set network correctly', () => {
229
+ const result = creator.onNetwork('testnet')
230
+
231
+ expect(result).toBe(creator)
232
+ expect(creator.network).toBe(Networks.testnet)
233
+ })
234
+
235
+ test('should default to mainnet', () => {
236
+ expect(creator.network).toBe(Networks.mainnet)
237
+ })
238
+ })
239
+
240
+ describe('error handling', () => {
241
+ test('should handle empty addresses array', () => {
242
+ const result = creator.from([])
243
+
244
+ expect(result).toBe(creator)
245
+ expect(creator['_availableAddresses']).toHaveLength(0)
246
+ })
247
+
248
+ test('should handle null/undefined addresses', () => {
249
+ // Test with addresses that don't have the address property
250
+ const invalidAddress = {} as WatchOnlyAddress
251
+ const result = creator.from(invalidAddress)
252
+
253
+ expect(result).toBe(creator)
254
+ // Should not add invalid addresses
255
+ expect(creator['_availableAddresses']).toHaveLength(0)
256
+ })
257
+ })
258
+ })