Skip to content

Commit

Permalink
Add formatting function to be use for registry look-up
Browse files Browse the repository at this point in the history
  • Loading branch information
neithanmo committed Dec 10, 2024
1 parent a174435 commit 2745dab
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 17 deletions.
12 changes: 9 additions & 3 deletions app/src/formatting.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,17 @@ zxerr_t number_inplace_thousands(char *s, uint16_t sMaxLen, char separator) {
}

zxerr_t formatICP(char *out, uint16_t outLen, uint64_t value) {
return formatValue(out, outLen, value, COIN_AMOUNT_DECIMAL_PLACES);
}

zxerr_t formatValue(char *out, uint16_t outLen, uint64_t value, uint8_t decimals) {
MEMZERO(out, outLen);

fpuint64_to_str(out, outLen, value, COIN_AMOUNT_DECIMAL_PLACES);
number_inplace_trimming(out, COIN_AMOUNT_DECIMAL_NON_TRIMMED_PLACES);
CHECK_ZXERR(number_inplace_thousands(out, outLen, COIN_AMOUNT_THOUSAND_SEPARATOR));
fpuint64_to_str(out, outLen, value, decimals);
if (decimals != 0) {
number_inplace_trimming(out, COIN_AMOUNT_DECIMAL_NON_TRIMMED_PLACES);
CHECK_ZXERR(number_inplace_thousands(out, outLen, COIN_AMOUNT_THOUSAND_SEPARATOR));
}

return zxerr_ok;
}
3 changes: 2 additions & 1 deletion app/src/formatting.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ zxerr_t inplace_insert_char(char *s, uint16_t sMaxLen, uint16_t pos, char separa
zxerr_t number_inplace_thousands(char *s, uint16_t sMaxLen, char separator);

zxerr_t formatICP(char *out, uint16_t outLen, uint64_t value);
zxerr_t formatValue(char *out, uint16_t outLen, uint64_t value, uint8_t decimals);

#ifdef __cplusplus
}
#endif
#endif
103 changes: 90 additions & 13 deletions app/src/parser_print_candid.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@
#include "candid_parser.h"
#include "parser_txdef.h"
#include "timeutils.h"
#include "token_info.h"
#include <zxformat.h>

#define DEFAULT_MAXIMUM_FEES 10000
#define AMOUNT_TITLE "Amount "
#define AMOUNT_TITTLE_LEN sizeof(AMOUNT_TITLE)

