1
1
use crate :: { config:: Config , sort:: UnsupportedAccount } ;
2
- use console:: Emoji ;
2
+ use console:: { style , Emoji } ;
3
3
use serde:: { Deserialize , Serialize , Serializer } ;
4
4
use solana_account_decoder:: {
5
5
parse_token:: { UiAccountState , UiMint , UiMultisig , UiTokenAccount , UiTokenAmount } ,
6
6
parse_token_extension:: {
7
- UiDefaultAccountState , UiExtension , UiMemoTransfer , UiMintCloseAuthority ,
8
- UiTransferFeeAmount ,
7
+ UiDefaultAccountState , UiExtension , UiInterestBearingConfig , UiMemoTransfer ,
8
+ UiMintCloseAuthority , UiTransferFee , UiTransferFeeAmount , UiTransferFeeConfig ,
9
9
} ,
10
10
} ;
11
11
use solana_cli_output:: { display:: writeln_name_value, OutputFormat , QuietDisplay , VerboseDisplay } ;
@@ -168,11 +168,11 @@ impl fmt::Display for CliMultisig {
168
168
let n = self . multisig . num_valid_signers ;
169
169
170
170
writeln ! ( f) ?;
171
- writeln_name_value ( f, "SPL Token Multisig" , " " ) ?;
171
+ writeln ! ( f, "{}" , style ( " SPL Token Multisig") . bold ( ) ) ?;
172
172
writeln_name_value ( f, " Address:" , & self . address ) ?;
173
173
writeln_name_value ( f, " Program:" , & self . program_id ) ?;
174
174
writeln_name_value ( f, " M/N:" , & format ! ( "{}/{}" , m, n) ) ?;
175
- writeln_name_value ( f, " Signers: " , " " ) ?;
175
+ writeln ! ( f, " {} " , style ( "Signers:" ) . bold ( ) ) ?;
176
176
let width = if n >= 9 { 4 } else { 3 } ;
177
177
for i in 0 ..n as usize {
178
178
let title = format ! ( " {1:>0$}:" , width, i + 1 ) ;
@@ -188,6 +188,7 @@ impl fmt::Display for CliMultisig {
188
188
pub ( crate ) struct CliTokenAccount {
189
189
pub ( crate ) address : String ,
190
190
pub ( crate ) program_id : String ,
191
+ pub ( crate ) epoch : u64 ,
191
192
pub ( crate ) decimals : Option < u8 > ,
192
193
pub ( crate ) is_associated : bool ,
193
194
#[ serde( flatten) ]
@@ -200,7 +201,7 @@ impl VerboseDisplay for CliTokenAccount {}
200
201
impl fmt:: Display for CliTokenAccount {
201
202
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
202
203
writeln ! ( f) ?;
203
- writeln_name_value ( f, "SPL Token Account" , " " ) ?;
204
+ writeln ! ( f, "{}" , style ( " SPL Token Account") . bold ( ) ) ?;
204
205
if self . is_associated {
205
206
writeln_name_value ( f, " Address:" , & self . address ) ?;
206
207
} else {
@@ -235,7 +236,7 @@ impl fmt::Display for CliTokenAccount {
235
236
writeln_name_value ( f, " Owner:" , & self . account . owner ) ?;
236
237
writeln_name_value ( f, " State:" , & format ! ( "{:?}" , self . account. state) ) ?;
237
238
if let Some ( delegate) = & self . account . delegate {
238
- writeln_name_value ( f, " Delegation: " , " " ) ?;
239
+ writeln ! ( f, " {} " , style ( "Delegation:" ) . bold ( ) ) ?;
239
240
writeln_name_value ( f, " Delegate:" , delegate) ?;
240
241
let allowance = self . account . delegated_amount . as_ref ( ) . unwrap ( ) ;
241
242
writeln_name_value ( f, " Allowance:" , & allowance. real_number_string_trimmed ( ) ) ?;
@@ -252,9 +253,9 @@ impl fmt::Display for CliTokenAccount {
252
253
) ?;
253
254
254
255
if !self . account . extensions . is_empty ( ) {
255
- writeln_name_value ( f, "Extensions " , " " ) ?;
256
+ writeln ! ( f, "{} " , style ( "Extensions:" ) . bold ( ) ) ?;
256
257
for extension in & self . account . extensions {
257
- display_ui_extension ( f, extension) ?;
258
+ display_ui_extension ( f, self . epoch , extension) ?;
258
259
}
259
260
}
260
261
@@ -272,6 +273,7 @@ impl fmt::Display for CliTokenAccount {
272
273
pub ( crate ) struct CliMint {
273
274
pub ( crate ) address : String ,
274
275
pub ( crate ) program_id : String ,
276
+ pub ( crate ) epoch : u64 ,
275
277
#[ serde( flatten) ]
276
278
pub ( crate ) mint : UiMint ,
277
279
}
@@ -282,7 +284,7 @@ impl VerboseDisplay for CliMint {}
282
284
impl fmt:: Display for CliMint {
283
285
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
284
286
writeln ! ( f) ?;
285
- writeln_name_value ( f, "SPL Token Mint" , " " ) ?;
287
+ writeln ! ( f, "{}" , style ( " SPL Token Mint") . bold ( ) ) ?;
286
288
287
289
writeln_name_value ( f, " Address:" , & self . address ) ?;
288
290
writeln_name_value ( f, " Program:" , & self . program_id ) ?;
@@ -303,9 +305,9 @@ impl fmt::Display for CliMint {
303
305
) ?;
304
306
305
307
if !self . mint . extensions . is_empty ( ) {
306
- writeln_name_value ( f, "Extensions " , " " ) ?;
308
+ writeln ! ( f, "{} " , style ( "Extensions" ) . bold ( ) ) ?;
307
309
for extension in & self . mint . extensions {
308
- display_ui_extension ( f, extension) ?;
310
+ display_ui_extension ( f, self . epoch , extension) ?;
309
311
}
310
312
}
311
313
@@ -479,9 +481,54 @@ impl fmt::Display for CliTokenAccounts {
479
481
}
480
482
}
481
483
482
- fn display_ui_extension ( f : & mut fmt:: Formatter , ui_extension : & UiExtension ) -> fmt:: Result {
484
+ fn display_ui_extension (
485
+ f : & mut fmt:: Formatter ,
486
+ epoch : u64 ,
487
+ ui_extension : & UiExtension ,
488
+ ) -> fmt:: Result {
483
489
match ui_extension {
484
- UiExtension :: TransferFeeConfig ( _) => unimplemented ! ( ) , // annoying
490
+ UiExtension :: TransferFeeConfig ( UiTransferFeeConfig {
491
+ transfer_fee_config_authority,
492
+ withdraw_withheld_authority,
493
+ withheld_amount,
494
+ older_transfer_fee,
495
+ newer_transfer_fee,
496
+ ..
497
+ } ) => {
498
+ let UiTransferFee {
499
+ transfer_fee_basis_points,
500
+ maximum_fee,
501
+ ..
502
+ } = if newer_transfer_fee. epoch >= epoch {
503
+ newer_transfer_fee
504
+ } else {
505
+ older_transfer_fee
506
+ } ;
507
+
508
+ writeln ! ( f, " {}" , style( "Transfer fees:" ) . bold( ) ) ?;
509
+ writeln ! (
510
+ f,
511
+ " {} {}bps" ,
512
+ style( "Fee:" ) . bold( ) ,
513
+ transfer_fee_basis_points
514
+ ) ?;
515
+ writeln_name_value ( f, " Maximum fee:" , & maximum_fee. to_string ( ) ) ?;
516
+ writeln_name_value (
517
+ f,
518
+ " Config authority:" ,
519
+ transfer_fee_config_authority
520
+ . as_ref ( )
521
+ . unwrap_or ( & String :: new ( ) ) ,
522
+ ) ?;
523
+ writeln_name_value (
524
+ f,
525
+ " Withdrawal authority:" ,
526
+ withdraw_withheld_authority
527
+ . as_ref ( )
528
+ . unwrap_or ( & String :: new ( ) ) ,
529
+ ) ?;
530
+ writeln_name_value ( f, " Withheld fees:" , & withheld_amount. to_string ( ) )
531
+ }
485
532
UiExtension :: TransferFeeAmount ( UiTransferFeeAmount { withheld_amount } ) => {
486
533
writeln_name_value ( f, " Transfer fees withheld:" , & withheld_amount. to_string ( ) )
487
534
}
@@ -497,7 +544,7 @@ fn display_ui_extension(f: &mut fmt::Formatter, ui_extension: &UiExtension) -> f
497
544
UiExtension :: DefaultAccountState ( UiDefaultAccountState { account_state } ) => {
498
545
writeln_name_value ( f, " Default state:" , & format ! ( "{:?}" , account_state) )
499
546
}
500
- UiExtension :: ImmutableOwner => writeln_name_value ( f, " Immutable owner " , " " ) ,
547
+ UiExtension :: ImmutableOwner => writeln ! ( f, " {} " , style ( "Immutable owner" ) . bold ( ) ) ,
501
548
UiExtension :: MemoTransfer ( UiMemoTransfer {
502
549
require_incoming_transfer_memos,
503
550
} ) => writeln_name_value (
@@ -509,8 +556,25 @@ fn display_ui_extension(f: &mut fmt::Formatter, ui_extension: &UiExtension) -> f
509
556
"Not required"
510
557
} ,
511
558
) ,
512
- UiExtension :: NonTransferable => writeln_name_value ( f, " Non-transferable" , " " ) ,
513
- UiExtension :: InterestBearingConfig ( _) => unimplemented ! ( ) , // little annoying
559
+ UiExtension :: NonTransferable => writeln ! ( f, " {}" , style( "Non-transferable" ) . bold( ) ) ,
560
+ UiExtension :: InterestBearingConfig ( UiInterestBearingConfig {
561
+ rate_authority,
562
+ current_rate,
563
+ ..
564
+ } ) => {
565
+ writeln ! ( f, " {}" , style( "Interest-bearing:" ) . bold( ) ) ?;
566
+ writeln ! (
567
+ f,
568
+ " {} {}bps" ,
569
+ style( "Interest rate:" ) . bold( ) ,
570
+ current_rate
571
+ ) ?;
572
+ writeln_name_value (
573
+ f,
574
+ " Rate authority:" ,
575
+ rate_authority. as_ref ( ) . unwrap_or ( & String :: new ( ) ) ,
576
+ )
577
+ }
514
578
UiExtension :: UnparseableExtension => panic ! ( "err here" ) ,
515
579
UiExtension :: Uninitialized => panic ! ( "err here...?" ) ,
516
580
}
0 commit comments