@@ -15,10 +15,12 @@ import {
15
15
DEFAULT_TX_VERSION ,
16
16
NATIVE_TOKEN_UID ,
17
17
NANO_CONTRACTS_INITIALIZE_METHOD ,
18
+ TOKEN_MINT_MASK ,
19
+ TOKEN_MELT_MASK
18
20
} from '../constants' ;
19
21
import Serializer from './serializer' ;
20
22
import HathorWallet from '../new/wallet' ;
21
- import { NanoContractTransactionError } from '../errors' ;
23
+ import { NanoContractTransactionError , UtxoError } from '../errors' ;
22
24
import {
23
25
ActionTypeToActionHeaderType ,
24
26
NanoContractActionHeader ,
@@ -196,18 +198,14 @@ class NanoContractTransactionBuilder {
196
198
* Create inputs (and maybe change outputs) to complete the deposit
197
199
*
198
200
* @param {action } Action to be completed (must be a deposit type)
199
- * @param {tokens } Array of tokens to get the token data correctly
200
201
*
201
202
* @memberof NanoContractTransactionBuilder
202
203
* @inner
203
204
*/
204
- async executeDeposit (
205
- action : NanoContractAction ,
206
- tokens : string [ ]
207
- ) : Promise < [ IDataInput [ ] , IDataOutput [ ] ] > {
205
+ async executeDeposit ( action : NanoContractAction ) : Promise < [ IDataInput [ ] , IDataOutput [ ] ] > {
208
206
if ( action . type !== NanoContractActionType . DEPOSIT ) {
209
207
throw new NanoContractTransactionError (
210
- "Can't execute a deposit with an action which type is differente than deposit."
208
+ "Can't execute a deposit with an action which type is different than deposit."
211
209
) ;
212
210
}
213
211
@@ -225,8 +223,17 @@ class NanoContractTransactionBuilder {
225
223
if ( action . address ) {
226
224
utxoOptions . filter_address = action . address ;
227
225
}
228
- const utxosData = await this . wallet . getUtxosForAmount ( action . amount , utxoOptions ) ;
229
- // XXX What if I don't have enough funds? Validate it!
226
+
227
+ let utxosData ;
228
+ try {
229
+ utxosData = await this . wallet . getUtxosForAmount ( action . amount , utxoOptions ) ;
230
+ } catch ( e ) {
231
+ if ( e instanceof UtxoError ) {
232
+ throw new NanoContractTransactionError ( 'Not enough utxos to execute the deposit.' ) ;
233
+ }
234
+
235
+ throw e ;
236
+ }
230
237
const inputs : IDataInput [ ] = [ ] ;
231
238
for ( const utxo of utxosData . utxos ) {
232
239
inputs . push ( {
@@ -266,21 +273,20 @@ class NanoContractTransactionBuilder {
266
273
* then creates the output only of the difference
267
274
*
268
275
* @param {action } Action to be completed (must be a withdrawal type)
269
- * @param {tokens } Array of tokens to get the token data correctly
270
276
*
271
277
* @memberof NanoContractTransactionBuilder
272
278
* @inner
273
279
*/
274
- executeWithdrawal ( action : NanoContractAction , tokens : string [ ] ) : IDataOutput | null {
280
+ executeWithdrawal ( action : NanoContractAction ) : IDataOutput | null {
275
281
if ( action . type !== NanoContractActionType . WITHDRAWAL ) {
276
282
throw new NanoContractTransactionError (
277
- "Can't execute a withdrawal with an action which type is differente than withdrawal."
283
+ "Can't execute a withdrawal with an action which type is different than withdrawal."
278
284
) ;
279
285
}
280
286
281
287
if ( ! action . amount || ! action . token ) {
282
288
throw new NanoContractTransactionError (
283
- 'Address, amount and token are required for withdrawal action.'
289
+ 'Amount and token are required for withdrawal action.'
284
290
) ;
285
291
}
286
292
@@ -327,6 +333,98 @@ class NanoContractTransactionBuilder {
327
333
} ;
328
334
}
329
335
336
+ /**
337
+ * Execute a grant authority action
338
+ * Create inputs (and maybe change output) to complete the action
339
+ *
340
+ * @param {action } Action to be completed (must be a grant authority type)
341
+ *
342
+ * @memberof NanoContractTransactionBuilder
343
+ * @inner
344
+ */
345
+ async executeGrantAuthority ( action : NanoContractAction ) : Promise < [ IDataInput [ ] , IDataOutput [ ] ] > {
346
+ if ( action . type !== NanoContractActionType . GRANT_AUTHORITY ) {
347
+ throw new NanoContractTransactionError (
348
+ "Can't execute a grant authority with an action which type is different than grant authority."
349
+ ) ;
350
+ }
351
+
352
+ if ( ! action . authority || ! action . token ) {
353
+ throw new NanoContractTransactionError ( 'Authority and token are required for grant authority action.' ) ;
354
+ }
355
+
356
+ const authorityAddressParam = action . authorityAddress ;
357
+ if ( authorityAddressParam && ! ( await this . wallet . isAddressMine ( authorityAddressParam ) ) ) {
358
+ throw new NanoContractTransactionError ( 'Authority address must belong to the same wallet.' ) ;
359
+ }
360
+
361
+ // Get the utxos with the authority of the action and create the input
362
+ const utxos = await this . wallet . getAuthorityUtxo ( action . token , action . authority , { many : false , only_available_utxos : true , filter_address : action . address } ) ;
363
+
364
+ if ( ! utxos || utxos . length === 0 ) {
365
+ throw new NanoContractTransactionError ( 'Not enough authority utxos to execute the grant authority.' ) ;
366
+ }
367
+
368
+ const inputs : IDataInput [ ] = [ ] ;
369
+ // The method gets only one utxo
370
+ const utxo = utxos [ 0 ] ;
371
+ inputs . push ( {
372
+ txId : utxo . txId ,
373
+ index : utxo . index ,
374
+ value : utxo . value ,
375
+ authorities : utxo . authorities ,
376
+ token : utxo . token ,
377
+ address : utxo . address ,
378
+ } ) ;
379
+
380
+ const outputs : IDataOutput [ ] = [ ] ;
381
+ // If there's the authorityAddress param, then we must create another authority output for this address
382
+ if ( action . authorityAddress ) {
383
+ outputs . push ( {
384
+ type : getAddressType ( action . authorityAddress , this . wallet . getNetworkObject ( ) ) ,
385
+ address : action . authorityAddress ,
386
+ value : action . authority === 'mint' ? TOKEN_MINT_MASK : TOKEN_MELT_MASK ,
387
+ timelock : null ,
388
+ token : action . token ,
389
+ authorities : action . authority === 'mint' ? 1n : 2n ,
390
+ } ) ;
391
+ }
392
+
393
+ return [ inputs , outputs ] ;
394
+ }
395
+
396
+ /**
397
+ * Execute an invoke authority action
398
+ *
399
+ * @param {action } Action to be completed (must be an invoke authority type)
400
+ *
401
+ * @memberof NanoContractTransactionBuilder
402
+ * @inner
403
+ */
404
+ executeInvokeAuthority ( action : NanoContractAction ) : IDataOutput | null {
405
+ if ( action . type !== NanoContractActionType . INVOKE_AUTHORITY ) {
406
+ throw new NanoContractTransactionError (
407
+ "Can't execute an invoke authority with an action which type is different than invoke authority."
408
+ ) ;
409
+ }
410
+
411
+ if ( ! action . address || ! action . authority || ! action . token ) {
412
+ throw new NanoContractTransactionError (
413
+ 'Address, authority, and token are required for invoke authority action.'
414
+ ) ;
415
+ }
416
+
417
+ // Create the output with the authority of the action
418
+ return {
419
+ type : getAddressType ( action . address , this . wallet . getNetworkObject ( ) ) ,
420
+ address : action . address ,
421
+ value : action . authority === 'mint' ? TOKEN_MINT_MASK : TOKEN_MELT_MASK ,
422
+ timelock : null ,
423
+ token : action . token ,
424
+ authorities : action . authority === 'mint' ? 1n : 2n ,
425
+ } ;
426
+ }
427
+
330
428
/**
331
429
* Verify if the builder attributes are valid for the nano build
332
430
*
0 commit comments