@@ -28,6 +28,44 @@ static tz_parser_result push_frame(tz_parser_state *state,
2828 tz_operation_parser_step_kind step );
2929static tz_parser_result pop_frame (tz_parser_state * state );
3030
31+ typedef struct {
32+ const char name [32 ];
33+ const char symbol [12 ];
34+ uint8_t decimals ;
35+ const uint8_t contract_hash [20 ];
36+ } fa2_token_metadata_t ;
37+
38+ static const fa2_token_metadata_t FA2_TOKEN_REGISTRY [] = {
39+ /* KT18amZmM5W7qDWVt2pH6uj7sCEd3kbzLrHT */
40+ {"FA2 Token" ,
41+ "FA2" ,
42+ 6 ,
43+ {0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
44+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
45+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
46+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 }},
47+ };
48+
49+ #define FA2_TOKEN_REGISTRY_SIZE \
50+ (sizeof(FA2_TOKEN_REGISTRY) / sizeof(FA2_TOKEN_REGISTRY[0]))
51+
52+ static const fa2_token_metadata_t *
53+ fa2_find_token (const uint8_t * destination_22bytes )
54+ {
55+ if (destination_22bytes [0 ] != 1 ) {
56+ return NULL ;
57+ }
58+ for (size_t i = 0 ; i < FA2_TOKEN_REGISTRY_SIZE ; i ++ ) {
59+ if (memcmp (destination_22bytes + 1 ,
60+ FA2_TOKEN_REGISTRY [i ].contract_hash ,
61+ 20 )
62+ == 0 ) {
63+ return & FA2_TOKEN_REGISTRY [i ];
64+ }
65+ }
66+ return NULL ;
67+ }
68+
3169#ifdef TEZOS_DEBUG
3270const char * const tz_operation_parser_step_name [] = {"OPTION" ,
3371 "TUPLE" ,
@@ -605,6 +643,69 @@ tz_step_tag(tz_parser_state *state)
605643#define FA2_TO_ADDR_OFS (TZ_CAPTURE_BUFFER_SIZE / 2)
606644#define FA2_ADDR_MAX_LEN (TZ_CAPTURE_BUFFER_SIZE / 2 - 1)
607645
646+ static void
647+ tz_format_token_amount (char * str , uint8_t decimals , const char * symbol )
648+ {
649+ int len = 0 ;
650+
651+ while (str [len ]) {
652+ len ++ ;
653+ }
654+ if (len == 0 ) {
655+ str [0 ] = '0' ;
656+ str [1 ] = 0 ;
657+ len = 1 ;
658+ }
659+
660+ if (decimals > 0 ) {
661+ if (len <= decimals ) {
662+ int pad = (int )decimals + 1 - len ;
663+ for (int j = len ; j >= 0 ; j -- ) {
664+ str [j + pad ] = str [j ];
665+ }
666+ for (int j = 0 ; j < pad ; j ++ ) {
667+ str [j ] = '0' ;
668+ }
669+ len += pad ;
670+ }
671+
672+ int no_decimals = 1 ;
673+ for (int i = 0 ; i < decimals ; i ++ ) {
674+ no_decimals &= (str [len - 1 - i ] == '0' );
675+ }
676+ if (no_decimals ) {
677+ str [len - decimals ] = 0 ;
678+ len -= decimals ;
679+ } else {
680+ for (int i = 0 ; i < decimals ; i ++ ) {
681+ str [len - i ] = str [len - i - 1 ];
682+ }
683+ str [len - decimals ] = '.' ;
684+ len ++ ;
685+ str [len ] = 0 ;
686+ while ((len > 0 ) && (str [len - 1 ] == '0' )) {
687+ len -- ;
688+ str [len ] = 0 ;
689+ }
690+ if ((len > 0 ) && (str [len - 1 ] == '.' )) {
691+ len -- ;
692+ str [len ] = 0 ;
693+ }
694+ }
695+ }
696+
697+ if ((symbol != NULL ) && symbol [0 ]) {
698+ str [len ] = ' ' ;
699+ len ++ ;
700+ while (* symbol ) {
701+ str [len ] = * symbol ;
702+ len ++ ;
703+ symbol ++ ;
704+ }
705+ str [len ] = 0 ;
706+ }
707+ }
708+
608709/**
609710 * @brief Switch FA2 parser to binary fallback for remaining bytes
610711 *
@@ -952,7 +1053,16 @@ tz_step_read_fa2_transfer(tz_parser_state *state)
9521053 if (regs -> oofs > 0 ) {
9531054 tz_stop (IM_FULL );
9541055 }
955- STRLCPY (state -> field_info .field_name , "Token Amount" );
1056+ if (op -> frame -> step_read_fa2 .token_idx >= 0 ) {
1057+ const fa2_token_metadata_t * token
1058+ = & FA2_TOKEN_REGISTRY [op -> frame -> step_read_fa2 .token_idx ];
1059+ tz_format_token_amount ((char * )state -> buffers .num .decimal ,
1060+ token -> decimals ,
1061+ token -> symbol );
1062+ STRLCPY (state -> field_info .field_name , token -> name );
1063+ } else {
1064+ STRLCPY (state -> field_info .field_name , "Token Amount" );
1065+ }
9561066 state -> field_info .is_field_complex = false;
9571067 state -> field_info .field_index ++ ;
9581068 /* Pop the FA2 frame first, then push PRINT so PRINT pops to parent */
@@ -1544,12 +1654,19 @@ tz_step_field(tz_parser_state *state)
15441654 }
15451655 case TZ_OPERATION_FIELD_EXPR : {
15461656 if (op -> is_fa2_candidate && !field -> skip ) {
1657+ const fa2_token_metadata_t * token ;
15471658 op -> frame -> step = TZ_OPERATION_STEP_READ_FA2_TRANSFER ;
15481659 op -> frame -> step_read_fa2 .sub_step = FA2_STEP_OUTER_SEQ_TAG ;
15491660 op -> frame -> step_read_fa2 .addr_ofs = 0 ;
15501661 op -> frame -> step_read_fa2 .size_ofs = 0 ;
15511662 op -> frame -> step_read_fa2 .size_val = 0 ;
15521663 op -> frame -> step_read_fa2 .addr_len = 0 ;
1664+ op -> frame -> step_read_fa2 .token_idx = -1 ;
1665+ token = fa2_find_token (op -> destination );
1666+ if (token != NULL ) {
1667+ op -> frame -> step_read_fa2 .token_idx
1668+ = (int8_t )(token - FA2_TOKEN_REGISTRY );
1669+ }
15531670 } else {
15541671 op -> frame -> step = TZ_OPERATION_STEP_READ_MICHELINE ;
15551672 op -> frame -> step_read_micheline .inited = 0 ;
0 commit comments