Skip to content

Commit b2c01e8

Browse files
authoredFeb 25, 2025
Chain support (#154)
* add chain support on get amount * bump version
1 parent 6d6a2a7 commit b2c01e8

File tree

14 files changed

+122
-52
lines changed

14 files changed

+122
-52
lines changed
 

‎app/Makefile.version

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ APPVERSION_M=2
33
# This is the `spec_version` field of `Runtime`
44
APPVERSION_N=36
55
# This is the patch version of this release
6-
APPVERSION_P=8
6+
APPVERSION_P=9

‎app/src/swap/handle_get_printable_amount.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ void handle_get_printable_amount(get_printable_amount_parameters_t *params) {
3737
memcpy(amount + COIN_AMOUNT_MAXSIZE - params->amount_length, params->amount, params->amount_length);
3838

3939
char tmp_amount[110] = {0};
40-
zxerr_t zxerr = bytesAmountToStringBalance(amount, sizeof(amount), tmp_amount, sizeof(tmp_amount));
40+
int8_t chain_index = find_chain_index_by_coin_config((char *)&params->coin_configuration[1], params->coin_configuration[0]);
41+
if (chain_index == -1) {
42+
return;
43+
}
44+
zxerr_t zxerr = bytesAmountToStringBalance(amount, sizeof(amount), tmp_amount, sizeof(tmp_amount), chain_index);
4145

4246
if (zxerr != zxerr_ok || strnlen(tmp_amount, sizeof(tmp_amount)) > sizeof(params->printable_amount)) {
4347
return;

‎app/src/swap/handle_sign_transaction.c

+53-30
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,6 @@ swap_globals_t G_swap_state;
2828
// Save the BSS address where we will write the return value when finished
2929
static uint8_t *G_swap_sign_return_value_address;
3030

31-
static const char * chain_ids[] = {COIN_DEFAULT_CHAINID, OSMOSIS_CHAINID, DYDX_CHAINID, MANTRA_CHAINID, XION_CHAINID};
32-
33-
bool is_allowed_chainid(const char *chainId) {
34-
for (uint32_t i = 0; i < array_length(chain_ids); i++) {
35-
if (strcmp(chainId, PIC(chain_ids[i])) == 0) {
36-
return true;
37-
}
38-
}
39-
return false;
40-
}
41-
4231
bool copy_transaction_parameters(create_transaction_parameters_t *sign_transaction_params) {
4332
if (sign_transaction_params == NULL) {
4433
return false;
@@ -91,7 +80,6 @@ bool copy_transaction_parameters(create_transaction_parameters_t *sign_transacti
9180
return true;
9281
}
9382

94-
9583
/*
9684
* This function verifies that a received transaction follows the expected format
9785
* based on the current application mode (expert or normal). The verification
@@ -138,11 +126,13 @@ parser_error_t parser_msg_send(parser_context_t *ctx_parsed_tx, uint8_t displayI
138126
}
139127
char tmpKey[20] = {0};
140128
char tmpValue[65] = {0};
129+
int8_t chain_index = 0;
141130

142131
// Check if app is in expert mode
143132
CHECK_PARSER_ERR(parser_getItem(ctx_parsed_tx, displayIdx, tmpKey, sizeof(tmpKey), tmpValue, sizeof(tmpValue), pageIdx, &pageCount))
144133
if (strcmp(tmpKey, "Chain ID") == 0) {
145-
if (!is_allowed_chainid(tmpValue)) {
134+
chain_index = find_chain_index_by_chain_id(tmpValue);
135+
if (chain_index == -1) {
146136
ZEMU_LOGF(200, " Not supported Chain Id\n");
147137
return parser_swap_wrong_chain_id;
148138
}
@@ -153,14 +143,14 @@ parser_error_t parser_msg_send(parser_context_t *ctx_parsed_tx, uint8_t displayI
153143

154144
// Check source address is present
155145
CHECK_PARSER_ERR(parser_getItem(ctx_parsed_tx, displayIdx, tmpKey, sizeof(tmpKey), tmpValue, sizeof(tmpValue), pageIdx, &pageCount))
156-
if (strcmp(tmpKey, "Type") != 0 && strcmp(tmpValue, "Send") != 0) {
146+
if (strcmp(tmpKey, "Type") != 0 || strcmp(tmpValue, "Send") != 0) {
157147
return parser_swap_unexpected_field;
158148
}
159149

160150
// Check amount
161151
displayIdx += 1;
162152
char tmp_amount[100] = {0};
163-
zxerr_t zxerr = format_amount(G_swap_state.amount, G_swap_state.amount_length, tmp_amount, sizeof(tmp_amount));
153+
zxerr_t zxerr = format_amount(G_swap_state.amount, G_swap_state.amount_length, tmp_amount, sizeof(tmp_amount), chain_index);
164154
if (zxerr != zxerr_ok) {
165155
return parser_swap_wrap_amount_computation_error;
166156
}
@@ -199,7 +189,7 @@ parser_error_t parser_msg_send(parser_context_t *ctx_parsed_tx, uint8_t displayI
199189
}
200190

201191
//Check fees
202-
zxerr = format_amount(G_swap_state.fees, G_swap_state.fees_length, tmp_amount, sizeof(tmp_amount));
192+
zxerr = format_amount(G_swap_state.fees, G_swap_state.fees_length, tmp_amount, sizeof(tmp_amount), chain_index);
203193
if (zxerr != zxerr_ok) {
204194
return parser_swap_wrap_amount_computation_error;
205195
}
@@ -209,17 +199,33 @@ parser_error_t parser_msg_send(parser_context_t *ctx_parsed_tx, uint8_t displayI
209199
return parser_swap_wrong_fee;
210200
}
211201

212-
switch (has_memo){
202+
switch (has_memo) {
213203
case 0:
214-
if ((app_mode_expert() && ctx_parsed_tx->tx_obj->tx_json.num_items != EXPERT_SEND_MODE_ITEMS - 1) || (!app_mode_expert() && ctx_parsed_tx->tx_obj->tx_json.num_items != NORMAL_SEND_MODE_ITEMS - 1)) {
215-
return parser_swap_unexpected_number_of_items;
204+
// When there's no memo, expect one less item
205+
if (chain_index != 0 || app_mode_expert()) {
206+
if (ctx_parsed_tx->tx_obj->tx_json.num_items != EXPERT_SEND_MODE_ITEMS - 1) {
207+
return parser_swap_unexpected_number_of_items;
208+
}
209+
} else {
210+
if (ctx_parsed_tx->tx_obj->tx_json.num_items != NORMAL_SEND_MODE_ITEMS - 1) {
211+
return parser_swap_unexpected_number_of_items;
212+
}
216213
}
217214
break;
215+
218216
case 1:
219-
if ((app_mode_expert() && ctx_parsed_tx->tx_obj->tx_json.num_items != EXPERT_SEND_MODE_ITEMS) || (!app_mode_expert() && ctx_parsed_tx->tx_obj->tx_json.num_items != NORMAL_SEND_MODE_ITEMS)) {
220-
return parser_swap_unexpected_number_of_items;
217+
// When there is a memo, expect full number of items
218+
if (chain_index != 0 || app_mode_expert()) {
219+
if (ctx_parsed_tx->tx_obj->tx_json.num_items != EXPERT_SEND_MODE_ITEMS) {
220+
return parser_swap_unexpected_number_of_items;
221+
}
222+
} else {
223+
if (ctx_parsed_tx->tx_obj->tx_json.num_items != NORMAL_SEND_MODE_ITEMS) {
224+
return parser_swap_unexpected_number_of_items;
225+
}
221226
}
222227
break;
228+
223229
default:
224230
break;
225231
}
@@ -271,11 +277,12 @@ parser_error_t parser_simple_transfer(parser_context_t *ctx_parsed_tx, uint8_t d
271277

272278
char tmpKey[20] = {0};
273279
char tmpValue[65] = {0};
274-
280+
int8_t chain_index = 0;
275281
// Check if app is in expert mode
276282
CHECK_PARSER_ERR(parser_getItem(ctx_parsed_tx, displayIdx, tmpKey, sizeof(tmpKey), tmpValue, sizeof(tmpValue), pageIdx, &pageCount))
277283
if (strcmp(tmpKey, "Chain ID") == 0) {
278-
if (!is_allowed_chainid(tmpValue)) {
284+
chain_index = find_chain_index_by_chain_id(tmpValue);
285+
if (chain_index == -1) {
279286
ZEMU_LOGF(200, " Not supported Chain Id\n");
280287
return parser_swap_wrong_chain_id;
281288
}
@@ -292,7 +299,7 @@ parser_error_t parser_simple_transfer(parser_context_t *ctx_parsed_tx, uint8_t d
292299

293300
// Check source coins are equal to the amount and equal to destination coins
294301
char tmp_amount[100] = {0};
295-
zxerr_t zxerr = format_amount(G_swap_state.amount, G_swap_state.amount_length, tmp_amount, sizeof(tmp_amount));
302+
zxerr_t zxerr = format_amount(G_swap_state.amount, G_swap_state.amount_length, tmp_amount, sizeof(tmp_amount), chain_index);
296303
if (zxerr != zxerr_ok) {
297304
return parser_swap_wrap_amount_computation_error;
298305
}
@@ -340,7 +347,7 @@ parser_error_t parser_simple_transfer(parser_context_t *ctx_parsed_tx, uint8_t d
340347
}
341348

342349
//Check fees
343-
zxerr = format_amount(G_swap_state.fees, G_swap_state.fees_length, tmp_amount, sizeof(tmp_amount));
350+
zxerr = format_amount(G_swap_state.fees, G_swap_state.fees_length, tmp_amount, sizeof(tmp_amount), chain_index);
344351
if (zxerr != zxerr_ok) {
345352
return parser_swap_wrap_amount_computation_error;
346353
}
@@ -350,17 +357,33 @@ parser_error_t parser_simple_transfer(parser_context_t *ctx_parsed_tx, uint8_t d
350357
return parser_swap_wrong_fee;
351358
}
352359

353-
switch (has_memo){
360+
switch (has_memo) {
354361
case 0:
355-
if ((app_mode_expert() && ctx_parsed_tx->tx_obj->tx_json.num_items != EXPERT_MODE_ITEMS - 1) || (!app_mode_expert() && ctx_parsed_tx->tx_obj->tx_json.num_items != NORMAL_MODE_ITEMS - 1)) {
356-
return parser_swap_unexpected_number_of_items;
362+
// When there's no memo, expect one less item
363+
if (chain_index != 0 || app_mode_expert()) {
364+
if (ctx_parsed_tx->tx_obj->tx_json.num_items != EXPERT_SEND_MODE_ITEMS - 1) {
365+
return parser_swap_unexpected_number_of_items;
366+
}
367+
} else {
368+
if (ctx_parsed_tx->tx_obj->tx_json.num_items != NORMAL_SEND_MODE_ITEMS - 1) {
369+
return parser_swap_unexpected_number_of_items;
370+
}
357371
}
358372
break;
373+
359374
case 1:
360-
if ((app_mode_expert() && ctx_parsed_tx->tx_obj->tx_json.num_items != EXPERT_MODE_ITEMS) || (!app_mode_expert() && ctx_parsed_tx->tx_obj->tx_json.num_items != NORMAL_MODE_ITEMS)) {
361-
return parser_swap_unexpected_number_of_items;
375+
// When there is a memo, expect full number of items
376+
if (chain_index != 0 || app_mode_expert()) {
377+
if (ctx_parsed_tx->tx_obj->tx_json.num_items != EXPERT_SEND_MODE_ITEMS) {
378+
return parser_swap_unexpected_number_of_items;
379+
}
380+
} else {
381+
if (ctx_parsed_tx->tx_obj->tx_json.num_items != NORMAL_SEND_MODE_ITEMS) {
382+
return parser_swap_unexpected_number_of_items;
383+
}
362384
}
363385
break;
386+
364387
default:
365388
break;
366389
}

‎app/src/swap/swap.h

+10
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ typedef struct {
4343
char memo[MEMO_MAXSIZE];
4444
} swap_globals_t;
4545

46+
typedef struct {
47+
const char *chain_id;
48+
const char *ticker;
49+
const char *expert_ticker;
50+
uint8_t decimals;
51+
const char * coin_config;
52+
} chains_t;
53+
54+
extern const chains_t chains[];
55+
extern const uint32_t chains_len;
4656
extern swap_globals_t G_swap_state;
4757

4858
// Handler for swap features

‎app/src/swap/swap_utils.c

+48-17
Original file line numberDiff line numberDiff line change
@@ -21,51 +21,82 @@
2121
#include "zxformat.h"
2222
#include "app_mode.h"
2323

24-
#define COSMOS_COIN_AMOUNT_DECIMAL_PLACES 6
25-
#define COSMOS_COIN_TICKER " ATOM"
26-
#define COSMOS_COIN_EXPERT_TICKER " uatom"
27-
////////////////////////////////////////////////////////////////
24+
const chains_t chains[] = {
25+
{COIN_DEFAULT_CHAINID, " ATOM", " uatom", 6, "cosmos"},
26+
{OSMOSIS_CHAINID, " OSMO", " uosmo", 6, "osmo"},
27+
{DYDX_CHAINID, " DYDX", " adydx", 18, "dydx"},
28+
{MANTRA_CHAINID, " OM", " uom", 18, "mantra"},
29+
{XION_CHAINID, " XION", " uxion", 18, "xion"},
30+
};
2831

29-
zxerr_t bytesAmountToStringBalance(uint8_t *amount, uint8_t amount_len, char *out, uint8_t out_len) {
32+
const uint32_t chains_len = sizeof(chains) / sizeof(chains[0]);
33+
34+
int8_t find_chain_index_by_coin_config(const char *coin_config, uint8_t coin_config_len) {
35+
if (coin_config == NULL) {
36+
return -1;
37+
}
38+
39+
for (uint8_t i = 0; i < chains_len; i++) {
40+
if (strncmp(coin_config, PIC(chains[i].coin_config), coin_config_len) == 0) {
41+
return i;
42+
}
43+
}
44+
45+
return -1;
46+
}
47+
48+
int8_t find_chain_index_by_chain_id(const char *chain_id) {
49+
if (chain_id == NULL) {
50+
return -1;
51+
}
52+
53+
for (uint8_t i = 0; i < chains_len; i++) {
54+
if (strncmp(chain_id, PIC(chains[i].chain_id), strlen(PIC(chains[i].chain_id))) == 0) {
55+
return i;
56+
}
57+
}
58+
59+
return -1;
60+
}
61+
62+
zxerr_t bytesAmountToStringBalance(uint8_t *amount, uint8_t amount_len, char *out, uint8_t out_len, int8_t chain_index) {
3063
uint8_t tmpBuf[COIN_AMOUNT_MAXSIZE] = {0};
3164

3265
bignumBigEndian_to_bcd(tmpBuf, sizeof(tmpBuf), amount, amount_len);
3366
bignumBigEndian_bcdprint(out, out_len, tmpBuf, sizeof(tmpBuf));
3467

3568
// Format number.
36-
if (!intstr_to_fpstr_inplace(out, out_len, COSMOS_COIN_AMOUNT_DECIMAL_PLACES)) {
69+
if (!intstr_to_fpstr_inplace(out, out_len, chains[chain_index].decimals)) {
3770
return zxerr_encoding_failed;
3871
}
3972

4073
// Add ticker prefix.
41-
CHECK_ZXERR(z_str3join(out, out_len, "", COSMOS_COIN_TICKER))
74+
CHECK_ZXERR(z_str3join(out, out_len, "", PIC(chains[chain_index].ticker)))
4275

4376
// Trim trailing zeros
4477
number_inplace_trimming(out, 1);
4578

4679
return zxerr_ok;
4780
}
4881

49-
zxerr_t bytesAmountToExpertStringBalance(uint8_t *amount, uint8_t amount_len, char *out, uint8_t out_len) {
82+
zxerr_t bytesAmountToExpertStringBalance(uint8_t *amount, uint8_t amount_len, char *out, uint8_t out_len, int8_t chain_index) {
5083
uint8_t tmpBuf[COIN_AMOUNT_MAXSIZE] = {0};
5184

5285
bignumBigEndian_to_bcd(tmpBuf, sizeof(tmpBuf), amount, amount_len);
5386
bignumBigEndian_bcdprint(out, out_len, tmpBuf, sizeof(tmpBuf));
5487

55-
// Add ticker prefix.
56-
CHECK_ZXERR(z_str3join(out, out_len, "", COSMOS_COIN_EXPERT_TICKER))
57-
58-
// Trim trailing zeros
59-
number_inplace_trimming(out, 1);
88+
// Add expert ticker prefix
89+
CHECK_ZXERR(z_str3join(out, out_len, "", PIC(chains[chain_index].expert_ticker)))
6090

6191
return zxerr_ok;
6292
}
6393

64-
zxerr_t format_amount(uint8_t *amount, uint8_t amount_len, char *out, uint8_t out_len) {
65-
if (app_mode_expert()) {
66-
return bytesAmountToExpertStringBalance(amount, amount_len, out, out_len);
94+
zxerr_t format_amount(uint8_t *amount, uint8_t amount_len, char *out, uint8_t out_len, int8_t chain_index) {
95+
// expert or not default chain
96+
if (app_mode_expert() || chain_index != 0) {
97+
return bytesAmountToExpertStringBalance(amount, amount_len, out, out_len, chain_index);
6798
} else {
68-
return bytesAmountToStringBalance(amount, amount_len, out, out_len);
99+
return bytesAmountToStringBalance(amount, amount_len, out, out_len, chain_index);
69100
}
70101
}
71102

‎app/src/swap/swap_utils.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
#include "zxerror.h"
2121

2222
// Helper functions for swap handlers
23-
zxerr_t bytesAmountToStringBalance(uint8_t *amount, uint8_t amount_len, char *out, uint8_t out_len);
24-
zxerr_t bytesAmountToExpertStringBalance(uint8_t *amount, uint8_t amount_len, char *out, uint8_t out_len);
25-
zxerr_t format_amount(uint8_t *amount, uint8_t amount_len, char *out, uint8_t out_len);
23+
int8_t find_chain_index_by_coin_config(const char *coin_config, uint8_t coin_config_len);
24+
int8_t find_chain_index_by_chain_id(const char *chain_id);
25+
zxerr_t bytesAmountToStringBalance(uint8_t *amount, uint8_t amount_len, char *out, uint8_t out_len, int8_t chain_index);
26+
zxerr_t bytesAmountToExpertStringBalance(uint8_t *amount, uint8_t amount_len, char *out, uint8_t out_len, int8_t chain_index);
27+
zxerr_t format_amount(uint8_t *amount, uint8_t amount_len, char *out, uint8_t out_len, int8_t chain_index);
2628
zxerr_t readU32BE(uint8_t *input, uint32_t *output);
-6 Bytes
Loading
-5 Bytes
Loading
-5 Bytes
Loading
9 Bytes
Loading
9 Bytes
Loading
43 Bytes
Loading
9 Bytes
Loading
9 Bytes
Loading

0 commit comments

Comments
 (0)
Please sign in to comment.