wallet_api: add multi destination tx support
This commit is contained in:
parent
0ba675622f
commit
def703abec
|
@ -1407,8 +1407,7 @@ PendingTransaction* WalletImpl::restoreMultisigTransaction(const string& signDat
|
||||||
// - unconfirmed_transfer_details;
|
// - unconfirmed_transfer_details;
|
||||||
// - confirmed_transfer_details)
|
// - confirmed_transfer_details)
|
||||||
|
|
||||||
PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const string &payment_id, optional<uint64_t> amount, uint32_t mixin_count,
|
PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<string> &dst_addr, const string &payment_id, optional<std::vector<uint64_t>> amount, uint32_t mixin_count, PendingTransaction::Priority priority, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices)
|
||||||
PendingTransaction::Priority priority, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
clearStatus();
|
clearStatus();
|
||||||
|
@ -1429,75 +1428,75 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const
|
||||||
PendingTransactionImpl * transaction = new PendingTransactionImpl(*this);
|
PendingTransactionImpl * transaction = new PendingTransactionImpl(*this);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), dst_addr)) {
|
std::vector<uint8_t> extra;
|
||||||
|
std::string extra_nonce;
|
||||||
|
vector<cryptonote::tx_destination_entry> dsts;
|
||||||
|
if (!amount && dst_addr.size() > 1) {
|
||||||
|
setStatusError(tr("Sending all requires one destination address"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (amount && (dst_addr.size() != (*amount).size())) {
|
||||||
|
setStatusError(tr("Destinations and amounts are unequal"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!payment_id.empty()) {
|
||||||
|
crypto::hash payment_id_long;
|
||||||
|
if (tools::wallet2::parse_long_payment_id(payment_id, payment_id_long)) {
|
||||||
|
cryptonote::set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id_long);
|
||||||
|
} else {
|
||||||
|
setStatusError(tr("payment id has invalid format, expected 64 character hex string: ") + payment_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool error = false;
|
||||||
|
for (size_t i = 0; i < dst_addr.size() && !error; i++) {
|
||||||
|
if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), dst_addr[i])) {
|
||||||
// TODO: copy-paste 'if treating as an address fails, try as url' from simplewallet.cpp:1982
|
// TODO: copy-paste 'if treating as an address fails, try as url' from simplewallet.cpp:1982
|
||||||
setStatusError(tr("Invalid destination address"));
|
setStatusError(tr("Invalid destination address"));
|
||||||
|
error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (info.has_payment_id) {
|
||||||
|
if (!extra_nonce.empty()) {
|
||||||
|
setStatusError(tr("a single transaction cannot use more than one payment id"));
|
||||||
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<uint8_t> extra;
|
|
||||||
// if dst_addr is not an integrated address, parse payment_id
|
|
||||||
if (!info.has_payment_id && !payment_id.empty()) {
|
|
||||||
// copy-pasted from simplewallet.cpp:2212
|
|
||||||
crypto::hash payment_id_long;
|
|
||||||
bool r = tools::wallet2::parse_long_payment_id(payment_id, payment_id_long);
|
|
||||||
if (r) {
|
|
||||||
std::string extra_nonce;
|
|
||||||
cryptonote::set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id_long);
|
|
||||||
r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
|
|
||||||
} else {
|
|
||||||
r = tools::wallet2::parse_short_payment_id(payment_id, info.payment_id);
|
|
||||||
if (r) {
|
|
||||||
std::string extra_nonce;
|
|
||||||
set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, info.payment_id);
|
set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, info.payment_id);
|
||||||
r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!r) {
|
|
||||||
setStatusError(tr("payment id has invalid format, expected 16 or 64 character hex string: ") + payment_id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (info.has_payment_id) {
|
|
||||||
std::string extra_nonce;
|
|
||||||
set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, info.payment_id);
|
|
||||||
bool r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
|
|
||||||
if (!r) {
|
|
||||||
setStatusError(tr("Failed to add short payment id: ") + epee::string_tools::pod_to_hex(info.payment_id));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//std::vector<tools::wallet2::pending_tx> ptx_vector;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (amount) {
|
if (amount) {
|
||||||
vector<cryptonote::tx_destination_entry> dsts;
|
|
||||||
cryptonote::tx_destination_entry de;
|
cryptonote::tx_destination_entry de;
|
||||||
de.original = dst_addr;
|
de.original = dst_addr[i];
|
||||||
de.addr = info.address;
|
de.addr = info.address;
|
||||||
de.amount = *amount;
|
de.amount = (*amount)[i];
|
||||||
de.is_subaddress = info.is_subaddress;
|
de.is_subaddress = info.is_subaddress;
|
||||||
de.is_integrated = info.has_payment_id;
|
de.is_integrated = info.has_payment_id;
|
||||||
dsts.push_back(de);
|
dsts.push_back(de);
|
||||||
|
} else {
|
||||||
|
if (subaddr_indices.empty()) {
|
||||||
|
for (uint32_t index = 0; index < m_wallet->get_num_subaddresses(subaddr_account); ++index)
|
||||||
|
subaddr_indices.insert(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!extra_nonce.empty() && !add_extra_nonce_to_tx_extra(extra, extra_nonce)) {
|
||||||
|
setStatusError(tr("failed to set up payment id, though it was decoded correctly"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (amount) {
|
||||||
transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */,
|
transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */,
|
||||||
adjusted_priority,
|
adjusted_priority,
|
||||||
extra, subaddr_account, subaddr_indices);
|
extra, subaddr_account, subaddr_indices);
|
||||||
} else {
|
} else {
|
||||||
// for the GUI, sweep_all (i.e. amount set as "(all)") will always sweep all the funds in all the addresses
|
|
||||||
if (subaddr_indices.empty())
|
|
||||||
{
|
|
||||||
for (uint32_t index = 0; index < m_wallet->get_num_subaddresses(subaddr_account); ++index)
|
|
||||||
subaddr_indices.insert(index);
|
|
||||||
}
|
|
||||||
transaction->m_pending_tx = m_wallet->create_transactions_all(0, info.address, info.is_subaddress, 1, fake_outs_count, 0 /* unlock_time */,
|
transaction->m_pending_tx = m_wallet->create_transactions_all(0, info.address, info.is_subaddress, 1, fake_outs_count, 0 /* unlock_time */,
|
||||||
adjusted_priority,
|
adjusted_priority,
|
||||||
extra, subaddr_account, subaddr_indices);
|
extra, subaddr_account, subaddr_indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
pendingTxPostProcess(transaction);
|
pendingTxPostProcess(transaction);
|
||||||
|
|
||||||
if (multisig().isMultisig) {
|
if (multisig().isMultisig) {
|
||||||
|
@ -1574,6 +1573,13 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const
|
||||||
return transaction;
|
return transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const string &payment_id, optional<uint64_t> amount, uint32_t mixin_count,
|
||||||
|
PendingTransaction::Priority priority, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices)
|
||||||
|
|
||||||
|
{
|
||||||
|
return createTransactionMultDest(std::vector<string> {dst_addr}, payment_id, amount ? (std::vector<uint64_t> {*amount}) : (optional<std::vector<uint64_t>>()), mixin_count, priority, subaddr_account, subaddr_indices);
|
||||||
|
}
|
||||||
|
|
||||||
PendingTransaction *WalletImpl::createSweepUnmixableTransaction()
|
PendingTransaction *WalletImpl::createSweepUnmixableTransaction()
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -149,6 +149,11 @@ public:
|
||||||
bool hasMultisigPartialKeyImages() const override;
|
bool hasMultisigPartialKeyImages() const override;
|
||||||
PendingTransaction* restoreMultisigTransaction(const std::string& signData) override;
|
PendingTransaction* restoreMultisigTransaction(const std::string& signData) override;
|
||||||
|
|
||||||
|
PendingTransaction * createTransactionMultDest(const std::vector<std::string> &dst_addr, const std::string &payment_id,
|
||||||
|
optional<std::vector<uint64_t>> amount, uint32_t mixin_count,
|
||||||
|
PendingTransaction::Priority priority = PendingTransaction::Priority_Low,
|
||||||
|
uint32_t subaddr_account = 0,
|
||||||
|
std::set<uint32_t> subaddr_indices = {}) override;
|
||||||
PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id,
|
PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id,
|
||||||
optional<uint64_t> amount, uint32_t mixin_count,
|
optional<uint64_t> amount, uint32_t mixin_count,
|
||||||
PendingTransaction::Priority priority = PendingTransaction::Priority_Low,
|
PendingTransaction::Priority priority = PendingTransaction::Priority_Low,
|
||||||
|
|
|
@ -812,6 +812,26 @@ struct Wallet
|
||||||
* @return PendingTransaction
|
* @return PendingTransaction
|
||||||
*/
|
*/
|
||||||
virtual PendingTransaction* restoreMultisigTransaction(const std::string& signData) = 0;
|
virtual PendingTransaction* restoreMultisigTransaction(const std::string& signData) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief createTransactionMultDest creates transaction with multiple destinations. if dst_addr is an integrated address, payment_id is ignored
|
||||||
|
* \param dst_addr vector of destination address as string
|
||||||
|
* \param payment_id optional payment_id, can be empty string
|
||||||
|
* \param amount vector of amounts
|
||||||
|
* \param mixin_count mixin count. if 0 passed, wallet will use default value
|
||||||
|
* \param subaddr_account subaddress account from which the input funds are taken
|
||||||
|
* \param subaddr_indices set of subaddress indices to use for transfer or sweeping. if set empty, all are chosen when sweeping, and one or more are automatically chosen when transferring. after execution, returns the set of actually used indices
|
||||||
|
* \param priority
|
||||||
|
* \return PendingTransaction object. caller is responsible to check PendingTransaction::status()
|
||||||
|
* after object returned
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual PendingTransaction * createTransactionMultDest(const std::vector<std::string> &dst_addr, const std::string &payment_id,
|
||||||
|
optional<std::vector<uint64_t>> amount, uint32_t mixin_count,
|
||||||
|
PendingTransaction::Priority = PendingTransaction::Priority_Low,
|
||||||
|
uint32_t subaddr_account = 0,
|
||||||
|
std::set<uint32_t> subaddr_indices = {}) = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief createTransaction creates transaction. if dst_addr is an integrated address, payment_id is ignored
|
* \brief createTransaction creates transaction. if dst_addr is an integrated address, payment_id is ignored
|
||||||
* \param dst_addr destination address as string
|
* \param dst_addr destination address as string
|
||||||
|
|
Loading…
Reference in New Issue