| 441 | } |
| 442 | |
| 443 | void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out, int& change_position, const UniValue& options, CCoinControl& coinControl, bool override_min_fee) |
| 444 | { |
| 445 | // Make sure the results are valid at least up to the most recent block |
| 446 | // the user could have gotten from another RPC command prior to now |
| 447 | wallet.BlockUntilSyncedToCurrentChain(); |
| 448 | |
| 449 | change_position = -1; |
| 450 | bool lockUnspents = false; |
| 451 | UniValue subtractFeeFromOutputs; |
| 452 | std::set<int> setSubtractFeeFromOutputs; |
| 453 | |
| 454 | if (!options.isNull()) { |
| 455 | if (options.type() == UniValue::VBOOL) { |
| 456 | // backward compatibility bool only fallback |
| 457 | coinControl.fAllowWatchOnly = options.get_bool(); |
| 458 | } |
| 459 | else { |
| 460 | RPCTypeCheckArgument(options, UniValue::VOBJ); |
| 461 | |
| 462 | RPCTypeCheckObj(options, |
| 463 | { |
| 464 | {"add_inputs", UniValueType(UniValue::VBOOL)}, |
| 465 | {"include_unsafe", UniValueType(UniValue::VBOOL)}, |
| 466 | {"add_to_wallet", UniValueType(UniValue::VBOOL)}, |
| 467 | {"changeAddress", UniValueType()}, // will be checked below |
| 468 | {"change_address", UniValueType()}, // will be checked below |
| 469 | {"changePosition", UniValueType(UniValue::VNUM)}, |
| 470 | {"change_position", UniValueType(UniValue::VNUM)}, |
| 471 | {"change_type", UniValueType(UniValue::VSTR)}, |
| 472 | {"includeWatching", UniValueType(UniValue::VBOOL)}, |
| 473 | {"include_watching", UniValueType(UniValue::VBOOL)}, |
| 474 | {"inputs", UniValueType(UniValue::VARR)}, |
| 475 | {"lockUnspents", UniValueType(UniValue::VBOOL)}, |
| 476 | {"lock_unspents", UniValueType(UniValue::VBOOL)}, |
| 477 | {"locktime", UniValueType(UniValue::VNUM)}, |
| 478 | {"fee_rate", UniValueType()}, // will be checked by AmountFromValue() in SetFeeEstimateMode() |
| 479 | {"feeRate", UniValueType()}, // will be checked by AmountFromValue() below |
| 480 | {"psbt", UniValueType(UniValue::VBOOL)}, |
| 481 | {"solving_data", UniValueType(UniValue::VOBJ)}, |
| 482 | {"subtractFeeFromOutputs", UniValueType(UniValue::VARR)}, |
| 483 | {"subtract_fee_from_outputs", UniValueType(UniValue::VARR)}, |
| 484 | {"replaceable", UniValueType(UniValue::VBOOL)}, |
| 485 | {"conf_target", UniValueType(UniValue::VNUM)}, |
| 486 | {"estimate_mode", UniValueType(UniValue::VSTR)}, |
| 487 | {"include_explicit", UniValueType(UniValue::VBOOL)}, |
| 488 | {"input_weights", UniValueType(UniValue::VARR)}, |
| 489 | }, |
| 490 | true, true); |
| 491 | |
| 492 | if (options.exists("add_inputs") ) { |
| 493 | coinControl.m_add_inputs = options["add_inputs"].get_bool(); |
| 494 | } |
| 495 | |
| 496 | if (options.exists("changeAddress") || options.exists("change_address")) { |
| 497 | const UniValue& change_address = options.exists("change_address") ? options["change_address"] : options["changeAddress"]; |
| 498 | std::map<CAsset, CTxDestination> destinations; |
| 499 | |
| 500 | if (change_address.isStr()) { |
no test coverage detected