@@ -26,7 +26,7 @@ export class Transaction extends BaseTransaction {
26
26
protected _chainName : string ;
27
27
protected _sender : string ;
28
28
29
- private static FAKE_SIGNATURE = `0x${ Buffer . from ( new Uint8Array ( 256 ) . fill ( 1 ) ) . toString ( 'hex' ) } ` ;
29
+ private static FAKE_SIGNATURE = `0x${ Buffer . from ( new Uint8Array ( 256 ) . fill ( 1 ) ) . toString ( 'hex' ) } ` as HexString ;
30
30
31
31
constructor ( coinConfig : Readonly < CoinConfig > ) {
32
32
super ( coinConfig ) ;
@@ -77,7 +77,7 @@ export class Transaction extends BaseTransaction {
77
77
addSignature ( signature : string ) : void {
78
78
this . _signedTransaction = utils . serializeSignedTransaction (
79
79
this . _substrateTransaction ,
80
- signature ,
80
+ signature as HexString ,
81
81
this . _substrateTransaction . metadataRpc ,
82
82
this . _registry
83
83
) ;
@@ -177,6 +177,11 @@ export class Transaction extends BaseTransaction {
177
177
result . to = keypairDest . getAddress ( this . getAddressFormat ( ) ) ;
178
178
result . amount = txMethod . amountStaked . toString ( ) ;
179
179
result . netuid = txMethod . netuid ;
180
+ } else if ( utils . isBond ( txMethod ) ) {
181
+ result . amount = txMethod . value ;
182
+ result . payee = typeof txMethod . payee === 'string' ? txMethod . payee : txMethod . payee . Account ;
183
+ } else if ( utils . isBondExtra ( txMethod ) ) {
184
+ result . amount = txMethod . maxAdditional ;
180
185
}
181
186
} else if ( this . type === TransactionType . StakingDeactivate ) {
182
187
if ( utils . isRemoveStake ( txMethod ) ) {
@@ -187,6 +192,28 @@ export class Transaction extends BaseTransaction {
187
192
result . to = keypairDest . getAddress ( this . getAddressFormat ( ) ) ;
188
193
result . amount = txMethod . amountUnstaked . toString ( ) ;
189
194
result . netuid = txMethod . netuid ;
195
+ } else if ( utils . isUnbond ( txMethod ) ) {
196
+ result . amount = txMethod . value ;
197
+ } else if ( utils . isWithdrawUnbonded ( txMethod ) ) {
198
+ result . numSlashingSpans = txMethod . numSlashingSpans ;
199
+ }
200
+ } else if ( this . type === TransactionType . Batch ) {
201
+ if ( utils . isBatch ( txMethod ) ) {
202
+ result . batchCalls = txMethod . calls ;
203
+ // Extract amount from batch calls for display
204
+ if ( txMethod . calls && txMethod . calls . length === 2 ) {
205
+ const firstCall = txMethod . calls [ 0 ] ;
206
+ const secondCall = txMethod . calls [ 1 ] ;
207
+ if ( firstCall . method === 'bond' && secondCall . method === 'nominate' ) {
208
+ // Staking batch: bond + nominate
209
+ const bondArgs = firstCall . args as Record < string , unknown > ;
210
+ result . amount = bondArgs . value as string ;
211
+ } else if ( firstCall . method === 'chill' && secondCall . method === 'unbond' ) {
212
+ // Unstaking batch: chill + unbond
213
+ const unbondArgs = secondCall . args as Record < string , unknown > ;
214
+ result . amount = unbondArgs . value as string ;
215
+ }
216
+ }
190
217
}
191
218
}
192
219
@@ -277,6 +304,8 @@ export class Transaction extends BaseTransaction {
277
304
this . decodeInputsAndOutputsForStakingActivate ( decodedTx ) ;
278
305
} else if ( this . type === TransactionType . StakingDeactivate ) {
279
306
this . decodeInputsAndOutputsForStakingDeactivate ( decodedTx ) ;
307
+ } else if ( this . type === TransactionType . Batch ) {
308
+ this . decodeInputsAndOutputsForBatch ( decodedTx ) ;
280
309
}
281
310
}
282
311
@@ -331,6 +360,14 @@ export class Transaction extends BaseTransaction {
331
360
to = keypairDest . getAddress ( this . getAddressFormat ( ) ) ;
332
361
value = txMethod . amountStaked . toString ( ) ;
333
362
from = decodedTx . address ;
363
+ } else if ( utils . isBond ( txMethod ) ) {
364
+ to = decodedTx . address ; // For bond, funds are locked in the same account
365
+ value = txMethod . value ;
366
+ from = decodedTx . address ;
367
+ } else if ( utils . isBondExtra ( txMethod ) ) {
368
+ to = decodedTx . address ; // For bond extra, funds are locked in the same account
369
+ value = txMethod . maxAdditional ;
370
+ from = decodedTx . address ;
334
371
} else {
335
372
throw new ParseTransactionError ( `Loading inputs of unknown StakingActivate type parameters` ) ;
336
373
}
@@ -363,6 +400,14 @@ export class Transaction extends BaseTransaction {
363
400
to = keypairDest . getAddress ( this . getAddressFormat ( ) ) ;
364
401
value = txMethod . amountUnstaked . toString ( ) ;
365
402
from = decodedTx . address ;
403
+ } else if ( utils . isUnbond ( txMethod ) ) {
404
+ to = decodedTx . address ; // For unbond, funds are unlocked from the same account
405
+ value = txMethod . value ;
406
+ from = decodedTx . address ;
407
+ } else if ( utils . isWithdrawUnbonded ( txMethod ) ) {
408
+ to = decodedTx . address ; // For withdraw unbonded, funds are returned to the same account
409
+ value = '0' ; // Amount is not specified in withdraw unbonded
410
+ from = decodedTx . address ;
366
411
} else {
367
412
throw new ParseTransactionError ( `Loading inputs of unknown StakingDeactivate type parameters` ) ;
368
413
}
@@ -383,6 +428,83 @@ export class Transaction extends BaseTransaction {
383
428
] ;
384
429
}
385
430
431
+ private decodeInputsAndOutputsForBatch ( decodedTx : DecodedTx ) {
432
+ const txMethod = decodedTx . method . args ;
433
+ const sender = decodedTx . address ;
434
+ this . _inputs = [ ] ;
435
+ this . _outputs = [ ] ;
436
+
437
+ if ( utils . isBatch ( txMethod ) ) {
438
+ if ( ! txMethod . calls ) {
439
+ throw new InvalidTransactionError ( 'failed to decode calls from batch transaction' ) ;
440
+ }
441
+ // Handle different types of batch operations
442
+ let totalStakingValue = '0' ;
443
+ let hasStakingOperations = false ;
444
+ let hasUnstakingOperations = false ;
445
+
446
+ for ( const call of txMethod . calls ) {
447
+ // Handle both possible formats: simple method names or callIndex with registry lookup
448
+ let methodName : string ;
449
+
450
+ if ( typeof call . method === 'string' ) {
451
+ methodName = call . method ;
452
+ } else {
453
+ try {
454
+ const callIndex = call . method as string ;
455
+ const decodedCall = this . _registry . findMetaCall (
456
+ new Uint8Array ( Buffer . from ( callIndex . replace ( '0x' , '' ) , 'hex' ) )
457
+ ) ;
458
+ methodName = decodedCall . method ;
459
+ } catch ( e ) {
460
+ methodName = call . method as string ;
461
+ }
462
+ }
463
+
464
+ if ( methodName === 'bond' ) {
465
+ const args = call . args as Record < string , unknown > ;
466
+ const value = ( args . value as string ) || '0' ;
467
+ totalStakingValue = value ;
468
+ hasStakingOperations = true ;
469
+ } else if ( methodName === 'chill' ) {
470
+ hasUnstakingOperations = true ;
471
+ } else if ( methodName === 'unbond' ) {
472
+ const args = call . args as Record < string , unknown > ;
473
+ const value = ( args . value as string ) || '0' ;
474
+ totalStakingValue = value ;
475
+ hasUnstakingOperations = true ;
476
+ }
477
+ }
478
+
479
+ // For staking batch operations (bond + nominate or bondExtra + nominate)
480
+ if ( hasStakingOperations && ! hasUnstakingOperations ) {
481
+ this . _inputs . push ( {
482
+ address : sender ,
483
+ value : totalStakingValue ,
484
+ coin : this . _coinConfig . name ,
485
+ } ) ;
486
+ this . _outputs . push ( {
487
+ address : sender , // For staking, funds are locked in the same account
488
+ value : totalStakingValue ,
489
+ coin : this . _coinConfig . name ,
490
+ } ) ;
491
+ }
492
+ // For unstaking batch operations (chill + unbond)
493
+ else if ( hasUnstakingOperations && ! hasStakingOperations ) {
494
+ this . _inputs . push ( {
495
+ address : sender ,
496
+ value : totalStakingValue ,
497
+ coin : this . _coinConfig . name ,
498
+ } ) ;
499
+ this . _outputs . push ( {
500
+ address : sender , // For unstaking, funds are unlocked from the same account
501
+ value : totalStakingValue ,
502
+ coin : this . _coinConfig . name ,
503
+ } ) ;
504
+ }
505
+ }
506
+ }
507
+
386
508
/**
387
509
* Constructs a signed payload using construct.signTx
388
510
* This method will be called during the build step if a TSS signature
0 commit comments