Skip to content

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(&params);
            // 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(&params);
            // 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(&params));
            // 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));
            }
        }
    }
}