Skip to content
A C++ library for using Monero
C++ CMake
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
bin
docs
external
src
test
.gitignore
.gitmodules
.project
CMakeLists.txt
README.md
donate.png
todo.txt

README.md

Compatible with Monero Core v0.15.0.1 Carbon Chameleon

Monero C++ Library

This project is a library for using Monero wallets in C++ by wrapping Monero Core's C++ wallet, wallet2.

In addition, this project conforms to an API specification intended to be intuitive, robust, and for long-term use in the Monero project.

This library may be used to build Monero-related applications, such as GUIs, libraries in other languages (e.g. monero-java), or a compliant REST/JSON-RPC API.

Main Features

  • Manage Monero wallets which connect to a daemon
  • Cohesive APIs and models with rigorous focus on ease-of-use
  • Query wallet transactions, transfers, and outputs by their attributes
  • Be notified when blocks are added to the chain, as the wallet synchronizes, or when the wallet sends or receives funds
  • Full multisig support
  • Tested by over 100 JUnit test cases using a native Java library

Sample Code

This code demonstrates the API. See the documentation or specification PDF for more details.

Note: This API might change depending on feedback, such as changing structs to classes, using pure object-oriented accessors and mutators, not using boost::optional with shared_ptrs, etc. Feedback is welcome.

// create a wallet from a mnemonic phrase
string mnemonic = "hefty value later extra artistic firm radar yodel talent future fungal nutshell because sanity awesome nail unjustly rage unafraid cedar delayed thumbs comb custom sanity";
monero_wallet* wallet_restored = monero_wallet_core::create_wallet_from_mnemonic(
    "MyWalletRestored",                               // wallet path and name
    "supersecretpassword123",                         // wallet password
    monero_network_type::STAGENET,                    // network type
    mnemonic,                                         // mnemonic phrase
    monero_rpc_connection("http://localhost:38081"),  // daemon connection
    380104,                                           // restore height
    ""                                                // seed offset
);

// synchronize the wallet and receive progress notifications
struct : monero_sync_listener {
  void on_sync_progress(uint64_t height, uint64_t start_height, uint64_t end_height, double percent_done, const string& message) {
    // feed a progress bar?
  }
} my_sync_listener;
wallet_restored->sync(my_sync_listener);

// start syncing the wallet continuously in the background
wallet_restored->start_syncing();

// get balance, account, subaddresses
string restored_primary = wallet_restored->get_primary_address();
uint64_t balance = wallet_restored->get_balance();    // can specify account and subaddress indices
monero_account account = wallet_restored->get_account(1, true);       // get account with subaddresses
uint64_t unlocked_account_balance = account.m_unlocked_balance.get(); // get boost::optional value

// query a transaction by id
monero_tx_query tx_query;
tx_query.m_id = "314a0f1375db31cea4dac4e0a51514a6282b43792269b3660166d4d2b46437ca";
shared_ptr<monero_tx_wallet> tx = wallet_restored->get_txs(tx_query)[0];
for (const shared_ptr<monero_incoming_transfer> in_transfer : tx->m_incoming_transfers) {
  uint64_t in_amount = in_transfer->m_amount.get();
  int account_index = in_transfer->m_account_index.get();
}

// query incoming transfers to account 1
monero_transfer_query transfer_query;
transfer_query.m_is_incoming = true;
transfer_query.m_account_index = 1;
vector<shared_ptr<monero_transfer>> transfers = wallet_restored->get_transfers(transfer_query);

// query unspent outputs
monero_output_query output_query;
output_query.m_is_spent = false;
vector<shared_ptr<monero_output_wallet>> outputs = wallet_restored->get_outputs(output_query);

// create and sync a new wallet with a random mnemonic phrase
monero_wallet* wallet_random = monero_wallet_core::create_wallet_random(
    "MyWalletRandom",                                 // wallet path and name
    "supersecretpassword123",                         // wallet password
    monero_network_type::STAGENET,                    // network type
    monero_rpc_connection("http://localhost:38081"),  // daemon connection
    "English"
);
wallet_random->sync();

// continuously synchronize the wallet in the background
wallet_random->start_syncing();

// get wallet info
string random_mnemonic = wallet_random->get_mnemonic();
string random_primary = wallet_random->get_primary_address();
uint64_t random_height = wallet_random->get_height();
bool random_is_synced = wallet_random->is_synced();

