34 "Returns an object containing various wallet state info.\n",
48 {
RPCResult::Type::NUM,
"keypoolsize",
"how many new keys are pre-generated (only counts external keys)"},
49 {
RPCResult::Type::NUM,
"keypoolsize_hd_internal",
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)"},
50 {
RPCResult::Type::NUM_TIME,
"unlocked_until",
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)"},
53 {
RPCResult::Type::BOOL,
"private_keys_enabled",
"false if privatekeys are disabled for this wallet (enforced watch-only wallet)"},
54 {
RPCResult::Type::BOOL,
"avoid_reuse",
"whether this wallet tracks clean/dirty coins in terms of reuse"},
55 {
RPCResult::Type::OBJ,
"scanning",
"current scanning details, or false if no scan is in progress",
60 {
RPCResult::Type::BOOL,
"descriptors",
"whether this wallet uses descriptors for scriptPubKey management"},
61 {
RPCResult::Type::BOOL,
"external_signer",
"whether this wallet is configured to use an external signer such as a hardware wallet"},
75 pwallet->BlockUntilSyncedToCurrentChain();
77 LOCK(pwallet->cs_wallet);
81 size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
83 obj.
pushKV(
"walletname", pwallet->GetName());
84 obj.
pushKV(
"walletversion", pwallet->GetVersion());
85 obj.
pushKV(
"format", pwallet->GetDatabase().Format());
89 obj.
pushKV(
"txcount", (
int)pwallet->mapWallet.size());
90 const auto kp_oldest = pwallet->GetOldestKeyPoolTime();
91 if (kp_oldest.has_value()) {
92 obj.
pushKV(
"keypoololdest", kp_oldest.value());
94 obj.
pushKV(
"keypoolsize", (int64_t)kpExternalSize);
105 obj.
pushKV(
"keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize));
107 if (pwallet->IsCrypted()) {
108 obj.
pushKV(
"unlocked_until", pwallet->nRelockTime);
113 if (pwallet->IsScanning()) {
115 scanning.
pushKV(
"duration", pwallet->ScanningDuration() / 1000);
116 scanning.
pushKV(
"progress", pwallet->ScanningProgress());
117 obj.
pushKV(
"scanning", scanning);
119 obj.
pushKV(
"scanning",
false);
131 "Returns a list of wallets in the wallet directory.\n",
154 wallet.pushKV(
"name", path.u8string());
159 result.
pushKV(
"wallets", wallets);
168 "Returns a list of currently loaded wallets.\n" 169 "For full information on the wallet, use \"getwalletinfo\"\n",
199 "\nLoads a wallet from a wallet file or directory." 200 "\nNote that all wallet command-line options used when starting bitcoind will be" 201 "\napplied to the new wallet.\n",
210 {
RPCResult::Type::STR,
"warning",
"Warning messages, if any, related to loading the wallet. Multiple messages will be delimited by newlines."},
220 const std::string
name(request.params[0].get_str());
225 options.require_existing =
true;
227 std::vector<bilingual_str> warnings;
228 std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
247 flags += (
flags ==
"" ?
"" :
", ") + it.first;
250 "\nChange the state of the given wallet flag for a wallet.\n",
272 std::string flag_str = request.params[0].get_str();
273 bool value = request.params[1].isNull() || request.params[1].get_bool();
287 if (pwallet->IsWalletFlagSet(flag) == value) {
291 res.pushKV(
"flag_name", flag_str);
292 res.pushKV(
"flag_state", value);
295 pwallet->SetWalletFlag(flag);
297 pwallet->UnsetWalletFlag(flag);
313 "\nCreates and loads a new wallet.\n",
319 {
"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."},
320 {
"descriptors",
RPCArg::Type::BOOL,
RPCArg::Default{
true},
"Create a native descriptor wallet. The wallet will use descriptors internally to handle address creation." 321 " Setting to \"false\" will create a legacy wallet; however, the legacy wallet type is being deprecated and" 322 " support for creating and opening legacy wallets will be removed in the future."},
324 {
"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."},
329 {
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."},
330 {
RPCResult::Type::STR,
"warning",
"Warning messages, if any, related to creating the wallet. Multiple messages will be delimited by newlines."},
336 +
HelpExampleCliNamed(
"createwallet", {{
"wallet_name",
"descriptors"}, {
"avoid_reuse",
true}, {
"descriptors",
true}, {
"load_on_startup",
true}})
337 +
HelpExampleRpcNamed(
"createwallet", {{
"wallet_name",
"descriptors"}, {
"avoid_reuse",
true}, {
"descriptors",
true}, {
"load_on_startup",
true}})
343 if (!request.params[1].isNull() && request.params[1].get_bool()) {
347 if (!request.params[2].isNull() && request.params[2].get_bool()) {
351 passphrase.reserve(100);
352 std::vector<bilingual_str> warnings;
353 if (!request.params[3].isNull()) {
354 passphrase = request.params[3].get_str().c_str();
355 if (passphrase.empty()) {
357 warnings.emplace_back(
Untranslated(
"Empty string given as passphrase, wallet will not be encrypted."));
361 if (!request.params[4].isNull() && request.params[4].get_bool()) {
364 if (request.params[5].isNull() || request.params[5].get_bool()) {
370 if (!request.params[7].isNull() && request.params[7].get_bool()) {
371 #ifdef ENABLE_EXTERNAL_SIGNER 391 std::optional<bool> load_on_start = request.params[6].isNull() ? std::nullopt : std::optional<bool>(request.params[6].get_bool());
410 "Unloads the wallet referenced by the request endpoint otherwise unloads the wallet specified in the argument.\n" 411 "Specifying the wallet name on a wallet endpoint is invalid.",
413 {
"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."},
417 {
RPCResult::Type::STR,
"warning",
"Warning messages, if any, related to unloading the wallet. Multiple messages will be delimited by newlines."},
425 std::string wallet_name;
427 if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
431 wallet_name = request.params[0].get_str();
443 std::vector<bilingual_str> warnings;
444 std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
461 "\nSet or generate a new HD wallet seed. Non-HD wallets will not be upgraded to being a HD wallet. Wallets that are already\n" 462 "HD will have a new HD seed set so that new keys added to the keypool will be derived from this new seed.\n" 463 "\nNote that you will need to MAKE A NEW BACKUP of your wallet after setting the HD wallet seed." +
466 {
"newkeypool",
RPCArg::Type::BOOL,
RPCArg::Default{
true},
"Whether to flush old unused addresses, including change addresses, from the keypool and regenerate it.\n" 467 "If true, the next address from getnewaddress and change address from getrawchangeaddress will be from this new seed.\n" 468 "If false, addresses (including change addresses if the wallet already had HD Chain Split enabled) from the existing\n" 469 "keypool will be used until it has been depleted."},
471 "The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1"},
494 if (!pwallet->CanSupportFeature(
FEATURE_HD)) {
495 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");
500 bool flush_key_pool =
true;
501 if (!request.params[0].isNull()) {
502 flush_key_pool = request.params[0].get_bool();
506 if (request.params[1].isNull()) {
532 "\nUpgrade the wallet. Upgrades to the latest version if no version number is specified.\n" 533 "New keys may be generated and a new wallet backup will need to be made.",
561 if (!request.params[0].isNull()) {
562 version = request.params[0].getInt<
int>();
565 const int previous_version{pwallet->GetVersion()};
566 const bool wallet_upgraded{pwallet->UpgradeWallet(version,
error)};
567 const int current_version{pwallet->GetVersion()};
570 if (wallet_upgraded) {
571 if (previous_version == current_version) {
572 result =
"Already at latest version. Wallet version unchanged.";
574 result =
strprintf(
"Wallet upgraded successfully from version %i to version %i.", previous_version, current_version);
579 obj.
pushKV(
"wallet_name", pwallet->GetName());
580 obj.
pushKV(
"previous_version", previous_version);
581 obj.
pushKV(
"current_version", current_version);
582 if (!result.empty()) {
583 obj.
pushKV(
"result", result);
596 "\nCalculate the balance change resulting in the signing and broadcasting of the given transaction(s).\n",
625 RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VOBJ},
true);
630 if (request.params[1].isObject()) {
631 UniValue options = request.params[1];
638 include_watchonly = options[
"include_watchonly"];
646 const auto& txs = request.params[0].get_array();
648 std::map<COutPoint, CAmount> new_utxos;
649 std::set<COutPoint> spent;
651 for (
size_t i = 0; i < txs.size(); ++i) {
653 if (!
DecodeHexTx(mtx, txs[i].get_str(),
true,
true)) {
658 std::map<COutPoint, Coin> coins;
662 wallet.chain().findCoins(coins);
666 for (
const auto& txin : mtx.
vin) {
667 const auto& outpoint = txin.
prevout;
668 if (spent.count(outpoint)) {
671 if (new_utxos.count(outpoint)) {
672 changes -= new_utxos.at(outpoint);
673 new_utxos.erase(outpoint);
675 if (coins.at(outpoint).IsSpent()) {
678 changes -=
wallet.GetDebit(txin, filter);
680 spent.insert(outpoint);
688 const auto& hash = mtx.
GetHash();
689 for (
size_t i = 0; i < mtx.
vout.size(); ++i) {
690 const auto& txout = mtx.
vout[i];
691 bool is_mine = 0 < (
wallet.IsMine(txout) & filter);
692 changes += new_utxos[
COutPoint(hash, i)] = is_mine ? txout.nValue : 0;
707 "EXPERIMENTAL warning: This call may not work as expected and may be changed in future releases\n" 708 "\nMigrate the wallet to a descriptor wallet.\n" 709 "A new wallet backup will need to be made.\n" 710 "\nThe migration process will create a backup of the wallet before migrating. This backup\n" 711 "file will be named <wallet name>-<timestamp>.legacy.bak and can be found in the directory\n" 712 "for this wallet. In the event of an incorrect migration, the backup can be restored using restorewallet." 713 "\nEncrypted wallets must have the passphrase provided as an argument to this call.",
715 {
"wallet_name",
RPCArg::Type::STR,
RPCArg::DefaultHint{
"the wallet name from the RPC endpoint"},
"The name of the wallet to migrate. If provided both here and in the RPC endpoint, the two must be identical."},
722 {
RPCResult::Type::STR,
"watchonly_name",
true,
"The name of the migrated wallet containing the watchonly scripts"},
723 {
RPCResult::Type::STR,
"solvables_name",
true,
"The name of the migrated wallet containing solvable but not watched scripts"},
733 std::string wallet_name;
735 if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
739 if (request.params[0].isNull()) {
742 wallet_name = request.params[0].get_str();
746 wallet_pass.reserve(100);
747 if (!request.params[1].isNull()) {
748 wallet_pass = std::string_view{request.params[1].get_str()};
758 r.pushKV(
"wallet_name", res->wallet_name);
759 if (res->watchonly_wallet) {
760 r.pushKV(
"watchonly_name", res->watchonly_wallet->GetName());
762 if (res->solvables_wallet) {
763 r.pushKV(
"solvables_name", res->solvables_wallet->GetName());
765 r.pushKV(
"backup_path", res->backup_path.u8string());
783 #ifdef ENABLE_EXTERNAL_SIGNER 785 #endif // ENABLE_EXTERNAL_SIGNER 909 #ifdef ENABLE_EXTERNAL_SIGNER 911 #endif // ENABLE_EXTERNAL_SIGNER
RPCHelpMan importwallet()
void push_back(UniValue val)
void ReadDatabaseArgs(const ArgsManager &args, DatabaseOptions &options)
RPCHelpMan listlockunspent()
static RPCHelpMan listwalletdir()
RPCHelpMan simulaterawtransaction()
static RPCHelpMan setwalletflag()
std::string HelpExampleRpcNamed(const std::string &methodname, const RPCArgList &args)
const CHDChain & GetHDChain() const
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
RPCHelpMan restorewallet()
bool NewKeyPool()
Mark old keypool keys as used, and generate all new keys.
static RPCHelpMan loadwallet()
RecursiveMutex cs_KeyStore
RPCHelpMan walletpassphrase()
CPubKey GetPubKey() const
Compute the public key from a private key.
RPCHelpMan sendtoaddress()
RPCHelpMan getreceivedbylabel()
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
std::shared_ptr< CWallet > LoadWallet(WalletContext &context, const std::string &name, std::optional< bool > load_on_start, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
RPCHelpMan listtransactions()
RPCHelpMan abandontransaction()
#define CHECK_NONFATAL(condition)
Identity function.
static RPCHelpMan sethdseed()
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
bool ParseIncludeWatchonly(const UniValue &include_watchonly, const CWallet &wallet)
Used by RPC commands that have an include_watchonly parameter.
const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
void SetHDSeed(const CPubKey &key)
Balance GetBalance(const CWallet &wallet, const int min_depth, bool avoid_reuse)
RPCHelpMan getaddressinfo()
const unsigned char * begin() const
fs::path GetWalletDir()
Get the path of the wallet directory.
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses, and other watch only things, and is therefore "blank.".
Invalid, missing or duplicate parameter.
static constexpr uint64_t MUTABLE_WALLET_FLAGS
static RPCHelpMan getwalletinfo()
static RPCHelpMan unloadwallet()
RPCHelpMan rescanblockchain()
RPCHelpMan walletdisplayaddress()
void HandleWalletError(const std::shared_ptr< CWallet > wallet, DatabaseStatus &status, bilingual_str &error)
RPCHelpMan walletcreatefundedpsbt()
int64_t CAmount
Amount in satoshis (Can be negative)
Special type that is a STR with only hex chars.
RPCHelpMan walletpassphrasechange()
Indicates that the wallet needs an external signer.
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
RPCHelpMan fundrawtransaction()
std::underlying_type< isminetype >::type isminefilter
used for bitflags of isminetype
UniValue JSONRPCError(int code, const std::string &message)
RPCHelpMan signrawtransactionwithwallet()
Special string with only hex chars.
SecureString create_passphrase
RPCHelpMan listsinceblock()
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start)
RPCHelpMan walletprocesspsbt()
An input of a transaction.
static RPCHelpMan createwallet()
RPCHelpMan listreceivedbylabel()
An encapsulated public key.
WalletContext & EnsureWalletContext(const std::any &context)
Special type where the user must set the keys e.g. to define multiple addresses; as opposed to e...
RPCHelpMan listdescriptors()
Indicate that this wallet supports DescriptorScriptPubKeyMan.
const std::string CURRENCY_UNIT
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
General application defined errors.
std::string HelpExampleCliNamed(const std::string &methodname, const RPCArgList &args)
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Invalid wallet specified.
An outpoint - a combination of a transaction hash and an index n into its vout.
static const std::map< std::string, WalletFlags > WALLET_FLAG_MAP
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
std::string getnewaddress(wallet::CWallet &w)
Returns a new address from the wallet.
std::vector< CTxOut > vout
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
const std::string HELP_REQUIRING_PASSPHRASE
util::Result< MigrationResult > MigrateLegacyToDescriptor(const std::string &wallet_name, const SecureString &passphrase, WalletContext &context)
Do all steps to migrate a legacy wallet to a descriptor wallet.
Special numeric to denote unix epoch time.
RPCHelpMan listreceivedbyaddress()
RPCHelpMan importdescriptors()
Optional arg that is a named argument and has a default value of null.
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
RPCHelpMan encryptwallet()
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
RPCHelpMan importpubkey()
Failed to encrypt the wallet.
Optional argument with default value omitted because they are implicitly clear.
CPubKey DeriveNewSeed(const CKey &key)
void importaddress(wallet::CWallet &wallet, const std::string &address)
Import the address to the wallet.
RPCHelpMan getunconfirmedbalance()
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
uint256 GetHash() const
Compute the hash of this CMutableTransaction.
An interface to be implemented by keystores that support signing.
RPCHelpMan importprunedfunds()
Special string to represent a floating point amount.
void pushKV(std::string key, UniValue val)
CPubKey GenerateNewSeed()
auto Join(const C &container, const S &separator, UnaryOp unary_op)
Join all container items.
RPCHelpMan gettransaction()
const unsigned char * end() const
RPCHelpMan getaddressesbylabel()
RPCHelpMan importprivkey()
A reference to a CKey: the Hash160 of its serialized public key.
bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness=false, bool try_witness=true)
std::string GetHex() const
bool HaveKey(const SigningProvider &wallet, const CKey &key)
Checks if a CKey is in the given CWallet compressed or otherwise.
UniValue ValueFromAmount(const CAmount amount)
WalletContext struct containing references to state shared between CWallet instances, like the reference to the chain interface, and the list of opened wallets.
void EnsureWalletIsUnlocked(const CWallet &wallet)
bilingual_str ErrorString(const Result< T > &result)
RPCHelpMan keypoolrefill()
A mutable version of CTransaction.
RPCHelpMan getreceivedbyaddress()
std::vector< fs::path > ListDatabases(const fs::path &wallet_dir)
Recursively list database paths in directory.
RPCHelpMan listaddressgroupings()
RPCHelpMan removeprunedfunds()
An encapsulated private key.
Span< const CRPCCommand > GetWalletRPCCommands()
A Span is an object that can refer to a contiguous sequence of objects.
std::shared_ptr< CWallet > wallet
RPCErrorCode
Bitcoin RPC error codes.
RPCHelpMan backupwallet()
CKey DecodeSecret(const std::string &str)
static RPCHelpMan migratewallet()
std::shared_ptr< CWallet > CreateWallet(WalletContext &context, const std::string &name, std::optional< bool > load_on_start, DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
static RPCHelpMan listwallets()
CKeyID seed_id
seed hash160
bool error(const char *fmt, const Args &... args)
RPCHelpMan getrawchangeaddress()
static RPCHelpMan upgradewallet()
Wrapper for UniValue::VType, which includes typeAny: Used to denote don't care type.
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest &request, std::string &wallet_name)
Error parsing or validating structure in raw format.
const std::string UNIX_EPOCH_TIME
String used to describe UNIX epoch time in documentation, factored out to a constant for consistency...
RPCHelpMan addmultisigaddress()
bool IsValid() const
Check whether this private key is valid.
void RPCTypeCheck(const UniValue ¶ms, const std::list< UniValueType > &typesExpected, bool fAllowNull)
Type-check arguments; throws JSONRPCError if wrong type given.