Skip to content

Commit

Permalink
Update sendmany RPC (#19)
Browse files Browse the repository at this point in the history
* Add fee_asset argument to sendmany RPC

* Add tests for sendmany

* Refactor argument parsing order

* Update sendmany JSON argument parameters

---------

Co-authored-by: Mihailo Milenkovic <[email protected]>
  • Loading branch information
JBetz and Mixa84 authored May 1, 2024
1 parent ca90ba2 commit d8d37a4
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "sendmany", 5 , "replaceable" },
{ "sendmany", 6 , "conf_target" },
{ "sendmany", 10, "fee_rate"},
{ "sendmany", 11, "verbose" },
{ "sendmany", 12, "verbose" },
{ "deriveaddresses", 1, "range" },
{ "scantxoutset", 1, "scanobjects" },
{ "addmultisigaddress", 0, "nrequired" },
Expand Down
14 changes: 13 additions & 1 deletion src/wallet/rpc/spend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ RPCHelpMan sendmany()
},
{"ignoreblindfail", RPCArg::Type::BOOL, RPCArg::Default{true}, "Return a transaction even when a blinding attempt fails due to number of blinded inputs/outputs."},
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
{"fee_asset", RPCArg::Type::STR_HEX, RPCArg::DefaultHint{"not set, fall back to asset being sent"}, "label or hex ID of asset used for fees"},
{"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "If true, return extra information about the transaction."},
},
{
Expand Down Expand Up @@ -377,7 +378,18 @@ RPCHelpMan sendmany()

std::vector<CRecipient> recipients;
ParseRecipients(sendTo, assets, subtractFeeFromAmount, recipients);
bool verbose = request.params[11].isNull() ? false : request.params[11].get_bool();
if (g_con_any_asset_fees && !recipients.empty()) {
CAsset feeAsset = recipients[0].asset;
if (request.params.size() > 11) {
std::string strFeeAsset = request.params[11].get_str();
feeAsset = GetAssetFromString(strFeeAsset);
if (feeAsset.IsNull()) {
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Unknown label and invalid asset hex for fee: %s", feeAsset.GetHex()));
}
}
coin_control.m_fee_asset = feeAsset;
}
bool verbose = request.params[12].isNull() ? false : request.params[12].get_bool();

return SendMoney(*pwallet, coin_control, recipients, std::move(mapValue), verbose, ignore_blind_fail);
},
Expand Down
38 changes: 35 additions & 3 deletions test/functional/feature_any_asset_fee.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def set_test_params(self):
self.num_nodes = 2
self.extra_args = [[
"-blindedaddresses=1",
"-initialfreecoins=1000000000",
"-initialfreecoins=10000000000",
"-con_blocksubsidy=0",
"-con_connect_genesis_outputs=1",
"-con_any_asset_fees=1",
Expand Down Expand Up @@ -106,7 +106,7 @@ def transfer_asset_to_node1(self):
assert_equal(node1_new_balance["trusted"][self.asset], Decimal('2') - Decimal('1') - Decimal('0.00049820'))
assert_equal(node1_new_balance["immature"][self.asset], Decimal('0.00049820'))

def multiple_asset_fees_transfers(self):
def multiple_asset_fees_transfers_with_sendtoaddress(self):
node0_balance = self.nodes[0].getbalances()["mine"]
node1_balance = self.nodes[1].getbalances()["mine"]
assert len(node0_balance["trusted"]) == 3
Expand Down Expand Up @@ -148,6 +148,36 @@ def multiple_asset_fees_transfers(self):
assert_equal(node1_new_balance["trusted"]["gasset"], Decimal('7'))
assert_equal(node1_new_balance["trusted"][self.asset], node1_balance["trusted"][self.asset] + Decimal('3'))

def multiple_asset_fees_transfers_with_sendmany(self):
node0_balance = self.nodes[0].getbalances()["mine"]["trusted"]
node1_balance = self.nodes[1].getbalances()["mine"]["trusted"]
assert len(node0_balance) == 3
assert len(node1_balance) == 2

tx1_id = self.nodes[0].sendmany(
amounts={ self.node1_address: 1.0 },
output_assets={ self.node1_address: self.asset },
fee_asset=self.asset)
tx1 = self.nodes[0].gettransaction(tx1_id)

tx2_id = self.nodes[0].sendmany(
amounts={ self.node1_address: 2.0 },
output_assets={ self.node1_address: self.asset },
fee_asset='gasset')
tx2 = self.nodes[0].gettransaction(tx2_id)

self.generatetoaddress(self.nodes[0], 1, self.node0_address)
self.sync_all()

node0_new_balance = self.nodes[0].getbalances()['mine']['trusted']
assert_equal(node0_new_balance[self.asset], node0_balance[self.asset] - Decimal('3') + tx1['fee'][self.asset])
assert_equal(node0_new_balance['gasset'], node0_balance['gasset'] + tx2['fee']['gasset'])

node1_new_balance = self.nodes[1].getbalances()['mine']['trusted']
assert len(node1_new_balance) == 2
assert_equal(node1_new_balance['gasset'], Decimal('7'))
assert_equal(node1_new_balance[self.asset], node1_balance[self.asset] + Decimal('3'))

def transfer_asset_amount_including_fee(self):
node1_balance = self.nodes[1].getbalances()["mine"]
assert len(node1_balance["trusted"]) == 2
Expand Down Expand Up @@ -194,7 +224,9 @@ def run_test(self):

self.transfer_asset_to_node1()

self.multiple_asset_fees_transfers()
self.multiple_asset_fees_transfers_with_sendtoaddress()

self.multiple_asset_fees_transfers_with_sendmany()

self.transfer_asset_amount_including_fee()

Expand Down

0 comments on commit d8d37a4

Please sign in to comment.