You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mymonero-core-cpp/src/monero_send_routine.hpp

249 lines
9.6 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

//
// monero_send_routine.hpp
// Copyright (c) 2014-2019, MyMonero.com
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//
#ifndef monero_send_routine_hpp
#define monero_send_routine_hpp
//
#include <boost/optional.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
//
#include "string_tools.h"
#include "crypto.h"
#include "cryptonote_basic.h"
#include "cryptonote_format_utils.h"
//
using namespace tools;
#include "tools__ret_vals.hpp"
//
#include "monero_transfer_utils.hpp"
//
namespace monero_send_routine
{
using namespace std;
using namespace boost;
using namespace cryptonote;
using namespace monero_transfer_utils;
using namespace crypto;
//
// Abstracted Send routine
// - Accessory types - Callbacks - Data fetch hooks
typedef std::function<void(
const property_tree::ptree & // opted not to send str but already parsed structure - this may not be optimal but makes it so that e.g. emscr_async_bridge doesn't have to send the response as an escaped JSON string nor redundantly parse/stringify
)> api_fetch_cb_fn;
//
struct LightwalletAPI_Req_GetUnspentOuts
{ // strings are NOT references, so they get copied, allowing scope of struct init not to be an issue
const string address;
const string view_key;
const string amount; // "0" uint64_string
size_t mixin;
bool use_dust; // true; send-funds is now coded to filter unmixable and below threshold dust properly when sweeping and not sweeping
const string dust_threshold; // uint64_string; String(MoneroConstants.dustThreshold, radix: 10)
};
static inline string json_string_from_req_GetUnspentOuts(const LightwalletAPI_Req_GetUnspentOuts &req_params)
{
boost::property_tree::ptree req_params_root;
req_params_root.put("address", req_params.address);
req_params_root.put("view_key", req_params.view_key);
req_params_root.put("amount", req_params.amount);
req_params_root.put("dust_threshold", req_params.dust_threshold);
req_params_root.put("use_dust", req_params.use_dust);
req_params_root.put("mixin", req_params.mixin);
stringstream req_params_ss;
boost::property_tree::write_json(req_params_ss, req_params_root, false/*pretty*/);
//
return req_params_ss.str();
}
LightwalletAPI_Req_GetUnspentOuts new__req_params__get_unspent_outs( // used internally and by emscr async send impl
string from_address_string,
string sec_viewKey_string
);
typedef std::function<void(
LightwalletAPI_Req_GetUnspentOuts, // req_params - use these for making the request
api_fetch_cb_fn // fn cb … call this after the request responds (successfully)
)> send__get_unspent_outs_fn_type;
//
struct LightwalletAPI_Req_GetRandomOuts
{
const vector<string> amounts;
const size_t count; // =mixin+1
};
static inline string json_string_from_req_GetRandomOuts(const LightwalletAPI_Req_GetRandomOuts &req_params)
{
boost::property_tree::ptree req_params_root;
boost::property_tree::ptree amounts_ptree;
BOOST_FOREACH(const string &amount_string, req_params.amounts)
{
property_tree::ptree amount_child;
amount_child.put("", amount_string);
amounts_ptree.push_back(std::make_pair("", amount_child));
}
req_params_root.add_child("amounts", amounts_ptree);
req_params_root.put("count", req_params.count);
stringstream req_params_ss;
boost::property_tree::write_json(req_params_ss, req_params_root, false/*pretty*/);
return req_params_ss.str();
}
LightwalletAPI_Req_GetRandomOuts new__req_params__get_random_outs( // used internally and by emscr async send impl
vector<SpendableOutput> &step1__using_outs
);
typedef std::function<void(
LightwalletAPI_Req_GetRandomOuts, // req_params - use these for making the request
api_fetch_cb_fn // fn cb … call this after the request responds (successfully)
)> send__get_random_outs_fn_type;
//
struct LightwalletAPI_Req_SubmitRawTx
{ // strings are NOT references, so they get copied, allowing scope of struct init not to be an issue
const string address;
const string view_key;
const string tx; // serialized tx
};
static inline string json_string_from_req_SubmitRawTx(const LightwalletAPI_Req_SubmitRawTx &req_params)
{
boost::property_tree::ptree req_params_root;
boost::property_tree::ptree amounts_ptree;
req_params_root.put("address", std::move(req_params.address));
req_params_root.put("view_key", std::move(req_params.view_key));
req_params_root.put("tx", std::move(req_params.tx));
stringstream req_params_ss;
boost::property_tree::write_json(req_params_ss, req_params_root, false/*pretty*/);
//
return req_params_ss.str();
}
typedef std::function<void(
LightwalletAPI_Req_SubmitRawTx, // req_params - use these for making the request
api_fetch_cb_fn // fn cb … call this after the request responds (successfully)
)> send__submit_raw_tx_fn_type;
//
// - Accessory types - Callbacks - Updates
enum SendFunds_ProcessStep
{ // These codes have values for serialization
fetchingLatestBalance = 1,
calculatingFee = 2,
fetchingDecoyOutputs = 3,
constructingTransaction = 4,
submittingTransaction = 5
};
typedef std::function<void(SendFunds_ProcessStep code)> send__status_update_fn_type;
static inline string err_msg_from_err_code__send_funds_step(SendFunds_ProcessStep code)
{
switch (code) {
case fetchingLatestBalance:
return "Fetching latest balance.";
case calculatingFee:
return "Calculating fee.";
case fetchingDecoyOutputs:
return "Fetching decoy outputs.";
case constructingTransaction:
return "Constructing transaction."; // which may go back to .calculatingFee
case submittingTransaction:
return "Submitted transaction.";
}
}
// - Accessory types - Callbacks - Routine completions
struct SendFunds_Error_RetVals
{
optional<string> explicit_errMsg;
optional<CreateTransactionErrorCode> errCode; // if != noError, abort Send process
// for display / information purposes on errCode=needMoreMoneyThanFound during step1:
uint64_t spendable_balance; // (effectively but not the same as spendable_balance)
uint64_t required_balance; // for display / information purposes on errCode=needMoreMoneyThanFound during step1
};
typedef std::function<void(const SendFunds_Error_RetVals &)> send__error_cb_fn_type;
//
struct SendFunds_Success_RetVals
{
uint64_t used_fee;
uint64_t total_sent; // final_total_wo_fee + final_fee
size_t mixin;
optional<string> final_payment_id; // will be filled if a payment id was passed in or an integrated address was used
string signed_serialized_tx_string;
string tx_hash_string;
string tx_key_string; // this includes additional_tx_keys
string tx_pub_key_string; // from get_tx_pub_key_from_extra()
};
typedef std::function<void(const SendFunds_Success_RetVals &)> send__success_cb_fn_type;
//
// Response parsing
struct LightwalletAPI_Res_GetUnspentOuts
{
optional<string> err_msg;
// OR
optional<uint64_t> per_byte_fee;
optional<uint64_t> fee_mask;
optional<vector<SpendableOutput>> unspent_outs;
uint8_t fork_version;
};
struct LightwalletAPI_Res_GetRandomOuts
{
optional<string> err_msg;
// OR
optional<vector<RandomAmountOutputs>> mix_outs;
};
LightwalletAPI_Res_GetUnspentOuts new__parsed_res__get_unspent_outs(
const property_tree::ptree &res,
const secret_key &sec_viewKey,
const secret_key &sec_spendKey,
const public_key &pub_spendKey
);
LightwalletAPI_Res_GetRandomOuts new__parsed_res__get_random_outs(
const property_tree::ptree &res
);
//
// - Routine entrypoint
struct Async_SendFunds_Args
{ // TODO: add a way to pass native structures if available
string from_address_string;
string sec_viewKey_string;
string sec_spendKey_string;
string pub_spendKey_string;
string to_address_string;
optional<string> payment_id_string;
uint64_t sending_amount;
bool is_sweeping;
uint32_t simple_priority;
send__get_unspent_outs_fn_type get_unspent_outs_fn;
send__get_random_outs_fn_type get_random_outs_fn;
send__submit_raw_tx_fn_type submit_raw_tx_fn;
send__status_update_fn_type status_update_fn;
send__error_cb_fn_type error_cb_fn;
send__success_cb_fn_type success_cb_fn;
//
optional<uint64_t> unlock_time; // default 0
optional<cryptonote::network_type> nettype;
};
void async__send_funds(Async_SendFunds_Args args);
}
#endif /* monero_send_routine_hpp */