// be notified when the wallet receives funds
struct : monero_wallet_listener {
  void on_output_received(const monero_output_wallet& output) {
    cout << "Wallet received funds!" << endl;
    string tx_id = output.m_tx->m_id.get();
    int account_index = output.m_account_index.get();
    int subaddress_index = output.m_subaddress_index.get();
    OUTPUT_RECEIVED = true;
  }
} my_listener;
wallet_random->add_listener(my_listener);

// send funds from the restored wallet to the random wallet
shared_ptr<monero_tx_wallet> sent_tx = wallet_restored->send(0, wallet_random->get_address(1, 0), 50000).m_txs[0];
bool in_pool = sent_tx->m_in_tx_pool.get();  // true

// mine with 7 threads to push the network along
int num_threads = 7;
bool is_background = false;
bool ignore_battery = false;
wallet_restored->start_mining(num_threads, is_background, ignore_battery);

// wait for the next block to be added to the chain
uint64_t next_height = wallet_random->wait_for_next_block();

// stop mining
wallet_restored->stop_mining();

// create a request to send funds to multiple destinations in the random wallet
monero_send_request send_request = monero_send_request();
send_request.m_account_index = 1;                // withdraw funds from this account
send_request.m_subaddress_indices = vector<uint32_t>();
send_request.m_subaddress_indices.push_back(0);
send_request.m_subaddress_indices.push_back(1);  // withdraw funds from these subaddresses within the account
send_request.m_priority = monero_send_priority::UNIMPORTANT;  // no rush
vector<shared_ptr<monero_destination>> destinations;  // specify the recipients and their amounts
destinations.push_back(make_shared<monero_destination>(wallet_random->get_address(1, 0), 50000));
destinations.push_back(make_shared<monero_destination>(wallet_random->get_address(2, 0), 50000));
send_request.m_destinations = destinations;

// create the transaction, confirm with the user, and relay to the network
shared_ptr<monero_tx_wallet> created_tx = wallet_restored->create_tx(send_request).m_txs[0];
uint64_t fee = created_tx->m_fee.get(); // "Are you sure you want to send ...?"
wallet_restored->relay_tx(*created_tx); // submit the transaction to the Monero network which will notify the recipient wallet

How to Run This Library

The following dependencies must be set up before running this project.

  1. Set up Boost
    1. Download and extract the boost 1.69.0 source code zip from https://www.boost.org/users/download/ to ./external/boost-sdk/.
    2. cd ./external/boost-sdk/
    3. ./bootstraph.sh
    4. ./b2
    5. Copy .a files from ./external/boost-sdk/bin.v2/libs/*/link-static/* to ./external-libs/boost according to CMakeLists.txt.
  2. Set up OpenSSL
    1. Download and extract the latest OpenSSL source code zip from https://github.com/openssl/openssl to ./external/openssl-sdk/.
    2. Build for your system.
      Mac: installed through boost at /usr/local/opt/openssl/lib
    3. Copy libcrypto.a and libssl.a ./external-libs/openssl.
  3. Set up Monero Core
    1. Initialize submodules: git submodule update --init --recursive
    2. cd ./submodules/monero-core
    3. Modify CMakeLists.txt: option(BUILD_GUI_DEPS "Build GUI dependencies." ON).
    4. Build twice to create libwallet_merged.a in addition to other .a libraries: make release-static -j8.
    5. Copy .a files from ./submodules/monero-core/build/release/* to ./external-libs/monero-core according to CMakeLists.txt.
  4. Set up hidapi
    1. Download the latest hidapi source code from https://github.com/signal11/hidapi.
    2. Build hidapi for your system.
      Mac requires autoreconf: brew install automake
    3. Copy libhidapi.a to ./external-libs/hidapi.
  5. Set up libsodium
    1. Build libsodium for your system.
    2. Copy libsodium.a to ./external-libs/libsodium.
      Mac: installed through homebrew at /usr/local/Cellar/libsodium/1.0.17/lib/libsodium.a

After the dependencies are set up, this project may be compiled as part of another application, as a dynamic library, or as a shared library. For example, the associated Java library depends on a dynamic library built from this project to support a wallet using Java JNI.

To build this project as a dynamic library at ./build/libmonero-cpp.dylib, execute: ./bin/build-libmonero-cpp.sh.

These build steps aspire to be automated further and any help is greatly appreciated.

See Also

API specification

monero-java

monero-javascript

License

This project is licensed under MIT.

Donate

Donations are gratefully accepted. Thank you for your support!

46FR1GKVqFNQnDiFkH7AuzbUBrGQwz2VdaXTDD4jcjRE8YkkoTYTmZ2Vohsz9gLSqkj5EM6ai9Q7sBoX4FPPYJdGKQQXPVz

You can’t perform that action at this time.