rpcclient: implement getwalletinfo command

This commit is contained in:
Anirudha Bose 2020-09-20 15:46:32 +02:00 committed by Jake Sylvestre
parent 1340513786
commit e9a51e8dcd
4 changed files with 154 additions and 9 deletions

View file

@ -6,6 +6,8 @@ package btcjson
import (
"encoding/json"
"fmt"
"github.com/btcsuite/btcd/txscript"
)
@ -150,6 +152,58 @@ type GetTransactionResult struct {
Hex string `json:"hex"`
}
type ScanningOrFalse struct {
Value interface{}
}
type ScanProgress struct {
Duration int `json:"duration"`
Progress float64 `json:"progress"`
}
// MarshalJSON implements the json.Marshaler interface
func (h ScanningOrFalse) MarshalJSON() ([]byte, error) {
return json.Marshal(h.Value)
}
// UnmarshalJSON implements the json.Unmarshaler interface
func (h *ScanningOrFalse) UnmarshalJSON(data []byte) error {
var unmarshalled interface{}
if err := json.Unmarshal(data, &unmarshalled); err != nil {
return err
}
switch v := unmarshalled.(type) {
case bool:
h.Value = v
case map[string]interface{}:
h.Value = ScanProgress{
Duration: int(v["duration"].(float64)),
Progress: v["progress"].(float64),
}
default:
return fmt.Errorf("invalid scanning value: %v", unmarshalled)
}
return nil
}
// GetWalletInfoResult models the result of the getwalletinfo command.
type GetWalletInfoResult struct {
WalletName string `json:"walletname"`
WalletVersion int `json:"walletversion"`
TransactionCount int `json:"txcount"`
KeyPoolOldest int `json:"keypoololdest"`
KeyPoolSize int `json:"keypoolsize"`
KeyPoolSizeHDInternal *int `json:"keypoolsize_hd_internal,omitempty"`
UnlockedUntil *int `json:"unlocked_until,omitempty"`
PayTransactionFee float64 `json:"paytxfee"`
HDSeedID *string `json:"hdseedid,omitempty"`
PrivateKeysEnabled bool `json:"private_keys_enabled"`
AvoidReuse bool `json:"avoid_reuse"`
Scanning ScanningOrFalse `json:"scanning"`
}
// InfoWalletResult models the data returned by the wallet server getinfo
// command.
type InfoWalletResult struct {

View file

@ -78,3 +78,50 @@ func TestGetAddressInfoResult(t *testing.T) {
}
}
}
// TestGetWalletInfoResult ensures that custom unmarshalling of
// GetWalletInfoResult works as intended.
func TestGetWalletInfoResult(t *testing.T) {
t.Parallel()
tests := []struct {
name string
result string
want GetWalletInfoResult
}{
{
name: "GetWalletInfoResult - not scanning",
result: `{"scanning":false}`,
want: GetWalletInfoResult{
Scanning: ScanningOrFalse{Value: false},
},
},
{
name: "GetWalletInfoResult - scanning",
result: `{"scanning":{"duration":10,"progress":1.0}}`,
want: GetWalletInfoResult{
Scanning: ScanningOrFalse{
Value: ScanProgress{Duration: 10, Progress: 1.0},
},
},
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
var out GetWalletInfoResult
err := json.Unmarshal([]byte(test.result), &out)
if err != nil {
t.Errorf("Test #%d (%s) unexpected error: %v", i,
test.name, err)
continue
}
if !reflect.DeepEqual(out, test.want) {
t.Errorf("Test #%d (%s) unexpected unmarshalled data - "+
"got %v, want %v", i, test.name, spew.Sdump(out),
spew.Sdump(test.want))
continue
}
}
}

View file

@ -82,14 +82,6 @@ func ExampleClient_DeriveAddresses() {
}
func ExampleClient_GetAddressInfo() {
connCfg = &ConnConfig{
Host: "localhost:18332",
User: "user",
Pass: "pass",
HTTPPostMode: true,
DisableTLS: true,
}
client, err := New(connCfg, nil)
if err != nil {
panic(err)
@ -106,3 +98,21 @@ func ExampleClient_GetAddressInfo() {
fmt.Println(*info.HDKeyPath) // m/49'/1'/0'/0/4
fmt.Println(info.Embedded.Address) // tb1q3x2h2kh57wzg7jz00jhwn0ycvqtdk2ane37j27
}
func ExampleClient_GetWalletInfo() {
client, err := New(connCfg, nil)
if err != nil {
panic(err)
}
defer client.Shutdown()
info, err := client.GetWalletInfo()
if err != nil {
panic(err)
}
fmt.Println(info.WalletVersion) // 169900
fmt.Println(info.TransactionCount) // 22
fmt.Println(*info.HDSeedID) // eb44e4e9b864ef17e7ba947da746375b000f5d94
fmt.Println(info.Scanning.Value) // false
}

View file

@ -2573,10 +2573,44 @@ func (c *Client) WalletProcessPsbt(
return c.WalletProcessPsbtAsync(psbt, sign, sighashType, bip32Derivs).Receive()
}
// FutureGetWalletInfoResult is a future promise to deliver the result of an
// GetWalletInfoAsync RPC invocation (or an applicable error).
type FutureGetWalletInfoResult chan *response
// Receive waits for the response promised by the future and returns the result
// of wallet state info.
func (r FutureGetWalletInfoResult) Receive() (*btcjson.GetWalletInfoResult, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
var getWalletInfoResult btcjson.GetWalletInfoResult
err = json.Unmarshal(res, &getWalletInfoResult)
if err != nil {
return nil, err
}
return &getWalletInfoResult, nil
}
// GetWalletInfoAsync 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 GetWalletInfo for the blocking version and more details.
func (c *Client) GetWalletInfoAsync() FutureGetWalletInfoResult {
cmd := btcjson.NewGetWalletInfoCmd()
return c.sendCmd(cmd)
}
// GetWalletInfo returns various wallet state info.
func (c *Client) GetWalletInfo() (*btcjson.GetWalletInfoResult, error) {
return c.GetWalletInfoAsync().Receive()
}
// TODO(davec): Implement
// backupwallet (NYI in btcwallet)
// encryptwallet (Won't be supported by btcwallet since it's always encrypted)
// getwalletinfo (NYI in btcwallet or btcjson)
// listaddressgroupings (NYI in btcwallet)
// listreceivedbyaccount (NYI in btcwallet)