|
25 | 25 | #include <utilmoneystr.h> |
26 | 26 | #include <validation.h> |
27 | 27 | #include <wallet/coincontrol.h> |
| 28 | +#include <wallet/rpcwallet.h> |
28 | 29 | #include <wallet/wallet.h> |
29 | 30 | #include <wallet/walletdb.h> |
30 | 31 | #include <wallet/walletutil.h> |
@@ -3569,6 +3570,147 @@ UniValue rescanblockchain(const JSONRPCRequest& request) |
3569 | 3570 | return response; |
3570 | 3571 | } |
3571 | 3572 |
|
| 3573 | +class DescribeWalletAddressVisitor : public boost::static_visitor<UniValue> |
| 3574 | +{ |
| 3575 | +public: |
| 3576 | + CWallet * const pwallet; |
| 3577 | + |
| 3578 | + explicit DescribeWalletAddressVisitor(CWallet *_pwallet) : pwallet(_pwallet) {} |
| 3579 | + |
| 3580 | + UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); } |
| 3581 | + |
| 3582 | + UniValue operator()(const CKeyID &keyID) const { |
| 3583 | + UniValue obj(UniValue::VOBJ); |
| 3584 | + CPubKey vchPubKey; |
| 3585 | + if (pwallet && pwallet->GetPubKey(keyID, vchPubKey)) { |
| 3586 | + obj.pushKV("pubkey", HexStr(vchPubKey)); |
| 3587 | + obj.pushKV("iscompressed", vchPubKey.IsCompressed()); |
| 3588 | + } |
| 3589 | + return obj; |
| 3590 | + } |
| 3591 | + |
| 3592 | + UniValue operator()(const CScriptID &scriptID) const { |
| 3593 | + UniValue obj(UniValue::VOBJ); |
| 3594 | + CScript subscript; |
| 3595 | + if (pwallet && pwallet->GetCScript(scriptID, subscript)) { |
| 3596 | + std::vector<CTxDestination> addresses; |
| 3597 | + txnouttype whichType; |
| 3598 | + int nRequired; |
| 3599 | + ExtractDestinations(subscript, whichType, addresses, nRequired); |
| 3600 | + obj.pushKV("script", GetTxnOutputType(whichType)); |
| 3601 | + obj.pushKV("hex", HexStr(subscript.begin(), subscript.end())); |
| 3602 | + UniValue a(UniValue::VARR); |
| 3603 | + for (const CTxDestination& addr : addresses) { |
| 3604 | + a.push_back(EncodeDestination(addr)); |
| 3605 | + } |
| 3606 | + obj.pushKV("addresses", a); |
| 3607 | + if (whichType == TX_MULTISIG) |
| 3608 | + obj.pushKV("sigsrequired", nRequired); |
| 3609 | + } |
| 3610 | + return obj; |
| 3611 | + } |
| 3612 | +}; |
| 3613 | + |
| 3614 | +UniValue DescribeWalletAddress(CWallet* pwallet, const CTxDestination& dest) |
| 3615 | +{ |
| 3616 | + UniValue ret(UniValue::VOBJ); |
| 3617 | + UniValue detail = DescribeAddress(dest); |
| 3618 | + ret.pushKVs(detail); |
| 3619 | + ret.pushKVs(boost::apply_visitor(DescribeWalletAddressVisitor(pwallet), dest)); |
| 3620 | + return ret; |
| 3621 | +} |
| 3622 | + |
| 3623 | +UniValue getaddressinfo(const JSONRPCRequest& request) |
| 3624 | +{ |
| 3625 | + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); |
| 3626 | + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { |
| 3627 | + return NullUniValue; |
| 3628 | + } |
| 3629 | + |
| 3630 | + if (request.fHelp || request.params.size() != 1) { |
| 3631 | + throw std::runtime_error( |
| 3632 | + "getaddressinfo \"address\"\n" |
| 3633 | + "\nReturn information about the given dash address. Some information requires the address\n" |
| 3634 | + "to be in the wallet.\n" |
| 3635 | + "\nArguments:\n" |
| 3636 | + "1. \"address\" (string, required) The dash address to get the information of.\n" |
| 3637 | + "\nResult:\n" |
| 3638 | + "{\n" |
| 3639 | + " \"address\" : \"address\", (string) The dash address validated\n" |
| 3640 | + " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n" |
| 3641 | + " \"ismine\" : true|false, (boolean) If the address is yours or not\n" |
| 3642 | + " \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n" |
| 3643 | + " \"isscript\" : true|false, (boolean) If the key is a script\n" |
| 3644 | + " \"script\" : \"type\" (string, optional) The output script type. Only if \"isscript\" is true and the redeemscript is known. Possible types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata\n" |
| 3645 | + " \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address\n" |
| 3646 | + " \"pubkeys\" (string, optional) Array of pubkeys associated with the known redeemscript (only if \"script\" is \"multisig\")\n" |
| 3647 | + " [\n" |
| 3648 | + " \"pubkey\"\n" |
| 3649 | + " ,...\n" |
| 3650 | + " ]\n" |
| 3651 | + " \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output (only if \"script\" is \"multisig\")\n" |
| 3652 | + " \"pubkey\" : \"publickeyhex\", (string, optional) The hex value of the raw public key, for single-key addresses (possibly embedded in P2SH)\n" |
| 3653 | + " \"embedded\" : {...}, (object, optional) Information about the address embedded in P2SH, if relevant and known. It includes all getaddressinfo output fields for the embedded address, excluding metadata (\"timestamp\", \"hdkeypath\") and relation to the wallet (\"ismine\", \"iswatchonly\", \"account\").\n" |
| 3654 | + " \"iscompressed\" : true|false, (boolean) If the address is compressed\n" |
| 3655 | + " \"account\" : \"account\" (string) The account associated with the address, \"\" is the default account\n" |
| 3656 | + " \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n" |
| 3657 | + " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n" |
| 3658 | + "}\n" |
| 3659 | + "\nExamples:\n" |
| 3660 | + + HelpExampleCli("getaddressinfo", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"") |
| 3661 | + + HelpExampleRpc("getaddressinfo", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"") |
| 3662 | + ); |
| 3663 | + } |
| 3664 | + |
| 3665 | + LOCK(pwallet->cs_wallet); |
| 3666 | + |
| 3667 | + UniValue ret(UniValue::VOBJ); |
| 3668 | + CTxDestination dest = DecodeDestination(request.params[0].get_str()); |
| 3669 | + |
| 3670 | + // Make sure the destination is valid |
| 3671 | + if (!IsValidDestination(dest)) { |
| 3672 | + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); |
| 3673 | + } |
| 3674 | + |
| 3675 | + std::string currentAddress = EncodeDestination(dest); |
| 3676 | + ret.pushKV("address", currentAddress); |
| 3677 | + |
| 3678 | + CScript scriptPubKey = GetScriptForDestination(dest); |
| 3679 | + ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())); |
| 3680 | + |
| 3681 | + isminetype mine = IsMine(*pwallet, dest); |
| 3682 | + ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE)); |
| 3683 | + ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY)); |
| 3684 | + UniValue detail = DescribeWalletAddress(pwallet, dest); |
| 3685 | + ret.pushKVs(detail); |
| 3686 | + if (pwallet->mapAddressBook.count(dest)) { |
| 3687 | + ret.pushKV("account", pwallet->mapAddressBook[dest].name); |
| 3688 | + } |
| 3689 | + const CKeyMetadata* meta = nullptr; |
| 3690 | + const CKeyID *key_id = boost::get<CKeyID>(&dest); |
| 3691 | + if (key_id != nullptr && !key_id->IsNull()) { |
| 3692 | + auto it = pwallet->mapKeyMetadata.find(*key_id); |
| 3693 | + if (it != pwallet->mapKeyMetadata.end()) { |
| 3694 | + meta = &it->second; |
| 3695 | + } |
| 3696 | + } |
| 3697 | + if (!meta) { |
| 3698 | + auto it = pwallet->m_script_metadata.find(CScriptID(scriptPubKey)); |
| 3699 | + if (it != pwallet->m_script_metadata.end()) { |
| 3700 | + meta = &it->second; |
| 3701 | + } |
| 3702 | + } |
| 3703 | + if (meta) { |
| 3704 | + ret.pushKV("timestamp", meta->nCreateTime); |
| 3705 | + CHDChain hdChainCurrent; |
| 3706 | + if (key_id && pwallet->mapHdPubKeys.count(*key_id) && pwallet->GetHDChain(hdChainCurrent)) { |
| 3707 | + ret.pushKV("hdkeypath", pwallet->mapHdPubKeys[*key_id].GetKeyPath()); |
| 3708 | + ret.pushKV("hdchainid", hdChainCurrent.GetID().GetHex()); |
| 3709 | + } |
| 3710 | + } |
| 3711 | + return ret; |
| 3712 | +} |
| 3713 | + |
3572 | 3714 | extern UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp |
3573 | 3715 | extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp |
3574 | 3716 | extern UniValue importprivkey(const JSONRPCRequest& request); |
@@ -3599,6 +3741,7 @@ static const CRPCCommand commands[] = |
3599 | 3741 | { "wallet", "getaccountaddress", &getaccountaddress, {"account"} }, |
3600 | 3742 | { "wallet", "getaccount", &getaccount, {"address"} }, |
3601 | 3743 | { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, {"account"} }, |
| 3744 | + { "wallet", "getaddressinfo", &getaddressinfo, {"address"} }, |
3602 | 3745 | { "wallet", "getbalance", &getbalance, {"account","minconf","addlocked","include_watchonly"} }, |
3603 | 3746 | { "wallet", "getnewaddress", &getnewaddress, {"account"} }, |
3604 | 3747 | { "wallet", "getrawchangeaddress", &getrawchangeaddress, {} }, |
|
0 commit comments