Examples » Build, Sign, and Send a Transaction using libcardano and libogmios

This module uses libcardano to build and sign a transaction that is then submitted to the blockchain using libogmios:

#include <cardano/address.hpp>
#include <cardano/crypto.hpp>
#include <cardano/encodings.hpp>
#include <cardano/ledger.hpp>
#include <cardano/transaction.hpp>
#include <ogmios/client.hpp>
#include <spdlog/spdlog.h>

auto main() -> int
{
    // Create a client to manage the Ogmios server connection.
    // The URL defaults to ws://localhost:1337
    auto client = ogmios::Client();

    // Setup the logging callback to print information to stdout.
    spdlog::set_level(spdlog::level::debug);  // Set global log level
    client.setLoggerCallback(
        [](int level, const std::string &msg)
        { spdlog::log(static_cast<spdlog::level::level_enum>(level), msg); }
    );

    // Get the signing key from the test seed phrase.
    constexpr auto seed_phrase =
        "firm useless gym escape dad game acid ready ocean hotel broccoli "
        "drift attack little depth prosper cliff forum hole unhappy split "
        "remove among model";
    auto mn = cardano::Mnemonic(seed_phrase, cardano::BIP39Language::English);
    auto root_xsk = cardano::BIP32PrivateKey::fromMnemonic(mn);

    auto payment_xsk = root_xsk.deriveChild(cardano::HardenIndex(1852))
                           .deriveChild(cardano::HardenIndex(1815))
                           .deriveChild(cardano::HardenIndex(0))
                           .deriveChild(0)
                           .deriveChild(0);

    auto stake_xsk = root_xsk.deriveChild(cardano::HardenIndex(1852))
                         .deriveChild(cardano::HardenIndex(1815))
                         .deriveChild(cardano::HardenIndex(0))
                         .deriveChild(2)
                         .deriveChild(0);

    // Create a base address from the corresponding payment and stake keys. This
    // is the address that will be used to send funds.
    auto from_addr = cardano::BaseAddress::fromKeys(
        cardano::NetworkID::testnet,
        payment_xsk.toPublic(),
        stake_xsk.toPublic()
    );

    // Query the UTxOs under the from address.
    auto params = json({{"addresses", {from_addr.toBech32("addr_test")}}});
    auto utxos = client.queryUtxo(params).get()["result"];
    if (utxos.empty()) throw std::runtime_error("No utxos found");

    // Find a UTxO for the transaction to consume.
    auto utxo = utxos[1];  // <- add logic here to select the UTxO.
    auto tx_input_id = utxo["transaction"]["id"].get<std::string>();
    auto tx_input_index = utxo["index"].get<uint32_t>();
    auto tx_input_value = utxo["value"]["ada"]["lovelace"].get<uint64_t>();

    // The addres to send the funds to.
    auto to_addr = cardano::EnterpriseAddress::fromBech32(
        "addr_test1vrm9x2zsux7va6w892g38tvchnzahvcd9tykqf3ygnmwtaqyfg52x"
    );

    auto tx_fee = 173861UL;
    auto tx_send = 1500000UL;
    if (tx_input_value < tx_fee + tx_send)
    {
        throw std::runtime_error("Insufficient funds");
    }

    // Get the current chain tip.
    auto tip = client.queryNetworkTip().get()["result"]["slot"].get<size_t>();

    auto tx_builder = cardano::TransactionBuilder();
    tx_builder.addInput(cardano::BASE16::decode(tx_input_id), tx_input_index)
        .addOutput(from_addr, tx_input_value - tx_fee - tx_send)
        .addOutput(to_addr, tx_send)
        .setFee(tx_fee)
        .setTtl(tip + 1000)
        .sign(payment_xsk);

    auto cborHex = cardano::BASE16::encode(tx_builder.serialize());
    spdlog::info("Transaction CBOR: {}", cborHex);

    // Submit the transaction to the Ogmios server.
    client.submitTransactionCbor(cborHex).get();

    return 0;
}  // main

Example output:

Image
Build, Sign, and Send Transaction Example Output

Open Example on Gitlab