Coin application entry point
C applications
For C applications, the lib_standard_app dispatches the command through the main() and
library_app_main() functions to the Coin application defined handler.
ledger-secure-sdk/lib_standard_app/main.c
/* This function is called by the main() function if this application was started by Exchange
* through an os_lib_call() as opposed to being started from the Dashboard.
*
* We dispatch the Exchange request to the correct handler.
* Handlers content are not defined in the `lib_standard_app`
*/
WEAK void library_app_main(libargs_t *args)
{
BEGIN_TRY
{
TRY
{
PRINTF("Inside library\n");
switch (args->command) {
case SIGN_TRANSACTION: {
// Backup up transaction parameters and wipe BSS to avoid collusion with
// app-exchange BSS data.
bool success = swap_copy_transaction_parameters(args->create_transaction);
if (success) {
// BSS was wiped, we can now init these globals
G_called_from_swap = true;
G_swap_response_ready = false;
// Keep the address at which we'll reply the signing status
G_swap_signing_return_value_address = &args->create_transaction->result;
common_app_init();
#ifdef HAVE_NBGL
nbgl_useCaseSpinner("Signing");
#endif // HAVE_NBGL
app_main();
}
break;
}
case CHECK_ADDRESS:
swap_handle_check_address(args->check_address);
break;
case GET_PRINTABLE_AMOUNT:
swap_handle_get_printable_amount(args->get_printable_amount);
break;
default:
break;
}
}
CATCH_OTHER(e)
{
(void) e;
PRINTF("Exiting following exception: 0x%04X\n", e);
}
FINALLY
{
os_lib_end();
}
}
END_TRY;
}
Rust applications
For Rust applications, the Coin application must handle the command dispatch (the same way the lib_standard_app does in C).
app-boilerplate-rust/src/main.rs
#[no_mangle]
extern "C" fn sample_main(arg0: u32) {
if arg0 != 0 {
// We have been started by the Exchange application through the os_lib_call API
// We need to answer the command instead of starting the normal app main loop
swap::swap_main(arg0);
} else {
// Normal app mode, start the main loop listening for APDU commands
normal_main(None);
}
}
app-boilerplate-rust/src/swap.rs
/// Main entry point when app is called as a library by the Exchange app.
///
/// # Arguments
///
/// * `arg0` - Parameter passed by `os_lib_call` containing command and data pointers
///
/// The Exchange app calls this function with different commands during a swap:
/// - `SwapCheckAddress`: Validate that an address belongs to this device
/// - `SwapGetPrintableAmount`: Format amounts/fees for display
/// - `SwapSignTransaction`: Sign the final transaction
pub fn swap_main(arg0: u32) {
debug_print("swap_main called\n");
let cmd = libcall::get_command(arg0);
match cmd {
libcall::LibCallCommand::SwapCheckAddress => {
debug_print("Received SwapCheckAddress command\n");
let mut params = swap::get_check_address_params(arg0);
let res = check_address(¶ms);
// Return to Exchange, forwarding the result
swap::swap_return(swap::SwapResult::CheckAddressResult(&mut params, res));
}
libcall::LibCallCommand::SwapGetPrintableAmount => {
debug_print("Received SwapGetPrintableAmount command\n");
let mut params = swap::get_printable_amount_params(arg0);
let amount_str = get_printable_amount(¶ms);
// Return to Exchange, forwarding the result
swap::swap_return(swap::SwapResult::PrintableAmountResult(
&mut params,
amount_str.as_str(),
));
}
libcall::LibCallCommand::SwapSignTransaction => {
debug_print("Received SwapSignTransaction command\n");
let mut params = swap::sign_tx_params(arg0);
// Call normal_main with Swap parameter set to enter the special Swap flow
let success = crate::normal_main(Some(¶ms));
// Return to Exchange, forwarding the result
if success {
swap::swap_return(swap::SwapResult::CreateTxResult(&mut params, 1));
} else {
swap::swap_return(swap::SwapResult::CreateTxResult(&mut params, 0));
}
}
}
}