2012-08-21 10:38:57 -04:00
// Copyright (c) 2010 Satoshi Nakamoto
2020-01-14 16:17:38 -03:00
// Copyright (c) 2009-2020 The Bitcoin Core developers
2014-11-19 23:19:29 -03:00
// Distributed under the MIT software license, see the accompanying
2012-08-21 10:38:57 -04:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2017-11-09 21:57:53 -03:00
# include <core_io.h>
2017-09-19 22:12:25 -03:00
# include <key_io.h>
2017-11-09 21:57:53 -03:00
# include <rpc/server.h>
2017-09-29 01:21:28 -03:00
# include <rpc/util.h>
2019-08-19 18:12:35 -04:00
# include <util/translation.h>
2021-02-12 20:01:22 -03:00
# include <wallet/receive.h>
2021-12-01 00:43:31 -03:00
# include <wallet/rpc/wallet.h>
2021-12-01 03:20:33 -03:00
# include <wallet/rpc/util.h>
2017-11-09 21:57:53 -03:00
# include <wallet/wallet.h>
2013-04-13 02:13:08 -03:00
2021-03-15 00:59:05 -03:00
# include <optional>
2013-04-13 02:13:08 -03:00
2015-09-04 11:11:34 -03:00
# include <univalue.h>
2012-08-21 10:38:57 -04:00
2019-07-13 11:34:49 -04:00
2019-06-06 10:49:52 -04:00
/** Checks if a CKey is in the given CWallet compressed or otherwise*/
2019-10-07 15:11:34 -03:00
bool HaveKey ( const SigningProvider & wallet , const CKey & key )
2019-06-06 10:49:52 -04:00
{
CKey key2 ;
key2 . Set ( key . begin ( ) , key . end ( ) , ! key . IsCompressed ( ) ) ;
return wallet . HaveKey ( key . GetPubKey ( ) . GetID ( ) ) | | wallet . HaveKey ( key2 . GetPubKey ( ) . GetID ( ) ) ;
}
2020-09-22 13:13:52 -03:00
static RPCHelpMan getwalletinfo ( )
2014-02-21 01:56:04 -03:00
{
2020-09-22 13:13:52 -03:00
return RPCHelpMan { " getwalletinfo " ,
2018-12-21 14:29:36 -03:00
" Returns an object containing various wallet state info. \n " ,
{ } ,
RPCResult {
2020-01-09 14:00:57 -03:00
RPCResult : : Type : : OBJ , " " , " " ,
{
{
{ RPCResult : : Type : : STR , " walletname " , " the wallet name " } ,
{ RPCResult : : Type : : NUM , " walletversion " , " the wallet version " } ,
2020-10-11 19:19:44 -03:00
{ RPCResult : : Type : : STR , " format " , " the database format (bdb or sqlite) " } ,
2020-01-09 14:00:57 -03:00
{ RPCResult : : Type : : STR_AMOUNT , " balance " , " DEPRECATED. Identical to getbalances().mine.trusted " } ,
{ RPCResult : : Type : : STR_AMOUNT , " unconfirmed_balance " , " DEPRECATED. Identical to getbalances().mine.untrusted_pending " } ,
{ RPCResult : : Type : : STR_AMOUNT , " immature_balance " , " DEPRECATED. Identical to getbalances().mine.immature " } ,
{ RPCResult : : Type : : NUM , " txcount " , " the total number of transactions in the wallet " } ,
2021-12-08 07:55:46 -03:00
{ RPCResult : : Type : : NUM_TIME , " keypoololdest " , /*optional=*/ true , " the " + UNIX_EPOCH_TIME + " of the oldest pre-generated key in the key pool. Legacy wallets only. " } ,
2020-01-09 14:00:57 -03:00
{ RPCResult : : Type : : NUM , " keypoolsize " , " how many new keys are pre-generated (only counts external keys) " } ,
2021-12-08 07:55:46 -03:00
{ RPCResult : : Type : : NUM , " keypoolsize_hd_internal " , /*optional=*/ true , " how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used) " } ,
{ RPCResult : : Type : : NUM_TIME , " unlocked_until " , /*optional=*/ true , " the " + UNIX_EPOCH_TIME + " until which the wallet is unlocked for transfers, or 0 if the wallet is locked (only present for passphrase-encrypted wallets) " } ,
2020-11-06 15:07:16 -03:00
{ RPCResult : : Type : : STR_AMOUNT , " paytxfee " , " the transaction fee configuration, set in " + CURRENCY_UNIT + " /kvB " } ,
2021-12-08 07:55:46 -03:00
{ RPCResult : : Type : : STR_HEX , " hdseedid " , /*optional=*/ true , " the Hash160 of the HD seed (only present when HD is enabled) " } ,
2020-01-09 14:00:57 -03:00
{ RPCResult : : Type : : BOOL , " private_keys_enabled " , " false if privatekeys are disabled for this wallet (enforced watch-only wallet) " } ,
{ RPCResult : : Type : : BOOL , " avoid_reuse " , " whether this wallet tracks clean/dirty coins in terms of reuse " } ,
{ RPCResult : : Type : : OBJ , " scanning " , " current scanning details, or false if no scan is in progress " ,
{
{ RPCResult : : Type : : NUM , " duration " , " elapsed seconds since scan start " } ,
{ RPCResult : : Type : : NUM , " progress " , " scanning progress percentage [0.0, 1.0] " } ,
} } ,
2019-07-05 22:32:59 -04:00
{ RPCResult : : Type : : BOOL , " descriptors " , " whether this wallet uses descriptors for scriptPubKey management " } ,
2020-01-09 14:00:57 -03:00
} } ,
2018-12-21 14:29:36 -03:00
} ,
RPCExamples {
HelpExampleCli ( " getwalletinfo " , " " )
2014-02-21 01:56:04 -03:00
+ HelpExampleRpc ( " getwalletinfo " , " " )
2018-12-21 14:29:36 -03:00
} ,
2020-09-22 13:13:52 -03:00
[ & ] ( const RPCHelpMan & self , const JSONRPCRequest & request ) - > UniValue
{
2021-08-25 03:39:04 -04:00
const std : : shared_ptr < const CWallet > pwallet = GetWalletForJSONRPCRequest ( request ) ;
2021-03-04 11:44:40 -03:00
if ( ! pwallet ) return NullUniValue ;
2020-06-11 10:23:26 -04:00
2017-09-12 14:05:28 -03:00
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet - > BlockUntilSyncedToCurrentChain ( ) ;
2017-07-26 10:23:01 -04:00
LOCK ( pwallet - > cs_wallet ) ;
2014-10-19 05:46:17 -03:00
2015-05-10 09:48:35 -03:00
UniValue obj ( UniValue : : VOBJ ) ;
2017-01-26 16:52:57 -03:00
2017-03-28 04:18:20 -03:00
size_t kpExternalSize = pwallet - > KeypoolCountExternalKeys ( ) ;
2021-02-12 20:01:22 -03:00
const auto bal = GetBalance ( * pwallet ) ;
2017-09-22 15:04:07 -03:00
obj . pushKV ( " walletname " , pwallet - > GetName ( ) ) ;
obj . pushKV ( " walletversion " , pwallet - > GetVersion ( ) ) ;
2020-10-11 19:19:44 -03:00
obj . pushKV ( " format " , pwallet - > GetDatabase ( ) . Format ( ) ) ;
2019-03-11 17:12:58 -03:00
obj . pushKV ( " balance " , ValueFromAmount ( bal . m_mine_trusted ) ) ;
obj . pushKV ( " unconfirmed_balance " , ValueFromAmount ( bal . m_mine_untrusted_pending ) ) ;
obj . pushKV ( " immature_balance " , ValueFromAmount ( bal . m_mine_immature ) ) ;
2017-09-22 15:04:07 -03:00
obj . pushKV ( " txcount " , ( int ) pwallet - > mapWallet . size ( ) ) ;
2021-10-30 16:19:22 -03:00
const auto kp_oldest = pwallet - > GetOldestKeyPoolTime ( ) ;
if ( kp_oldest . has_value ( ) ) {
obj . pushKV ( " keypoololdest " , kp_oldest . value ( ) ) ;
2019-07-11 16:14:17 -04:00
}
2017-09-22 15:04:07 -03:00
obj . pushKV ( " keypoolsize " , ( int64_t ) kpExternalSize ) ;
2019-10-07 15:11:34 -03:00
LegacyScriptPubKeyMan * spk_man = pwallet - > GetLegacyScriptPubKeyMan ( ) ;
if ( spk_man ) {
CKeyID seed_id = spk_man - > GetHDChain ( ) . seed_id ;
if ( ! seed_id . IsNull ( ) ) {
obj . pushKV ( " hdseedid " , seed_id . GetHex ( ) ) ;
}
}
2018-11-06 11:44:51 -03:00
if ( pwallet - > CanSupportFeature ( FEATURE_HD_SPLIT ) ) {
2017-09-22 15:04:07 -03:00
obj . pushKV ( " keypoolsize_hd_internal " , ( int64_t ) ( pwallet - > GetKeyPoolSize ( ) - kpExternalSize ) ) ;
2017-01-10 12:45:30 -03:00
}
2016-10-25 05:04:23 -03:00
if ( pwallet - > IsCrypted ( ) ) {
2017-09-22 15:04:07 -03:00
obj . pushKV ( " unlocked_until " , pwallet - > nRelockTime ) ;
2016-10-25 05:04:23 -03:00
}
2018-04-07 13:12:46 -03:00
obj . pushKV ( " paytxfee " , ValueFromAmount ( pwallet - > m_pay_tx_fee . GetFeePerK ( ) ) ) ;
2017-05-05 03:53:39 -03:00
obj . pushKV ( " private_keys_enabled " , ! pwallet - > IsWalletFlagSet ( WALLET_FLAG_DISABLE_PRIVATE_KEYS ) ) ;
2018-09-11 03:53:36 -03:00
obj . pushKV ( " avoid_reuse " , pwallet - > IsWalletFlagSet ( WALLET_FLAG_AVOID_REUSE ) ) ;
2019-04-03 12:56:58 -03:00
if ( pwallet - > IsScanning ( ) ) {
UniValue scanning ( UniValue : : VOBJ ) ;
scanning . pushKV ( " duration " , pwallet - > ScanningDuration ( ) / 1000 ) ;
scanning . pushKV ( " progress " , pwallet - > ScanningProgress ( ) ) ;
obj . pushKV ( " scanning " , scanning ) ;
} else {
obj . pushKV ( " scanning " , false ) ;
}
2019-07-05 22:32:59 -04:00
obj . pushKV ( " descriptors " , pwallet - > IsWalletFlagSet ( WALLET_FLAG_DESCRIPTORS ) ) ;
2014-02-21 01:56:04 -03:00
return obj ;
2020-09-22 13:13:52 -03:00
} ,
} ;
2014-02-21 01:56:04 -03:00
}
2015-03-23 14:47:18 -03:00
2020-09-22 13:13:52 -03:00
static RPCHelpMan listwalletdir ( )
2018-09-24 19:55:30 -03:00
{
2020-09-22 13:13:52 -03:00
return RPCHelpMan { " listwalletdir " ,
2018-12-21 14:29:36 -03:00
" Returns a list of wallets in the wallet directory. \n " ,
{ } ,
RPCResult {
2020-01-09 14:00:57 -03:00
RPCResult : : Type : : OBJ , " " , " " ,
{
{ RPCResult : : Type : : ARR , " wallets " , " " ,
{
{ RPCResult : : Type : : OBJ , " " , " " ,
{
{ RPCResult : : Type : : STR , " name " , " The wallet name " } ,
} } ,
} } ,
}
2018-12-21 14:29:36 -03:00
} ,
RPCExamples {
HelpExampleCli ( " listwalletdir " , " " )
2018-09-24 19:55:30 -03:00
+ HelpExampleRpc ( " listwalletdir " , " " )
2018-12-21 14:29:36 -03:00
} ,
2020-09-22 13:13:52 -03:00
[ & ] ( const RPCHelpMan & self , const JSONRPCRequest & request ) - > UniValue
{
2018-09-24 19:55:30 -03:00
UniValue wallets ( UniValue : : VARR ) ;
2020-10-30 17:25:56 -03:00
for ( const auto & path : ListDatabases ( GetWalletDir ( ) ) ) {
2018-09-24 19:55:30 -03:00
UniValue wallet ( UniValue : : VOBJ ) ;
2021-09-10 01:17:20 -03:00
wallet . pushKV ( " name " , path . u8string ( ) ) ;
2018-09-24 19:55:30 -03:00
wallets . push_back ( wallet ) ;
}
UniValue result ( UniValue : : VOBJ ) ;
result . pushKV ( " wallets " , wallets ) ;
return result ;
2020-09-22 13:13:52 -03:00
} ,
} ;
2018-09-24 19:55:30 -03:00
}
2020-09-22 13:13:52 -03:00
static RPCHelpMan listwallets ( )
2017-06-27 09:46:55 -04:00
{
2020-09-22 13:13:52 -03:00
return RPCHelpMan { " listwallets " ,
2018-10-20 09:19:44 -03:00
" Returns a list of currently loaded wallets. \n "
" For full information on the wallet, use \" getwalletinfo \" \n " ,
2018-12-21 14:29:36 -03:00
{ } ,
RPCResult {
2020-01-09 14:00:57 -03:00
RPCResult : : Type : : ARR , " " , " " ,
{
{ RPCResult : : Type : : STR , " walletname " , " the wallet name " } ,
}
2018-12-21 14:29:36 -03:00
} ,
RPCExamples {
HelpExampleCli ( " listwallets " , " " )
2017-06-27 09:46:55 -04:00
+ HelpExampleRpc ( " listwallets " , " " )
2018-12-21 14:29:36 -03:00
} ,
2020-09-22 13:13:52 -03:00
[ & ] ( const RPCHelpMan & self , const JSONRPCRequest & request ) - > UniValue
{
2017-06-27 09:46:55 -04:00
UniValue obj ( UniValue : : VARR ) ;
2020-05-28 13:06:43 -04:00
WalletContext & context = EnsureWalletContext ( request . context ) ;
for ( const std : : shared_ptr < CWallet > & wallet : GetWallets ( context ) ) {
2018-05-22 11:18:07 -04:00
LOCK ( wallet - > cs_wallet ) ;
obj . push_back ( wallet - > GetName ( ) ) ;
2017-06-27 09:46:55 -04:00
}
return obj ;
2020-09-22 13:13:52 -03:00
} ,
} ;
2017-06-27 09:46:55 -04:00
}
2020-09-22 13:13:52 -03:00
static RPCHelpMan loadwallet ( )
2018-04-18 17:01:39 -03:00
{
2020-09-22 13:13:52 -03:00
return RPCHelpMan { " loadwallet " ,
2018-10-20 09:19:44 -03:00
" \n Loads a wallet from a wallet file or directory. "
" \n Note that all wallet command-line options used when starting bitcoind will be "
2021-09-29 00:32:07 -03:00
" \n applied to the new wallet. \n " ,
2018-10-20 09:19:44 -03:00
{
2018-12-10 18:56:51 -03:00
{ " filename " , RPCArg : : Type : : STR , RPCArg : : Optional : : NO , " The wallet directory or .dat file. " } ,
2021-05-11 11:49:49 -04:00
{ " load_on_startup " , RPCArg : : Type : : BOOL , RPCArg : : Optional : : OMITTED_NAMED_ARG , " Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged. " } ,
2018-12-21 14:29:36 -03:00
} ,
RPCResult {
2020-01-09 14:00:57 -03:00
RPCResult : : Type : : OBJ , " " , " " ,
{
{ RPCResult : : Type : : STR , " name " , " The wallet name if loaded successfully. " } ,
{ RPCResult : : Type : : STR , " warning " , " Warning message if wallet was not loaded cleanly. " } ,
}
2018-12-21 14:29:36 -03:00
} ,
RPCExamples {
HelpExampleCli ( " loadwallet " , " \" test.dat \" " )
2018-04-18 17:01:39 -03:00
+ HelpExampleRpc ( " loadwallet " , " \" test.dat \" " )
2018-12-21 14:29:36 -03:00
} ,
2020-09-22 13:13:52 -03:00
[ & ] ( const RPCHelpMan & self , const JSONRPCRequest & request ) - > UniValue
{
2020-05-28 02:13:19 -04:00
WalletContext & context = EnsureWalletContext ( request . context ) ;
2020-07-28 19:25:14 -04:00
const std : : string name ( request . params [ 0 ] . get_str ( ) ) ;
2018-04-18 17:01:39 -03:00
2021-12-14 20:10:21 -03:00
DatabaseOptions options ;
DatabaseStatus status ;
options . require_existing = true ;
bilingual_str error ;
std : : vector < bilingual_str > warnings ;
std : : optional < bool > load_on_start = request . params [ 1 ] . isNull ( ) ? std : : nullopt : std : : optional < bool > ( request . params [ 1 ] . get_bool ( ) ) ;
std : : shared_ptr < CWallet > const wallet = LoadWallet ( context , name , load_on_start , options , status , error , warnings ) ;
HandleWalletError ( wallet , status , error ) ;
2018-04-18 17:01:39 -03:00
UniValue obj ( UniValue : : VOBJ ) ;
obj . pushKV ( " name " , wallet - > GetName ( ) ) ;
2020-05-10 14:28:29 -04:00
obj . pushKV ( " warning " , Join ( warnings , Untranslated ( " \n " ) ) . original ) ;
2018-04-18 17:01:39 -03:00
return obj ;
2020-09-22 13:13:52 -03:00
} ,
} ;
2018-04-18 17:01:39 -03:00
}
2020-09-22 13:13:52 -03:00
static RPCHelpMan setwalletflag ( )
2018-09-13 01:35:10 -03:00
{
2019-06-19 00:59:11 -04:00
std : : string flags = " " ;
for ( auto & it : WALLET_FLAG_MAP )
if ( it . second & MUTABLE_WALLET_FLAGS )
flags + = ( flags = = " " ? " " : " , " ) + it . first ;
2020-09-22 13:13:52 -03:00
return RPCHelpMan { " setwalletflag " ,
2018-09-13 01:35:10 -03:00
" \n Change the state of the given wallet flag for a wallet. \n " ,
{
{ " flag " , RPCArg : : Type : : STR , RPCArg : : Optional : : NO , " The name of the flag to change. Current available flags: " + flags } ,
2021-04-14 10:01:00 -04:00
{ " value " , RPCArg : : Type : : BOOL , RPCArg : : Default { true } , " The new state. " } ,
2018-09-13 01:35:10 -03:00
} ,
RPCResult {
2020-01-09 14:00:57 -03:00
RPCResult : : Type : : OBJ , " " , " " ,
{
{ RPCResult : : Type : : STR , " flag_name " , " The name of the flag that was modified " } ,
{ RPCResult : : Type : : BOOL , " flag_state " , " The new state of the flag " } ,
{ RPCResult : : Type : : STR , " warnings " , " Any warnings associated with the change " } ,
}
2018-09-13 01:35:10 -03:00
} ,
RPCExamples {
HelpExampleCli ( " setwalletflag " , " avoid_reuse " )
+ HelpExampleRpc ( " setwalletflag " , " \" avoid_reuse \" " )
} ,
2020-09-22 13:13:52 -03:00
[ & ] ( const RPCHelpMan & self , const JSONRPCRequest & request ) - > UniValue
{
2021-03-04 11:44:40 -03:00
std : : shared_ptr < CWallet > const pwallet = GetWalletForJSONRPCRequest ( request ) ;
if ( ! pwallet ) return NullUniValue ;
2020-06-11 10:23:26 -04:00
2018-09-13 01:35:10 -03:00
std : : string flag_str = request . params [ 0 ] . get_str ( ) ;
bool value = request . params [ 1 ] . isNull ( ) | | request . params [ 1 ] . get_bool ( ) ;
if ( ! WALLET_FLAG_MAP . count ( flag_str ) ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , strprintf ( " Unknown wallet flag: %s " , flag_str ) ) ;
}
auto flag = WALLET_FLAG_MAP . at ( flag_str ) ;
if ( ! ( flag & MUTABLE_WALLET_FLAGS ) ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , strprintf ( " Wallet flag is immutable: %s " , flag_str ) ) ;
}
UniValue res ( UniValue : : VOBJ ) ;
if ( pwallet - > IsWalletFlagSet ( flag ) = = value ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , strprintf ( " Wallet flag is already set to %s: %s " , value ? " true " : " false " , flag_str ) ) ;
}
res . pushKV ( " flag_name " , flag_str ) ;
res . pushKV ( " flag_state " , value ) ;
if ( value ) {
pwallet - > SetWalletFlag ( flag ) ;
} else {
pwallet - > UnsetWalletFlag ( flag ) ;
}
if ( flag & & value & & WALLET_FLAG_CAVEATS . count ( flag ) ) {
res . pushKV ( " warnings " , WALLET_FLAG_CAVEATS . at ( flag ) ) ;
}
return res ;
2020-09-22 13:13:52 -03:00
} ,
} ;
2018-09-13 01:35:10 -03:00
}
2020-09-22 13:13:52 -03:00
static RPCHelpMan createwallet ( )
2018-04-23 13:44:22 -03:00
{
2020-09-22 13:13:52 -03:00
return RPCHelpMan {
2018-12-19 18:30:49 -03:00
" createwallet " ,
" \n Creates and loads a new wallet. \n " ,
{
{ " wallet_name " , RPCArg : : Type : : STR , RPCArg : : Optional : : NO , " The name for the new wallet. If this is a path, the wallet will be created at the path location. " } ,
2021-04-14 10:01:00 -04:00
{ " disable_private_keys " , RPCArg : : Type : : BOOL , RPCArg : : Default { false } , " Disable the possibility of private keys (only watchonlys are possible in this mode). " } ,
{ " blank " , RPCArg : : Type : : BOOL , RPCArg : : Default { false } , " Create a blank wallet. A blank wallet has no keys or HD seed. One can be set using sethdseed. " } ,
2021-05-11 06:05:51 -04:00
{ " passphrase " , RPCArg : : Type : : STR , RPCArg : : Optional : : OMITTED_NAMED_ARG , " Encrypt the wallet with this passphrase. " } ,
2021-04-14 10:01:00 -04:00
{ " avoid_reuse " , RPCArg : : Type : : BOOL , RPCArg : : Default { false } , " Keep track of coin reuse, and treat dirty and clean coins differently with privacy considerations in mind. " } ,
2021-09-16 19:05:44 -03:00
{ " descriptors " , RPCArg : : Type : : BOOL , RPCArg : : Default { true } , " Create a native descriptor wallet. The wallet will use descriptors internally to handle address creation " } ,
2021-05-11 11:49:49 -04:00
{ " load_on_startup " , RPCArg : : Type : : BOOL , RPCArg : : Optional : : OMITTED_NAMED_ARG , " Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged. " } ,
2021-04-14 10:01:00 -04:00
{ " external_signer " , RPCArg : : Type : : BOOL , RPCArg : : Default { false } , " Use an external signer such as a hardware wallet. Requires -signer to be configured. Wallet creation will fail if keys cannot be fetched. Requires disable_private_keys and descriptors set to true. " } ,
2018-12-19 18:30:49 -03:00
} ,
RPCResult {
2020-01-09 14:00:57 -03:00
RPCResult : : Type : : OBJ , " " , " " ,
{
{ RPCResult : : Type : : STR , " name " , " The wallet name if created successfully. If the wallet was created using a full path, the wallet_name will be the full path. " } ,
{ RPCResult : : Type : : STR , " warning " , " Warning message if wallet was not loaded cleanly. " } ,
}
2018-12-19 18:30:49 -03:00
} ,
RPCExamples {
HelpExampleCli ( " createwallet " , " \" testwallet \" " )
2018-04-23 14:14:34 -03:00
+ HelpExampleRpc ( " createwallet " , " \" testwallet \" " )
2021-02-26 11:03:50 -03:00
+ HelpExampleCliNamed ( " createwallet " , { { " wallet_name " , " descriptors " } , { " avoid_reuse " , true } , { " descriptors " , true } , { " load_on_startup " , true } } )
+ HelpExampleRpcNamed ( " createwallet " , { { " wallet_name " , " descriptors " } , { " avoid_reuse " , true } , { " descriptors " , true } , { " load_on_startup " , true } } )
2018-12-19 18:30:49 -03:00
} ,
2020-09-22 13:13:52 -03:00
[ & ] ( const RPCHelpMan & self , const JSONRPCRequest & request ) - > UniValue
{
2020-05-28 02:13:19 -04:00
WalletContext & context = EnsureWalletContext ( request . context ) ;
2019-02-06 23:26:55 -03:00
uint64_t flags = 0 ;
if ( ! request . params [ 1 ] . isNull ( ) & & request . params [ 1 ] . get_bool ( ) ) {
flags | = WALLET_FLAG_DISABLE_PRIVATE_KEYS ;
}
if ( ! request . params [ 2 ] . isNull ( ) & & request . params [ 2 ] . get_bool ( ) ) {
2018-12-19 18:30:49 -03:00
flags | = WALLET_FLAG_BLANK_WALLET ;
}
SecureString passphrase ;
passphrase . reserve ( 100 ) ;
2019-08-19 18:12:35 -04:00
std : : vector < bilingual_str > warnings ;
2018-12-19 18:30:49 -03:00
if ( ! request . params [ 3 ] . isNull ( ) ) {
passphrase = request . params [ 3 ] . get_str ( ) . c_str ( ) ;
if ( passphrase . empty ( ) ) {
2019-07-15 15:33:56 -04:00
// Empty string means unencrypted
2019-08-19 18:12:35 -04:00
warnings . emplace_back ( Untranslated ( " Empty string given as passphrase, wallet will not be encrypted. " ) ) ;
2018-12-19 18:30:49 -03:00
}
2018-06-13 14:35:41 -04:00
}
2018-09-11 03:53:36 -03:00
if ( ! request . params [ 4 ] . isNull ( ) & & request . params [ 4 ] . get_bool ( ) ) {
flags | = WALLET_FLAG_AVOID_REUSE ;
}
2021-09-16 19:05:44 -03:00
if ( request . params [ 5 ] . isNull ( ) | | request . params [ 5 ] . get_bool ( ) ) {
2020-10-15 17:20:00 -03:00
# ifndef USE_SQLITE
throw JSONRPCError ( RPC_WALLET_ERROR , " Compiled without sqlite support (required for descriptor wallets) " ) ;
# endif
2019-07-11 18:21:21 -04:00
flags | = WALLET_FLAG_DESCRIPTORS ;
}
2019-08-04 11:56:17 -04:00
if ( ! request . params [ 7 ] . isNull ( ) & & request . params [ 7 ] . get_bool ( ) ) {
# ifdef ENABLE_EXTERNAL_SIGNER
flags | = WALLET_FLAG_EXTERNAL_SIGNER ;
# else
2021-04-13 03:08:33 -04:00
throw JSONRPCError ( RPC_WALLET_ERROR , " Compiled without external signing support (required for external signing) " ) ;
2019-08-04 11:56:17 -04:00
# endif
}
2018-09-11 03:53:36 -03:00
2020-10-19 18:34:20 -03:00
# ifndef USE_BDB
if ( ! ( flags & WALLET_FLAG_DESCRIPTORS ) ) {
throw JSONRPCError ( RPC_WALLET_ERROR , " Compiled without bdb support (required for legacy wallets) " ) ;
}
# endif
2020-08-04 17:55:13 -04:00
DatabaseOptions options ;
DatabaseStatus status ;
2020-08-04 21:03:27 -04:00
options . require_create = true ;
2020-08-04 17:55:13 -04:00
options . create_flags = flags ;
options . create_passphrase = passphrase ;
2019-08-19 18:12:35 -04:00
bilingual_str error ;
2021-03-14 23:41:30 -03:00
std : : optional < bool > load_on_start = request . params [ 6 ] . isNull ( ) ? std : : nullopt : std : : optional < bool > ( request . params [ 6 ] . get_bool ( ) ) ;
2021-08-25 03:37:14 -04:00
const std : : shared_ptr < CWallet > wallet = CreateWallet ( context , request . params [ 0 ] . get_str ( ) , load_on_start , options , status , error , warnings ) ;
2020-08-04 17:55:13 -04:00
if ( ! wallet ) {
RPCErrorCode code = status = = DatabaseStatus : : FAILED_ENCRYPT ? RPC_WALLET_ENCRYPTION_FAILED : RPC_WALLET_ERROR ;
throw JSONRPCError ( code , error . original ) ;
2018-12-19 18:30:49 -03:00
}
2018-04-23 13:44:22 -03:00
UniValue obj ( UniValue : : VOBJ ) ;
obj . pushKV ( " name " , wallet - > GetName ( ) ) ;
2020-05-10 14:28:29 -04:00
obj . pushKV ( " warning " , Join ( warnings , Untranslated ( " \n " ) ) . original ) ;
2018-04-23 13:44:22 -03:00
return obj ;
2020-09-22 13:13:52 -03:00
} ,
} ;
2018-04-23 13:44:22 -03:00
}
2020-09-22 13:13:52 -03:00
static RPCHelpMan unloadwallet ( )
2018-04-28 18:36:43 -03:00
{
2020-09-22 13:13:52 -03:00
return RPCHelpMan { " unloadwallet " ,
2018-10-20 09:19:44 -03:00
" Unloads the wallet referenced by the request endpoint otherwise unloads the wallet specified in the argument. \n "
" Specifying the wallet name on a wallet endpoint is invalid. " ,
{
2021-04-14 10:01:00 -04:00
{ " wallet_name " , RPCArg : : Type : : STR , RPCArg : : DefaultHint { " the wallet name from the RPC endpoint " } , " The name of the wallet to unload. If provided both here and in the RPC endpoint, the two must be identical. " } ,
2021-05-11 11:49:49 -04:00
{ " load_on_startup " , RPCArg : : Type : : BOOL , RPCArg : : Optional : : OMITTED_NAMED_ARG , " Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged. " } ,
2018-12-21 14:29:36 -03:00
} ,
2019-05-01 15:12:44 -04:00
RPCResult { RPCResult : : Type : : OBJ , " " , " " , {
{ RPCResult : : Type : : STR , " warning " , " Warning message if wallet was not unloaded cleanly. " } ,
} } ,
2018-12-21 14:29:36 -03:00
RPCExamples {
HelpExampleCli ( " unloadwallet " , " wallet_name " )
2018-04-28 18:36:43 -03:00
+ HelpExampleRpc ( " unloadwallet " , " wallet_name " )
2018-12-21 14:29:36 -03:00
} ,
2020-09-22 13:13:52 -03:00
[ & ] ( const RPCHelpMan & self , const JSONRPCRequest & request ) - > UniValue
{
2018-04-28 18:36:43 -03:00
std : : string wallet_name ;
if ( GetWalletNameFromJSONRPCRequest ( request , wallet_name ) ) {
2020-11-21 15:57:22 -03:00
if ( ! ( request . params [ 0 ] . isNull ( ) | | request . params [ 0 ] . get_str ( ) = = wallet_name ) ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " RPC endpoint wallet and wallet_name parameter specify different wallets " ) ;
2018-04-28 18:36:43 -03:00
}
} else {
wallet_name = request . params [ 0 ] . get_str ( ) ;
}
2020-05-28 13:06:43 -04:00
WalletContext & context = EnsureWalletContext ( request . context ) ;
std : : shared_ptr < CWallet > wallet = GetWallet ( context , wallet_name ) ;
2018-04-28 18:36:43 -03:00
if ( ! wallet ) {
throw JSONRPCError ( RPC_WALLET_NOT_FOUND , " Requested wallet does not exist or is not loaded " ) ;
}
// Release the "main" shared pointer and prevent further notifications.
// Note that any attempt to load the same wallet would fail until the wallet
// is destroyed (see CheckUniqueFileid).
2020-08-17 15:21:50 -04:00
std : : vector < bilingual_str > warnings ;
2021-03-14 23:41:30 -03:00
std : : optional < bool > load_on_start = request . params [ 1 ] . isNull ( ) ? std : : nullopt : std : : optional < bool > ( request . params [ 1 ] . get_bool ( ) ) ;
2020-05-28 13:06:43 -04:00
if ( ! RemoveWallet ( context , wallet , load_on_start , warnings ) ) {
2018-04-28 18:36:43 -03:00
throw JSONRPCError ( RPC_MISC_ERROR , " Requested wallet already unloaded " ) ;
}
2018-12-12 20:21:19 -03:00
UnloadWallet ( std : : move ( wallet ) ) ;
2018-04-28 18:36:43 -03:00
2019-05-01 15:12:44 -04:00
UniValue result ( UniValue : : VOBJ ) ;
result . pushKV ( " warning " , Join ( warnings , Untranslated ( " \n " ) ) . original ) ;
return result ;
2020-09-22 13:13:52 -03:00
} ,
} ;
2018-04-28 18:36:43 -03:00
}
2020-09-22 13:13:52 -03:00
static RPCHelpMan sethdseed ( )
2017-09-12 18:01:12 -03:00
{
2020-09-22 13:13:52 -03:00
return RPCHelpMan { " sethdseed " ,
2018-10-20 09:19:44 -03:00
" \n Set or generate a new HD wallet seed. Non-HD wallets will not be upgraded to being a HD wallet. Wallets that are already \n "
" HD will have a new HD seed set so that new keys added to the keypool will be derived from this new seed. \n "
2018-11-23 13:21:38 -03:00
" \n Note that you will need to MAKE A NEW BACKUP of your wallet after setting the HD wallet seed. " +
2020-03-31 23:31:43 -03:00
HELP_REQUIRING_PASSPHRASE ,
2018-10-20 09:19:44 -03:00
{
2021-04-14 10:01:00 -04:00
{ " newkeypool " , RPCArg : : Type : : BOOL , RPCArg : : Default { true } , " Whether to flush old unused addresses, including change addresses, from the keypool and regenerate it. \n "
2020-09-30 04:20:37 -03:00
" If true, the next address from getnewaddress and change address from getrawchangeaddress will be from this new seed. \n "
" If false, addresses (including change addresses if the wallet already had HD Chain Split enabled) from the existing \n "
" keypool will be used until it has been depleted. " } ,
2021-04-14 10:01:00 -04:00
{ " seed " , RPCArg : : Type : : STR , RPCArg : : DefaultHint { " random seed " } , " The WIF private key to use as the new HD seed. \n "
2020-09-30 04:20:37 -03:00
" The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1 " } ,
2018-12-21 14:29:36 -03:00
} ,
2020-03-13 15:40:53 -03:00
RPCResult { RPCResult : : Type : : NONE , " " , " " } ,
2018-12-21 14:29:36 -03:00
RPCExamples {
HelpExampleCli ( " sethdseed " , " " )
2017-09-12 18:01:12 -03:00
+ HelpExampleCli ( " sethdseed " , " false " )
+ HelpExampleCli ( " sethdseed " , " true \" wifkey \" " )
+ HelpExampleRpc ( " sethdseed " , " true, \" wifkey \" " )
2018-12-21 14:29:36 -03:00
} ,
2020-09-22 13:13:52 -03:00
[ & ] ( const RPCHelpMan & self , const JSONRPCRequest & request ) - > UniValue
{
2021-03-04 11:44:40 -03:00
std : : shared_ptr < CWallet > const pwallet = GetWalletForJSONRPCRequest ( request ) ;
if ( ! pwallet ) return NullUniValue ;
2020-06-11 10:23:26 -04:00
2019-10-07 15:11:34 -03:00
LegacyScriptPubKeyMan & spk_man = EnsureLegacyScriptPubKeyMan ( * pwallet , true ) ;
2019-10-07 15:11:34 -03:00
2019-01-25 16:38:34 -03:00
if ( pwallet - > IsWalletFlagSet ( WALLET_FLAG_DISABLE_PRIVATE_KEYS ) ) {
throw JSONRPCError ( RPC_WALLET_ERROR , " Cannot set a HD seed to a wallet with private keys disabled " ) ;
}
2019-10-07 15:11:34 -03:00
LOCK2 ( pwallet - > cs_wallet , spk_man . cs_KeyStore ) ;
2017-09-12 18:01:12 -03:00
// Do not do anything to non-HD wallets
2019-02-06 23:26:55 -03:00
if ( ! pwallet - > CanSupportFeature ( FEATURE_HD ) ) {
2020-11-16 14:23:10 -03:00
throw JSONRPCError ( RPC_WALLET_ERROR , " Cannot set an HD seed on a non-HD wallet. Use the upgradewallet RPC in order to upgrade a non-HD wallet to HD " ) ;
2017-09-12 18:01:12 -03:00
}
2021-03-04 12:20:13 -03:00
EnsureWalletIsUnlocked ( * pwallet ) ;
2017-09-12 18:01:12 -03:00
bool flush_key_pool = true ;
if ( ! request . params [ 0 ] . isNull ( ) ) {
flush_key_pool = request . params [ 0 ] . get_bool ( ) ;
}
CPubKey master_pub_key ;
if ( request . params [ 1 ] . isNull ( ) ) {
2019-11-05 12:13:43 -03:00
master_pub_key = spk_man . GenerateNewSeed ( ) ;
2017-09-12 18:01:12 -03:00
} else {
CKey key = DecodeSecret ( request . params [ 1 ] . get_str ( ) ) ;
if ( ! key . IsValid ( ) ) {
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Invalid private key " ) ;
}
2019-11-05 12:13:43 -03:00
if ( HaveKey ( spk_man , key ) ) {
2017-09-12 18:01:12 -03:00
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Already have this key (either as an HD seed or as a loose private key) " ) ;
}
2019-11-05 12:13:43 -03:00
master_pub_key = spk_man . DeriveNewSeed ( key ) ;
2017-09-12 18:01:12 -03:00
}
2019-11-05 12:13:43 -03:00
spk_man . SetHDSeed ( master_pub_key ) ;
if ( flush_key_pool ) spk_man . NewKeyPool ( ) ;
2017-09-12 18:01:12 -03:00
return NullUniValue ;
2020-09-22 13:13:52 -03:00
} ,
} ;
2017-09-12 18:01:12 -03:00
}
2020-09-22 13:13:52 -03:00
static RPCHelpMan upgradewallet ( )
2019-04-06 13:56:06 -03:00
{
2020-09-22 13:13:52 -03:00
return RPCHelpMan { " upgradewallet " ,
2020-11-16 14:23:10 -03:00
" \n Upgrade the wallet. Upgrades to the latest version if no version number is specified. \n "
2019-04-06 13:56:06 -03:00
" New keys may be generated and a new wallet backup will need to be made. " ,
{
2021-04-14 10:01:00 -04:00
{ " version " , RPCArg : : Type : : NUM , RPCArg : : Default { FEATURE_LATEST } , " The version number to upgrade to. Default is the latest wallet version. " }
2019-04-06 13:56:06 -03:00
} ,
2020-10-18 22:01:42 -03:00
RPCResult {
RPCResult : : Type : : OBJ , " " , " " ,
{
2020-11-16 14:23:10 -03:00
{ RPCResult : : Type : : STR , " wallet_name " , " Name of wallet this operation was performed on " } ,
{ RPCResult : : Type : : NUM , " previous_version " , " Version of wallet before this operation " } ,
{ RPCResult : : Type : : NUM , " current_version " , " Version of wallet after this operation " } ,
2021-12-08 07:55:46 -03:00
{ RPCResult : : Type : : STR , " result " , /*optional=*/ true , " Description of result, if no error " } ,
{ RPCResult : : Type : : STR , " error " , /*optional=*/ true , " Error message (if there is one) " }
2020-10-18 22:01:42 -03:00
} ,
} ,
2019-04-06 13:56:06 -03:00
RPCExamples {
HelpExampleCli ( " upgradewallet " , " 169900 " )
+ HelpExampleRpc ( " upgradewallet " , " 169900 " )
2020-09-22 13:13:52 -03:00
} ,
[ & ] ( const RPCHelpMan & self , const JSONRPCRequest & request ) - > UniValue
{
2021-03-04 11:44:40 -03:00
std : : shared_ptr < CWallet > const pwallet = GetWalletForJSONRPCRequest ( request ) ;
if ( ! pwallet ) return NullUniValue ;
2020-06-11 10:23:26 -04:00
2019-04-06 13:56:06 -03:00
RPCTypeCheck ( request . params , { UniValue : : VNUM } , true ) ;
2021-03-04 12:20:13 -03:00
EnsureWalletIsUnlocked ( * pwallet ) ;
2019-04-06 13:56:06 -03:00
int version = 0 ;
if ( ! request . params [ 0 ] . isNull ( ) ) {
version = request . params [ 0 ] . get_int ( ) ;
}
2019-08-19 18:12:35 -04:00
bilingual_str error ;
2020-11-16 14:23:10 -03:00
const int previous_version { pwallet - > GetVersion ( ) } ;
const bool wallet_upgraded { pwallet - > UpgradeWallet ( version , error ) } ;
const int current_version { pwallet - > GetVersion ( ) } ;
std : : string result ;
2020-11-17 11:57:14 -03:00
if ( wallet_upgraded ) {
if ( previous_version = = current_version ) {
result = " Already at latest version. Wallet version unchanged. " ;
} else {
result = strprintf ( " Wallet upgraded successfully from version %i to version %i. " , previous_version , current_version ) ;
}
2019-04-06 13:56:06 -03:00
}
2020-11-16 14:23:10 -03:00
2020-10-18 22:01:42 -03:00
UniValue obj ( UniValue : : VOBJ ) ;
2020-11-16 14:23:10 -03:00
obj . pushKV ( " wallet_name " , pwallet - > GetName ( ) ) ;
obj . pushKV ( " previous_version " , previous_version ) ;
obj . pushKV ( " current_version " , current_version ) ;
if ( ! result . empty ( ) ) {
obj . pushKV ( " result " , result ) ;
2020-11-17 11:57:14 -03:00
} else {
CHECK_NONFATAL ( ! error . empty ( ) ) ;
2020-10-18 22:01:42 -03:00
obj . pushKV ( " error " , error . original ) ;
}
return obj ;
2020-09-22 13:13:52 -03:00
} ,
} ;
2019-04-06 13:56:06 -03:00
}
2021-12-01 00:52:29 -03:00
// addresses
RPCHelpMan getaddressinfo ( ) ;
RPCHelpMan getnewaddress ( ) ;
RPCHelpMan getrawchangeaddress ( ) ;
RPCHelpMan setlabel ( ) ;
RPCHelpMan listaddressgroupings ( ) ;
RPCHelpMan addmultisigaddress ( ) ;
RPCHelpMan keypoolrefill ( ) ;
RPCHelpMan newkeypool ( ) ;
RPCHelpMan getaddressesbylabel ( ) ;
RPCHelpMan listlabels ( ) ;
# ifdef ENABLE_EXTERNAL_SIGNER
RPCHelpMan walletdisplayaddress ( ) ;
# endif // ENABLE_EXTERNAL_SIGNER
// backup
2020-08-14 05:22:05 -04:00
RPCHelpMan dumpprivkey ( ) ;
RPCHelpMan importprivkey ( ) ;
RPCHelpMan importaddress ( ) ;
RPCHelpMan importpubkey ( ) ;
RPCHelpMan dumpwallet ( ) ;
RPCHelpMan importwallet ( ) ;
RPCHelpMan importprunedfunds ( ) ;
RPCHelpMan removeprunedfunds ( ) ;
RPCHelpMan importmulti ( ) ;
RPCHelpMan importdescriptors ( ) ;
2020-10-09 04:24:20 -03:00
RPCHelpMan listdescriptors ( ) ;
2021-11-29 23:19:02 -03:00
RPCHelpMan backupwallet ( ) ;
RPCHelpMan restorewallet ( ) ;
2016-01-07 04:33:49 -03:00
2021-12-01 00:09:30 -03:00
// coins
RPCHelpMan getreceivedbyaddress ( ) ;
RPCHelpMan getreceivedbylabel ( ) ;
RPCHelpMan getbalance ( ) ;
RPCHelpMan getunconfirmedbalance ( ) ;
RPCHelpMan lockunspent ( ) ;
RPCHelpMan listlockunspent ( ) ;
RPCHelpMan getbalances ( ) ;
RPCHelpMan listunspent ( ) ;
2021-11-30 22:50:19 -03:00
// encryption
RPCHelpMan walletpassphrase ( ) ;
RPCHelpMan walletpassphrasechange ( ) ;
RPCHelpMan walletlock ( ) ;
RPCHelpMan encryptwallet ( ) ;
2021-12-01 00:40:55 -03:00
// spend
RPCHelpMan sendtoaddress ( ) ;
RPCHelpMan sendmany ( ) ;
RPCHelpMan settxfee ( ) ;
RPCHelpMan fundrawtransaction ( ) ;
RPCHelpMan bumpfee ( ) ;
RPCHelpMan psbtbumpfee ( ) ;
RPCHelpMan send ( ) ;
RPCHelpMan walletprocesspsbt ( ) ;
RPCHelpMan walletcreatefundedpsbt ( ) ;
2021-12-01 00:52:29 -03:00
RPCHelpMan signrawtransactionwithwallet ( ) ;
// signmessage
RPCHelpMan signmessage ( ) ;
2021-12-01 00:40:55 -03:00
2021-11-30 23:06:45 -03:00
// transactions
RPCHelpMan listreceivedbyaddress ( ) ;
RPCHelpMan listreceivedbylabel ( ) ;
RPCHelpMan listtransactions ( ) ;
RPCHelpMan listsinceblock ( ) ;
RPCHelpMan gettransaction ( ) ;
RPCHelpMan abandontransaction ( ) ;
RPCHelpMan rescanblockchain ( ) ;
2021-12-07 19:54:08 -03:00
RPCHelpMan abortrescan ( ) ;
2021-11-30 23:06:45 -03:00
2020-05-28 02:13:19 -04:00
Span < const CRPCCommand > GetWalletRPCCommands ( )
2020-04-05 12:21:33 -04:00
{
2018-08-20 09:19:43 -03:00
// clang-format off
2016-03-29 14:43:02 -03:00
static const CRPCCommand commands [ ] =
2021-01-12 02:41:46 -03:00
{ // category actor (function)
// ------------------ ------------------------
{ " rawtransactions " , & fundrawtransaction , } ,
{ " wallet " , & abandontransaction , } ,
{ " wallet " , & abortrescan , } ,
{ " wallet " , & addmultisigaddress , } ,
{ " wallet " , & backupwallet , } ,
{ " wallet " , & bumpfee , } ,
{ " wallet " , & psbtbumpfee , } ,
{ " wallet " , & createwallet , } ,
2021-07-27 13:28:23 -04:00
{ " wallet " , & restorewallet , } ,
2021-01-12 02:41:46 -03:00
{ " wallet " , & dumpprivkey , } ,
{ " wallet " , & dumpwallet , } ,
{ " wallet " , & encryptwallet , } ,
{ " wallet " , & getaddressesbylabel , } ,
{ " wallet " , & getaddressinfo , } ,
{ " wallet " , & getbalance , } ,
{ " wallet " , & getnewaddress , } ,
{ " wallet " , & getrawchangeaddress , } ,
{ " wallet " , & getreceivedbyaddress , } ,
{ " wallet " , & getreceivedbylabel , } ,
{ " wallet " , & gettransaction , } ,
{ " wallet " , & getunconfirmedbalance , } ,
{ " wallet " , & getbalances , } ,
{ " wallet " , & getwalletinfo , } ,
{ " wallet " , & importaddress , } ,
{ " wallet " , & importdescriptors , } ,
{ " wallet " , & importmulti , } ,
{ " wallet " , & importprivkey , } ,
{ " wallet " , & importprunedfunds , } ,
{ " wallet " , & importpubkey , } ,
{ " wallet " , & importwallet , } ,
{ " wallet " , & keypoolrefill , } ,
{ " wallet " , & listaddressgroupings , } ,
{ " wallet " , & listdescriptors , } ,
{ " wallet " , & listlabels , } ,
{ " wallet " , & listlockunspent , } ,
{ " wallet " , & listreceivedbyaddress , } ,
{ " wallet " , & listreceivedbylabel , } ,
{ " wallet " , & listsinceblock , } ,
{ " wallet " , & listtransactions , } ,
{ " wallet " , & listunspent , } ,
{ " wallet " , & listwalletdir , } ,
{ " wallet " , & listwallets , } ,
{ " wallet " , & loadwallet , } ,
{ " wallet " , & lockunspent , } ,
2021-09-25 19:36:59 -03:00
{ " wallet " , & newkeypool , } ,
2021-01-12 02:41:46 -03:00
{ " wallet " , & removeprunedfunds , } ,
{ " wallet " , & rescanblockchain , } ,
{ " wallet " , & send , } ,
{ " wallet " , & sendmany , } ,
{ " wallet " , & sendtoaddress , } ,
{ " wallet " , & sethdseed , } ,
{ " wallet " , & setlabel , } ,
{ " wallet " , & settxfee , } ,
{ " wallet " , & setwalletflag , } ,
{ " wallet " , & signmessage , } ,
{ " wallet " , & signrawtransactionwithwallet , } ,
{ " wallet " , & unloadwallet , } ,
{ " wallet " , & upgradewallet , } ,
{ " wallet " , & walletcreatefundedpsbt , } ,
2021-03-18 10:17:39 -03:00
# ifdef ENABLE_EXTERNAL_SIGNER
{ " wallet " , & walletdisplayaddress , } ,
# endif // ENABLE_EXTERNAL_SIGNER
2021-01-12 02:41:46 -03:00
{ " wallet " , & walletlock , } ,
{ " wallet " , & walletpassphrase , } ,
{ " wallet " , & walletpassphrasechange , } ,
{ " wallet " , & walletprocesspsbt , } ,
2016-01-07 04:33:49 -03:00
} ;
2018-08-20 09:19:43 -03:00
// clang-format on
2021-11-02 11:07:46 -03:00
return commands ;
2016-01-07 04:33:49 -03:00
}