@@ -2437,7 +2437,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
24372437
24382438 if (fHelp || params.size () < 1 || params.size () > 2 )
24392439 throw runtime_error (
2440- " fundrawtransaction \" hexstring\" includeWatching \n "
2440+ " fundrawtransaction \" hexstring\" ( options ) \n "
24412441 " \n Add inputs to a transaction until it has enough in value to meet its out value.\n "
24422442 " This will not modify existing inputs, and will add one change output to the outputs.\n "
24432443 " Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n "
@@ -2447,8 +2447,15 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
24472447 " in the wallet using importaddress or addmultisigaddress (to calculate fees).\n "
24482448 " Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n "
24492449 " \n Arguments:\n "
2450- " 1. \" hexstring\" (string, required) The hex string of the raw transaction\n "
2451- " 2. includeWatching (boolean, optional, default false) Also select inputs which are watch only\n "
2450+ " 1. \" hexstring\" (string, required) The hex string of the raw transaction\n "
2451+ " 2. options (object, optional)\n "
2452+ " {\n "
2453+ " \" changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n "
2454+ " \" changePosition\" (numeric, optional, default random) The index of the change output\n "
2455+ " \" includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n "
2456+ " \" lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n "
2457+ " }\n "
2458+ " for backward compatibility: passing in a true instzead of an object will result in {\" includeWatching\" :true}\n "
24522459 " \n Result:\n "
24532460 " {\n "
24542461 " \" hex\" : \" value\" , (string) The resulting raw transaction (hex-encoded string)\n "
@@ -2467,7 +2474,44 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
24672474 + HelpExampleCli (" sendrawtransaction" , " \" signedtransactionhex\" " )
24682475 );
24692476
2470- RPCTypeCheck (params, boost::assign::list_of (UniValue::VSTR)(UniValue::VBOOL));
2477+ RPCTypeCheck (params, boost::assign::list_of (UniValue::VSTR));
2478+
2479+ CTxDestination changeAddress = CNoDestination ();
2480+ int changePosition = -1 ;
2481+ bool includeWatching = false ;
2482+ bool lockUnspents = false ;
2483+
2484+ if (params.size () > 1 ) {
2485+ if (params[1 ].type () == UniValue::VBOOL) {
2486+ // backward compatibility bool only fallback
2487+ includeWatching = params[1 ].get_bool ();
2488+ }
2489+ else {
2490+ RPCTypeCheck (params, boost::assign::list_of (UniValue::VSTR)(UniValue::VOBJ));
2491+
2492+ UniValue options = params[1 ];
2493+
2494+ RPCTypeCheckObj (options, boost::assign::map_list_of (" changeAddress" , UniValue::VSTR)(" changePosition" , UniValue::VNUM)(" includeWatching" , UniValue::VBOOL)(" lockUnspents" , UniValue::VBOOL), true , true );
2495+
2496+ if (options.exists (" changeAddress" )) {
2497+ CBitcoinAddress address (options[" changeAddress" ].get_str ());
2498+
2499+ if (!address.IsValid ())
2500+ throw JSONRPCError (RPC_INVALID_PARAMETER, " changeAddress must be a valid bitcoin address" );
2501+
2502+ changeAddress = address.Get ();
2503+ }
2504+
2505+ if (options.exists (" changePosition" ))
2506+ changePosition = options[" changePosition" ].get_int ();
2507+
2508+ if (options.exists (" includeWatching" ))
2509+ includeWatching = options[" includeWatching" ].get_bool ();
2510+
2511+ if (options.exists (" lockUnspents" ))
2512+ lockUnspents = options[" lockUnspents" ].get_bool ();
2513+ }
2514+ }
24712515
24722516 // parse hex string from parameter
24732517 CTransaction origTx;
@@ -2477,20 +2521,19 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
24772521 if (origTx.vout .size () == 0 )
24782522 throw JSONRPCError (RPC_INVALID_PARAMETER, " TX must have at least one output" );
24792523
2480- bool includeWatching = false ;
2481- if (params.size () > 1 )
2482- includeWatching = params[1 ].get_bool ();
2524+ if (changePosition != -1 && (changePosition < 0 || changePosition > origTx.vout .size ()))
2525+ throw JSONRPCError (RPC_INVALID_PARAMETER, " changePosition out of bounds" );
24832526
24842527 CMutableTransaction tx (origTx);
24852528 CAmount nFee;
24862529 string strFailReason;
2487- int nChangePos = - 1 ;
2488- if (!pwalletMain->FundTransaction (tx, nFee, nChangePos , strFailReason, includeWatching))
2530+
2531+ if (!pwalletMain->FundTransaction (tx, nFee, changePosition , strFailReason, includeWatching, lockUnspents, changeAddress ))
24892532 throw JSONRPCError (RPC_INTERNAL_ERROR, strFailReason);
24902533
24912534 UniValue result (UniValue::VOBJ);
24922535 result.push_back (Pair (" hex" , EncodeHexTx (tx)));
2493- result.push_back (Pair (" changepos" , nChangePos ));
2536+ result.push_back (Pair (" changepos" , changePosition ));
24942537 result.push_back (Pair (" fee" , ValueFromAmount (nFee)));
24952538
24962539 return result;
0 commit comments