@@ -152,6 +152,11 @@ UniValue getnewaddress(const JSONRPCRequest& request)
return CBitcoinAddress (keyID).ToString ();
}
+void DeleteAccount (CWallet * const pwallet, std::string strAccount)
+{
+ CWalletDB walletdb (pwallet->GetDBHandle ());
+ walletdb.EraseAccount (strAccount);
+}
CBitcoinAddress GetAccountAddress (CWallet* const pwallet, std::string strAccount, bool bForceNew=false )
{
@@ -2922,6 +2927,236 @@ UniValue bumpfee(const JSONRPCRequest& request)
return result;
}
+UniValue getlabeladdress (const JSONRPCRequest& request)
+{
+ CWallet * const pwallet = GetWalletForJSONRPCRequest (request);
+ if (!EnsureWalletIsAvailable (pwallet, request.fHelp )) {
+ return NullUniValue;
+ }
+
+ if (request.fHelp || request.params .size () != 1 )
+ throw std::runtime_error (
+ " getlabeladdress \" label\"\n "
+ " \n Returns the current 'label address' for this label.\n "
+ " \n Arguments:\n "
+ " 1. \" label\" (string, required) The label for the address. It can also be set to the empty string \"\" to represent the default label.\n "
+ " \n Result:\n "
+ " \" bitcoinaddress\" (string) The 'label address' for the label\n "
+ " \n Examples:\n "
+ + HelpExampleCli (" getlabeladdress" , " " )
+ + HelpExampleCli (" getlabeladdress" , " \"\" " )
+ + HelpExampleCli (" getlabeladdress" , " \" mylabel\" " )
+ + HelpExampleRpc (" getlabeladdress" , " \" mylabel\" " )
+ );
+
+ LOCK2 (cs_main, pwallet->cs_wallet);
+
+ // Parse the label first so we don't generate a key if there's an error
+ std::string strLabel = AccountFromValue (request.params [0 ]);
+
+ UniValue ret (UniValue::VSTR);
+
+ ret = GetAccountAddress (pwallet, strLabel).ToString ();
+ return ret;
+}
+
+/* * Convert CAddressBookData to JSON record.
+ * The verbosity of the output is configurable based on the command.
+ */
+static UniValue AddressBookDataToJSON (const CAddressBookData& data, bool verbose)
+{
+ UniValue ret (UniValue::VOBJ);
+ if (verbose) {
+ ret.push_back (Pair (" name" , data.name ));
+ }
+ ret.push_back (Pair (" purpose" , data.purpose ));
+ if (verbose) {
+ UniValue ddata (UniValue::VOBJ);
+ for (const std::pair<std::string, std::string>& item : data.destdata ) {
+ ddata.push_back (Pair (item.first , item.second ));
+ }
+ ret.push_back (Pair (" destdata" , ddata));
+ }
+ return ret;
+}
+
+UniValue getlabel (const JSONRPCRequest& request)
+{
+ CWallet * const pwallet = GetWalletForJSONRPCRequest (request);
+ if (!EnsureWalletIsAvailable (pwallet, request.fHelp )) {
+ return NullUniValue;
+ }
+
+ if (request.fHelp || request.params .size () != 1 )
+ throw std::runtime_error (
+ " getlabel \" bitcoinaddress\"\n "
+ " \n Returns the label associated with the given address.\n "
+ " \n Arguments:\n "
+ " 1. \" bitcoinaddress\" (string, required) The bitcoin address for label lookup.\n "
+ " \n Result:\n "
+ " { (json object with information about address)\n "
+ " \" name\" : \" labelname\" (string) The label\n "
+ " \" purpose\" : \" string\" (string) Purpose of address (\" send\" for sending address, \" receive\" for receiving address)\n "
+ " },...\n "
+ " Result is null if there is no record for this address.\n "
+ " \n Examples:\n "
+ + HelpExampleCli (" getlabel" , " \" 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" " )
+ + HelpExampleRpc (" getlabel" , " \" 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" " )
+ );
+
+ LOCK2 (cs_main, pwallet->cs_wallet);
+
+ CBitcoinAddress address (request.params [0 ].get_str ());
+ if (!address.IsValid ()) {
+ throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, " Invalid Bitcoin address" );
+ }
+
+ std::map<CTxDestination, CAddressBookData>::iterator mi = pwallet->mapAddressBook.find (address.Get ());
+ if (mi != pwallet->mapAddressBook.end ()) {
+ return AddressBookDataToJSON ((*mi).second , true );
+ }
+ return NullUniValue;
+}
+
+UniValue getaddressesbylabel (const JSONRPCRequest& request)
+{
+ CWallet * const pwallet = GetWalletForJSONRPCRequest (request);
+ if (!EnsureWalletIsAvailable (pwallet, request.fHelp )) {
+ return NullUniValue;
+ }
+
+ if (request.fHelp || request.params .size () != 1 )
+ throw std::runtime_error (
+ " getaddressesbylabel \" label\"\n "
+ " \n Returns the list of addresses assigned the specified label.\n "
+ " \n Arguments:\n "
+ " 1. \" label\" (string, required) The label.\n "
+ " \n Result:\n "
+ " { (json object with addresses as keys)\n "
+ " \" bitcoinaddress\" : { (json object with information about address)\n "
+ " \" purpose\" : \" string\" (string) Purpose of address (\" send\" for sending address, \" receive\" for receiving address)\n "
+ " },...\n "
+ " }\n "
+ " \n Examples:\n "
+ + HelpExampleCli (" getaddressesbylabel" , " \" tabby\" " )
+ + HelpExampleRpc (" getaddressesbylabel" , " \" tabby\" " )
+ );
+
+ LOCK2 (cs_main, pwallet->cs_wallet);
+
+ std::string strLabel = AccountFromValue (request.params [0 ]);
+
+ // Find all addresses that have the given label
+ UniValue ret (UniValue::VOBJ);
+ for (const std::pair<CBitcoinAddress, CAddressBookData>& item : pwallet->mapAddressBook) {
+ if (item.second .name == strLabel) {
+ ret.push_back (Pair (item.first .ToString (), AddressBookDataToJSON (item.second , false )));
+ }
+ }
+ return ret;
+}
+
+UniValue listlabels (const JSONRPCRequest& request)
+{
+ CWallet * const pwallet = GetWalletForJSONRPCRequest (request);
+ if (!EnsureWalletIsAvailable (pwallet, request.fHelp )) {
+ return NullUniValue;
+ }
+
+ if (request.fHelp || request.params .size () > 1 )
+ throw std::runtime_error (
+ " listlabels ( \" purpose\" )\n "
+ " \n Returns the list of all labels, or labels that are assigned to addresses with a specific purpose.\n "
+ " \n Arguments:\n "
+ " 1. \" purpose\" (string, optional) Address purpose to list labels for ('send','receive'). An empty string is the same as not providing this argument.\n "
+ " \n Result:\n "
+ " [ (json array of string)\n "
+ " \" label\" , (string) Label name\n "
+ " ...\n "
+ " ]\n "
+ " \n Examples:\n "
+ " \n List all labels\n "
+ + HelpExampleCli (" listlabels" , " " ) +
+ " \n List labels that have receiving addresses\n "
+ + HelpExampleCli (" listlabels" , " receive" ) +
+ " \n List labels that have sending addresses\n "
+ + HelpExampleCli (" listlabels" , " send" ) +
+ " \n As json rpc call\n "
+ + HelpExampleRpc (" listlabels" , " receive" )
+ );
+
+ LOCK2 (cs_main, pwallet->cs_wallet);
+
+ std::string purpose;
+ if (request.params .size () > 0 ) {
+ purpose = request.params [0 ].get_str ();
+ }
+
+ std::set<std::string> setLabels;
+ for (const std::pair<CTxDestination, CAddressBookData>& entry : pwallet->mapAddressBook) {
+ if (purpose.empty () || entry.second .purpose == purpose){
+ setLabels.insert (entry.second .name );
+ }
+ }
+ UniValue ret (UniValue::VARR);
+ for (const std::string &name : setLabels) {
+ ret.push_back (name);
+ }
+
+ return ret;
+}
+
+UniValue setlabel (const JSONRPCRequest& request)
+{
+ CWallet * const pwallet = GetWalletForJSONRPCRequest (request);
+ if (!EnsureWalletIsAvailable (pwallet, request.fHelp )) {
+ return NullUniValue;
+ }
+
+ if (request.fHelp || request.params .size () < 1 || request.params .size () > 2 )
+ throw std::runtime_error (
+ " setlabel \" bitcoinaddress\" \" label\"\n "
+ " \n Sets the label associated with the given address.\n "
+ " \n Arguments:\n "
+ " 1. \" bitcoinaddress\" (string, required) The bitcoin address to be associated with an label.\n "
+ " 2. \" label\" (string, required) The label to assign to the address.\n "
+ " \n Examples:\n "
+ + HelpExampleCli (" setlabel" , " \" 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \" tabby\" " )
+ + HelpExampleRpc (" setlabel" , " \" 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" , \" tabby\" " )
+ );
+
+ LOCK2 (cs_main, pwallet->cs_wallet);
+
+ CBitcoinAddress address (request.params [0 ].get_str ());
+ if (!address.IsValid ()) {
+ throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, " Invalid Bitcoin address" );
+ }
+
+ std::string strLabel;
+ if (request.params .size () > 1 ){
+ strLabel = AccountFromValue (request.params [1 ]);
+ }
+
+ if (IsMine (*pwallet, address.Get ()))
+ {
+ // Detect when changing the label of an address that is the 'label address' of another label:
+ // If so, delete the account record for it. Labels, unlike addresses can be deleted,
+ // and we wouldn't do this, the record would stick around forever.
+ if (pwallet->mapAddressBook.count (address.Get ()))
+ {
+ std::string strOldLabel = pwallet->mapAddressBook[address.Get ()].name ;
+ if (strOldLabel != strLabel && address == GetAccountAddress (pwallet, strOldLabel)) {
+ DeleteAccount (pwallet, strOldLabel);
+ }
+ }
+ pwallet->SetAddressBook (address.Get (), strLabel, " receive" );
+ } else {
+ pwallet->SetAddressBook (address.Get (), strLabel, " send" );
+ }
+
+ return NullUniValue;
+}
+
extern UniValue abortrescan (const JSONRPCRequest& request); // in rpcdump.cpp
extern UniValue dumpprivkey (const JSONRPCRequest& request); // in rpcdump.cpp
extern UniValue importprivkey (const JSONRPCRequest& request);
@@ -2947,13 +3182,9 @@ static const CRPCCommand commands[] =
{ " wallet" , " dumpprivkey" , &dumpprivkey, true , {" address" } },
{ " wallet" , " dumpwallet" , &dumpwallet, true , {" filename" } },
{ " wallet" , " encryptwallet" , &encryptwallet, true , {" passphrase" } },
- { " wallet" , " getaccountaddress" , &getaccountaddress, true , {" account" } },
- { " wallet" , " getaccount" , &getaccount, true , {" address" } },
- { " wallet" , " getaddressesbyaccount" , &getaddressesbyaccount, true , {" account" } },
{ " wallet" , " getbalance" , &getbalance, false , {" account" ," minconf" ," include_watchonly" } },
{ " wallet" , " getnewaddress" , &getnewaddress, true , {" account" } },
{ " wallet" , " getrawchangeaddress" , &getrawchangeaddress, true , {} },
- { " wallet" , " getreceivedbyaccount" , &getreceivedbyaccount, false , {" account" ," minconf" } },
{ " wallet" , " getreceivedbyaddress" , &getreceivedbyaddress, false , {" address" ," minconf" } },
{ " wallet" , " gettransaction" , &gettransaction, false , {" txid" ," include_watchonly" } },
{ " wallet" , " getunconfirmedbalance" , &getunconfirmedbalance, false , {} },
@@ -2965,26 +3196,39 @@ static const CRPCCommand commands[] =
{ " wallet" , " importprunedfunds" , &importprunedfunds, true , {" rawtransaction" ," txoutproof" } },
{ " wallet" , " importpubkey" , &importpubkey, true , {" pubkey" ," label" ," rescan" } },
{ " wallet" , " keypoolrefill" , &keypoolrefill, true , {" newsize" } },
- { " wallet" , " listaccounts" , &listaccounts, false , {" minconf" ," include_watchonly" } },
{ " wallet" , " listaddressgroupings" , &listaddressgroupings, false , {} },
{ " wallet" , " listlockunspent" , &listlockunspent, false , {} },
- { " wallet" , " listreceivedbyaccount" , &listreceivedbyaccount, false , {" minconf" ," include_empty" ," include_watchonly" } },
{ " wallet" , " listreceivedbyaddress" , &listreceivedbyaddress, false , {" minconf" ," include_empty" ," include_watchonly" } },
{ " wallet" , " listsinceblock" , &listsinceblock, false , {" blockhash" ," target_confirmations" ," include_watchonly" } },
{ " wallet" , " listtransactions" , &listtransactions, false , {" account" ," count" ," skip" ," include_watchonly" } },
{ " wallet" , " listunspent" , &listunspent, false , {" minconf" ," maxconf" ," addresses" ," include_unsafe" ," query_options" } },
{ " wallet" , " lockunspent" , &lockunspent, true , {" unlock" ," transactions" } },
- { " wallet" , " move" , &movecmd, false , {" fromaccount" ," toaccount" ," amount" ," minconf" ," comment" } },
{ " wallet" , " sendfrom" , &sendfrom, false , {" fromaccount" ," toaddress" ," amount" ," minconf" ," comment" ," comment_to" } },
{ " wallet" , " sendmany" , &sendmany, false , {" fromaccount" ," amounts" ," minconf" ," comment" ," subtractfeefrom" } },
{ " wallet" , " sendtoaddress" , &sendtoaddress, false , {" address" ," amount" ," comment" ," comment_to" ," subtractfeefromamount" } },
- { " wallet" , " setaccount" , &setaccount, true , {" address" ," account" } },
{ " wallet" , " settxfee" , &settxfee, true , {" amount" } },
{ " wallet" , " signmessage" , &signmessage, true , {" address" ," message" } },
{ " wallet" , " walletlock" , &walletlock, true , {} },
{ " wallet" , " walletpassphrasechange" , &walletpassphrasechange, true , {" oldpassphrase" ," newpassphrase" } },
{ " wallet" , " walletpassphrase" , &walletpassphrase, true , {" passphrase" ," timeout" } },
{ " wallet" , " removeprunedfunds" , &removeprunedfunds, true , {" txid" } },
+
+ /* * Account functions (deprecated) */
+ { " wallet" , " getaccountaddress" , &getaccountaddress, true , {" account" } },
+ { " wallet" , " getaccount" , &getaccount, true , {" address" } },
+ { " wallet" , " getaddressesbyaccount" , &getaddressesbyaccount, true , {" account" } },
+ { " wallet" , " getreceivedbyaccount" , &getreceivedbyaccount, false , {" account" ," minconf" } },
+ { " wallet" , " listaccounts" , &listaccounts, false , {" minconf" ," include_watchonly" } },
+ { " wallet" , " listreceivedbyaccount" , &listreceivedbyaccount, false , {" minconf" ," include_empty" ," include_watchonly" } },
+ { " wallet" , " setaccount" , &setaccount, true , {" address" ," account" } },
+ { " wallet" , " move" , &movecmd, false , {" fromaccount" ," toaccount" ," amount" ," minconf" ," comment" } },
+
+ /* * Label functions (to replace non-balance account functions) */
+ { " wallet" , " getlabeladdress" , &getlabeladdress, true , {" label" } },
+ { " wallet" , " getlabel" , &getlabel, true , {" bitcoinaddress" } },
+ { " wallet" , " getaddressesbylabel" , &getaddressesbylabel, true , {" label" } },
+ { " wallet" , " listlabels" , &listlabels, false , {" purpose" } },
+ { " wallet" , " setlabel" , &setlabel, true , {" bitcoinaddress" ," label" } },
};
void RegisterWalletRPCCommands (CRPCTable &t)
Nit, shouldn't we follow the convention in new code in favor of consistency? In that case rename
strAccounttoaccount_namefor instance?