#include #include "cstdlib" #include #include #include #include #include #include "thread" #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 #include "plain_wallet_api.h" //#include "plain_wallet_api_ex.h" //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(_id); address = _address; label = _label; } }; struct AccountRow { uint64_t id; char *label; AccountRow(std::size_t _id, char *_label) { id = static_cast(_id); label = _label; } }; struct ZanoBalance { uint64_t amount; char *assetType; ZanoBalance(char *_assetType, uint64_t _amount) { amount = _amount; assetType = _assetType; } }; struct ZanoRate { uint64_t rate; char *assetType; ZanoRate(char *_assetType, uint64_t _rate) { rate = _rate; assetType = _assetType; } }; /*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, std::string assetType) { m_new_transaction = true; } void moneyReceived(const std::string &txId, uint64_t amount, std::string assetType) { 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; char *assetType; int64_t datetime; TransactionInfoRow(/*wallet_public::wallet_transfer_info& wti*/) { /* amount = wti.subtransfers. fee = transaction->fee(); blockHeight = transaction->blockHeight(); subaddrAccount = transaction->subaddrAccount(); std::set::iterator it = transaction->subaddrIndex().begin(); subaddrIndex = *it; confirmations = transaction->confirmations(); datetime = static_cast(transaction->timestamp()); direction = transaction->direction(); isPending = static_cast(transaction->isPending()); std::string *hash_str = new std::string(transaction->hash()); hash = strdup(hash_str->c_str()); paymentId = strdup(transaction->paymentId().c_str()); assetType = strdup(transaction->assetType().c_str()); */ } }; struct PendingTransactionRaw { uint64_t amount; uint64_t fee; char *hash; Monero::PendingTransaction *transaction; PendingTransactionRaw(Monero::PendingTransaction *_transaction) { transaction = _transaction; amount = _transaction->amount(); fee = _transaction->fee(); hash = strdup(_transaction->txid()[0].c_str()); } }; /* 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::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; } */ //} //Monero::Wallet *get_current_wallet() //{ // return nullptr;//return m_wallet; //} char * create_wallet(char *path, char *password, char *language, int32_t networkType, char *error) { return strdup(plain_wallet::generate(path, password).c_str()); } char * restore_wallet_from_seed(char *path, char *password, char *seed, int32_t networkType, uint64_t restoreHeight, char *error) { return strdup(restore(seed, path, password, ""); } 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(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 false; } char * load_wallet(char *path, char *password, int32_t nettype) { return strdup(open(path, password)); } char *error_string() { return strdup("");//strdup(get_current_wallet()->errorString().c_str()); } bool is_wallet_exist(char *path) { return plain_wallet::is_wallet_exist(path); } void close_wallet(uint64_t hwallet) { plain_wallet::close_wallet(hwallet); } char *get_wallet_info(uint64_t hwallet) { return strdup(plain_wallet::get_wallet_info(hwallet)); } /* get_filename(): -> get_wallet_info(h).wi.path secret_view_key(): -> get_wallet_info(h).wi_extended.view_private_key public_view_key(): -> get_wallet_info(h).wi_extended.view_public_key secret_spend_key(): -> get_wallet_info(h).wi_extended.spend_private_key public_spend_key(): -> get_wallet_info(h).wi_extended.spend_public_key get_address(): -> get_wallet_info(h).wi.address seed(): -> get_wallet_info(h).wi_extended.seed get_current_height(): -> get_wallet_status(h).current_wallet_height get_node_height(): -> get_wallet_status(h).current_daemon_height start_refresh() ??? set_refresh_from_block_height ??? set_recovering_from_seed ??? connect_to_node()/is_connected(): -> get_connectivity_status(): { "is_online": true, "last_daemon_is_disconnected": false, "is_server_busy": false, "last_proxy_communicate_timestamp": 12121212 } } get_full_balance/get_unlocked_balance(): -> async_call("get_recent_txs_and_info", hwallet, "{ params: {offset: 0,count: 30,update_provision_info: true}}") return list of last transactions + balances store(): -> async_call("store", hwallet, "{params: {}}") set_password() return "OK" if succeded */ char* get_wallet_status(uint64_t hwallet) { return strdup(plain_wallet::get_wallet_status(hwallet)); } char* async_call(char* method_name, uint64_t instance_id, char* params) { return strdup(plain_wallet::async_call(method_name, instance_id, params)); } char* try_pull_result(uint64_t job_id) { return strdup(plain_wallet::try_pull_result(job_id)); } char* get_connectivity_status() { return strdup(plain_wallet::get_connectivity_status()); } bool setup_node(char *address, char *login, char *password, bool use_ssl, bool is_light_wallet, char *error) { nice(19); if(use_ssl) { //LOG_ERROR("SSL is not supported yet for Zano"); return false; } std::string res = plain_wallet::init(address, "", 0); if(API_RETURN_CODE_OK != res) { //LOG_ERROR("Failed init wallet"); return false; } return true; } //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); //} char* set_password(uint64_t hwallet, char *password, Utf8Box &error) { return strdup(plain_wallet::reset_wallet_password(hwallet, password)); } bool transaction_create(char *address, char *asset_type, char *payment_id, char *amount, uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction) { /* nice(19); auto priority = static_cast(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, std::string(asset_type), std::string(asset_type), m_wallet->defaultMixin(), priority, subaddr_account, {}); } else { transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional(),std::string(asset_type), std::string(asset_type), 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; */ return false; } bool transaction_create_mult_dest(char **addresses, char *asset_type, char *payment_id, char **amounts, uint32_t size, uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction) { /* nice(19); std::vector _addresses; std::vector _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++; } auto priority = static_cast(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, std::string(asset_type), std::string(asset_type), 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; */ return false; } 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; */ return false; } 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; */ return 0; } 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; */ return 0; } 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; */ return 0; } 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 _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(_row); } return subaddresses; */ return nullptr; } int32_t subaddrress_size() { //std::vector _subaddresses = m_subaddress->getAll(); //return _subaddresses.size(); return 0; } 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 _accocunts = m_account->getAll(); //return _accocunts.size(); return 0; } int64_t *account_get_all() { /* std::vector _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(_row); } return accocunts; */ return nullptr; } 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 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(tx); } return transactionAddresses; */ return nullptr; } void transactions_refresh() { //m_transaction_history->refresh(); } int64_t transactions_count() { //return m_transaction_history->count(); return 0; } 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(4); } void rescan_blockchain() { //m_wallet->rescanBlockchainAsync(); } char * get_tx_key(char * txId) { return nullptr; //return strdup(m_wallet->getTxKey(std::string(txId)).c_str()); } int32_t asset_types_size() { return 0; //return Monero::Assets::list().size(); } char **asset_types() { /* size_t size = Monero::Assets::list().size(); std::vector assetList = Monero::Assets::list(); char **assetTypesPts; assetTypesPts = (char **) malloc( size * sizeof(char*)); for (int i = 0; i < size; i++) { std::string asset = assetList[i]; //assetTypes[i] = (char *)malloc( 5 * sizeof(char)); assetTypesPts[i] = strdup(asset.c_str()); } return assetTypesPts; */ return nullptr; } //std::map rates; void update_rate() { //rates = get_current_wallet()->oracleRates(); } int64_t *get_rate() { /* size_t size = rates.size(); int64_t *havenRates = (int64_t *)malloc(size * sizeof(int64_t)); int i = 0; for (auto const& rate : rates) { char *assetType = strdup(rate.first.c_str()); HavenRate *havenRate = new HavenRate(assetType, rate.second); havenRates[i] = reinterpret_cast(havenRate); i++; } return havenRates; */ return nullptr; } int32_t size_of_rate() { return 0; //return static_cast(rates.size()); } void set_trusted_daemon(bool arg) { //m_wallet->setTrustedDaemon(arg); } bool trusted_daemon() { return false; //return m_wallet->trustedDaemon(); } #ifdef __cplusplus } #endif