From bf91c4eb6c73dde658730ae31bb24cacd5fc0fd5 Mon Sep 17 00:00:00 2001 From: DanS Date: Thu, 11 Jun 2026 22:36:37 -0500 Subject: [PATCH] fix(send): pass the z_sendmany fee as a number, not a string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A prior change passed the user-selected fee to z_sendmany as a fixed-decimal string (mirroring the recipient amount). But the daemon reads the fee param with UniValue::get_real(), which rejects a string with "JSON value is not a number as expected" — breaking every z_sendmany send (surfaced via the address-to-address transfer feature). Pass the raw double instead. get_real() parses it directly and accepts any number notation (including the "5e-05" form of a small fee), so this is correct for all fee values. The recipient "amount" stays a fixed-decimal string on purpose — that field is parsed with ParseFixedPoint, which a scientific-notation double would break. Co-Authored-By: Claude Opus 4.8 --- src/app_network.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/app_network.cpp b/src/app_network.cpp index e97ba9d..544b119 100644 --- a/src/app_network.cpp +++ b/src/app_network.cpp @@ -2300,16 +2300,18 @@ void App::sendTransaction(const std::string& from, const std::string& to, send_progress_active_ = true; ++send_submissions_in_flight_; - // z_sendmany signature is (fromaddress, amounts, minconf, fee). Pass the user-selected - // fee explicitly — formatted as a fixed-decimal string so the daemon's ParseFixedPoint - // accepts it (a small double like 0.00005 would serialize to "5e-05" and be rejected). - const std::string fee_str = util::formatAmountFixed(fee); - worker_->post([this, from, to, amount, fee_str, memo, recipients, callback]() -> rpc::RPCWorker::MainCb { + // z_sendmany signature is (fromaddress, amounts, minconf, fee). The fee MUST be a JSON number: + // the daemon reads it with get_real(), so a string is rejected ("JSON value is not a number as + // expected"). get_real() parses the double directly and accepts any number notation (incl. the + // "5e-05" form of a small fee), so passing the raw double is correct for every fee value. + // (The recipient "amount" above is intentionally a fixed-decimal STRING — that field is parsed + // with ParseFixedPoint, which a scientific-notation double would break.) + worker_->post([this, from, to, amount, fee, memo, recipients, callback]() -> rpc::RPCWorker::MainCb { bool ok = false; std::string result_str; try { rpc::RPCClient::TraceScope trace("Send tab / Submit transaction"); - auto result = rpc_->call("z_sendmany", {from, recipients, 1, fee_str}); + auto result = rpc_->call("z_sendmany", {from, recipients, 1, fee}); result_str = result.get(); ok = true; } catch (const std::exception& e) {