Skip to content

swap_copy_transaction_parameters()

ledger-secure-sdk/lib_standard_app/swap_entrypoints.h

/* This handle is called when the user has validated on screen the transaction
 * proposal sent by the partner and started the FROM Coin application to sign
 * the payment transaction.
 *
 * This handler needs to save in the heap the details of what has been validated
 * in Exchange. These elements will be checked against the received transaction
 * upon its reception from the Ledger Live.
 *
 * return false on error, true otherwise
 */
bool swap_copy_transaction_parameters(create_transaction_parameters_t *sign_transaction_params);

ledger-secure-sdk/lib_standard_app/swap_lib_calls.h

typedef struct create_transaction_parameters_s {
    // INPUTS //
    // Additional data when dealing with tokens
    // Content is coin application specific
    uint8_t *coin_configuration;
    uint8_t  coin_configuration_length;

    // The amount validated on the screen by the user
    uint8_t *amount;
    uint8_t  amount_length;

    // The fees amount validated on the screen by the user
    uint8_t *fee_amount;
    uint8_t  fee_amount_length;

    // The partner address that will receive the funds
    char *destination_address;
    char *destination_address_extra_id;

    // OUTPUT //
    // /!\ This parameter is handled by the lib_standard_app, DO NOT interact
    // with it in the Coin application
    //
    // After reception and signature or refusal of the transaction, the Coin
    // application will return to Exchange. This boolean is used to inform the
    // Exchange application of the result.
    // Set to 1 if the transaction was successfully signed, 0 otherwise.
    uint8_t result;
} create_transaction_parameters_t;


Example of handle implementation in Solana

app-solana/src/swap/handle_swap_sign_transaction.c

#include "handle_swap_sign_transaction.h"
#include "utils.h"
#include "os.h"
#include "swap_lib_calls.h"
#include "swap_utils.h"
#include "sol/printer.h"
#include "swap_common.h"
#include "util.h"

typedef struct swap_validated_s {
    bool initialized;
    uint8_t decimals;
    char ticker[MAX_SWAP_TOKEN_LENGTH];
    uint64_t amount;
    uint64_t fee;
    char recipient[BASE58_PUBKEY_LENGTH];
} swap_validated_t;

static swap_validated_t G_swap_validated;

// Save the BSS address where we will write the return value when finished
static uint8_t *G_swap_sign_return_value_address;

// Save the data validated during the Exchange app flow
bool copy_transaction_parameters(create_transaction_parameters_t *params) {
    // Ensure no extraid
    if (params->destination_address_extra_id == NULL) {
        PRINTF("destination_address_extra_id expected\n");
        return false;
    } else if (params->destination_address_extra_id[0] != '\0') {
        PRINTF("destination_address_extra_id expected empty, not '%s'\n",
               params->destination_address_extra_id);
        return false;
    }

    // first copy parameters to stack, and then to global data.
    // We need this "trick" as the input data position can overlap with app globals
    swap_validated_t swap_validated;
    memset(&swap_validated, 0, sizeof(swap_validated));

    // Parse config and save decimals and ticker
    // If there is no coin_configuration, consider that we are doing a SOL swap
    if (params->coin_configuration == NULL) {
        memcpy(swap_validated.ticker, "SOL", sizeof("SOL"));
        swap_validated.decimals = SOL_DECIMALS;
    } else {
        if (!swap_parse_config(params->coin_configuration,
                               params->coin_configuration_length,
                               swap_validated.ticker,
                               sizeof(swap_validated.ticker),
                               &swap_validated.decimals)) {
            PRINTF("Fail to parse coin_configuration\n");
            return false;
        }
    }

    // Save recipient
    strlcpy(swap_validated.recipient,
            params->destination_address,
            sizeof(swap_validated.recipient));
    if (swap_validated.recipient[sizeof(swap_validated.recipient) - 1] != '\0') {
        PRINTF("Address copy error\n");
        return false;
    }

    // Save amount
    if (!swap_str_to_u64(params->amount, params->amount_length, &swap_validated.amount)) {
        return false;
    }

    // Save amount
    if (!swap_str_to_u64(params->fee_amount, params->fee_amount_length, &swap_validated.fee)) {
        return false;
    }

    swap_validated.initialized = true;

    // Full reset the global variables
    os_explicit_zero_BSS_segment();

    // Keep the address at which we'll reply the signing status
    G_swap_sign_return_value_address = &params->result;

    // Commit the values read from exchange to the clean global space
    memcpy(&G_swap_validated, &swap_validated, sizeof(swap_validated));
    return true;
}