28 for (
size_t i = 0U; i < CW_TRON_ADDRESS_BYTES; i++) {
29 (void)snprintf(&out[i * 2U], 3U,
"%02x",
30 static_cast<unsigned>(addr21[i]));
52 uint64_t amount,
char *err,
size_t err_max)
54 const bool is_token = (token_hex != NULL) && (token_hex[0] !=
'\0');
56 uint64_t trx_sun = 0U;
58 ESP_LOGW(
TAG,
"pre-flight: TRX balance read failed - letting it run");
65 if (trx_sun < amount) {
66 (void)snprintf(err, err_max,
"Not enough TRX for this amount");
74 ESP_LOGW(
TAG,
"pre-flight: token balance read failed - letting it run");
75 }
else if (have < amount) {
76 (void)snprintf(err, err_max,
"Not enough %s on the card",
92 (void)snprintf(err, err_max,
"No TRX for the network fee");
126 Pn532NfcTransport &transport,
127 CW_CryptoProvider &crypto,
131 const char *pin,
size_t pin_chars,
133 char *err_out,
size_t err_max)
139 (void)snprintf(err_out, err_max,
"Integrity check failed");
142 if ((token != NULL) && !token->
ok) {
143 (void)snprintf(err_out, err_max,
"Token contract not configured");
149 uint8_t to21[CW_TRON_ADDRESS_BYTES];
150 to21[0] = CW_TRON_ADDRESS_PREFIX;
151 (void)CW_Utils::safe_memcpy(&to21[1],
sizeof(to21) - 1U,
160 uint8_t c21[CW_TRON_ADDRESS_BYTES];
161 c21[0] = CW_TRON_ADDRESS_PREFIX;
162 (void)CW_Utils::safe_memcpy(&c21[1],
sizeof(c21) - 1U,
169 CW_SecureSession session;
172 (void)snprintf(err_out, err_max,
"%s",
186 char owner_b58[CW_TRON_ADDRESS_STR_SIZE] = { 0 };
188 uint8_t owner21[CW_TRON_ADDRESS_BYTES];
190 if (!wallet.verifyPin(session,
191 reinterpret_cast<const uint8_t *
>(pin),
192 static_cast<uint8_t
>(pin_chars))) {
193 (void)snprintf(err_out, err_max,
"%s",
pin_fail_text(transport,
"Wrong PIN"));
194 wallet.disconnect(session);
197 if (!wallet.getPublicKey(session, CW_TRON_DERIVE_PATH,
198 CW_TRON_PATH_LENGTH, pubkey) ||
199 !CW_Tron::addressBytesFromPublicKey(pubkey, owner21) ||
200 !CW_Tron::encodeAddress(owner21, crypto,
201 owner_b58,
sizeof(owner_b58))) {
202 wallet.disconnect(session);
203 (void)snprintf(err_out, err_max,
"Cannot read card address");
207 ESP_LOGI(
TAG,
"Tron sender (this card): %s", owner_b58);
211 amount_sun, err_out, err_max)) {
212 wallet.disconnect(session);
217 const bool built = (token == NULL)
223 wallet.disconnect(session);
227 (void)snprintf(err_out, err_max,
"No %s on %.12s...",
228 (token == NULL) ?
"TRX" :
"funds/TRX", owner_b58);
238 (void)snprintf(err_out, err_max,
"Integrity check failed");
239 wallet.disconnect(session);
246 static_cast<uint8_t
>(
sizeof(tx.
txid)),
247 CW_TRON_DERIVE_PATH, CW_TRON_PATH_LENGTH,
248 pin, pin_chars, rs, err_out, err_max)) {
251 const uint8_t *sig_r = rs;
252 const uint8_t *sig_s = rs + 32U;
266 (void)CW_Utils::safe_memcpy(sig,
sizeof(sig), sig_r, 32U);
267 (void)CW_Utils::safe_memcpy(sig + 32U,
sizeof(sig) - 32U, sig_s, 32U);
282 for (uint8_t v = 0U; (v < 2U) && !sent; v++) {
286 ESP_LOGW(
TAG,
"broadcast rejected with v=%u",
static_cast<unsigned>(v));
290 ESP_LOGI(
TAG,
"main stack after Tron broadcast: %u bytes free",
291 static_cast<unsigned>(uxTaskGetStackHighWaterMark(NULL)));
301 ESP_LOGW(
TAG,
"broadcast not confirmed - polling %s until it expires",
static const pos_asset_t * pos_asset_of(pos_chain_t chain)
The row describing chain.
bool card_sign(CryptnoxWallet &wallet, CW_SecureSession &session, const uint8_t *hash, uint8_t hash_len, const uint8_t *path, uint8_t path_len, const char *pin, size_t pin_chars, uint8_t rs_out[64], char *err_out, size_t err_max)
Have the card sign hash, then close the session.
const char * s_card_fault
bool card_connect(CryptnoxWallet &wallet, Pn532NfcTransport &transport, CW_SecureSession &session, bool setup)
Wait for a card and open a secure channel, cancellable from the UI.
const char * pin_fail_text(Pn532NfcTransport &transport, const char *wrong)
Why verifyPin said no: the PIN, or the card leaving the field.
#define TRON_TRC20_FEE_LIMIT_SUN
#define ETH_ADDR_LEN
Length of a raw (binary) Ethereum address, in bytes.
static const char *const TAG
eth_rpc_receipt_result_t
Outcome of one eth_getTransactionReceipt poll.
@ ETH_RPC_RECEIPT_RPC_ERROR
@ ETH_RPC_RECEIPT_REVERTED
@ ETH_RPC_RECEIPT_PENDING
@ ETH_RPC_RECEIPT_SUCCESS
void pos_handle_anomaly(const char *where)
Report an anomaly: bump a self-checked persisted counter, log it, and keep a local ring buffer for on...
static bool32 amount_consistent(const pos_amount_t *a)
static bool32 address_consistent(const pos_addr_t *a)
std::atomic< bool > s_user_cancelled
void inflight_persist(const inflight_t *fl)
Write the sale to NVS just before it leaves the terminal.
eth_rpc_receipt_result_t tron_receipt_as_eth(tron_receipt_t r)
Map a Tron receipt onto the Ethereum verdicts the UI flow uses.
static bool tron_balance_ok(const char *owner_hex, const char *token_hex, uint64_t amount, char *err, size_t err_max)
Refuse a Tron sale the tapped card cannot fund, before it signs.
bcast_t sign_and_broadcast_tron(CryptnoxWallet &wallet, Pn532NfcTransport &transport, CW_CryptoProvider &crypto, const pos_amount_t *amount, const pos_addr_t *to, const token_t *token, const char *pin, size_t pin_chars, inflight_t *fl, char *err_out, size_t err_max)
Sign a Tron transfer on the card and broadcast it — TRX or TRC-20.
void tron_addr_to_hex(const uint8_t *addr21, char *out, size_t n)
Format a raw 21-byte Tron address as the "41..." hex the API wants.
Private to the application files (main, boot, card_io, pay, pay_evm, pay_tron): the state they share ...
pos_chain_t settings_get_chain(void)
Selected chain, or POS_CHAIN_ETH_USDC if never set.
Scrubs a buffer with CW_Utils::secure_wipe when it leaves scope.
uint8_t addr[ETH_ADDR_LEN]
A token's contract, dual-stored.
A created-and-verified transfer, ready to sign and broadcast.
bool tron_rpc_get_trc20_balance(const char *owner_hex, const char *contract_hex, uint64_t *units_out)
Read an account's TRC-20 balance via a constant balanceOf call.
bool tron_rpc_get_balance(const char *owner_hex, uint64_t *sun_out)
Read an account's TRX balance, in sun.
bool tron_rpc_create_trc20_transfer(const char *owner_hex, const char *contract_hex, const char *to_hex, uint64_t amount, uint64_t fee_limit_sun, tron_tx_ctx_t *out)
Create a TRC-20 transfer (USDT, USDC, …) and verify what the node serialised for us.
bool tron_rpc_get_energy(const char *owner_hex, uint64_t *energy_out)
Read the energy an account still has available.
bool tron_rpc_broadcast(const tron_tx_ctx_t *tx, const uint8_t sig[65])
Broadcast a created transfer with its 65-byte signature.
bool tron_rpc_create_transfer(const char *owner_hex, const char *to_hex, uint64_t amount_sun, tron_tx_ctx_t *out)
Create a TRX transfer and verify what the node serialised for us.
tron_receipt_t
Outcome of one gettransactioninfobyid poll.
#define TRON_ADDR_HEX_LEN
Hex length of a Tron address (21 bytes: 0x41 || 20-byte key hash).
void ui_show_tx_status(ui_tx_state_t state, const char *info)
Switch to the transaction-status screen.