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,438 @@
1
+ import {
2
+ Address,
3
+ AddressType,
4
+ GroupToken,
5
+ Networkish,
6
+ Networks, Output, Script,
7
+ ScriptFactory,
8
+ Transaction,
9
+ TransactionBuilder
10
+ } from "libnexa-ts";
11
+ import {PermissionLabel, TokenAction, TxOptions} from "../../../models/transaction.entities";
12
+ import {isValidNexaAddress} from "../../../utils/WalletUtils";
13
+ import {parseInt} from "lodash-es";
14
+ import {MAX_INT64} from "../../../utils/CommonUtils";
15
+ import {rostrumProvider} from "../../../network/RostrumProvider";
16
+
17
+ /**
18
+ * Abstract base class for creating and managing transactions in the NEXA blockchain.
19
+ * Provides common functionality for transaction building including token operations,
20
+ * address validation, and output creation.
21
+ */
22
+ export abstract class TransactionCreator {
23
+
24
+ /** The underlying transaction builder instance */
25
+ private _transactionBuilder!: TransactionBuilder;
26
+ /** Set of token actions to be performed in this transaction */
27
+ private _tokens!: Set<TokenAction>;
28
+ /** Array of async functions to execute when building the transaction */
29
+ private _builder: (() => Promise<any>)[] = [];
30
+ /** Total value of NEXA being sent in this transaction */
31
+ private _totalValue: bigint = BigInt(0);
32
+ /** Network this transaction will be broadcast on */
33
+ private _network: Networkish = Networks.mainnet
34
+ /** Transaction options for customizing behavior */
35
+ private _txOptions: TxOptions = {}
36
+
37
+ /**
38
+ * Creates a new TransactionCreator instance
39
+ * @param tx Optional existing TransactionBuilder, hex string, or buffer
40
+ */
41
+ protected constructor(tx?: TransactionBuilder | string | Buffer) {
42
+ if (tx instanceof TransactionBuilder) {
43
+ this.transactionBuilder = tx;
44
+ }
45
+ this.tokens = new Set<TokenAction>()
46
+ this.transactionBuilder = new TransactionBuilder();
47
+ }
48
+
49
+ /** Parse transaction from hex string - must be implemented by subclasses */
50
+ public abstract parseTxHex(tx:string): this
51
+ /** Parse transaction from buffer - must be implemented by subclasses */
52
+ public abstract parseTxBuffer(tx: Buffer): this
53
+
54
+ /**
55
+ * Sets the network for this transaction
56
+ * @param network Network name or Networkish object
57
+ * @returns This instance for chaining
58
+ */
59
+ public onNetwork(network: string | Networkish) {
60
+ this.network = Networks.get(network)!
61
+ return this
62
+ }
63
+
64
+ /** Gets transaction options */
65
+ get txOptions(): TxOptions {
66
+ return this._txOptions;
67
+ }
68
+
69
+ /** Sets transaction options */
70
+ set txOptions(value: TxOptions) {
71
+ this._txOptions = value;
72
+ }
73
+
74
+ /** Gets the network for this transaction */
75
+ get network(): Networkish {
76
+ return this._network;
77
+ }
78
+
79
+ /** Sets the network for this transaction */
80
+ set network(value: Networkish) {
81
+ this._network = value;
82
+ }
83
+
84
+ /** Gets the builder function array */
85
+ get builder(): (() => Promise<any>)[] {
86
+ return this._builder;
87
+ }
88
+
89
+ /** Sets the builder function array */
90
+ set builder(value: (() => Promise<any>)[]) {
91
+ this._builder = value;
92
+ }
93
+
94
+ /** Gets the underlying transaction builder */
95
+ get transactionBuilder(): TransactionBuilder {
96
+ return this._transactionBuilder;
97
+ }
98
+
99
+ /** Sets the underlying transaction builder */
100
+ set transactionBuilder(value: TransactionBuilder) {
101
+ this._transactionBuilder = value;
102
+ }
103
+
104
+ /** Gets the set of token actions */
105
+ get tokens(): Set<TokenAction> {
106
+ return this._tokens;
107
+ }
108
+
109
+ /** Sets the set of token actions */
110
+ set tokens(value: Set<TokenAction>) {
111
+ this._tokens = value;
112
+ }
113
+
114
+ /** Gets the total NEXA value being sent */
115
+ get totalValue(): bigint {
116
+ return this._totalValue;
117
+ }
118
+
119
+ /** Sets the total NEXA value being sent */
120
+ set totalValue(value: bigint) {
121
+ this._totalValue = value;
122
+ }
123
+
124
+ /**
125
+ * Validates and creates a token action
126
+ * @param toAddr Destination address
127
+ * @param amount Amount to send
128
+ * @param token Token ID
129
+ * @param action Action type (mint, melt, send, etc.)
130
+ * @throws Error if validation fails
131
+ */
132
+ protected tokenAction(toAddr: string, amount: string, token: string, action: string){
133
+ // Validate destination address
134
+ if (!isValidNexaAddress(toAddr, this.network) && !isValidNexaAddress(toAddr, this.network, AddressType.PayToPublicKeyHash)) {
135
+ throw new Error('Invalid Address.');
136
+ }
137
+
138
+ // Validate amount ranges
139
+ if ((token && BigInt(amount) < 1n) || (!token && parseInt(amount) < Transaction.DUST_AMOUNT)) {
140
+ throw new Error("The amount is too low.");
141
+ }
142
+ if ((token && BigInt(amount) > MAX_INT64) || (!token && parseInt(amount) > Transaction.MAX_MONEY)) {
143
+ throw new Error("The amount is too high.");
144
+ }
145
+
146
+ // Validate token ID
147
+ if (!isValidNexaAddress(token, this.network, AddressType.GroupIdAddress)) {
148
+ throw new Error('Invalid Token ID');
149
+ }
150
+
151
+ // Ensure tokens are sent to script template addresses
152
+ if (Address.getOutputType(toAddr) === 0) {
153
+ throw new Error('Token must be sent to script template address');
154
+ }
155
+
156
+ // Add output to transaction
157
+ this.transactionBuilder.to(toAddr, Transaction.DUST_AMOUNT, token, BigInt(amount))
158
+
159
+ // Record the token action
160
+ this.tokens.add({
161
+ token: token,
162
+ amount: BigInt(amount),
163
+ action: action
164
+ })
165
+ }
166
+
167
+ /**
168
+ * Configures transaction to consolidate UTXOs to a single address
169
+ * @param toAddr Address to consolidate funds to
170
+ * @returns This instance for chaining
171
+ */
172
+ public consolidate(toAddr: string): this {
173
+ this.builder.push(async () => {
174
+ if (!isValidNexaAddress(toAddr, this.network) && !isValidNexaAddress(toAddr, this.network, AddressType.PayToPublicKeyHash)) {
175
+ throw new Error('Invalid Address.');
176
+ }
177
+ this._txOptions.isConsolidate = true
178
+ this._txOptions.toChange = toAddr
179
+ })
180
+ return this
181
+ }
182
+
183
+ /**
184
+ * Configures transaction to deduct fee from the send amount
185
+ * @returns This instance for chaining
186
+ */
187
+ public feeFromAmount(): this{
188
+ this.builder.push(async () => {
189
+ this._txOptions.feeFromAmount = true
190
+ })
191
+ return this
192
+ }
193
+
194
+ /**
195
+ * Adds a token send operation to the transaction
196
+ * @param toAddr Destination address
197
+ * @param amount Amount of tokens to send
198
+ * @param token Token ID
199
+ * @returns This instance for chaining
200
+ */
201
+ public sendToToken(toAddr: string, amount: string, token: string): this {
202
+ this.builder.push(async () => {
203
+ this.tokenAction(toAddr, amount, token, 'send')
204
+ })
205
+
206
+ return this;
207
+ }
208
+
209
+ /**
210
+ * Adds a NEXA send operation to the transaction
211
+ * @param toAddr Destination address
212
+ * @param amount Amount of NEXA to send
213
+ * @returns This instance for chaining
214
+ */
215
+ public sendTo(toAddr: string, amount: string){
216
+ this.builder.push(async () => {
217
+ if (!isValidNexaAddress(toAddr, this.network) && !isValidNexaAddress(toAddr, this.network, AddressType.PayToPublicKeyHash)) {
218
+ throw new Error('Invalid Address.');
219
+ }
220
+ this.transactionBuilder.to(toAddr, amount);
221
+ this.totalValue = BigInt(this.totalValue + amount)
222
+ })
223
+ return this;
224
+ }
225
+
226
+ /**
227
+ * Adds a token authority renewal operation
228
+ * @param token Token ID to renew authority for
229
+ * @param perms Permissions to renew
230
+ * @param toAddr
231
+ * @returns This instance for chaining
232
+ */
233
+ public renewAuthority(token: string, perms: PermissionLabel[], toAddr?: string): this {
234
+ this.builder.push(async() => {
235
+ if(toAddr != null) {
236
+ if (!isValidNexaAddress(toAddr, this.network) && !isValidNexaAddress(toAddr, this.network, AddressType.PayToPublicKeyHash)) {
237
+ throw new Error('Invalid Address.');
238
+ }
239
+ }
240
+
241
+ this.tokens.add({
242
+ token: token,
243
+ action: 'renew',
244
+ amount: BigInt(Transaction.DUST_AMOUNT),
245
+ parentToken: undefined,
246
+ extraData: {
247
+ perms: perms,
248
+ address: toAddr
249
+ }
250
+ })
251
+ })
252
+ return this
253
+ }
254
+
255
+ /**
256
+ * Adds a token authority deletion operation
257
+ * @param token Token ID to delete authority for
258
+ * @param outpoint Outpoint of the authority to delete
259
+ * @returns This instance for chaining
260
+ */
261
+ public deleteAuthority(token:string, outpoint: string): this {
262
+ this.builder.push(async () => {
263
+ this.tokens.add({
264
+ token: token,
265
+ action: 'delete',
266
+ amount: BigInt(Transaction.DUST_AMOUNT),
267
+ parentToken: undefined,
268
+ extraData: {
269
+ outpoint: outpoint
270
+ }
271
+ })
272
+ })
273
+ return this
274
+ }
275
+
276
+ /**
277
+ * Creates a legacy token (not implemented)
278
+ * @returns This instance for chaining
279
+ */
280
+ public legacyToken(name: string, ticker: string, decimals: number, docUrl: string, docHash: string): this {
281
+ this.builder.push(async () => {
282
+ const opReturn = ScriptFactory.buildTokenDescriptionLegacy(
283
+ ticker,
284
+ name,
285
+ docUrl,
286
+ docHash,
287
+ decimals
288
+ )
289
+ this.transactionBuilder.addData(opReturn, true)
290
+ this.tokens.add({
291
+ action: 'group',
292
+ amount: BigInt(Transaction.DUST_AMOUNT),
293
+ extraData: {
294
+ opReturnData: opReturn.toHex()
295
+ }
296
+ })
297
+ })
298
+ return this
299
+ }
300
+
301
+ /**
302
+ * Creates a legacy group (not implemented)
303
+ * @returns This instance for chaining
304
+ */
305
+ public legacyGroup(name: string, ticker: string, docUrl: string, docHash: string): this {
306
+ this.builder.push(async () => {
307
+ const opReturn = ScriptFactory.buildTokenDescriptionLegacy(
308
+ ticker,
309
+ name,
310
+ docUrl,
311
+ docHash,
312
+ )
313
+ this.transactionBuilder.addData(opReturn, true)
314
+ this.tokens.add({
315
+ action: 'group',
316
+ amount: BigInt(Transaction.DUST_AMOUNT),
317
+ extraData: {
318
+ opReturnData: opReturn.toHex()
319
+ }
320
+ })
321
+ })
322
+ return this
323
+ }
324
+
325
+ /**
326
+ * Creates a token with metadata
327
+ * @param name Token name
328
+ * @param ticker Token ticker symbol
329
+ * @param decimals Number of decimal places
330
+ * @param docUrl URL to token documentation
331
+ * @param docHash Hash of token documentation
332
+ * @returns This instance for chaining
333
+ */
334
+ public token(name: string, ticker: string, decimals: number, docUrl: string, docHash: string): this {
335
+ this.builder.push(async () => {
336
+ const opReturn = ScriptFactory.buildTokenDescription(
337
+ ticker,
338
+ name,
339
+ docUrl,
340
+ docHash,
341
+ decimals
342
+ )
343
+ this.transactionBuilder.addData(opReturn, true)
344
+ this.tokens.add({
345
+ action: 'group',
346
+ amount: BigInt(Transaction.DUST_AMOUNT),
347
+ extraData: {
348
+ opReturnData: opReturn.toHex()
349
+ }
350
+ })
351
+ })
352
+ return this
353
+ }
354
+
355
+ /**
356
+ * Creates an NFT collection with metadata
357
+ * @param name Collection name
358
+ * @param ticker Collection ticker symbol
359
+ * @param docUrl URL to collection documentation
360
+ * @param docHash Hash of collection documentation
361
+ * @returns This instance for chaining
362
+ */
363
+ public collection(name: string, ticker: string, docUrl: string, docHash: string): this {
364
+ this.builder.push(async () => {
365
+ const opReturn = ScriptFactory.buildNFTCollectionDescription(
366
+ ticker,
367
+ name,
368
+ docUrl,
369
+ docHash
370
+ )
371
+ this.transactionBuilder.addData(opReturn, true)
372
+ this.tokens.add({
373
+ action: 'group',
374
+ amount: BigInt(Transaction.DUST_AMOUNT),
375
+ extraData: {
376
+ opReturnData: opReturn.toHex()
377
+ }
378
+ })
379
+ })
380
+
381
+ return this
382
+ }
383
+
384
+ /**
385
+ * Creates an NFT within a collection
386
+ * @param parent Parent collection token ID
387
+ * @param zipUrl URL to NFT content ZIP file
388
+ * @param zipHash Hash of NFT content ZIP file
389
+ * @returns This instance for chaining
390
+ */
391
+ public nft(parent: string, zipUrl: string, zipHash: string) {
392
+ this.builder.push(async () => {
393
+ // add op_return for the nft
394
+ let opReturn = ScriptFactory.buildNFTDescription(zipUrl, zipHash);
395
+ this.transactionBuilder.addData(opReturn, true);
396
+ // generate subgroup ID
397
+ const subGroup = GroupToken.generateSubgroupId(parent, opReturn.toBuffer()).toString('hex')
398
+ this.tokens.add({
399
+ token: subGroup,
400
+ parentToken: parent,
401
+ amount: BigInt(Transaction.DUST_AMOUNT),
402
+ action: 'subgroup'
403
+ })
404
+ })
405
+ return this
406
+ }
407
+
408
+ /**
409
+ * Adds an OP_RETURN output to the transaction
410
+ * @param data Data to include in the OP_RETURN
411
+ * @param isFullScript Whether the data is already a complete script
412
+ * @returns This instance for chaining
413
+ */
414
+ public addOpReturn(data: Buffer | string | Script, isFullScript = false) {
415
+ this.builder.push(async () => {
416
+ let script = isFullScript ? new Script(data) : ScriptFactory.buildDataOut(data);
417
+ let output = new Output(0, script);
418
+ this.transactionBuilder.transaction.addOutput(output);
419
+ })
420
+
421
+ return this;
422
+ }
423
+
424
+ /** Populates the transaction with inputs and outputs - must be implemented by subclasses */
425
+ abstract populate(): this
426
+
427
+ /**
428
+ * Builds the transaction by executing all queued operations
429
+ * @returns Promise resolving to the serialized transaction hex
430
+ */
431
+ public async build(): Promise<string>{
432
+ for (const task of this.builder) {
433
+ await task();
434
+ }
435
+ return this.transactionBuilder.transaction.serialize(({disableAll: true}));
436
+ }
437
+
438
+ }