Inside Bitcoin
Opening the selected file…
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.
251{"comment", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A comment used to store what the transaction is for.\n"252"This is not part of the transaction, just kept in your wallet."},253{"comment_to", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A comment to store the name of the person or organization\n"254"to which you're sending the transaction. This is not part of the \n"255"transaction, just kept in your wallet."},256{"subtractfeefromamount", RPCArg::Type::BOOL, RPCArg::Default{false}, "The fee will be deducted from the amount being sent.\n"257"The recipient will receive less bitcoins than you enter in the amount field."},258{"replaceable", RPCArg::Type::BOOL, RPCArg::DefaultHint{"wallet default"}, "Signal that this transaction can be replaced by a transaction (BIP 125)"},259{"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"},260{"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"261+ FeeModesDetail(std::string("economical mode is used if the transaction is replaceable;\notherwise, conservative mode is used"))},262{"avoid_reuse", RPCArg::Type::BOOL, RPCArg::Default{true}, "(only available if avoid_reuse wallet flag is set) Avoid spending from dirty addresses; addresses are considered\n"263"dirty if they have previously been used in a transaction. If true, this also activates avoidpartialspends, grouping outputs by their addresses."},264{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},265{"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "If true, return extra information about the transaction."},266},267{268RPCResult{"if verbose is not set or set to false",269RPCResult::Type::STR_HEX, "txid", "The transaction id."270},271RPCResult{"if verbose is set to true",272RPCResult::Type::OBJ, "", "",273{274{RPCResult::Type::STR_HEX, "txid", "The transaction id."},275{RPCResult::Type::STR, "fee_reason", "The reason the wallet selected this fee rate (e.g. fee rate estimator, mempool minimum, fallback, or minimum required)."}276},277},278},279RPCExamples{280"\nSend 0.1 BTC\n"281+ HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1") +282"\nSend 0.1 BTC with a confirmation target of 6 blocks in economical fee estimate mode using positional arguments\n"283+ HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"donation\" \"sean's outpost\" false true 6 economical") +284"\nSend 0.1 BTC with a fee rate of 1.1 " + CURRENCY_ATOM + "/vB, subtract fee from amount, BIP125-replaceable, using positional arguments\n"285+ HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"drinks\" \"room77\" true true null \"unset\" null 1.1") +286"\nSend 0.2 BTC with a confirmation target of 6 blocks in economical fee estimate mode using named arguments\n"287+ HelpExampleCli("-named sendtoaddress", "address=\"" + EXAMPLE_ADDRESS[0] + "\" amount=0.2 conf_target=6 estimate_mode=\"economical\"") +288"\nSend 0.5 BTC with a fee rate of 25 " + CURRENCY_ATOM + "/vB using named arguments\n"289+ HelpExampleCli("-named sendtoaddress", "address=\"" + EXAMPLE_ADDRESS[0] + "\" amount=0.5 fee_rate=25")290+ HelpExampleCli("-named sendtoaddress", "address=\"" + EXAMPLE_ADDRESS[0] + "\" amount=0.5 fee_rate=25 subtractfeefromamount=false replaceable=true avoid_reuse=true comment=\"2 pizzas\" comment_to=\"jeremy\" verbose=true")291},292[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue293{294std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);295if (!pwallet) return UniValue::VNULL;297// Make sure the results are valid at least up to the most recent block298// the user could have gotten from another RPC command prior to now299pwallet->BlockUntilSyncedToCurrentChain();301LOCK(pwallet->cs_wallet);303// Wallet comments304std::optional<std::string> comment;305std::optional<std::string> comment_to;306if (!request.params[2].isNull() && !request.params[2].get_str().empty())307comment = request.params[2].get_str();308if (!request.params[3].isNull() && !request.params[3].get_str().empty())309comment_to = request.params[3].get_str();311CCoinControl coin_control;312if (!request.params[5].isNull()) {313coin_control.m_signal_bip125_rbf = request.params[5].get_bool();314}316coin_control.m_avoid_address_reuse = GetAvoidReuseFlag(*pwallet, request.params[8]);317// We also enable partial spend avoidance if reuse avoidance is set.318coin_control.m_avoid_partial_spends |= coin_control.m_avoid_address_reuse;320SetFeeEstimateMode(*pwallet, coin_control, /*conf_target=*/request.params[6], /*estimate_mode=*/request.params[7], /*fee_rate=*/request.params[9], /*override_min_fee=*/false);322EnsureWalletIsUnlocked(*pwallet);324UniValue address_amounts(UniValue::VOBJ);325const std::string address = request.params[0].get_str();326address_amounts.pushKV(address, request.params[1]);328std::set<int> sffo_set;329if (!request.params[4].isNull() && request.params[4].get_bool()) {330sffo_set.insert(0);331}333std::vector<CRecipient> recipients{CreateRecipients(ParseOutputs(address_amounts), sffo_set)};334const bool verbose{request.params[10].isNull() ? false : request.params[10].get_bool()};336return SendMoney(*pwallet, coin_control, recipients, comment, comment_to, verbose);337},338};339}341RPCMethod sendmany()342{343return RPCMethod{"sendmany",344"Send multiple times. Amounts are double-precision floating point numbers." +345HELP_REQUIRING_PASSPHRASE,346{347{"dummy", RPCArg::Type::STR, RPCArg::Default{"\"\""}, "Must be set to \"\" for backwards compatibility.",348RPCArgOptions{349.oneline_description = "\"\"",350.placeholder = true,351}},352{"amounts", RPCArg::Type::OBJ_USER_KEYS, RPCArg::Optional::NO, "The addresses and amounts",353{354{"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value"},355},356},357{"minconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "Ignored dummy value",358RPCArgOptions{.placeholder = true}},359{"comment", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A comment"},360{"subtractfeefrom", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "The addresses.\n"361"The fee will be equally deducted from the amount of each selected address.\n"362"Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"363"If no addresses are specified here, the sender pays the fee.",364{365{"address", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Subtract fee from this address"},366},367},368{"replaceable", RPCArg::Type::BOOL, RPCArg::DefaultHint{"wallet default"}, "Signal that this transaction can be replaced by a transaction (BIP 125)"},369{"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"},370{"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"371+ FeeModesDetail(std::string("economical mode is used if the transaction is replaceable;\notherwise, conservative mode is used"))},372{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},373{"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "If true, return extra information about the transaction."},374},375{376RPCResult{"if verbose is not set or set to false",377RPCResult::Type::STR_HEX, "txid", "The transaction id for the send. Only 1 transaction is created regardless of\n"378"the number of addresses."379},380RPCResult{"if verbose is set to true",381RPCResult::Type::OBJ, "", "",382{383{RPCResult::Type::STR_HEX, "txid", "The transaction id for the send. Only 1 transaction is created regardless of\n"384"the number of addresses."},385{RPCResult::Type::STR, "fee_reason", "The reason the wallet selected this fee rate (e.g. fee rate estimator, mempool minimum, fallback, or minimum required)."}386},387},388},389RPCExamples{390"\nSend two amounts to two different addresses:\n"391+ HelpExampleCli("sendmany", "\"\" \"{\\\"" + EXAMPLE_ADDRESS[0] + "\\\":0.01,\\\"" + EXAMPLE_ADDRESS[1] + "\\\":0.02}\"") +392"\nSend two amounts to two different addresses setting the confirmation and comment:\n"393+ HelpExampleCli("sendmany", "\"\" \"{\\\"" + EXAMPLE_ADDRESS[0] + "\\\":0.01,\\\"" + EXAMPLE_ADDRESS[1] + "\\\":0.02}\" 6 \"testing\"") +394"\nSend two amounts to two different addresses, subtract fee from amount:\n"395+ HelpExampleCli("sendmany", "\"\" \"{\\\"" + EXAMPLE_ADDRESS[0] + "\\\":0.01,\\\"" + EXAMPLE_ADDRESS[1] + "\\\":0.02}\" 1 \"\" \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"") +396"\nAs a JSON-RPC call\n"397+ HelpExampleRpc("sendmany", "\"\", {\"" + EXAMPLE_ADDRESS[0] + "\":0.01,\"" + EXAMPLE_ADDRESS[1] + "\":0.02}, 6, \"testing\"")398},399[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue400{401std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);402if (!pwallet) return UniValue::VNULL;404// Make sure the results are valid at least up to the most recent block405// the user could have gotten from another RPC command prior to now406pwallet->BlockUntilSyncedToCurrentChain();408LOCK(pwallet->cs_wallet);410if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {411throw JSONRPCError(RPC_INVALID_PARAMETER, "Dummy value must be set to \"\"");412}413UniValue sendTo = request.params[1].get_obj();415std::optional<std::string> comment;416if (!request.params[3].isNull() && !request.params[3].get_str().empty())417comment = request.params[3].get_str();419CCoinControl coin_control;420if (!request.params[5].isNull()) {421coin_control.m_signal_bip125_rbf = request.params[5].get_bool();422}424SetFeeEstimateMode(*pwallet, coin_control, /*conf_target=*/request.params[6], /*estimate_mode=*/request.params[7], /*fee_rate=*/request.params[8], /*override_min_fee=*/false);426std::vector<CRecipient> recipients = CreateRecipients(427ParseOutputs(sendTo),428InterpretSubtractFeeFromOutputInstructions(request.params[4], sendTo.getKeys())429);430const bool verbose{request.params[9].isNull() ? false : request.params[9].get_bool()};432return SendMoney(*pwallet, coin_control, recipients, comment, /*comment_to=*/std::nullopt, verbose);433},434};435}437// Only includes key documentation where the key is snake_case in all RPC methods. MixedCase keys can be added later.438static std::vector<RPCArg> FundTxDoc(bool solving_data = true)439{440std::vector<RPCArg> args = {441{"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks", RPCArgOptions{.also_positional = true}},442{"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"443+ FeeModesDetail(std::string("economical mode is used if the transaction is replaceable;\notherwise, conservative mode is used")), RPCArgOptions{.also_positional = true}},444{445"replaceable", RPCArg::Type::BOOL, RPCArg::DefaultHint{"wallet default"}, "Marks this transaction as BIP125-replaceable.\n"446"Allows this transaction to be replaced by a transaction with higher fees"447},448};449if (solving_data) {450args.push_back({"solving_data", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "Keys and scripts needed for producing a final transaction with a dummy signature.\n"451"Used for fee estimation during coin selection.",452{453{454"pubkeys", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Public keys involved in this transaction.",455{456{"pubkey", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A public key"},457}458},459{460"scripts", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Scripts involved in this transaction.",461{462{"script", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A script"},463}464},465{466"descriptors", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Descriptors that provide solving data for this transaction.",467{468{"descriptor", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A descriptor"},469}470},471}472});473}474return args;475}477CreatedTransactionResult FundTransaction(CWallet& wallet, const CMutableTransaction& tx, const std::vector<CRecipient>& recipients, const UniValue& options, CCoinControl& coinControl, bool override_min_fee)478{479// We want to make sure tx.vout is not used now that we are passing outputs as a vector of recipients.480// This sets us up to remove tx completely in a future PR in favor of passing the inputs directly.481CHECK_NONFATAL(tx.vout.empty());482// Make sure the results are valid at least up to the most recent block483// the user could have gotten from another RPC command prior to now484wallet.BlockUntilSyncedToCurrentChain();486std::optional<unsigned int> change_position;487bool lockUnspents = false;488if (!options.isNull()) {489RPCTypeCheckObj(options,490{491{"add_inputs", UniValueType(UniValue::VBOOL)},492{"include_unsafe", UniValueType(UniValue::VBOOL)},493{"add_to_wallet", UniValueType(UniValue::VBOOL)},494{"changeAddress", UniValueType(UniValue::VSTR)},495{"change_address", UniValueType(UniValue::VSTR)},496{"changePosition", UniValueType(UniValue::VNUM)},497{"change_position", UniValueType(UniValue::VNUM)},498{"change_type", UniValueType(UniValue::VSTR)},499{"includeWatching", UniValueType(UniValue::VBOOL)},500{"include_watching", UniValueType(UniValue::VBOOL)},