mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-23 12:09:43 +00:00
4c60b178be
* Fix web3dart versioning issue * Add primary receive address extracted from private key * Implement open wallet functionality * Implement restore wallet from seed functionality * Fixate web3dart version as higher versions cause some issues * Add Initial Transaction priorities for eth Add estimated gas price * Rename priority value to tip * Re-order wallet types * Change ethereum node Fix connection issues * Fix estimating gas for priority * Add case for ethereum to fetch it's seeds * Add case for ethereum to request node * Fix Exchange screen initial pairs * Add initial send transaction flow * Add missing configure for ethereum class * Add Eth address initial setup * Fix Private key for Ethereum wallets * Change sign/send transaction flow * - Fix Conflicts with main - Remove unused function from Haven configure.dart * Add build command for ethereum package * Add missing Node list file to pubspec * - Fix balance display - Fix parsing of Ethereum amount - Add more Ethereum Nodes [skip ci] * - Fix extracting Ethereum Private key from seeds - Integrate signing/sending transaction with the send view model * - Update and Fix Conflicts with main * Add Balances for ERC20 tokens * Fix conflicts with main * Add erc20 abi json * Add send erc20 tokens initial function * add missing getHeightByDate in Haven [skip ci] * Allow contacts and wallets from the same tag * Add Shiba Inu icon * Add send ERC-20 tokens initial flow * Add missing import in generated file * Add initial approach for transaction sending for ERC-20 tokens * Refactor signing/sending transactions * Add initial flow for transactions subscription * Refactor signing/sending transactions * Add home settings icon * Fix conflicts with main * Initial flow for home settings * Add logic flow for adding erc20 tokens * Fix initial UI * Finalize UI for Tokens * Integrate UI with Ethereum flow * Add "Enable/Disable" feature for ERC20 tokens * Add initial Erc20 tokens * Add Sorting and Pin Native Token features * Fix price sorting * Sort tokens list as well when Sort criteria changes * - Improve sorting balances flow - Add initial add token from search bar flow * Fix Accounts Popup UI * Fix Pin native token * Fix Enabling/Disabling tokens Fix sorting by fiat once app is opened Improve token availability mechanism * Fix deleting token Fix renaming tokens * Fix issue with search * Add more tokens * - Fix scroll issue - Add ERC20 tokens placeholder image in picker * - Separate and organize default erc20 tokens - Fix scrolling - Add token placeholder images in picker - Sort disabled tokens alphabetically * Change BNB token initial availability [skip ci] * Fix Conflicts with main * Fix Conflicts with main * Add Verse ERC20 token to the initial tokens list * Add rename wallet to Ethereum * Integrate EtherScan API for fetching address transactions Generate Ethereum specific secrets in Ethereum package * Adjust transactions fiat price for ERC20 tokens * Free Up GitHub Actions Ubuntu Runner Disk Space * Free Up GitHub Actions Ubuntu Runner Disk space (trial 2) * Fix Transaction Fee display * Save transaction history * Enhance loading time for erc20 tokens transactions * Minor Fixes and Enhancements * Fix sending erc20 fix block explorer issue * Fix int overflow * Fix transaction amount conversions * Minor: `slow` -> `Slow` [skip-ci] * initial changes * more base config stuff * config changes * successfully builds! * save * successfully add nano wallet * save * seed generation * receive screen + node screen working * tx history working and fiat fixes * balance working * derivation updates * nano-unfinished * sends working * remove fees from send screen, send and receive transactions working * fixes + auto receive incoming txs * fix for scanning QR codes * save * update translations * fixes * more fixes * more strings * small fix * fix github actions workflow * potential fix * potential fix * ci/cd fix * change rep working * seed generation fixes * fixes * save * change rep screen functional * save * banano changes * fixes, start adding ui for PoW * pow node changes * update translations * fix * account changing barely working * save * disable account generation * small fix * save * UI work * save * fixes after merge main * fixes * remove monero stuff, work on derivation ui * lots of fixes + finish up seed derivation * last minute fixes * node related fixes * more fixes * small fix * more fixes * fixes * pretty big refactor for pow, still some bugs * finally works! * get transactions after send * fix * merge conflict fixes * save * fix pow node showing up twice * done * initial changes * small fix * more merge fixes * fixes * more fixes * fix * save * fix manage pow nodes setting appearing on other wallets * fix contact bug * fixes * fiat fixes * save * save * save * save * updates * cleanup * restore fix * fixes * remove deprecated alert * fix * small fix * remove outdated warning * electrum restore fixes * fixes * fixes * fix * derivation fixes * nano fixes pt.1 * nano fixes pt.2 * bip39 fixes * pownode refactor * nodes pages fixes * observer fix * ssl fix * remove old references * remove unused imports * code cleanup * small fix * small potential fix * save * undo all bitcoin related changes * remove dead code * review fixes * more fixes * fix * fix * review fix * small fix * nano derivation and nanoutil fixes * exchange nano fix * nano review fixes pt.1 * nano fixes pt.2 * nano fixes pt.3 * remove old imports + stop using dynamic in di * nanoutil fixes * add nano.dart to gitignore, configure fixes * review fixes, getnanowalletservice removed * fix settings screen, add changeRep to configure.dart, other minor fixes * remove manage_pow_nodes_page, key derivation edge case handled * remove old refs * more small fixes * Generic Enhancements/Minor fixes * review fixes * hopefully final fixes * review fixes * node connection fixes --------- Co-authored-by: OmarHatem <omarh.ismail1@gmail.com> Co-authored-by: Justin Ehrenhofer <justin.ehrenhofer@gmail.com> Co-authored-by: fossephate <fosse@book.local>
976 lines
27 KiB
C++
976 lines
27 KiB
C++
#include <stdint.h>
|
|
#include "cstdlib"
|
|
#include <chrono>
|
|
#include <functional>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <unistd.h>
|
|
#include <mutex>
|
|
#include <list>
|
|
#include "thread"
|
|
#include "CwWalletListener.h"
|
|
#if __APPLE__
|
|
// Fix for randomx on ios
|
|
void __clear_cache(void* start, void* end) { }
|
|
#include "../External/ios/include/wallet2_api.h"
|
|
#else
|
|
#include "../External/android/include/wallet2_api.h"
|
|
#endif
|
|
|
|
using namespace std::chrono_literals;
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
{
|
|
#endif
|
|
const uint64_t MONERO_BLOCK_SIZE = 1000;
|
|
|
|
struct Utf8Box
|
|
{
|
|
char *value;
|
|
|
|
Utf8Box(char *_value)
|
|
{
|
|
value = _value;
|
|
}
|
|
};
|
|
|
|
struct SubaddressRow
|
|
{
|
|
uint64_t id;
|
|
char *address;
|
|
char *label;
|
|
|
|
SubaddressRow(std::size_t _id, char *_address, char *_label)
|
|
{
|
|
id = static_cast<uint64_t>(_id);
|
|
address = _address;
|
|
label = _label;
|
|
}
|
|
};
|
|
|
|
struct AccountRow
|
|
{
|
|
uint64_t id;
|
|
char *label;
|
|
|
|
AccountRow(std::size_t _id, char *_label)
|
|
{
|
|
id = static_cast<uint64_t>(_id);
|
|
label = _label;
|
|
}
|
|
};
|
|
|
|
struct MoneroWalletListener : Monero::WalletListener
|
|
{
|
|
uint64_t m_height;
|
|
bool m_need_to_refresh;
|
|
bool m_new_transaction;
|
|
|
|
MoneroWalletListener()
|
|
{
|
|
m_height = 0;
|
|
m_need_to_refresh = false;
|
|
m_new_transaction = false;
|
|
}
|
|
|
|
void moneySpent(const std::string &txId, uint64_t amount)
|
|
{
|
|
m_new_transaction = true;
|
|
}
|
|
|
|
void moneyReceived(const std::string &txId, uint64_t amount)
|
|
{
|
|
m_new_transaction = true;
|
|
}
|
|
|
|
void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount)
|
|
{
|
|
m_new_transaction = true;
|
|
}
|
|
|
|
void newBlock(uint64_t height)
|
|
{
|
|
m_height = height;
|
|
}
|
|
|
|
void updated()
|
|
{
|
|
m_new_transaction = true;
|
|
}
|
|
|
|
void refreshed()
|
|
{
|
|
m_need_to_refresh = true;
|
|
}
|
|
|
|
void resetNeedToRefresh()
|
|
{
|
|
m_need_to_refresh = false;
|
|
}
|
|
|
|
bool isNeedToRefresh()
|
|
{
|
|
return m_need_to_refresh;
|
|
}
|
|
|
|
bool isNewTransactionExist()
|
|
{
|
|
return m_new_transaction;
|
|
}
|
|
|
|
void resetIsNewTransactionExist()
|
|
{
|
|
m_new_transaction = false;
|
|
}
|
|
|
|
uint64_t height()
|
|
{
|
|
return m_height;
|
|
}
|
|
};
|
|
|
|
struct TransactionInfoRow
|
|
{
|
|
uint64_t amount;
|
|
uint64_t fee;
|
|
uint64_t blockHeight;
|
|
uint64_t confirmations;
|
|
uint32_t subaddrAccount;
|
|
int8_t direction;
|
|
int8_t isPending;
|
|
uint32_t subaddrIndex;
|
|
|
|
char *hash;
|
|
char *paymentId;
|
|
|
|
int64_t datetime;
|
|
|
|
TransactionInfoRow(Monero::TransactionInfo *transaction)
|
|
{
|
|
amount = transaction->amount();
|
|
fee = transaction->fee();
|
|
blockHeight = transaction->blockHeight();
|
|
subaddrAccount = transaction->subaddrAccount();
|
|
std::set<uint32_t>::iterator it = transaction->subaddrIndex().begin();
|
|
subaddrIndex = *it;
|
|
confirmations = transaction->confirmations();
|
|
datetime = static_cast<int64_t>(transaction->timestamp());
|
|
direction = transaction->direction();
|
|
isPending = static_cast<int8_t>(transaction->isPending());
|
|
std::string *hash_str = new std::string(transaction->hash());
|
|
hash = strdup(hash_str->c_str());
|
|
paymentId = strdup(transaction->paymentId().c_str());
|
|
}
|
|
};
|
|
|
|
struct PendingTransactionRaw
|
|
{
|
|
uint64_t amount;
|
|
uint64_t fee;
|
|
char *hash;
|
|
char *hex;
|
|
char *txKey;
|
|
Monero::PendingTransaction *transaction;
|
|
|
|
PendingTransactionRaw(Monero::PendingTransaction *_transaction)
|
|
{
|
|
transaction = _transaction;
|
|
amount = _transaction->amount();
|
|
fee = _transaction->fee();
|
|
hash = strdup(_transaction->txid()[0].c_str());
|
|
hex = strdup(_transaction->hex()[0].c_str());
|
|
txKey = strdup(_transaction->txKey()[0].c_str());
|
|
}
|
|
};
|
|
|
|
struct CoinsInfoRow
|
|
{
|
|
uint64_t blockHeight;
|
|
char *hash;
|
|
uint64_t internalOutputIndex;
|
|
uint64_t globalOutputIndex;
|
|
bool spent;
|
|
bool frozen;
|
|
uint64_t spentHeight;
|
|
uint64_t amount;
|
|
bool rct;
|
|
bool keyImageKnown;
|
|
uint64_t pkIndex;
|
|
uint32_t subaddrIndex;
|
|
uint32_t subaddrAccount;
|
|
char *address;
|
|
char *addressLabel;
|
|
char *keyImage;
|
|
uint64_t unlockTime;
|
|
bool unlocked;
|
|
char *pubKey;
|
|
bool coinbase;
|
|
char *description;
|
|
|
|
CoinsInfoRow(Monero::CoinsInfo *coinsInfo)
|
|
{
|
|
blockHeight = coinsInfo->blockHeight();
|
|
std::string *hash_str = new std::string(coinsInfo->hash());
|
|
hash = strdup(hash_str->c_str());
|
|
internalOutputIndex = coinsInfo->internalOutputIndex();
|
|
globalOutputIndex = coinsInfo->globalOutputIndex();
|
|
spent = coinsInfo->spent();
|
|
frozen = coinsInfo->frozen();
|
|
spentHeight = coinsInfo->spentHeight();
|
|
amount = coinsInfo->amount();
|
|
rct = coinsInfo->rct();
|
|
keyImageKnown = coinsInfo->keyImageKnown();
|
|
pkIndex = coinsInfo->pkIndex();
|
|
subaddrIndex = coinsInfo->subaddrIndex();
|
|
subaddrAccount = coinsInfo->subaddrAccount();
|
|
address = strdup(coinsInfo->address().c_str()) ;
|
|
addressLabel = strdup(coinsInfo->addressLabel().c_str());
|
|
keyImage = strdup(coinsInfo->keyImage().c_str());
|
|
unlockTime = coinsInfo->unlockTime();
|
|
unlocked = coinsInfo->unlocked();
|
|
pubKey = strdup(coinsInfo->pubKey().c_str());
|
|
coinbase = coinsInfo->coinbase();
|
|
description = strdup(coinsInfo->description().c_str());
|
|
}
|
|
|
|
void setUnlocked(bool unlocked);
|
|
};
|
|
|
|
Monero::Coins *m_coins;
|
|
|
|
Monero::Wallet *m_wallet;
|
|
Monero::TransactionHistory *m_transaction_history;
|
|
MoneroWalletListener *m_listener;
|
|
Monero::Subaddress *m_subaddress;
|
|
Monero::SubaddressAccount *m_account;
|
|
uint64_t m_last_known_wallet_height;
|
|
uint64_t m_cached_syncing_blockchain_height = 0;
|
|
std::list<Monero::CoinsInfo*> m_coins_info;
|
|
std::mutex store_lock;
|
|
bool is_storing = false;
|
|
|
|
void change_current_wallet(Monero::Wallet *wallet)
|
|
{
|
|
m_wallet = wallet;
|
|
m_listener = nullptr;
|
|
|
|
|
|
if (wallet != nullptr)
|
|
{
|
|
m_transaction_history = wallet->history();
|
|
}
|
|
else
|
|
{
|
|
m_transaction_history = nullptr;
|
|
}
|
|
|
|
if (wallet != nullptr)
|
|
{
|
|
m_account = wallet->subaddressAccount();
|
|
}
|
|
else
|
|
{
|
|
m_account = nullptr;
|
|
}
|
|
|
|
if (wallet != nullptr)
|
|
{
|
|
m_subaddress = wallet->subaddress();
|
|
}
|
|
else
|
|
{
|
|
m_subaddress = nullptr;
|
|
}
|
|
|
|
m_coins_info = std::list<Monero::CoinsInfo*>();
|
|
|
|
if (wallet != nullptr)
|
|
{
|
|
m_coins = wallet->coins();
|
|
}
|
|
else
|
|
{
|
|
m_coins = nullptr;
|
|
}
|
|
}
|
|
|
|
Monero::Wallet *get_current_wallet()
|
|
{
|
|
return m_wallet;
|
|
}
|
|
|
|
bool create_wallet(char *path, char *password, char *language, int32_t networkType, char *error)
|
|
{
|
|
Monero::NetworkType _networkType = static_cast<Monero::NetworkType>(networkType);
|
|
Monero::WalletManager *walletManager = Monero::WalletManagerFactory::getWalletManager();
|
|
Monero::Wallet *wallet = walletManager->createWallet(path, password, language, _networkType);
|
|
|
|
int status;
|
|
std::string errorString;
|
|
|
|
wallet->statusWithErrorString(status, errorString);
|
|
|
|
if (wallet->status() != Monero::Wallet::Status_Ok)
|
|
{
|
|
error = strdup(wallet->errorString().c_str());
|
|
return false;
|
|
}
|
|
|
|
change_current_wallet(wallet);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool restore_wallet_from_seed(char *path, char *password, char *seed, int32_t networkType, uint64_t restoreHeight, char *error)
|
|
{
|
|
Monero::NetworkType _networkType = static_cast<Monero::NetworkType>(networkType);
|
|
Monero::Wallet *wallet = Monero::WalletManagerFactory::getWalletManager()->recoveryWallet(
|
|
std::string(path),
|
|
std::string(password),
|
|
std::string(seed),
|
|
_networkType,
|
|
(uint64_t)restoreHeight);
|
|
|
|
int status;
|
|
std::string errorString;
|
|
|
|
wallet->statusWithErrorString(status, errorString);
|
|
|
|
if (status != Monero::Wallet::Status_Ok || !errorString.empty())
|
|
{
|
|
error = strdup(errorString.c_str());
|
|
return false;
|
|
}
|
|
|
|
change_current_wallet(wallet);
|
|
return true;
|
|
}
|
|
|
|
bool restore_wallet_from_keys(char *path, char *password, char *language, char *address, char *viewKey, char *spendKey, int32_t networkType, uint64_t restoreHeight, char *error)
|
|
{
|
|
Monero::NetworkType _networkType = static_cast<Monero::NetworkType>(networkType);
|
|
Monero::Wallet *wallet = Monero::WalletManagerFactory::getWalletManager()->createWalletFromKeys(
|
|
std::string(path),
|
|
std::string(password),
|
|
std::string(language),
|
|
_networkType,
|
|
(uint64_t)restoreHeight,
|
|
std::string(address),
|
|
std::string(viewKey),
|
|
std::string(spendKey));
|
|
|
|
int status;
|
|
std::string errorString;
|
|
|
|
wallet->statusWithErrorString(status, errorString);
|
|
|
|
if (status != Monero::Wallet::Status_Ok || !errorString.empty())
|
|
{
|
|
error = strdup(errorString.c_str());
|
|
return false;
|
|
}
|
|
|
|
change_current_wallet(wallet);
|
|
return true;
|
|
}
|
|
|
|
bool load_wallet(char *path, char *password, int32_t nettype)
|
|
{
|
|
nice(19);
|
|
Monero::NetworkType networkType = static_cast<Monero::NetworkType>(nettype);
|
|
Monero::WalletManager *walletManager = Monero::WalletManagerFactory::getWalletManager();
|
|
Monero::Wallet *wallet = walletManager->openWallet(std::string(path), std::string(password), networkType);
|
|
int status;
|
|
std::string errorString;
|
|
|
|
wallet->statusWithErrorString(status, errorString);
|
|
change_current_wallet(wallet);
|
|
|
|
return !(status != Monero::Wallet::Status_Ok || !errorString.empty());
|
|
}
|
|
|
|
char *error_string() {
|
|
return strdup(get_current_wallet()->errorString().c_str());
|
|
}
|
|
|
|
|
|
bool is_wallet_exist(char *path)
|
|
{
|
|
return Monero::WalletManagerFactory::getWalletManager()->walletExists(std::string(path));
|
|
}
|
|
|
|
void close_current_wallet()
|
|
{
|
|
Monero::WalletManagerFactory::getWalletManager()->closeWallet(get_current_wallet());
|
|
change_current_wallet(nullptr);
|
|
}
|
|
|
|
char *get_filename()
|
|
{
|
|
return strdup(get_current_wallet()->filename().c_str());
|
|
}
|
|
|
|
char *secret_view_key()
|
|
{
|
|
return strdup(get_current_wallet()->secretViewKey().c_str());
|
|
}
|
|
|
|
char *public_view_key()
|
|
{
|
|
return strdup(get_current_wallet()->publicViewKey().c_str());
|
|
}
|
|
|
|
char *secret_spend_key()
|
|
{
|
|
return strdup(get_current_wallet()->secretSpendKey().c_str());
|
|
}
|
|
|
|
char *public_spend_key()
|
|
{
|
|
return strdup(get_current_wallet()->publicSpendKey().c_str());
|
|
}
|
|
|
|
char *get_address(uint32_t account_index, uint32_t address_index)
|
|
{
|
|
return strdup(get_current_wallet()->address(account_index, address_index).c_str());
|
|
}
|
|
|
|
|
|
const char *seed()
|
|
{
|
|
return strdup(get_current_wallet()->seed().c_str());
|
|
}
|
|
|
|
uint64_t get_full_balance(uint32_t account_index)
|
|
{
|
|
return get_current_wallet()->balance(account_index);
|
|
}
|
|
|
|
uint64_t get_unlocked_balance(uint32_t account_index)
|
|
{
|
|
return get_current_wallet()->unlockedBalance(account_index);
|
|
}
|
|
|
|
uint64_t get_current_height()
|
|
{
|
|
return get_current_wallet()->blockChainHeight();
|
|
}
|
|
|
|
uint64_t get_node_height()
|
|
{
|
|
return get_current_wallet()->daemonBlockChainHeight();
|
|
}
|
|
|
|
bool connect_to_node(char *error)
|
|
{
|
|
nice(19);
|
|
bool is_connected = get_current_wallet()->connectToDaemon();
|
|
|
|
if (!is_connected)
|
|
{
|
|
error = strdup(get_current_wallet()->errorString().c_str());
|
|
}
|
|
|
|
return is_connected;
|
|
}
|
|
|
|
bool setup_node(char *address, char *login, char *password, bool use_ssl, bool is_light_wallet, char *socksProxyAddress, char *error)
|
|
{
|
|
nice(19);
|
|
Monero::Wallet *wallet = get_current_wallet();
|
|
|
|
std::string _login = "";
|
|
std::string _password = "";
|
|
std::string _socksProxyAddress = "";
|
|
|
|
if (login != nullptr)
|
|
{
|
|
_login = std::string(login);
|
|
}
|
|
|
|
if (password != nullptr)
|
|
{
|
|
_password = std::string(password);
|
|
}
|
|
|
|
if (socksProxyAddress != nullptr)
|
|
{
|
|
_socksProxyAddress = std::string(socksProxyAddress);
|
|
}
|
|
|
|
bool inited = wallet->init(std::string(address), 0, _login, _password, use_ssl, is_light_wallet, _socksProxyAddress);
|
|
|
|
if (!inited)
|
|
{
|
|
error = strdup(wallet->errorString().c_str());
|
|
} else if (!wallet->connectToDaemon()) {
|
|
error = strdup(wallet->errorString().c_str());
|
|
}
|
|
|
|
return inited;
|
|
}
|
|
|
|
bool is_connected()
|
|
{
|
|
return get_current_wallet()->connected();
|
|
}
|
|
|
|
void start_refresh()
|
|
{
|
|
get_current_wallet()->refreshAsync();
|
|
get_current_wallet()->startRefresh();
|
|
}
|
|
|
|
void set_refresh_from_block_height(uint64_t height)
|
|
{
|
|
get_current_wallet()->setRefreshFromBlockHeight(height);
|
|
}
|
|
|
|
void set_recovering_from_seed(bool is_recovery)
|
|
{
|
|
get_current_wallet()->setRecoveringFromSeed(is_recovery);
|
|
}
|
|
|
|
void store(char *path)
|
|
{
|
|
store_lock.lock();
|
|
if (is_storing) {
|
|
return;
|
|
}
|
|
|
|
is_storing = true;
|
|
get_current_wallet()->store(std::string(path));
|
|
is_storing = false;
|
|
store_lock.unlock();
|
|
}
|
|
|
|
bool set_password(char *password, Utf8Box &error) {
|
|
bool is_changed = get_current_wallet()->setPassword(std::string(password));
|
|
|
|
if (!is_changed) {
|
|
error = Utf8Box(strdup(get_current_wallet()->errorString().c_str()));
|
|
}
|
|
|
|
return is_changed;
|
|
}
|
|
|
|
bool transaction_create(char *address, char *payment_id, char *amount,
|
|
uint8_t priority_raw, uint32_t subaddr_account,
|
|
char **preferred_inputs, uint32_t preferred_inputs_size,
|
|
Utf8Box &error, PendingTransactionRaw &pendingTransaction)
|
|
{
|
|
nice(19);
|
|
|
|
std::set<std::string> _preferred_inputs;
|
|
|
|
for (int i = 0; i < preferred_inputs_size; i++) {
|
|
_preferred_inputs.insert(std::string(*preferred_inputs));
|
|
preferred_inputs++;
|
|
}
|
|
|
|
auto priority = static_cast<Monero::PendingTransaction::Priority>(priority_raw);
|
|
std::string _payment_id;
|
|
Monero::PendingTransaction *transaction;
|
|
|
|
if (payment_id != nullptr)
|
|
{
|
|
_payment_id = std::string(payment_id);
|
|
}
|
|
|
|
if (amount != nullptr)
|
|
{
|
|
uint64_t _amount = Monero::Wallet::amountFromString(std::string(amount));
|
|
transaction = m_wallet->createTransaction(std::string(address), _payment_id, _amount, m_wallet->defaultMixin(), priority, subaddr_account, {}, _preferred_inputs);
|
|
}
|
|
else
|
|
{
|
|
transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional<uint64_t>(), m_wallet->defaultMixin(), priority, subaddr_account, {}, _preferred_inputs);
|
|
}
|
|
|
|
int status = transaction->status();
|
|
|
|
if (status == Monero::PendingTransaction::Status::Status_Error || status == Monero::PendingTransaction::Status::Status_Critical)
|
|
{
|
|
error = Utf8Box(strdup(transaction->errorString().c_str()));
|
|
return false;
|
|
}
|
|
|
|
if (m_listener != nullptr) {
|
|
m_listener->m_new_transaction = true;
|
|
}
|
|
|
|
pendingTransaction = PendingTransactionRaw(transaction);
|
|
return true;
|
|
}
|
|
|
|
bool transaction_create_mult_dest(char **addresses, char *payment_id, char **amounts, uint32_t size,
|
|
uint8_t priority_raw, uint32_t subaddr_account,
|
|
char **preferred_inputs, uint32_t preferred_inputs_size,
|
|
Utf8Box &error, PendingTransactionRaw &pendingTransaction)
|
|
{
|
|
nice(19);
|
|
|
|
std::vector<std::string> _addresses;
|
|
std::vector<uint64_t> _amounts;
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
_addresses.push_back(std::string(*addresses));
|
|
_amounts.push_back(Monero::Wallet::amountFromString(std::string(*amounts)));
|
|
addresses++;
|
|
amounts++;
|
|
}
|
|
|
|
std::set<std::string> _preferred_inputs;
|
|
|
|
for (int i = 0; i < preferred_inputs_size; i++) {
|
|
_preferred_inputs.insert(std::string(*preferred_inputs));
|
|
preferred_inputs++;
|
|
}
|
|
|
|
auto priority = static_cast<Monero::PendingTransaction::Priority>(priority_raw);
|
|
std::string _payment_id;
|
|
Monero::PendingTransaction *transaction;
|
|
|
|
if (payment_id != nullptr)
|
|
{
|
|
_payment_id = std::string(payment_id);
|
|
}
|
|
|
|
transaction = m_wallet->createTransactionMultDest(_addresses, _payment_id, _amounts, m_wallet->defaultMixin(), priority, subaddr_account);
|
|
|
|
int status = transaction->status();
|
|
|
|
if (status == Monero::PendingTransaction::Status::Status_Error || status == Monero::PendingTransaction::Status::Status_Critical)
|
|
{
|
|
error = Utf8Box(strdup(transaction->errorString().c_str()));
|
|
return false;
|
|
}
|
|
|
|
if (m_listener != nullptr) {
|
|
m_listener->m_new_transaction = true;
|
|
}
|
|
|
|
pendingTransaction = PendingTransactionRaw(transaction);
|
|
return true;
|
|
}
|
|
|
|
bool transaction_commit(PendingTransactionRaw *transaction, Utf8Box &error)
|
|
{
|
|
bool committed = transaction->transaction->commit();
|
|
|
|
if (!committed)
|
|
{
|
|
error = Utf8Box(strdup(transaction->transaction->errorString().c_str()));
|
|
} else if (m_listener != nullptr) {
|
|
m_listener->m_new_transaction = true;
|
|
}
|
|
|
|
return committed;
|
|
}
|
|
|
|
uint64_t get_node_height_or_update(uint64_t base_eight)
|
|
{
|
|
if (m_cached_syncing_blockchain_height < base_eight) {
|
|
m_cached_syncing_blockchain_height = base_eight;
|
|
}
|
|
|
|
return m_cached_syncing_blockchain_height;
|
|
}
|
|
|
|
uint64_t get_syncing_height()
|
|
{
|
|
if (m_listener == nullptr) {
|
|
return 0;
|
|
}
|
|
|
|
uint64_t height = m_listener->height();
|
|
|
|
if (height <= 1) {
|
|
return 0;
|
|
}
|
|
|
|
if (height != m_last_known_wallet_height)
|
|
{
|
|
m_last_known_wallet_height = height;
|
|
}
|
|
|
|
return height;
|
|
}
|
|
|
|
uint64_t is_needed_to_refresh()
|
|
{
|
|
if (m_listener == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
bool should_refresh = m_listener->isNeedToRefresh();
|
|
|
|
if (should_refresh) {
|
|
m_listener->resetNeedToRefresh();
|
|
}
|
|
|
|
return should_refresh;
|
|
}
|
|
|
|
uint8_t is_new_transaction_exist()
|
|
{
|
|
if (m_listener == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
bool is_new_transaction_exist = m_listener->isNewTransactionExist();
|
|
|
|
if (is_new_transaction_exist)
|
|
{
|
|
m_listener->resetIsNewTransactionExist();
|
|
}
|
|
|
|
return is_new_transaction_exist;
|
|
}
|
|
|
|
void set_listener()
|
|
{
|
|
m_last_known_wallet_height = 0;
|
|
|
|
if (m_listener != nullptr)
|
|
{
|
|
free(m_listener);
|
|
}
|
|
|
|
m_listener = new MoneroWalletListener();
|
|
get_current_wallet()->setListener(m_listener);
|
|
}
|
|
|
|
int64_t *subaddrress_get_all()
|
|
{
|
|
std::vector<Monero::SubaddressRow *> _subaddresses = m_subaddress->getAll();
|
|
size_t size = _subaddresses.size();
|
|
int64_t *subaddresses = (int64_t *)malloc(size * sizeof(int64_t));
|
|
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
Monero::SubaddressRow *row = _subaddresses[i];
|
|
SubaddressRow *_row = new SubaddressRow(row->getRowId(), strdup(row->getAddress().c_str()), strdup(row->getLabel().c_str()));
|
|
subaddresses[i] = reinterpret_cast<int64_t>(_row);
|
|
}
|
|
|
|
return subaddresses;
|
|
}
|
|
|
|
int32_t subaddrress_size()
|
|
{
|
|
std::vector<Monero::SubaddressRow *> _subaddresses = m_subaddress->getAll();
|
|
return _subaddresses.size();
|
|
}
|
|
|
|
void subaddress_add_row(uint32_t accountIndex, char *label)
|
|
{
|
|
m_subaddress->addRow(accountIndex, std::string(label));
|
|
}
|
|
|
|
void subaddress_set_label(uint32_t accountIndex, uint32_t addressIndex, char *label)
|
|
{
|
|
m_subaddress->setLabel(accountIndex, addressIndex, std::string(label));
|
|
}
|
|
|
|
void subaddress_refresh(uint32_t accountIndex)
|
|
{
|
|
m_subaddress->refresh(accountIndex);
|
|
}
|
|
|
|
int32_t account_size()
|
|
{
|
|
std::vector<Monero::SubaddressAccountRow *> _accocunts = m_account->getAll();
|
|
return _accocunts.size();
|
|
}
|
|
|
|
int64_t *account_get_all()
|
|
{
|
|
std::vector<Monero::SubaddressAccountRow *> _accocunts = m_account->getAll();
|
|
size_t size = _accocunts.size();
|
|
int64_t *accocunts = (int64_t *)malloc(size * sizeof(int64_t));
|
|
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
Monero::SubaddressAccountRow *row = _accocunts[i];
|
|
AccountRow *_row = new AccountRow(row->getRowId(), strdup(row->getLabel().c_str()));
|
|
accocunts[i] = reinterpret_cast<int64_t>(_row);
|
|
}
|
|
|
|
return accocunts;
|
|
}
|
|
|
|
void account_add_row(char *label)
|
|
{
|
|
m_account->addRow(std::string(label));
|
|
}
|
|
|
|
void account_set_label_row(uint32_t account_index, char *label)
|
|
{
|
|
m_account->setLabel(account_index, label);
|
|
}
|
|
|
|
void account_refresh()
|
|
{
|
|
m_account->refresh();
|
|
}
|
|
|
|
int64_t *transactions_get_all()
|
|
{
|
|
std::vector<Monero::TransactionInfo *> transactions = m_transaction_history->getAll();
|
|
size_t size = transactions.size();
|
|
int64_t *transactionAddresses = (int64_t *)malloc(size * sizeof(int64_t));
|
|
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
Monero::TransactionInfo *row = transactions[i];
|
|
TransactionInfoRow *tx = new TransactionInfoRow(row);
|
|
transactionAddresses[i] = reinterpret_cast<int64_t>(tx);
|
|
}
|
|
|
|
return transactionAddresses;
|
|
}
|
|
|
|
void transactions_refresh()
|
|
{
|
|
m_transaction_history->refresh();
|
|
}
|
|
|
|
int64_t transactions_count()
|
|
{
|
|
return m_transaction_history->count();
|
|
}
|
|
|
|
int LedgerExchange(
|
|
unsigned char *command,
|
|
unsigned int cmd_len,
|
|
unsigned char *response,
|
|
unsigned int max_resp_len)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
int LedgerFind(char *buffer, size_t len)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
void on_startup()
|
|
{
|
|
Monero::Utils::onStartup();
|
|
Monero::WalletManagerFactory::setLogLevel(0);
|
|
}
|
|
|
|
void rescan_blockchain()
|
|
{
|
|
m_wallet->rescanBlockchainAsync();
|
|
}
|
|
|
|
char * get_tx_key(char * txId)
|
|
{
|
|
return strdup(m_wallet->getTxKey(std::string(txId)).c_str());
|
|
}
|
|
|
|
char *get_subaddress_label(uint32_t accountIndex, uint32_t addressIndex)
|
|
{
|
|
return strdup(get_current_wallet()->getSubaddressLabel(accountIndex, addressIndex).c_str());
|
|
}
|
|
|
|
void set_trusted_daemon(bool arg)
|
|
{
|
|
m_wallet->setTrustedDaemon(arg);
|
|
}
|
|
|
|
bool trusted_daemon()
|
|
{
|
|
return m_wallet->trustedDaemon();
|
|
}
|
|
|
|
CoinsInfoRow* coin(int index)
|
|
{
|
|
if (index >= 0 && index < m_coins_info.size()) {
|
|
std::list<Monero::CoinsInfo*>::iterator it = m_coins_info.begin();
|
|
std::advance(it, index);
|
|
Monero::CoinsInfo* element = *it;
|
|
std::cout << "Element at index " << index << ": " << element << std::endl;
|
|
return new CoinsInfoRow(element);
|
|
} else {
|
|
std::cout << "Invalid index." << std::endl;
|
|
return nullptr; // Return a default value (nullptr) for invalid index
|
|
}
|
|
}
|
|
|
|
void refresh_coins(uint32_t accountIndex)
|
|
{
|
|
m_coins_info.clear();
|
|
|
|
m_coins->refresh();
|
|
for (const auto i : m_coins->getAll()) {
|
|
if (i->subaddrAccount() == accountIndex && !(i->spent())) {
|
|
m_coins_info.push_back(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
uint64_t coins_count()
|
|
{
|
|
return m_coins_info.size();
|
|
}
|
|
|
|
CoinsInfoRow** coins_from_account(uint32_t accountIndex)
|
|
{
|
|
std::vector<CoinsInfoRow*> matchingCoins;
|
|
|
|
for (int i = 0; i < coins_count(); i++) {
|
|
CoinsInfoRow* coinInfo = coin(i);
|
|
if (coinInfo->subaddrAccount == accountIndex) {
|
|
matchingCoins.push_back(coinInfo);
|
|
}
|
|
}
|
|
|
|
CoinsInfoRow** result = new CoinsInfoRow*[matchingCoins.size()];
|
|
std::copy(matchingCoins.begin(), matchingCoins.end(), result);
|
|
return result;
|
|
}
|
|
|
|
CoinsInfoRow** coins_from_txid(const char* txid, size_t* count)
|
|
{
|
|
std::vector<CoinsInfoRow*> matchingCoins;
|
|
|
|
for (int i = 0; i < coins_count(); i++) {
|
|
CoinsInfoRow* coinInfo = coin(i);
|
|
if (std::string(coinInfo->hash) == txid) {
|
|
matchingCoins.push_back(coinInfo);
|
|
}
|
|
}
|
|
|
|
*count = matchingCoins.size();
|
|
CoinsInfoRow** result = new CoinsInfoRow*[*count];
|
|
std::copy(matchingCoins.begin(), matchingCoins.end(), result);
|
|
return result;
|
|
}
|
|
|
|
CoinsInfoRow** coins_from_key_image(const char** keyimages, size_t keyimageCount, size_t* count)
|
|
{
|
|
std::vector<CoinsInfoRow*> matchingCoins;
|
|
|
|
for (int i = 0; i < coins_count(); i++) {
|
|
CoinsInfoRow* coinsInfoRow = coin(i);
|
|
for (size_t j = 0; j < keyimageCount; j++) {
|
|
if (coinsInfoRow->keyImageKnown && std::string(coinsInfoRow->keyImage) == keyimages[j]) {
|
|
matchingCoins.push_back(coinsInfoRow);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
*count = matchingCoins.size();
|
|
CoinsInfoRow** result = new CoinsInfoRow*[*count];
|
|
std::copy(matchingCoins.begin(), matchingCoins.end(), result);
|
|
return result;
|
|
}
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|