Skip to content

Commit

Permalink
rpcclient: add more wallet commands
Browse files Browse the repository at this point in the history
Implement backupwallet, dumpwallet, loadwallet and unloadwallet.
  • Loading branch information
torkelrogstad authored and jcvernaleo committed Oct 26, 2020
1 parent 6adfc07 commit 1d75e0a
Show file tree
Hide file tree
Showing 4 changed files with 224 additions and 5 deletions.
11 changes: 11 additions & 0 deletions btcjson/chainsvrresults.go
Original file line number Diff line number Diff line change
Expand Up @@ -828,3 +828,14 @@ type GetDescriptorInfoResult struct {

// DeriveAddressesResult models the data from the deriveaddresses command.
type DeriveAddressesResult []string

// LoadWalletResult models the data from the loadwallet command
type LoadWalletResult struct {
Name string `json:"name"`
Warning string `json:"warning"`
}

// DumpWalletResult models the data from the dumpwallet command
type DumpWalletResult struct {
Filename string `json:"filename"`
}
36 changes: 36 additions & 0 deletions btcjson/walletsvrcmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,39 @@ func NewGetWalletInfoCmd() *GetWalletInfoCmd {
return &GetWalletInfoCmd{}
}

// BackupWalletCmd defines the backupwallet JSON-RPC command
type BackupWalletCmd struct {
Destination string
}

// NewBackupWalletCmd returns a new instance which can be used to issue a
// backupwallet JSON-RPC command
func NewBackupWalletCmd(destination string) *BackupWalletCmd {
return &BackupWalletCmd{Destination: destination}
}

// UnloadWalletCmd defines the unloadwallet JSON-RPC command
type UnloadWalletCmd struct {
WalletName *string
}

// NewUnloadWalletCmd returns a new instance which can be used to issue a
// unloadwallet JSON-RPC command.
func NewUnloadWalletCmd(walletName *string) *UnloadWalletCmd {
return &UnloadWalletCmd{WalletName: walletName}
}

// LoadWalletCmd defines the loadwallet JSON-RPC command
type LoadWalletCmd struct {
WalletName string
}

// NewLoadWalletCmd returns a new instance which can be used to issue a
// loadwallet JSON-RPC command
func NewLoadWalletCmd(walletName string) *LoadWalletCmd {
return &LoadWalletCmd{WalletName: walletName}
}

// ImportPrivKeyCmd defines the importprivkey JSON-RPC command.
type ImportPrivKeyCmd struct {
PrivKey string
Expand Down Expand Up @@ -1030,6 +1063,7 @@ func init() {

MustRegisterCmd("addmultisigaddress", (*AddMultisigAddressCmd)(nil), flags)
MustRegisterCmd("addwitnessaddress", (*AddWitnessAddressCmd)(nil), flags)
MustRegisterCmd("backupwallet", (*BackupWalletCmd)(nil), flags)
MustRegisterCmd("createmultisig", (*CreateMultisigCmd)(nil), flags)
MustRegisterCmd("dumpprivkey", (*DumpPrivKeyCmd)(nil), flags)
MustRegisterCmd("encryptwallet", (*EncryptWalletCmd)(nil), flags)
Expand Down Expand Up @@ -1059,6 +1093,7 @@ func init() {
MustRegisterCmd("listsinceblock", (*ListSinceBlockCmd)(nil), flags)
MustRegisterCmd("listtransactions", (*ListTransactionsCmd)(nil), flags)
MustRegisterCmd("listunspent", (*ListUnspentCmd)(nil), flags)
MustRegisterCmd("loadwallet", (*LoadWalletCmd)(nil), flags)
MustRegisterCmd("lockunspent", (*LockUnspentCmd)(nil), flags)
MustRegisterCmd("move", (*MoveCmd)(nil), flags)
MustRegisterCmd("sendfrom", (*SendFromCmd)(nil), flags)
Expand All @@ -1069,6 +1104,7 @@ func init() {
MustRegisterCmd("signmessage", (*SignMessageCmd)(nil), flags)
MustRegisterCmd("signrawtransaction", (*SignRawTransactionCmd)(nil), flags)
MustRegisterCmd("signrawtransactionwithwallet", (*SignRawTransactionWithWalletCmd)(nil), flags)
MustRegisterCmd("unloadwallet", (*UnloadWalletCmd)(nil), flags)
MustRegisterCmd("walletlock", (*WalletLockCmd)(nil), flags)
MustRegisterCmd("walletpassphrase", (*WalletPassphraseCmd)(nil), flags)
MustRegisterCmd("walletpassphrasechange", (*WalletPassphraseChangeCmd)(nil), flags)
Expand Down
43 changes: 43 additions & 0 deletions btcjson/walletsvrcmds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,49 @@ func TestWalletSvrCmds(t *testing.T) {
Address: "1address",
},
},
{
name: "backupwallet",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("backupwallet", "backup.dat")
},
staticCmd: func() interface{} {
return btcjson.NewBackupWalletCmd("backup.dat")
},
marshalled: `{"jsonrpc":"1.0","method":"backupwallet","params":["backup.dat"],"id":1}`,
unmarshalled: &btcjson.BackupWalletCmd{Destination: "backup.dat"},
},
{
name: "loadwallet",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("loadwallet", "wallet.dat")
},
staticCmd: func() interface{} {
return btcjson.NewLoadWalletCmd("wallet.dat")
},
marshalled: `{"jsonrpc":"1.0","method":"loadwallet","params":["wallet.dat"],"id":1}`,
unmarshalled: &btcjson.LoadWalletCmd{WalletName: "wallet.dat"},
},
{
name: "unloadwallet",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("unloadwallet", "default")
},
staticCmd: func() interface{} {
return btcjson.NewUnloadWalletCmd(btcjson.String("default"))
},
marshalled: `{"jsonrpc":"1.0","method":"unloadwallet","params":["default"],"id":1}`,
unmarshalled: &btcjson.UnloadWalletCmd{WalletName: btcjson.String("default")},
},
{name: "unloadwallet - nil arg",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("unloadwallet")
},
staticCmd: func() interface{} {
return btcjson.NewUnloadWalletCmd(nil)
},
marshalled: `{"jsonrpc":"1.0","method":"unloadwallet","params":[],"id":1}`,
unmarshalled: &btcjson.UnloadWalletCmd{WalletName: nil},
},
{
name: "createmultisig",
newCmd: func() (interface{}, error) {
Expand Down
139 changes: 134 additions & 5 deletions rpcclient/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -2608,12 +2608,141 @@ func (c *Client) GetWalletInfo() (*btcjson.GetWalletInfoResult, error) {
return c.GetWalletInfoAsync().Receive()
}

// FutureBackupWalletResult is a future promise to deliver the result of an
// BackupWalletAsync RPC invocation (or an applicable error)
type FutureBackupWalletResult chan *response

// Receive waits for the response promised by the future
func (r FutureBackupWalletResult) Receive() error {
_, err := receiveFuture(r)
return err
}

// BackupWalletAsync returns an instance of a type that can be used to get the result
// of the RPC at some future time by invoking the Receive function on the
// returned instance.
//
// See BackupWallet for the blocking version and more details.
func (c *Client) BackupWalletAsync(destination string) FutureBackupWalletResult {
return c.sendCmd(btcjson.NewBackupWalletCmd(destination))
}

// BackupWallet safely copies current wallet file to destination, which can
// be a directory or a path with filename
func (c *Client) BackupWallet(destination string) error {
return c.BackupWalletAsync(destination).Receive()
}

// FutureDumpWalletResult is a future promise to deliver the result of an
// DumpWallet RPC invocation (or an applicable error)
type FutureDumpWalletResult chan *response

// Receive waits for the response promised by the future
func (r FutureDumpWalletResult) Receive() (*btcjson.DumpWalletResult, error) {
bytes, err := receiveFuture(r)
if err != nil {
return nil, err
}

var res btcjson.DumpWalletResult
err = json.Unmarshal(bytes, &res)
return &res, err
}

// DumpWalletAsync returns an instance of a type that can be used to get the result
// of the RPC at some future time by invoking the Receive function on the
// returned instance.
//
// See DumpWalletAsync for the blocking version and more details.
func (c *Client) DumpWalletAsync(destination string) FutureDumpWalletResult {
return c.sendCmd(btcjson.NewDumpWalletCmd(destination))
}

// DumpWallet dumps all wallet keys in a human-readable format to a server-side file.
func (c *Client) DumpWallet(destination string) (*btcjson.DumpWalletResult, error) {
return c.DumpWalletAsync(destination).Receive()
}

// FutureImportWalletResult is a future promise to deliver the result of an
// ImportWalletAsync RPC invocation (or an applicable error)
type FutureImportWalletResult chan *response

// Receive waits for the response promised by the future
func (r FutureImportWalletResult) Receive() error {
_, err := receiveFuture(r)
return err
}

// ImportWalletAsync returns an instance of a type that can be used to get the result
// of the RPC at some future time by invoking the Receive function on the
// returned instance.
//
// See ImportWallet for the blocking version and more details.
func (c *Client) ImportWalletAsync(filename string) FutureImportWalletResult {
return c.sendCmd(btcjson.NewImportWalletCmd(filename))
}

// ImportWallet imports keys from a wallet dump file (see DumpWallet).
func (c *Client) ImportWallet(filename string) error {
return c.ImportWalletAsync(filename).Receive()
}

// FutureUnloadWalletResult is a future promise to deliver the result of an
// UnloadWalletAsync RPC invocation (or an applicable error)
type FutureUnloadWalletResult chan *response

// Receive waits for the response promised by the future
func (r FutureUnloadWalletResult) Receive() error {
_, err := receiveFuture(r)
return err
}

// UnloadWalletAsync returns an instance of a type that can be used to get the result
// of the RPC at some future time by invoking the Receive function on the
// returned instance.
//
// See UnloadWallet for the blocking version and more details.
func (c *Client) UnloadWalletAsync(walletName *string) FutureUnloadWalletResult {
return c.sendCmd(btcjson.NewUnloadWalletCmd(walletName))
}

// UnloadWallet unloads the referenced wallet. If the RPC server URL already
// contains the name of the wallet, like http://127.0.0.1:8332/wallet/<walletname>,
// the parameter must be nil, or it'll return an error.
func (c *Client) UnloadWallet(walletName *string) error {
return c.UnloadWalletAsync(walletName).Receive()
}

// FutureLoadWalletResult is a future promise to deliver the result of an
// LoadWalletAsync RPC invocation (or an applicable error)
type FutureLoadWalletResult chan *response

// Receive waits for the response promised by the future
func (r FutureLoadWalletResult) Receive() (*btcjson.LoadWalletResult, error) {
bytes, err := receiveFuture(r)
if err != nil {
return nil, err
}
var result btcjson.LoadWalletResult
err = json.Unmarshal(bytes, &result)
return &result, err
}

// LoadWalletAsync returns an instance of a type that can be used to get the result
// of the RPC at some future time by invoking the Receive function on the
// returned instance.
//
// See LoadWallet for the blocking version and more details.
func (c *Client) LoadWalletAsync(walletName string) FutureLoadWalletResult {
return c.sendCmd(btcjson.NewLoadWalletCmd(walletName))
}

// LoadWallet loads a wallet from a wallet file or directory.
func (c *Client) LoadWallet(walletName string) (*btcjson.LoadWalletResult, error) {
return c.LoadWalletAsync(walletName).Receive()
}

// TODO(davec): Implement
// backupwallet (NYI in btcwallet)
// encryptwallet (Won't be supported by btcwallet since it's always encrypted)
// listaddressgroupings (NYI in btcwallet)
// listreceivedbyaccount (NYI in btcwallet)

// DUMP
// importwallet (NYI in btcwallet)
// dumpwallet (NYI in btcwallet)

0 comments on commit 1d75e0a

Please sign in to comment.