Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1251},1252RPCExamples{""1253"\nSend 0.1 BTC with a confirmation target of 6 blocks in economical fee estimate mode\n"1254+ HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.1}' 6 economical\n") +1255"Send 0.2 BTC with a fee rate of 1.1 " + CURRENCY_ATOM + "/vB using positional arguments\n"1256+ HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.2}' null \"unset\" 1.1\n") +1257"Send 0.2 BTC with a fee rate of 1 " + CURRENCY_ATOM + "/vB using the options argument\n"1258+ HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.2}' null \"unset\" null '{\"fee_rate\": 1}'\n") +1259"Send 0.3 BTC with a fee rate of 25 " + CURRENCY_ATOM + "/vB using named arguments\n"1260+ HelpExampleCli("-named send", "outputs='{\"" + EXAMPLE_ADDRESS[0] + "\": 0.3}' fee_rate=25\n") +1261"Create a transaction that should confirm the next block, with a specific input, and return result without adding to wallet or broadcasting to the network\n"1262+ HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.1}' 1 economical null '{\"add_to_wallet\": false, \"inputs\": [{\"txid\":\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\", \"vout\":1}]}'")1263},1264[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue1265{1266std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);1267if (!pwallet) return UniValue::VNULL;1269UniValue options{request.params[4].isNull() ? UniValue::VOBJ : request.params[4]};1270InterpretFeeEstimationInstructions(/*conf_target=*/request.params[1], /*estimate_mode=*/request.params[2], /*fee_rate=*/request.params[3], options);1271PreventOutdatedOptions(options);1274bool rbf{options.exists("replaceable") ? options["replaceable"].get_bool() : pwallet->m_signal_rbf};1275UniValue outputs(UniValue::VOBJ);1276outputs = NormalizeOutputs(request.params[0]);1277std::vector<CRecipient> recipients = CreateRecipients(1278ParseOutputs(outputs),1279InterpretSubtractFeeFromOutputInstructions(options["subtract_fee_from_outputs"], outputs.getKeys())1280);1281CCoinControl coin_control;1282coin_control.m_version = self.Arg<uint32_t>("version");1283CMutableTransaction rawTx = ConstructTransaction(options["inputs"], request.params[0], options["locktime"], rbf, coin_control.m_version);1284// Automatically select coins, unless at least one is manually selected. Can1285// be overridden by options.add_inputs.1286coin_control.m_allow_other_inputs = rawTx.vin.size() == 0;1287if (options.exists("max_tx_weight")) {1288coin_control.m_max_tx_weight = options["max_tx_weight"].getInt<int>();1289}1291SetOptionsInputWeights(options["inputs"], options);1292// Clear tx.vout since it is not meant to be used now that we are passing outputs directly.1293// This sets us up for a future PR to completely remove tx from the function signature in favor of passing inputs directly1294rawTx.vout.clear();1295auto txr = FundTransaction(*pwallet, rawTx, recipients, options, coin_control, /*override_min_fee=*/false);1297CMutableTransaction tx = CMutableTransaction(*txr.tx);1298return FinishTransaction(pwallet, options, tx);1299}1300};1301}1303RPCMethod sendall()1304{1305return RPCMethod{"sendall",1306"Spend the value of all (or specific) confirmed UTXOs and unconfirmed change in the wallet to one or more recipients.\n"1307"Unconfirmed inbound UTXOs and locked UTXOs will not be spent. Sendall will respect the avoid_reuse wallet flag.\n"1308"If your wallet contains many small inputs, either because it received tiny payments or as a result of accumulating change, consider using `send_max` to exclude inputs that are worth less than the fees needed to spend them.\n",1309{1310{"recipients", RPCArg::Type::ARR, RPCArg::Optional::NO, "The sendall destinations. Each address may only appear once.\n"1311"Optionally some recipients can be specified with an amount to perform payments, but at least one address must appear without a specified amount.\n",1312{1313{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "A bitcoin address which receives an equal share of the unspecified amount."},1314{"", RPCArg::Type::OBJ_USER_KEYS, RPCArg::Optional::OMITTED, "",1315{1316{"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "A key-value pair. The key (string) is the bitcoin address, the value (float or string) is the amount in " + CURRENCY_UNIT + ""},1317},1318},1319},1320},1321{"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"},1322{"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"1323+ FeeModesDetail(std::string("economical mode is used if the transaction is replaceable;\notherwise, conservative mode is used"))},1324{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},1325{1326"options", RPCArg::Type::OBJ_NAMED_PARAMS, RPCArg::Optional::OMITTED, "",1327Cat<std::vector<RPCArg>>(1328{1329{"add_to_wallet", RPCArg::Type::BOOL, RPCArg::Default{true}, "When false, returns the serialized transaction without broadcasting or adding it to the wallet"},1330{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB.", RPCArgOptions{.also_positional = true}},1331{"include_watching", RPCArg::Type::BOOL, RPCArg::Default{false}, "(DEPRECATED) No longer used"},1332{"inputs", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Use exactly the specified inputs to build the transaction. Specifying inputs is incompatible with the send_max, minconf, and maxconf options.",1333{1334{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",1335{1336{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},1337{"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},1338{"sequence", RPCArg::Type::NUM, RPCArg::DefaultHint{"depends on the value of the 'replaceable' and 'locktime' arguments"}, "The sequence number"},1339},1340},1341},1342},1343{"locktime", RPCArg::Type::NUM, RPCArg::DefaultHint{"locktime close to block height to prevent fee sniping"}, "Raw locktime. Non-0 value also locktime-activates inputs"},1344{"lock_unspents", RPCArg::Type::BOOL, RPCArg::Default{false}, "Lock selected unspent outputs"},1345{"psbt", RPCArg::Type::BOOL, RPCArg::DefaultHint{"automatic"}, "Always return a PSBT, implies add_to_wallet=false."},1346{"send_max", RPCArg::Type::BOOL, RPCArg::Default{false}, "When true, only use UTXOs that can pay for their own fees to maximize the output amount. When 'false' (default), no UTXO is left behind. send_max is incompatible with providing specific inputs."},1347{"minconf", RPCArg::Type::NUM, RPCArg::Default{0}, "Require inputs with at least this many confirmations."},1348{"maxconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "Require inputs with at most this many confirmations."},1349{"version", RPCArg::Type::NUM, RPCArg::Default{DEFAULT_WALLET_TX_VERSION}, "Transaction version"},1350},1351FundTxDoc()1352),1353RPCArgOptions{.oneline_description="options"}1354},1355},1356RPCResult{1357RPCResult::Type::OBJ, "", "",1358{1359{RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},1360{RPCResult::Type::STR_HEX, "txid", /*optional=*/true, "The transaction id for the send. Only 1 transaction is created regardless of the number of addresses."},1361{RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "If add_to_wallet is false, the hex-encoded raw transaction with signature(s)"},1362{RPCResult::Type::STR, "psbt", /*optional=*/true, "If more signatures are needed, or if add_to_wallet is false, the base64-encoded (partially) signed transaction"}1363}1364},1365RPCExamples{""1366"\nSpend all UTXOs from the wallet with a fee rate of 1 " + CURRENCY_ATOM + "/vB using named arguments\n"1367+ HelpExampleCli("-named sendall", "recipients='[\"" + EXAMPLE_ADDRESS[0] + "\"]' fee_rate=1\n") +1368"Spend all UTXOs with a fee rate of 1.1 " + CURRENCY_ATOM + "/vB using positional arguments\n"1369+ HelpExampleCli("sendall", "'[\"" + EXAMPLE_ADDRESS[0] + "\"]' null \"unset\" 1.1\n") +1370"Spend all UTXOs split into equal amounts to two addresses with a fee rate of 1.5 " + CURRENCY_ATOM + "/vB using the options argument\n"1371+ HelpExampleCli("sendall", "'[\"" + EXAMPLE_ADDRESS[0] + "\", \"" + EXAMPLE_ADDRESS[1] + "\"]' null \"unset\" null '{\"fee_rate\": 1.5}'\n") +1372"Leave dust UTXOs in wallet, spend only UTXOs with positive effective value with a fee rate of 10 " + CURRENCY_ATOM + "/vB using the options argument\n"1373+ HelpExampleCli("sendall", "'[\"" + EXAMPLE_ADDRESS[0] + "\"]' null \"unset\" null '{\"fee_rate\": 10, \"send_max\": true}'\n") +1374"Spend all UTXOs with a fee rate of 1.3 " + CURRENCY_ATOM + "/vB using named arguments and sending a 0.25 " + CURRENCY_UNIT + " to another recipient\n"1375+ HelpExampleCli("-named sendall", "recipients='[{\"" + EXAMPLE_ADDRESS[1] + "\": 0.25}, \""+ EXAMPLE_ADDRESS[0] + "\"]' fee_rate=1.3\n")1376},1377[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue1378{1379std::shared_ptr<CWallet> const pwallet{GetWalletForJSONRPCRequest(request)};1380if (!pwallet) return UniValue::VNULL;1381// Make sure the results are valid at least up to the most recent block1382// the user could have gotten from another RPC command prior to now1383pwallet->BlockUntilSyncedToCurrentChain();1385UniValue options{request.params[4].isNull() ? UniValue::VOBJ : request.params[4]};1386InterpretFeeEstimationInstructions(/*conf_target=*/request.params[1], /*estimate_mode=*/request.params[2], /*fee_rate=*/request.params[3], options);1387PreventOutdatedOptions(options);1390std::set<std::string> addresses_without_amount;1391UniValue recipient_key_value_pairs(UniValue::VARR);1392const UniValue& recipients{request.params[0]};1393for (unsigned int i = 0; i < recipients.size(); ++i) {1394const UniValue& recipient{recipients[i]};1395if (recipient.isStr()) {1396UniValue rkvp(UniValue::VOBJ);1397rkvp.pushKV(recipient.get_str(), 0);1398recipient_key_value_pairs.push_back(std::move(rkvp));1399addresses_without_amount.insert(recipient.get_str());1400} else {1401recipient_key_value_pairs.push_back(recipient);1402}1403}1405if (addresses_without_amount.size() == 0) {1406throw JSONRPCError(RPC_INVALID_PARAMETER, "Must provide at least one address without a specified amount");1407}1409CCoinControl coin_control;1411SetFeeEstimateMode(*pwallet, coin_control, options["conf_target"], options["estimate_mode"], options["fee_rate"], /*override_min_fee=*/false);1413if (options.exists("minconf")) {1414if (options["minconf"].getInt<int>() < 0)1415{1416throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid minconf (minconf cannot be negative): %s", options["minconf"].getInt<int>()));1417}1419coin_control.m_min_depth = options["minconf"].getInt<int>();1420}1422if (options.exists("maxconf")) {1423coin_control.m_max_depth = options["maxconf"].getInt<int>();1425if (coin_control.m_max_depth < coin_control.m_min_depth) {1426throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("maxconf can't be lower than minconf: %d < %d", coin_control.m_max_depth, coin_control.m_min_depth));1427}1428}1430if (options.exists("version")) {1431coin_control.m_version = options["version"].getInt<decltype(coin_control.m_version)>();1432}1434if (coin_control.m_version == TRUC_VERSION) {1435coin_control.m_max_tx_weight = TRUC_MAX_WEIGHT;1436} else {1437coin_control.m_max_tx_weight = MAX_STANDARD_TX_WEIGHT;1438}1440const bool rbf{options.exists("replaceable") ? options["replaceable"].get_bool() : pwallet->m_signal_rbf};1442auto [fee_rate, fee_reason, returned_target] = GetMinimumFeeRate(*pwallet, coin_control);1443// Do not, ever, assume that it's fine to change the fee rate if the user has explicitly1444// provided one1445if (coin_control.m_feerate && fee_rate > *coin_control.m_feerate) {1446const auto feerate_format = FeeRateFormat::SAT_VB;1447auto msg{strprintf("Fee rate (%s) is lower than the minimum fee rate setting (%s).",1448coin_control.m_feerate->ToString(feerate_format),1449fee_rate.ToString(feerate_format))};1450if (fee_reason == FeeReason::REQUIRED) {1451msg += strprintf("\nConsider modifying -mintxfee (%s) or -minrelaytxfee (%s).",1452pwallet->m_min_fee.ToString(feerate_format),1453pwallet->chain().relayMinFee().ToString(feerate_format));1454}1455throw JSONRPCError(RPC_INVALID_PARAMETER, msg);1456}1457if (fee_reason == FeeReason::FALLBACK && !pwallet->m_allow_fallback_fee) {1458// eventually allow a fallback fee1459throw JSONRPCError(RPC_WALLET_ERROR, "Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.");1460}1462CMutableTransaction rawTx{ConstructTransaction(options["inputs"], recipient_key_value_pairs, options["locktime"], rbf, coin_control.m_version)};1463LOCK(pwallet->cs_wallet);1465CAmount total_input_value(0);1466bool send_max{options.exists("send_max") ? options["send_max"].get_bool() : false};1467if (options.exists("inputs") && options.exists("send_max")) {1468throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot combine send_max with specific inputs.");1469} else if (options.exists("inputs") && (options.exists("minconf") || options.exists("maxconf"))) {1470throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot combine minconf or maxconf with specific inputs.");1471} else if (options.exists("inputs")) {1472for (const CTxIn& input : rawTx.vin) {1473if (pwallet->IsSpent(input.prevout)) {1474throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input not available. UTXO (%s:%d) was already spent.", input.prevout.hash.ToString(), input.prevout.n));1475}1476const CWalletTx* tx{pwallet->GetWalletTx(input.prevout.hash)};1477if (!tx || input.prevout.n >= tx->GetTx()->vout.size() || !pwallet->IsMine(tx->GetTx()->vout[input.prevout.n])) {1478throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input not found. UTXO (%s:%d) is not part of wallet.", input.prevout.hash.ToString(), input.prevout.n));1479}1480if (pwallet->GetTxDepthInMainChain(*tx) == 0) {1481if (tx->GetTx()->version == TRUC_VERSION && coin_control.m_version != TRUC_VERSION) {1482throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Can't spend unconfirmed version 3 pre-selected input with a version %d tx", coin_control.m_version));1483} else if (coin_control.m_version == TRUC_VERSION && tx->GetTx()->version != TRUC_VERSION) {1484throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Can't spend unconfirmed version %d pre-selected input with a version 3 tx", tx->GetTx()->version));1485}1486}1487total_input_value += tx->GetTx()->vout[input.prevout.n].nValue;1488}1489} else {1490CoinFilterParams coins_params;1491coins_params.min_amount = 0;1492for (const COutput& output : AvailableCoins(*pwallet, &coin_control, fee_rate, coins_params).All()) {1493if (send_max && fee_rate.GetFee(output.input_bytes) > output.txout.nValue) {1494continue;1495}1496// we are spending an unconfirmed TRUC transaction, so lower max weight1497if (output.depth == 0 && coin_control.m_version == TRUC_VERSION) {1498coin_control.m_max_tx_weight = TRUC_CHILD_MAX_WEIGHT;1499}1500CTxIn input(output.outpoint.hash, output.outpoint.n, CScript(), rbf ? MAX_BIP125_RBF_SEQUENCE : CTxIn::MAX_SEQUENCE_NONFINAL);