__Z_INLINE parser_error_t print_permission(int32_t permission, char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount) {
switch (permission)
Expand Down Expand Up @@ -249,6 +252,17 @@ static parser_error_t parser_getItemDisburseCandid(uint8_t displayIdx,
*pageCount = 1;

const candid_ManageNeuron_t *fields = &parser_tx_obj.tx_fields.call.data.candid_manageNeuron;
uint8_t *canister_id = parser_tx_obj.tx_fields.call.canister_id.data;
uint8_t canister_id_len = sizeof(parser_tx_obj.tx_fields.call.canister_id);
const token_info_t *token = get_token(canister_id, canister_id_len);

const char *tokenSymbol = NULL;
uint8_t decimals = 0;

if (token != NULL) {
tokenSymbol = token->token_symbol;
decimals = token->decimals;
}

if (displayIdx == 0) {
snprintf(outKey, outKeyLen, "Transaction type");
Expand Down Expand Up @@ -283,9 +297,12 @@ static parser_error_t parser_getItemDisburseCandid(uint8_t displayIdx,
}

if (displayIdx == 3) {
snprintf(outKey, outKeyLen, "Amount (ICP)");
snprintf(outKey, outKeyLen, AMOUNT_TITLE);
if (tokenSymbol != NULL) {
snprintf(outKey + AMOUNT_TITTLE_LEN, outKeyLen - AMOUNT_TITTLE_LEN, "(%s)", tokenSymbol);
}
if (fields->command.disburse.has_amount) {
return print_ICP(fields->command.disburse.amount, outVal, outValLen, pageIdx, pageCount);
return print_Amount(fields->command.disburse.amount, outVal, outValLen, pageIdx, pageCount, decimals);
} else {
snprintf(outVal, outValLen, "All");
return parser_ok;
Expand Down Expand Up @@ -604,6 +621,19 @@ static parser_error_t parser_getItemSplit(uint8_t displayIdx,
const candid_ManageNeuron_t *fields = &parser_tx_obj.tx_fields.call.data.candid_manageNeuron;
PARSER_ASSERT_OR_ERROR(fields->command.hash == hash_command_Split, parser_unexpected_value)

uint8_t *canister_id = parser_tx_obj.tx_fields.call.canister_id.data;
uint8_t canister_id_len = sizeof(parser_tx_obj.tx_fields.call.canister_id);
const token_info_t *token = get_token(canister_id, canister_id_len);

const char *tokenSymbol = NULL;
uint8_t decimals = 0;

if (token != NULL) {
tokenSymbol = token->token_symbol;
decimals = token->decimals;
}


if (displayIdx == 0) {
snprintf(outKey, outKeyLen, "Transaction type");
snprintf(outVal, outValLen, "Split Neuron");
Expand All @@ -626,8 +656,11 @@ static parser_error_t parser_getItemSplit(uint8_t displayIdx,
}

if (displayIdx == 2) {
snprintf(outKey, outKeyLen, "Amount (ICP)");
return print_ICP(fields->command.split.amount_e8s, outVal, outValLen, pageIdx, pageCount);
snprintf(outKey, outKeyLen, AMOUNT_TITLE);
if (tokenSymbol != NULL) {
snprintf(outKey + AMOUNT_TITTLE_LEN, outKeyLen - AMOUNT_TITTLE_LEN, "(%s)", tokenSymbol);
}
return print_Amount(fields->command.disburse.amount, outVal, outValLen, pageIdx, pageCount, decimals);
}

return parser_no_data;
Expand Down Expand Up @@ -881,6 +914,18 @@ static parser_error_t parser_getItemCandidTransfer(uint8_t displayIdx,

const bool is_stake_tx = parser_tx_obj.special_transfer_type == neuron_stake_transaction;

uint8_t *canister_id = parser_tx_obj.tx_fields.call.canister_id.data;
uint8_t canister_id_len = sizeof(parser_tx_obj.tx_fields.call.canister_id);
const token_info_t *token = get_token(canister_id, canister_id_len);

const char *tokenSymbol = NULL;
uint8_t decimals = 0;

if (token != NULL) {
tokenSymbol = token->token_symbol;
decimals = token->decimals;
}

if (displayIdx == 0) {
snprintf(outKey, outKeyLen, "Transaction type");
snprintf(outVal, outValLen, is_stake_tx ? "Stake Neuron" : "Send ICP");
Expand Down Expand Up @@ -923,10 +968,13 @@ static parser_error_t parser_getItemCandidTransfer(uint8_t displayIdx,
}

if (displayIdx == 3) {
snprintf(outKey, outKeyLen, "Amount (ICP)");
return print_ICP(fields->data.candid_transfer.amount,
snprintf(outKey, outKeyLen, AMOUNT_TITLE);
if (tokenSymbol != NULL) {
snprintf(outKey + AMOUNT_TITTLE_LEN, outKeyLen - AMOUNT_TITTLE_LEN, "(%s)", tokenSymbol);
}
return print_Amount(fields->data.candid_transfer.amount,
outVal, outValLen,
pageIdx, pageCount);
pageIdx, pageCount, decimals);
}

if (displayIdx == 4) {
Expand All @@ -953,6 +1001,18 @@ static parser_error_t parser_getItemICRCTransfer(uint8_t displayIdx,
const bool icp_canisterId = call->data.icrcTransfer.icp_canister;
const bool is_stake_tx = parser_tx_obj.special_transfer_type == neuron_stake_transaction;

uint8_t *canister_id = call->canister_id.data;
uint8_t canister_id_len = sizeof(parser_tx_obj.tx_fields.call.canister_id);
const token_info_t *token = get_token(canister_id, canister_id_len);

const char *tokenSymbol = NULL;
uint8_t decimals = 0;

if (token != NULL) {
tokenSymbol = token->token_symbol;
decimals = token->decimals;
}

if (displayIdx == 0) {
if (icp_canisterId) {
snprintf(outKey, outKeyLen, "Transaction type");
Expand Down Expand Up @@ -1000,10 +1060,14 @@ static parser_error_t parser_getItemICRCTransfer(uint8_t displayIdx,
}

if (displayIdx == 4) {
const char *title = icp_canisterId ? "Amount (ICP)" : "Amount (Tokens)";
snprintf(outKey, outKeyLen, "%s", title);
snprintf(outKey, outKeyLen, AMOUNT_TITLE);
if (tokenSymbol != NULL && icp_canisterId ) {
snprintf(outKey + AMOUNT_TITTLE_LEN, outKeyLen - AMOUNT_TITTLE_LEN, "(%s)", tokenSymbol);
} else {
snprintf(outKey + AMOUNT_TITTLE_LEN, outKeyLen - AMOUNT_TITTLE_LEN, "(Tokens)");
}

return print_ICP(call->data.icrcTransfer.amount, outVal, outValLen, pageIdx, pageCount);
return print_Amount(call->data.icrcTransfer.amount, outVal, outValLen, pageIdx, pageCount, decimals);
}

// Skip fee if not present and not icp canister id
Expand Down Expand Up @@ -1041,6 +1105,18 @@ static parser_error_t parser_getItemDisburseSNS(uint8_t displayIdx,
*pageCount = 1;
const sns_Disburse_t *fields = &parser_tx_obj.tx_fields.call.data.sns_manageNeuron.command.sns_disburse;

uint8_t *canister_id = parser_tx_obj.tx_fields.call.canister_id.data;
uint8_t canister_id_len = sizeof(parser_tx_obj.tx_fields.call.canister_id);
const token_info_t *token = get_token(canister_id, canister_id_len);

const char *tokenSymbol = NULL;
uint8_t decimals = 0;

if (token != NULL) {
tokenSymbol = token->token_symbol;
decimals = token->decimals;
}

if (displayIdx == 0) {
snprintf(outKey, outKeyLen, "Transaction type");
snprintf(outVal, outValLen, "Disburse Neuron");
Expand Down Expand Up @@ -1084,9 +1160,10 @@ static parser_error_t parser_getItemDisburseSNS(uint8_t displayIdx,
}
}
if (displayIdx == 4) {
snprintf(outKey, outKeyLen, "Amount");
if (fields->has_amount) {
return print_ICP(fields->amount, outVal, outValLen, pageIdx, pageCount);
snprintf(outKey, outKeyLen, AMOUNT_TITLE);
if (tokenSymbol != NULL && fields->has_amount) {
snprintf(outKey + AMOUNT_TITTLE_LEN, outKeyLen - AMOUNT_TITTLE_LEN, "(%s)", tokenSymbol);
return print_Amount(fields->amount, outVal, outValLen, pageIdx, pageCount, decimals);
} else {
snprintf(outVal, outValLen, "All");
return parser_ok;
Expand Down
73 changes: 73 additions & 0 deletions app/src/parser_print_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,41 @@
static const char SEPARATOR = 0x20; // space
#endif

parser_error_t format_principal_with_delimiters(const char *input, const uint16_t inputLen,
char *output, const uint16_t outputLen) {
const uint8_t CHARS_PER_CHUNK = 5;

if (outputLen < 35) {
return parser_unexpected_buffer_end;
}

const size_t inputStrLen = strnlen(input, inputLen);
size_t outPos = 0; // Track position in output buffer explicitly

for (size_t idx = 0; idx * CHARS_PER_CHUNK < inputStrLen; idx++) {
// Add separator between groups of 3 chunks
if (idx % 3 == 0 && idx != 0) {
output[outPos++] = '-'; // Using SEPARATOR or '-' directly
}

// Copy the chunk
size_t inPos = idx * CHARS_PER_CHUNK;
for (int i = 0; i < CHARS_PER_CHUNK && inPos + i < inputStrLen; i++) {
output[outPos++] = input[inPos + i];
}

// Add dash unless it's the last chunk or after every 3rd chunk
const bool isLastChunk = ((idx + 1) * CHARS_PER_CHUNK >= inputStrLen);
const bool skipDash = (idx % 3 == 2);
if (!skipDash && !isLastChunk) {
output[outPos++] = '-';
}
}

output[outPos] = '\0';
return parser_ok;
}

parser_error_t page_textual_with_delimiters(const char *input, const uint16_t inputLen, char *output, const uint16_t outputLen, const uint8_t pageIdx, uint8_t *pageCount) {
const uint8_t CHARS_PER_CHUNK = 5;
const uint8_t CHARS_PER_PAGE = 15 * LINES_PER_PAGE;
Expand Down Expand Up @@ -273,6 +308,19 @@ parser_error_t print_ICP(uint64_t value,
return parser_ok;
}

parser_error_t print_Amount(uint64_t value,
char *outVal, uint16_t outValLen,
uint8_t pageIdx, uint8_t *pageCount, uint8_t decimals) {
char buffer[200] = {0};
zxerr_t err = formatValue(buffer, sizeof(buffer), value, decimals);
if (err != zxerr_ok) {
return parser_unexpected_error;
}

pageString(outVal, outValLen, buffer, pageIdx, pageCount);
return parser_ok;
}

parser_error_t print_principal(const uint8_t *data, uint16_t len,
char *outVal, uint16_t outValLen,
uint8_t pageIdx, uint8_t *pageCount) {
Expand Down Expand Up @@ -357,3 +405,28 @@ parser_error_t parser_printDelay(uint64_t value, char *buffer, uint16_t bufferSi
buffer[index] = 0;
return parser_ok;
}

parser_error_t format_principal(const uint8_t *data, uint16_t len,
char *outVal, uint16_t outValLen) {
if (outValLen < 35) {
return parser_unexpected_buffer_end;
}

// First convert to textual representation
char tmpBuffer[100] = {'\0'};
uint16_t outLen = sizeof(tmpBuffer);
zxerr_t err = crypto_principalToTextual(data, len, tmpBuffer, &outLen);
if (err != zxerr_ok) {
return parser_unexpected_error;
}

// Remove any newlines that might have been added
char *newline = strchr(tmpBuffer, '\n');
if (newline != NULL) {
*newline = '\0';
outLen = (uint16_t)(newline - tmpBuffer);
}

// Now format with delimiters
return format_principal_with_delimiters(tmpBuffer, outLen, outVal, outValLen);
}
7 changes: 7 additions & 0 deletions app/src/parser_print_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ extern "C" {

parser_error_t print_u64(uint64_t value, char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount);
parser_error_t print_ICP(uint64_t value, char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount);
parser_error_t print_Amount(uint64_t value, char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount, uint8_t decimals);
parser_error_t print_principal(const uint8_t *data, uint16_t len, char *outVal, uint16_t outValLen, uint8_t pageIdx, uint8_t *pageCount);
parser_error_t parser_printDelay(uint64_t value, char *buffer, uint16_t bufferSize);

Expand All @@ -40,6 +41,12 @@ parser_error_t page_principal_with_subaccount(const uint8_t *sender, uint16_t se

parser_error_t page_textual_with_delimiters(const char *input, const uint16_t inputLen, char *output, const uint16_t outputLen, const uint8_t pageIdx, uint8_t *pageCount);

parser_error_t format_principal_with_delimiters(const char *input, const uint16_t inputLen,
char *output, const uint16_t outputLen);

parser_error_t format_principal(const uint8_t *data, uint16_t len,
char *outVal, uint16_t outValLen);

#ifdef __cplusplus
}
#endif
9 changes: 9 additions & 0 deletions app/src/parser_txdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ extern "C" {
#define PATH_MAX_LEN 40
#define PATH_MAX_ARRAY 2

#define TOKEN_SYMBOL_MAX_LEN 16
#define CANISTER_ID_STR_MAX_LEN 32

typedef enum {
unknown = 0x00, // default is not accepted
call = 0x01,
Expand Down Expand Up @@ -199,6 +202,12 @@ typedef struct {
uint64_t candid_rootType;
} parser_tx_t;

typedef struct {
char canister_id[CANISTER_ID_STR_MAX_LEN]; // Keeping as string for now
char token_symbol[TOKEN_SYMBOL_MAX_LEN];
uint8_t decimals;
} token_info_t;

#ifdef __cplusplus
}
#endif

0 comments on commit 2745dab

Please sign in to comment.