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: