27 "You need to rescan the blockchain in order to correctly mark used "
28 "destinations in the past. Until this is done, some destinations may "
29 "be considered unused, even if the opposite is the case."},
43 "Returns an object containing various wallet state info.\n",
57 {
RPCResult::Type::NUM,
"keypoolsize",
"how many new keys are pre-generated (only counts external keys)"},
58 {
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)"},
59 {
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)"},
62 {
RPCResult::Type::BOOL,
"private_keys_enabled",
"false if privatekeys are disabled for this wallet (enforced watch-only wallet)"},
63 {
RPCResult::Type::BOOL,
"avoid_reuse",
"whether this wallet tracks clean/dirty coins in terms of reuse"},
64 {
RPCResult::Type::OBJ,
"scanning",
"current scanning details, or false if no scan is in progress",
69 {
RPCResult::Type::BOOL,
"descriptors",
"whether this wallet uses descriptors for scriptPubKey management"},
70 {
RPCResult::Type::BOOL,
"external_signer",
"whether this wallet is configured to use an external signer such as a hardware wallet"},
85 pwallet->BlockUntilSyncedToCurrentChain();
87 LOCK(pwallet->cs_wallet);
91 size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
93 obj.
pushKV(
"walletname", pwallet->GetName());
94 obj.
pushKV(
"walletversion", pwallet->GetVersion());
95 obj.
pushKV(
"format", pwallet->GetDatabase().Format());
99 obj.
pushKV(
"txcount", (
int)pwallet->mapWallet.size());
100 const auto kp_oldest = pwallet->GetOldestKeyPoolTime();
101 if (kp_oldest.has_value()) {
102 obj.
pushKV(
"keypoololdest", kp_oldest.value());
104 obj.
pushKV(
"keypoolsize", (int64_t)kpExternalSize);
115 obj.
pushKV(
"keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize));
117 if (pwallet->IsCrypted()) {
118 obj.
pushKV(
"unlocked_until", pwallet->nRelockTime);
123 if (pwallet->IsScanning()) {
125 scanning.
pushKV(
"duration", Ticks<std::chrono::seconds>(pwallet->ScanningDuration()));
126 scanning.
pushKV(
"progress", pwallet->ScanningProgress());
127 obj.
pushKV(
"scanning", scanning);
129 obj.
pushKV(
"scanning",
false);
143 "Returns a list of wallets in the wallet directory.\n",
166 wallet.pushKV(
"name", path.u8string());
171 result.
pushKV(
"wallets", wallets);
180 "Returns a list of currently loaded wallets.\n"
181 "For full information on the wallet, use \"getwalletinfo\"\n",
211 "\nLoads a wallet from a wallet file or directory."
212 "\nNote that all wallet command-line options used when starting bitcoind will be"
213 "\napplied to the new wallet.\n",
222 {
RPCResult::Type::STR,
"warning",
true,
"Warning messages, if any, related to loading the wallet. Multiple messages will be delimited by newlines. (DEPRECATED, returned only if config option -deprecatedrpc=walletwarningfield is passed.)"},
223 {
RPCResult::Type::ARR,
"warnings",
true,
"Warning messages, if any, related to loading the wallet.",
236 const std::string
name(request.params[0].get_str());
243 std::vector<bilingual_str> warnings;
244 std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
248 if (std::any_of(
context.wallets.begin(),
context.wallets.end(), [&
name](
const auto&
wallet) { return wallet->GetName() == name; })) {
259 if (
wallet->chain().rpcEnableDeprecated(
"walletwarningfield")) {
274 flags += (
flags ==
"" ?
"" :
", ") + it.first;
277 "\nChange the state of the given wallet flag for a wallet.\n",
299 std::string flag_str = request.params[0].get_str();
300 bool value = request.params[1].isNull() || request.params[1].get_bool();
314 if (pwallet->IsWalletFlagSet(flag) == value) {
318 res.pushKV(
"flag_name", flag_str);
319 res.pushKV(
"flag_state", value);
322 pwallet->SetWalletFlag(flag);
324 pwallet->UnsetWalletFlag(flag);
340 "\nCreates and loads a new wallet.\n",
346 {
"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."},
347 {
"descriptors",
RPCArg::Type::BOOL,
RPCArg::Default{
true},
"Create a native descriptor wallet. The wallet will use descriptors internally to handle address creation."
348 " Setting to \"false\" will create a legacy wallet; however, the legacy wallet type is being deprecated and"
349 " support for creating and opening legacy wallets will be removed in the future."},
351 {
"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."},
356 {
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."},
357 {
RPCResult::Type::STR,
"warning",
true,
"Warning messages, if any, related to creating the wallet. Multiple messages will be delimited by newlines. (DEPRECATED, returned only if config option -deprecatedrpc=walletwarningfield is passed.)"},
358 {
RPCResult::Type::ARR,
"warnings",
true,
"Warning messages, if any, related to creating the wallet.",
367 +
HelpExampleCliNamed(
"createwallet", {{
"wallet_name",
"descriptors"}, {
"avoid_reuse",
true}, {
"descriptors",
true}, {
"load_on_startup",
true}})
368 +
HelpExampleRpcNamed(
"createwallet", {{
"wallet_name",
"descriptors"}, {
"avoid_reuse",
true}, {
"descriptors",
true}, {
"load_on_startup",
true}})
374 if (!request.params[1].isNull() && request.params[1].get_bool()) {
378 if (!request.params[2].isNull() && request.params[2].get_bool()) {
382 passphrase.reserve(100);
383 std::vector<bilingual_str> warnings;
384 if (!request.params[3].isNull()) {
385 passphrase = std::string_view{request.params[3].get_str()};
386 if (passphrase.empty()) {
388 warnings.emplace_back(
Untranslated(
"Empty string given as passphrase, wallet will not be encrypted."));
392 if (!request.params[4].isNull() && request.params[4].get_bool()) {
395 if (request.params[5].isNull() || request.params[5].get_bool()) {
401 if (!request.params[7].isNull() && request.params[7].get_bool()) {
402 #ifdef ENABLE_EXTERNAL_SIGNER
422 std::optional<bool> load_on_start = request.params[6].isNull() ? std::nullopt : std::optional<bool>(request.params[6].get_bool());
431 if (
wallet->chain().rpcEnableDeprecated(
"walletwarningfield")) {
444 "Unloads the wallet referenced by the request endpoint otherwise unloads the wallet specified in the argument.\n"
445 "Specifying the wallet name on a wallet endpoint is invalid.",
447 {
"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."},
451 {
RPCResult::Type::STR,
"warning",
true,
"Warning messages, if any, related to unloading the wallet. Multiple messages will be delimited by newlines. (DEPRECATED, returned only if config option -deprecatedrpc=walletwarningfield is passed.)"},
452 {
RPCResult::Type::ARR,
"warnings",
true,
"Warning messages, if any, related to unloading the wallet.",
463 std::string wallet_name;
465 if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
469 wallet_name = request.params[0].get_str();
478 std::vector<bilingual_str> warnings;
488 std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
494 if (
wallet->chain().rpcEnableDeprecated(
"walletwarningfield")) {
508 "\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"
509 "HD will have a new HD seed set so that new keys added to the keypool will be derived from this new seed.\n"
510 "\nNote that you will need to MAKE A NEW BACKUP of your wallet after setting the HD wallet seed." +
HELP_REQUIRING_PASSPHRASE +
511 "Note: This command is only compatible with legacy wallets.\n",
513 {
"newkeypool",
RPCArg::Type::BOOL,
RPCArg::Default{
true},
"Whether to flush old unused addresses, including change addresses, from the keypool and regenerate it.\n"
514 "If true, the next address from getnewaddress and change address from getrawchangeaddress will be from this new seed.\n"
515 "If false, addresses (including change addresses if the wallet already had HD Chain Split enabled) from the existing\n"
516 "keypool will be used until it has been depleted."},
518 "The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1"},
541 if (!pwallet->CanSupportFeature(
FEATURE_HD)) {
542 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");
547 bool flush_key_pool =
true;
548 if (!request.params[0].isNull()) {
549 flush_key_pool = request.params[0].get_bool();
553 if (request.params[1].isNull()) {
579 "\nUpgrade the wallet. Upgrades to the latest version if no version number is specified.\n"
580 "New keys may be generated and a new wallet backup will need to be made.",
606 if (!request.params[0].isNull()) {
607 version = request.params[0].getInt<
int>();
610 const int previous_version{pwallet->GetVersion()};
611 const bool wallet_upgraded{pwallet->UpgradeWallet(version,
error)};
612 const int current_version{pwallet->GetVersion()};
615 if (wallet_upgraded) {
616 if (previous_version == current_version) {
617 result =
"Already at latest version. Wallet version unchanged.";
619 result =
strprintf(
"Wallet upgraded successfully from version %i to version %i.", previous_version, current_version);
624 obj.
pushKV(
"wallet_name", pwallet->GetName());
625 obj.
pushKV(
"previous_version", previous_version);
626 obj.
pushKV(
"current_version", current_version);
627 if (!result.empty()) {
628 obj.
pushKV(
"result", result);
641 "\nCalculate the balance change resulting in the signing and broadcasting of the given transaction(s).\n",
673 if (request.params[1].isObject()) {
674 UniValue options = request.params[1];
681 include_watchonly = options[
"include_watchonly"];
689 const auto& txs = request.params[0].get_array();
691 std::map<COutPoint, CAmount> new_utxos;
692 std::set<COutPoint> spent;
694 for (
size_t i = 0; i < txs.size(); ++i) {
696 if (!
DecodeHexTx(mtx, txs[i].get_str(),
true,
true)) {
701 std::map<COutPoint, Coin> coins;
705 wallet.chain().findCoins(coins);
709 for (
const auto& txin : mtx.
vin) {
710 const auto& outpoint = txin.
prevout;
711 if (spent.count(outpoint)) {
714 if (new_utxos.count(outpoint)) {
715 changes -= new_utxos.at(outpoint);
716 new_utxos.erase(outpoint);
718 if (coins.at(outpoint).IsSpent()) {
721 changes -=
wallet.GetDebit(txin, filter);
723 spent.insert(outpoint);
731 const auto& hash = mtx.
GetHash();
732 for (
size_t i = 0; i < mtx.
vout.size(); ++i) {
733 const auto& txout = mtx.
vout[i];
734 bool is_mine = 0 < (
wallet.IsMine(txout) & filter);
735 changes += new_utxos[
COutPoint(hash, i)] = is_mine ? txout.nValue : 0;
750 "EXPERIMENTAL warning: This call may not work as expected and may be changed in future releases\n"
751 "\nMigrate the wallet to a descriptor wallet.\n"
752 "A new wallet backup will need to be made.\n"
753 "\nThe migration process will create a backup of the wallet before migrating. This backup\n"
754 "file will be named <wallet name>-<timestamp>.legacy.bak and can be found in the directory\n"
755 "for this wallet. In the event of an incorrect migration, the backup can be restored using restorewallet."
756 "\nEncrypted wallets must have the passphrase provided as an argument to this call.",
758 {
"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."},
765 {
RPCResult::Type::STR,
"watchonly_name",
true,
"The name of the migrated wallet containing the watchonly scripts"},
766 {
RPCResult::Type::STR,
"solvables_name",
true,
"The name of the migrated wallet containing solvable but not watched scripts"},
776 std::string wallet_name;
778 if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
782 if (request.params[0].isNull()) {
785 wallet_name = request.params[0].get_str();
789 wallet_pass.reserve(100);
790 if (!request.params[1].isNull()) {
791 wallet_pass = std::string_view{request.params[1].get_str()};
801 r.pushKV(
"wallet_name", res->wallet_name);
802 if (res->watchonly_wallet) {
803 r.pushKV(
"watchonly_name", res->watchonly_wallet->GetName());
805 if (res->solvables_wallet) {
806 r.pushKV(
"solvables_name", res->solvables_wallet->GetName());
808 r.pushKV(
"backup_path", res->backup_path.u8string());
826 #ifdef ENABLE_EXTERNAL_SIGNER
952 #ifdef ENABLE_EXTERNAL_SIGNER
int64_t CAmount
Amount in satoshis (Can be negative)
#define CHECK_NONFATAL(condition)
Identity function.
An encapsulated private key.
const unsigned char * end() const
bool IsValid() const
Check whether this private key is valid.
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
CPubKey GetPubKey() const
Compute the public key from a private key.
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
const unsigned char * begin() const
A reference to a CKey: the Hash160 of its serialized public key.
An outpoint - a combination of a transaction hash and an index n into its vout.
An encapsulated public key.
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
An input of a transaction.
RecursiveMutex cs_KeyStore
An interface to be implemented by keystores that support signing.
A Span is an object that can refer to a contiguous sequence of objects.
void push_back(UniValue val)
void pushKV(std::string key, UniValue val)
constexpr bool IsNull() const
std::string GetHex() const
CKeyID seed_id
seed hash160
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
const CHDChain & GetHDChain() const
bool NewKeyPool()
Mark old keypool keys as used, and generate all new keys.
CPubKey GenerateNewSeed()
CPubKey DeriveNewSeed(const CKey &key)
void SetHDSeed(const CPubKey &key)
RAII object to check and reserve a wallet rescan.
bool reserve(bool with_passphrase=false)
UniValue ValueFromAmount(const CAmount amount)
bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness=false, bool try_witness=true)
const std::string CURRENCY_UNIT
CKey DecodeSecret(const std::string &str)
bool error(const char *fmt, const Args &... args)
void ReadDatabaseArgs(const ArgsManager &args, DBOptions &options)
bilingual_str ErrorString(const Result< T > &result)
static RPCHelpMan sethdseed()
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
void AppendLastProcessedBlock(UniValue &entry, const CWallet &wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
void ReadDatabaseArgs(const ArgsManager &args, DatabaseOptions &options)
Balance GetBalance(const CWallet &wallet, const int min_depth, bool avoid_reuse)
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)
static RPCHelpMan loadwallet()
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
RPCHelpMan listreceivedbyaddress()
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
RPCHelpMan keypoolrefill()
RPCHelpMan removeprunedfunds()
RPCHelpMan listlockunspent()
static const RPCResult RESULT_LAST_PROCESSED_BLOCK
RPCHelpMan importwallet()
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest &request, std::string &wallet_name)
RPCHelpMan walletprocesspsbt()
void HandleWalletError(const std::shared_ptr< CWallet > wallet, DatabaseStatus &status, bilingual_str &error)
void EnsureWalletIsUnlocked(const CWallet &wallet)
static RPCHelpMan getwalletinfo()
RPCHelpMan backupwallet()
static RPCHelpMan listwalletdir()
RPCHelpMan walletpassphrase()
const std::string HELP_REQUIRING_PASSPHRASE
std::vector< fs::path > ListDatabases(const fs::path &wallet_dir)
Recursively list database paths in directory.
RPCHelpMan getreceivedbyaddress()
RPCHelpMan walletdisplayaddress()
RPCHelpMan importaddress()
RPCHelpMan importprunedfunds()
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
RPCHelpMan simulaterawtransaction()
static RPCHelpMan setwalletflag()
RPCHelpMan importprivkey()
RPCHelpMan walletcreatefundedpsbt()
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start)
RPCHelpMan addmultisigaddress()
WalletContext & EnsureWalletContext(const std::any &context)
RPCHelpMan listaddressgroupings()
RPCHelpMan walletpassphrasechange()
std::underlying_type< isminetype >::type isminefilter
used for bitflags of isminetype
fs::path GetWalletDir()
Get the path of the wallet directory.
RPCHelpMan abandontransaction()
bool HaveKey(const SigningProvider &wallet, const CKey &key)
Checks if a CKey is in the given CWallet compressed or otherwise.
RPCHelpMan listdescriptors()
RPCHelpMan listtransactions()
RPCHelpMan signrawtransactionwithwallet()
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.
RPCHelpMan importpubkey()
static RPCHelpMan listwallets()
static RPCHelpMan upgradewallet()
static const std::map< std::string, WalletFlags > WALLET_FLAG_MAP
static RPCHelpMan unloadwallet()
RPCHelpMan listsinceblock()
RPCHelpMan restorewallet()
bool ParseIncludeWatchonly(const UniValue &include_watchonly, const CWallet &wallet)
Used by RPC commands that have an include_watchonly parameter.
RPCHelpMan getreceivedbylabel()
RPCHelpMan importdescriptors()
RPCHelpMan getrawchangeaddress()
static RPCHelpMan createwallet()
RPCHelpMan getaddressinfo()
RPCHelpMan encryptwallet()
RPCHelpMan gettransaction()
RPCHelpMan getaddressesbylabel()
RPCHelpMan fundrawtransaction()
static const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
Span< const CRPCCommand > GetWalletRPCCommands()
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 migratewallet()
RPCHelpMan rescanblockchain()
@ WALLET_FLAG_EXTERNAL_SIGNER
Indicates that the wallet needs an external signer.
@ WALLET_FLAG_AVOID_REUSE
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
@ WALLET_FLAG_BLANK_WALLET
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses,...
static constexpr uint64_t MUTABLE_WALLET_FLAGS
RPCHelpMan getnewaddress()
RPCHelpMan listreceivedbylabel()
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
RPCHelpMan getunconfirmedbalance()
RPCHelpMan sendtoaddress()
std::shared_ptr< CWallet > wallet
UniValue JSONRPCError(int code, const std::string &message)
RPCErrorCode
Bitcoin RPC error codes.
@ RPC_MISC_ERROR
General application defined errors.
@ RPC_WALLET_ENCRYPTION_FAILED
Failed to encrypt the wallet.
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
@ RPC_WALLET_ERROR
Wallet errors.
@ RPC_WALLET_ALREADY_LOADED
This same wallet is already loaded.
@ RPC_WALLET_NOT_FOUND
Invalid wallet specified.
@ RPC_DESERIALIZATION_ERROR
Error parsing or validating structure in raw format.
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
std::string HelpExampleRpcNamed(const std::string &methodname, const RPCArgList &args)
void PushWarnings(const UniValue &warnings, UniValue &obj)
Push warning messages to an RPC "warnings" field as a JSON array of strings.
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
const std::string UNIX_EPOCH_TIME
String used to describe UNIX epoch time in documentation, factored out to a constant for consistency.
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
std::string HelpExampleCliNamed(const std::string &methodname, const RPCArgList &args)
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
auto Join(const C &container, const S &separator, UnaryOp unary_op)
Join all container items.
A mutable version of CTransaction.
uint256 GetHash() const
Compute the hash of this CMutableTransaction.
std::vector< CTxOut > vout
@ STR_HEX
Special type that is a STR with only hex chars.
@ OBJ_NAMED_PARAMS
Special type that behaves almost exactly like OBJ, defining an options object with a list of pre-defi...
std::string DefaultHint
Hint for default value.
@ OMITTED
Optional argument for which the default value is omitted from help text for one of two reasons:
@ NUM_TIME
Special numeric to denote unix epoch time.
@ STR_HEX
Special string with only hex chars.
@ STR_AMOUNT
Special string to represent a floating point amount.
Wrapper for UniValue::VType, which includes typeAny: Used to denote don't care type.
SecureString create_passphrase
WalletContext struct containing references to state shared between CWallet instances,...
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.