20#define MAIN_LOOP_TICK_MS 5000U
21#define HEAP_LOG_PERIOD_US (10LL * 60LL * 1000000LL)
54 CryptnoxWallet &wallet = hw.
wallet;
55 Pn532NfcTransport &nfcTransport = hw.
transport;
56 CW_CryptoProvider &cryptoProvider = hw.
crypto;
64 ESP_LOGW(
TAG,
"resuming the sale in flight at reset: %s",
s_inflight.hash);
79 bool restart_due =
false;
84 if (esp_task_wdt_add(NULL) != ESP_OK) {
85 ESP_LOGE(
TAG,
"main loop not on the task watchdog");
93 if (esp_timer_get_time() >= next_heap_log_us) {
95 ESP_LOGI(
TAG,
"heap: %u free, %u largest block",
96 static_cast<unsigned>(esp_get_free_heap_size()),
97 static_cast<unsigned>(
98 heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT)));
113 ?
"Offline - re-joining the Wi-Fi"
114 :
"Waiting for network time");
125 "Payout address not configured");
133 "Payout address invalid - set it again");
140 if ((tok != NULL) && !tok->
ok) {
142 "Token contract not configured");
192 ESP_LOGW(
TAG,
"stale PIN_ENTERED ignored");
196 char pin[16] = { 0 };
200 char err_msg[64] = { 0 };
202 CW_Utils::secure_wipe(
reinterpret_cast<uint8_t *
>(fl),
sizeof(*fl));
209 &pending_amount, pin, pin_chars, fl,
210 err_msg,
sizeof(err_msg));
212 CW_Utils::secure_wipe(
reinterpret_cast<uint8_t *
>(pin),
sizeof(pin));
284 if (card_tron[0] !=
'\0') {
289 if (!restart_due) {
break; }
293 ESP_LOGW(
TAG,
"config changed from the admin page - restarting");
296 vTaskDelay(pdMS_TO_TICKS(600));
310 char pin[16] = { 0 };
314 char err[48] = { 0 };
318 c_eth,
sizeof(c_eth),
319 c_tron,
sizeof(c_tron),
321 CW_Utils::secure_wipe(
reinterpret_cast<uint8_t *
>(pin),
sizeof(pin));
330 prov_set_note(
"Accept each address on the terminal screen.");
334 if (c_eth[0] !=
'\0') {
336 (void)snprintf(card_tron,
sizeof(card_tron),
"%s", c_tron);
337 }
else if (c_tron[0] !=
'\0') {
360 char w_ssid[33] = { 0 };
361 char w_pass[65] = { 0 };
363 w_pass,
sizeof(w_pass)) > 0U) {
369 const char *why = NULL;
373 ESP_LOGW(
TAG,
"'%s' joined but has no network time -"
374 " not saved", w_ssid);
390 char b_ssid[33] = { 0 };
391 char b_pass[65] = { 0 };
393 b_pass,
sizeof(b_pass)) &&
394 (b_ssid[0] !=
'\0')) {
395 ESP_LOGW(
TAG,
"rolling back to saved network '%s'",
405 CW_Utils::secure_wipe(
406 reinterpret_cast<uint8_t *
>(b_pass),
sizeof(b_pass));
420 CW_Utils::secure_wipe(
reinterpret_cast<uint8_t *
>(w_pass),
sizeof(w_pass));
pos_hw_t pos_boot(void)
Everything before the main loop. Returns the card stack, which lives for the life of the program.
const char *const NOTE_NO_TIME
const char *const NOTE_JOIN_FAILED
bool card_read_payouts(CryptnoxWallet &wallet, Pn532NfcTransport &transport, CW_CryptoProvider &crypto, const char *pin, size_t pin_chars, char *eth_out, size_t eth_n, char *tron_out, size_t tron_n, char *err, size_t err_n)
Read the card's payout addresses and put them through the panel.
static const char *const TAG
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)
static void pos_amount_set(pos_amount_t *a, uint64_t v)
Write both amount stores from one value (two independent writes).
#define HEAP_LOG_PERIOD_US
std::atomic< bool > s_user_cancelled
void app_main(void)
ESP-IDF application entry point: bring-up, then the main interaction loop (amount → confirm → sign+br...
#define MAIN_LOOP_TICK_MS
void ui_event_dispatch(ui_event_t event, uint64_t payload)
UI-task callback: forward a touch event to the main task queue.
void net_wifi_disconnect(void)
Drop the station association, without the retry loop pulling it back.
void net_wifi_keep_trying(void)
Hold on to the network last configured, even though it is down now.
bool net_time_sync(uint32_t timeout_ms)
Block until the system clock has been set via SNTP and sanity-checked.
bool net_wifi_online(void)
true while the station holds an IP address.
bool net_wifi_connect(const char *ssid, const char *password)
Connect to a WiFi network and block until an IP is obtained (up to 30 s). May be called repeatedly to...
uint16_t net_wifi_scan(net_wifi_ap_t *out, uint16_t max)
Scan for nearby access points (blocking).
token_t * active_token(pos_chain_t chain)
The selection's token, or NULL for a native coin.
char s_payout_tron[SETTINGS_PAYOUT_MAX]
uint64_t wall_ms(void)
Unix time in ms, 0 while the clock is unset.
bool token_decimals_ok(pos_chain_t chain, char *err, size_t err_max)
Before the first sale in an operator-set token, read its decimals() and refuse anything but 6.
bcast_t pay_sign_and_broadcast(CryptnoxWallet &wallet, Pn532NfcTransport &transport, CW_CryptoProvider &crypto, const pos_amount_t *amount, const char *pin, size_t pin_chars, inflight_t *fl, char *err_out, size_t err_max)
Sign and broadcast the reconciled sale on whichever family is selected. The family is read once,...
void sale_fee_text(char *out, size_t n)
The most network fee the customer's card can be charged on top of the sale, for the confirm screen....
void ui_refresh_addresses(void)
Implemented by main: repoint those two rows at the selected chain.
void settle_inflight(void)
Poll the in-flight sale for up to 120 s and show what the chain says.
const pos_addr_t * active_dest(void)
The reconciled recipient for the chain currently selected.
char s_payout_eth[SETTINGS_PAYOUT_MAX]
void evm_fees_wei(bool polygon, uint64_t *max_fee, uint64_t *prio_fee)
The EIP-1559 fees one EVM sale will offer, in wei per gas.
Private to the application files (main, boot, card_io, pay, pay_evm, pay_tron): the state they share ...
static bool chain_is_tron(void)
true when the operator has switched the terminal to Tron.
static bool chain_is_polygon(void)
true when the terminal is charging on Polygon rather than Ethereum.
void prov_set_note(const char *note)
Put a one-line message on the page.
bool prov_propose(prov_ask_t kind, const char *addr)
Propose a value on behalf of the panel itself.
prov_mode_t prov_mode(void)
Which mode is running, or PROV_MODE_OFF.
void prov_stop(void)
Stop the portal, drop the AP, and withdraw anything unaccepted.
void prov_set_scan(const net_wifi_ap_t *aps, uint16_t n)
Hand the portal a Wi-Fi scan for the browser to choose from.
bool settings_get_wifi(char *ssid, size_t ssid_n, char *pass, size_t pass_n)
Read the stored Wi-Fi credentials.
pos_chain_t settings_get_chain(void)
Selected chain, or POS_CHAIN_ETH_USDC if never set.
void settings_set_wifi(const char *ssid, const char *pass)
Persist Wi-Fi credentials (plaintext — see README threat model).
bool settings_inflight_load(void *rec, size_t n)
Read the persisted sale back. false if none, or not n bytes.
void settings_inflight_clear(void)
Drop the persisted sale. Writes nothing when there is none.
bool settings_has_payout(bool tron)
Whether an operator has actually set the payout address for a network.
#define SETTINGS_PAYOUT_MAX
Longest payout address plus NUL — "0x" + 40 hex, or 34 base58 Tron.
A scanned access point (subset of fields the UI needs).
The card stack pos_boot() brought up; lives for the program.
CW_CryptoProvider & crypto
Pn532NfcTransport & transport
A token's contract, dual-stored.
void ui_show_confirm(uint64_t amount_units, const char *dest_addr, const char *fee)
Switch to the confirm screen.
void ui_show_prov_auth(void)
Demand the admin code so a browser can be authorised.
void ui_set_boot_status(const char *step)
Set the one-line progress note on the splash screen.
void ui_show_wifi_list(const net_wifi_ap_t *aps, uint16_t n, const char *note)
Show the scanned Wi-Fi networks for the user to pick from.
void ui_show_card_pin(void)
Ask for the card PIN before reading an address off a Cryptnox card.
void ui_show_ota_confirm(void)
Raise the modal that asks the operator to accept a firmware image the update page has uploaded,...
size_t ui_take_wifi_creds(char *ssid, size_t ssid_n, char *pass, size_t pass_n)
Fetch the selected SSID + entered password and wipe the UI's copy.
void ui_show_tx_status(ui_tx_state_t state, const char *info)
Switch to the transaction-status screen.
void ui_show_amount_entry(void)
Switch to the amount-entry screen (forces a value redraw).
void ui_show_prov_confirm(void)
Raise the modal that asks the operator to accept a value a browser proposed, reading the pending prop...
void ui_show_wifi_connecting(const char *ssid)
Show a "Connecting to <ssid>…" screen while main associates.
size_t ui_take_pin(char *out, size_t n)
Copy the most recently entered PIN out and wipe the UI's copy.
ui_event_t
Events emitted by the UI task towards the main task.
@ UI_EVENT_CONFIRM_CANCEL
@ UI_EVENT_AMOUNT_CONFIRMED
@ UI_EVENT_PROV_VALUE_SET
static void wdt_feed(void)
Feed the task watchdog if, and only if, the calling task is subscribed.