@@ -152,6 +152,11 @@ UniValue getnewaddress(const JSONRPCRequest& request)
152152 return CBitcoinAddress (keyID).ToString ();
153153}
154154
155+ void DeleteAccount (CWallet * const pwallet, std::string strAccount)
156+ {
157+ CWalletDB walletdb (pwallet->GetDBHandle ());
158+ walletdb.EraseAccount (strAccount);
159+ }
155160
156161CBitcoinAddress GetAccountAddress (CWallet* const pwallet, std::string strAccount, bool bForceNew=false )
157162{
@@ -2922,6 +2927,236 @@ UniValue bumpfee(const JSONRPCRequest& request)
29222927 return result;
29232928}
29242929
2930+ UniValue getlabeladdress (const JSONRPCRequest& request)
2931+ {
2932+ CWallet * const pwallet = GetWalletForJSONRPCRequest (request);
2933+ if (!EnsureWalletIsAvailable (pwallet, request.fHelp )) {
2934+ return NullUniValue;
2935+ }
2936+
2937+ if (request.fHelp || request.params .size () != 1 )
2938+ throw std::runtime_error (
2939+ " getlabeladdress \" label\"\n "
2940+ " \n Returns the current 'label address' for this label.\n "
2941+ " \n Arguments:\n "
2942+ " 1. \" label\" (string, required) The label for the address. It can also be set to the empty string \"\" to represent the default label.\n "
2943+ " \n Result:\n "
2944+ " \" bitcoinaddress\" (string) The 'label address' for the label\n "
2945+ " \n Examples:\n "
2946+ + HelpExampleCli (" getlabeladdress" , " " )
2947+ + HelpExampleCli (" getlabeladdress" , " \"\" " )
2948+ + HelpExampleCli (" getlabeladdress" , " \" mylabel\" " )
2949+ + HelpExampleRpc (" getlabeladdress" , " \" mylabel\" " )
2950+ );
2951+
2952+ LOCK2 (cs_main, pwallet->cs_wallet );
2953+
2954+ // Parse the label first so we don't generate a key if there's an error
2955+ std::string strLabel = AccountFromValue (request.params [0 ]);
2956+
2957+ UniValue ret (UniValue::VSTR);
2958+
2959+ ret = GetAccountAddress (pwallet, strLabel).ToString ();
2960+ return ret;
2961+ }
2962+
2963+ /* * Convert CAddressBookData to JSON record.
2964+ * The verbosity of the output is configurable based on the command.
2965+ */
2966+ static UniValue AddressBookDataToJSON (const CAddressBookData& data, bool verbose)
2967+ {
2968+ UniValue ret (UniValue::VOBJ);
2969+ if (verbose) {
2970+ ret.push_back (Pair (" name" , data.name ));
2971+ }
2972+ ret.push_back (Pair (" purpose" , data.purpose ));
2973+ if (verbose) {
2974+ UniValue ddata (UniValue::VOBJ);
2975+ for (const std::pair<std::string, std::string>& item : data.destdata ) {
2976+ ddata.push_back (Pair (item.first , item.second ));
2977+ }
2978+ ret.push_back (Pair (" destdata" , ddata));
2979+ }
2980+ return ret;
2981+ }
2982+
2983+ UniValue getlabel (const JSONRPCRequest& request)
2984+ {
2985+ CWallet * const pwallet = GetWalletForJSONRPCRequest (request);
2986+ if (!EnsureWalletIsAvailable (pwallet, request.fHelp )) {
2987+ return NullUniValue;
2988+ }
2989+
2990+ if (request.fHelp || request.params .size () != 1 )
2991+ throw std::runtime_error (
2992+ " getlabel \" bitcoinaddress\"\n "
2993+ " \n Returns the label associated with the given address.\n "
2994+ " \n Arguments:\n "
2995+ " 1. \" bitcoinaddress\" (string, required) The bitcoin address for label lookup.\n "
2996+ " \n Result:\n "
2997+ " { (json object with information about address)\n "
2998+ " \" name\" : \" labelname\" (string) The label\n "
2999+ " \" purpose\" : \" string\" (string) Purpose of address (\" send\" for sending address, \" receive\" for receiving address)\n "
3000+ " },...\n "
3001+ " Result is null if there is no record for this address.\n "
3002+ " \n Examples:\n "
3003+ + HelpExampleCli (" getlabel" , " \" 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" " )
3004+ + HelpExampleRpc (" getlabel" , " \" 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" " )
3005+ );
3006+
3007+ LOCK2 (cs_main, pwallet->cs_wallet );
3008+
3009+ CBitcoinAddress address (request.params [0 ].get_str ());
3010+ if (!address.IsValid ()) {
3011+ throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, " Invalid Bitcoin address" );
3012+ }
3013+
3014+ std::map<CTxDestination, CAddressBookData>::iterator mi = pwallet->mapAddressBook .find (address.Get ());
3015+ if (mi != pwallet->mapAddressBook .end ()) {
3016+ return AddressBookDataToJSON ((*mi).second , true );
3017+ }
3018+ return NullUniValue;
3019+ }
3020+
3021+ UniValue getaddressesbylabel (const JSONRPCRequest& request)
3022+ {
3023+ CWallet * const pwallet = GetWalletForJSONRPCRequest (request);
3024+ if (!EnsureWalletIsAvailable (pwallet, request.fHelp )) {
3025+ return NullUniValue;
3026+ }
3027+
3028+ if (request.fHelp || request.params .size () != 1 )
3029+ throw std::runtime_error (
3030+ " getaddressesbylabel \" label\"\n "
3031+ " \n Returns the list of addresses assigned the specified label.\n "
3032+ " \n Arguments:\n "
3033+ " 1. \" label\" (string, required) The label.\n "
3034+ " \n Result:\n "
3035+ " { (json object with addresses as keys)\n "
3036+ " \" bitcoinaddress\" : { (json object with information about address)\n "
3037+ " \" purpose\" : \" string\" (string) Purpose of address (\" send\" for sending address, \" receive\" for receiving address)\n "
3038+ " },...\n "
3039+ " }\n "
3040+ " \n Examples:\n "
3041+ + HelpExampleCli (" getaddressesbylabel" , " \" tabby\" " )
3042+ + HelpExampleRpc (" getaddressesbylabel" , " \" tabby\" " )
3043+ );
3044+
3045+ LOCK2 (cs_main, pwallet->cs_wallet );
3046+
3047+ std::string strLabel = AccountFromValue (request.params [0 ]);
3048+
3049+ // Find all addresses that have the given label
3050+ UniValue ret (UniValue::VOBJ);
3051+ for (const std::pair<CBitcoinAddress, CAddressBookData>& item : pwallet->mapAddressBook ) {
3052+ if (item.second .name == strLabel) {
3053+ ret.push_back (Pair (item.first .ToString (), AddressBookDataToJSON (item.second , false )));
3054+ }
3055+ }
3056+ return ret;
3057+ }
3058+
3059+ UniValue listlabels (const JSONRPCRequest& request)
3060+ {
3061+ CWallet * const pwallet = GetWalletForJSONRPCRequest (request);
3062+ if (!EnsureWalletIsAvailable (pwallet, request.fHelp )) {
3063+ return NullUniValue;
3064+ }
3065+
3066+ if (request.fHelp || request.params .size () > 1 )
3067+ throw std::runtime_error (
3068+ " listlabels ( \" purpose\" )\n "
3069+ " \n Returns the list of all labels, or labels that are assigned to addresses with a specific purpose.\n "
3070+ " \n Arguments:\n "
3071+ " 1. \" purpose\" (string, optional) Address purpose to list labels for ('send','receive'). An empty string is the same as not providing this argument.\n "
3072+ " \n Result:\n "
3073+ " [ (json array of string)\n "
3074+ " \" label\" , (string) Label name\n "
3075+ " ...\n "
3076+ " ]\n "
3077+ " \n Examples:\n "
3078+ " \n List all labels\n "
3079+ + HelpExampleCli (" listlabels" , " " ) +
3080+ " \n List labels that have receiving addresses\n "
3081+ + HelpExampleCli (" listlabels" , " receive" ) +
3082+ " \n List labels that have sending addresses\n "
3083+ + HelpExampleCli (" listlabels" , " send" ) +
3084+ " \n As json rpc call\n "
3085+ + HelpExampleRpc (" listlabels" , " receive" )
3086+ );
3087+
3088+ LOCK2 (cs_main, pwallet->cs_wallet );
3089+
3090+ std::string purpose;
3091+ if (request.params .size () > 0 ) {
3092+ purpose = request.params [0 ].get_str ();
3093+ }
3094+
3095+ std::set<std::string> setLabels;
3096+ for (const std::pair<CTxDestination, CAddressBookData>& entry : pwallet->mapAddressBook ) {
3097+ if (purpose.empty () || entry.second .purpose == purpose){
3098+ setLabels.insert (entry.second .name );
3099+ }
3100+ }
3101+ UniValue ret (UniValue::VARR);
3102+ for (const std::string &name : setLabels) {
3103+ ret.push_back (name);
3104+ }
3105+
3106+ return ret;
3107+ }
3108+
3109+ UniValue setlabel (const JSONRPCRequest& request)
3110+ {
3111+ CWallet * const pwallet = GetWalletForJSONRPCRequest (request);
3112+ if (!EnsureWalletIsAvailable (pwallet, request.fHelp )) {
3113+ return NullUniValue;
3114+ }
3115+
3116+ if (request.fHelp || request.params .size () < 1 || request.params .size () > 2 )
3117+ throw std::runtime_error (
3118+ " setlabel \" bitcoinaddress\" \" label\"\n "
3119+ " \n Sets the label associated with the given address.\n "
3120+ " \n Arguments:\n "
3121+ " 1. \" bitcoinaddress\" (string, required) The bitcoin address to be associated with an label.\n "
3122+ " 2. \" label\" (string, required) The label to assign to the address.\n "
3123+ " \n Examples:\n "
3124+ + HelpExampleCli (" setlabel" , " \" 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \" tabby\" " )
3125+ + HelpExampleRpc (" setlabel" , " \" 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" , \" tabby\" " )
3126+ );
3127+
3128+ LOCK2 (cs_main, pwallet->cs_wallet );
3129+
3130+ CBitcoinAddress address (request.params [0 ].get_str ());
3131+ if (!address.IsValid ()) {
3132+ throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, " Invalid Bitcoin address" );
3133+ }
3134+
3135+ std::string strLabel;
3136+ if (request.params .size () > 1 ){
3137+ strLabel = AccountFromValue (request.params [1 ]);
3138+ }
3139+
3140+ if (IsMine (*pwallet, address.Get ()))
3141+ {
3142+ // Detect when changing the label of an address that is the 'label address' of another label:
3143+ // If so, delete the account record for it. Labels, unlike addresses can be deleted,
3144+ // and we wouldn't do this, the record would stick around forever.
3145+ if (pwallet->mapAddressBook .count (address.Get ()))
3146+ {
3147+ std::string strOldLabel = pwallet->mapAddressBook [address.Get ()].name ;
3148+ if (address == GetAccountAddress (pwallet, strOldLabel)) {
3149+ DeleteAccount (pwallet, strOldLabel);
3150+ }
3151+ }
3152+ pwallet->SetAddressBook (address.Get (), strLabel, " receive" );
3153+ } else {
3154+ pwallet->SetAddressBook (address.Get (), strLabel, " send" );
3155+ }
3156+
3157+ return NullUniValue;
3158+ }
3159+
29253160extern UniValue abortrescan (const JSONRPCRequest& request); // in rpcdump.cpp
29263161extern UniValue dumpprivkey (const JSONRPCRequest& request); // in rpcdump.cpp
29273162extern UniValue importprivkey (const JSONRPCRequest& request);
@@ -2947,13 +3182,9 @@ static const CRPCCommand commands[] =
29473182 { " wallet" , " dumpprivkey" , &dumpprivkey, true , {" address" } },
29483183 { " wallet" , " dumpwallet" , &dumpwallet, true , {" filename" } },
29493184 { " wallet" , " encryptwallet" , &encryptwallet, true , {" passphrase" } },
2950- { " wallet" , " getaccountaddress" , &getaccountaddress, true , {" account" } },
2951- { " wallet" , " getaccount" , &getaccount, true , {" address" } },
2952- { " wallet" , " getaddressesbyaccount" , &getaddressesbyaccount, true , {" account" } },
29533185 { " wallet" , " getbalance" , &getbalance, false , {" account" ," minconf" ," include_watchonly" } },
29543186 { " wallet" , " getnewaddress" , &getnewaddress, true , {" account" } },
29553187 { " wallet" , " getrawchangeaddress" , &getrawchangeaddress, true , {} },
2956- { " wallet" , " getreceivedbyaccount" , &getreceivedbyaccount, false , {" account" ," minconf" } },
29573188 { " wallet" , " getreceivedbyaddress" , &getreceivedbyaddress, false , {" address" ," minconf" } },
29583189 { " wallet" , " gettransaction" , &gettransaction, false , {" txid" ," include_watchonly" } },
29593190 { " wallet" , " getunconfirmedbalance" , &getunconfirmedbalance, false , {} },
@@ -2965,26 +3196,39 @@ static const CRPCCommand commands[] =
29653196 { " wallet" , " importprunedfunds" , &importprunedfunds, true , {" rawtransaction" ," txoutproof" } },
29663197 { " wallet" , " importpubkey" , &importpubkey, true , {" pubkey" ," label" ," rescan" } },
29673198 { " wallet" , " keypoolrefill" , &keypoolrefill, true , {" newsize" } },
2968- { " wallet" , " listaccounts" , &listaccounts, false , {" minconf" ," include_watchonly" } },
29693199 { " wallet" , " listaddressgroupings" , &listaddressgroupings, false , {} },
29703200 { " wallet" , " listlockunspent" , &listlockunspent, false , {} },
2971- { " wallet" , " listreceivedbyaccount" , &listreceivedbyaccount, false , {" minconf" ," include_empty" ," include_watchonly" } },
29723201 { " wallet" , " listreceivedbyaddress" , &listreceivedbyaddress, false , {" minconf" ," include_empty" ," include_watchonly" } },
29733202 { " wallet" , " listsinceblock" , &listsinceblock, false , {" blockhash" ," target_confirmations" ," include_watchonly" } },
29743203 { " wallet" , " listtransactions" , &listtransactions, false , {" account" ," count" ," skip" ," include_watchonly" } },
29753204 { " wallet" , " listunspent" , &listunspent, false , {" minconf" ," maxconf" ," addresses" ," include_unsafe" ," query_options" } },
29763205 { " wallet" , " lockunspent" , &lockunspent, true , {" unlock" ," transactions" } },
2977- { " wallet" , " move" , &movecmd, false , {" fromaccount" ," toaccount" ," amount" ," minconf" ," comment" } },
29783206 { " wallet" , " sendfrom" , &sendfrom, false , {" fromaccount" ," toaddress" ," amount" ," minconf" ," comment" ," comment_to" } },
29793207 { " wallet" , " sendmany" , &sendmany, false , {" fromaccount" ," amounts" ," minconf" ," comment" ," subtractfeefrom" } },
29803208 { " wallet" , " sendtoaddress" , &sendtoaddress, false , {" address" ," amount" ," comment" ," comment_to" ," subtractfeefromamount" } },
2981- { " wallet" , " setaccount" , &setaccount, true , {" address" ," account" } },
29823209 { " wallet" , " settxfee" , &settxfee, true , {" amount" } },
29833210 { " wallet" , " signmessage" , &signmessage, true , {" address" ," message" } },
29843211 { " wallet" , " walletlock" , &walletlock, true , {} },
29853212 { " wallet" , " walletpassphrasechange" , &walletpassphrasechange, true , {" oldpassphrase" ," newpassphrase" } },
29863213 { " wallet" , " walletpassphrase" , &walletpassphrase, true , {" passphrase" ," timeout" } },
29873214 { " wallet" , " removeprunedfunds" , &removeprunedfunds, true , {" txid" } },
3215+
3216+ /* * Account functions (deprecated) */
3217+ { " wallet" , " getaccountaddress" , &getaccountaddress, true , {" account" } },
3218+ { " wallet" , " getaccount" , &getaccount, true , {" address" } },
3219+ { " wallet" , " getaddressesbyaccount" , &getaddressesbyaccount, true , {" account" } },
3220+ { " wallet" , " getreceivedbyaccount" , &getreceivedbyaccount, false , {" account" ," minconf" } },
3221+ { " wallet" , " listaccounts" , &listaccounts, false , {" minconf" ," include_watchonly" } },
3222+ { " wallet" , " listreceivedbyaccount" , &listreceivedbyaccount, false , {" minconf" ," include_empty" ," include_watchonly" } },
3223+ { " wallet" , " setaccount" , &setaccount, true , {" address" ," account" } },
3224+ { " wallet" , " move" , &movecmd, false , {" fromaccount" ," toaccount" ," amount" ," minconf" ," comment" } },
3225+
3226+ /* * Label functions (to replace non-balance account functions) */
3227+ { " wallet" , " getlabeladdress" , &getlabeladdress, true , {" label" } },
3228+ { " wallet" , " getlabel" , &getlabel, true , {" bitcoinaddress" } },
3229+ { " wallet" , " getaddressesbylabel" , &getaddressesbylabel, true , {" label" } },
3230+ { " wallet" , " listlabels" , &listlabels, false , {" purpose" } },
3231+ { " wallet" , " setlabel" , &setlabel, true , {" bitcoinaddress" ," label" } },
29883232};
29893233
29903234void RegisterWalletRPCCommands (CRPCTable &t)
0 commit comments