Skip to content
This repository was archived by the owner on Aug 25, 2026. It is now read-only.

Commit 8e0ffe3

Browse files
JBetzMixa84
andcommitted
Update sendmany RPC (ElementsProject#19)
* 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 <mihailo.milenkovic84@gmail.com>
1 parent cffcaa1 commit 8e0ffe3

3 files changed

Lines changed: 49 additions & 5 deletions

File tree

src/rpc/client.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
8080
{ "sendmany", 5 , "replaceable" },
8181
{ "sendmany", 6 , "conf_target" },
8282
{ "sendmany", 10, "fee_rate"},
83-
{ "sendmany", 11, "verbose" },
83+
{ "sendmany", 12, "verbose" },
8484
{ "deriveaddresses", 1, "range" },
8585
{ "scantxoutset", 1, "scanobjects" },
8686
{ "addmultisigaddress", 0, "nrequired" },

src/wallet/rpc/spend.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ RPCHelpMan sendmany()
305305
},
306306
{"ignoreblindfail", RPCArg::Type::BOOL, RPCArg::Default{true}, "Return a transaction even when a blinding attempt fails due to number of blinded inputs/outputs."},
307307
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
308+
{"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"},
308309
{"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "If true, return extra information about the transaction."},
309310
},
310311
{
@@ -377,7 +378,18 @@ RPCHelpMan sendmany()
377378

378379
std::vector<CRecipient> recipients;
379380
ParseRecipients(sendTo, assets, subtractFeeFromAmount, recipients);
380-
bool verbose = request.params[11].isNull() ? false : request.params[11].get_bool();
381+
if (g_con_any_asset_fees && !recipients.empty()) {
382+
CAsset feeAsset = recipients[0].asset;
383+
if (request.params.size() > 11) {
384+
std::string strFeeAsset = request.params[11].get_str();
385+
feeAsset = GetAssetFromString(strFeeAsset);
386+
if (feeAsset.IsNull()) {
387+
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Unknown label and invalid asset hex for fee: %s", feeAsset.GetHex()));
388+
}
389+
}
390+
coin_control.m_fee_asset = feeAsset;
391+
}
392+
bool verbose = request.params[12].isNull() ? false : request.params[12].get_bool();
381393

382394
return SendMoney(*pwallet, coin_control, recipients, std::move(mapValue), verbose, ignore_blind_fail);
383395
},

test/functional/feature_any_asset_fee.py

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def set_test_params(self):
1818
self.num_nodes = 2
1919
self.extra_args = [[
2020
"-blindedaddresses=1",
21-
"-initialfreecoins=1000000000",
21+
"-initialfreecoins=10000000000",
2222
"-con_blocksubsidy=0",
2323
"-con_connect_genesis_outputs=1",
2424
"-con_any_asset_fees=1",
@@ -106,7 +106,7 @@ def transfer_asset_to_node1(self):
106106
assert_equal(node1_new_balance["trusted"][self.asset], Decimal('2') - Decimal('1') - Decimal('0.00049820'))
107107
assert_equal(node1_new_balance["immature"][self.asset], Decimal('0.00049820'))
108108

109-
def multiple_asset_fees_transfers(self):
109+
def multiple_asset_fees_transfers_with_sendtoaddress(self):
110110
node0_balance = self.nodes[0].getbalances()["mine"]
111111
node1_balance = self.nodes[1].getbalances()["mine"]
112112
assert len(node0_balance["trusted"]) == 3
@@ -148,6 +148,36 @@ def multiple_asset_fees_transfers(self):
148148
assert_equal(node1_new_balance["trusted"]["gasset"], Decimal('7'))
149149
assert_equal(node1_new_balance["trusted"][self.asset], node1_balance["trusted"][self.asset] + Decimal('3'))
150150

151+
def multiple_asset_fees_transfers_with_sendmany(self):
152+
node0_balance = self.nodes[0].getbalances()["mine"]["trusted"]
153+
node1_balance = self.nodes[1].getbalances()["mine"]["trusted"]
154+
assert len(node0_balance) == 3
155+
assert len(node1_balance) == 2
156+
157+
tx1_id = self.nodes[0].sendmany(
158+
amounts={ self.node1_address: 1.0 },
159+
output_assets={ self.node1_address: self.asset },
160+
fee_asset=self.asset)
161+
tx1 = self.nodes[0].gettransaction(tx1_id)
162+
163+
tx2_id = self.nodes[0].sendmany(
164+
amounts={ self.node1_address: 2.0 },
165+
output_assets={ self.node1_address: self.asset },
166+
fee_asset='gasset')
167+
tx2 = self.nodes[0].gettransaction(tx2_id)
168+
169+
self.generatetoaddress(self.nodes[0], 1, self.node0_address)
170+
self.sync_all()
171+
172+
node0_new_balance = self.nodes[0].getbalances()['mine']['trusted']
173+
assert_equal(node0_new_balance[self.asset], node0_balance[self.asset] - Decimal('3') + tx1['fee'][self.asset])
174+
assert_equal(node0_new_balance['gasset'], node0_balance['gasset'] + tx2['fee']['gasset'])
175+
176+
node1_new_balance = self.nodes[1].getbalances()['mine']['trusted']
177+
assert len(node1_new_balance) == 2
178+
assert_equal(node1_new_balance['gasset'], Decimal('7'))
179+
assert_equal(node1_new_balance[self.asset], node1_balance[self.asset] + Decimal('3'))
180+
151181
def transfer_asset_amount_including_fee(self):
152182
node1_balance = self.nodes[1].getbalances()["mine"]
153183
assert len(node1_balance["trusted"]) == 2
@@ -194,7 +224,9 @@ def run_test(self):
194224

195225
self.transfer_asset_to_node1()
196226

197-
self.multiple_asset_fees_transfers()
227+
self.multiple_asset_fees_transfers_with_sendtoaddress()
228+
229+
self.multiple_asset_fees_transfers_with_sendmany()
198230

199231
self.transfer_asset_amount_including_fee()
200232

0 commit comments

Comments
 (0)