diff --git a/cmds.go b/cmds.go index 9b2d30cf..7204231d 100644 --- a/cmds.go +++ b/cmds.go @@ -84,14 +84,16 @@ func parseAuthenticateCmd(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrWrongNumberOfParams } - username, ok := r.Params[0].(string) - if !ok { - return nil, errors.New("first parameter username must be a string") + var username string + if err := json.Unmarshal(r.Params[0], &username); err != nil { + return nil, errors.New("first parameter 'username' must be " + + "a string: " + err.Error()) } - passphrase, ok := r.Params[1].(string) - if !ok { - return nil, errors.New("second parameter passphrase must be a string") + var passphrase string + if err := json.Unmarshal(r.Params[1], &passphrase); err != nil { + return nil, errors.New("second parameter 'passphrase' must " + + "be a string: " + err.Error()) } return NewAuthenticateCmd(r.Id, username, passphrase), nil @@ -114,15 +116,14 @@ func (cmd *AuthenticateCmd) Method() string { // MarshalJSON returns the JSON encoding of cmd. Part of the Cmd interface. func (cmd *AuthenticateCmd) MarshalJSON() ([]byte, error) { - // Fill a RawCmd and marshal. - raw := btcjson.RawCmd{ - Jsonrpc: "1.0", - Method: cmd.Method(), - Id: cmd.id, - Params: []interface{}{ - cmd.Username, - cmd.Passphrase, - }, + params := []interface{}{ + cmd.Username, + cmd.Passphrase, + } + + raw, err := btcjson.NewRawCmd(cmd.id, cmd.Method(), params) + if err != nil { + return nil, err } return json.Marshal(raw) } @@ -192,11 +193,9 @@ func (cmd *GetCurrentNetCmd) Method() string { // MarshalJSON returns the JSON encoding of cmd. Part of the Cmd interface. func (cmd *GetCurrentNetCmd) MarshalJSON() ([]byte, error) { - // Fill a RawCmd and marshal. - raw := btcjson.RawCmd{ - Jsonrpc: "1.0", - Method: "getcurrentnet", - Id: cmd.id, + raw, err := btcjson.NewRawCmd(cmd.id, cmd.Method(), []interface{}{}) + if err != nil { + return nil, err } return json.Marshal(raw) } @@ -272,7 +271,30 @@ func NewExportWatchingWalletCmd(id interface{}, optArgs ...interface{}) (*Export // satisifying the btcjson.Cmd interface. This is used when registering // the custom command with the btcjson parser. func parseExportWatchingWalletCmd(r *btcjson.RawCmd) (btcjson.Cmd, error) { - return NewExportWatchingWalletCmd(r.Id, r.Params...) + if len(r.Params) > 2 { + return nil, btcjson.ErrTooManyOptArgs + } + + optArgs := make([]interface{}, 0, 2) + if len(r.Params) > 0 { + var account string + if err := json.Unmarshal(r.Params[0], &account); err != nil { + return nil, errors.New("first optional parameter " + + " 'account' must be a string: " + err.Error()) + } + optArgs = append(optArgs, account) + } + + if len(r.Params) > 1 { + var download bool + if err := json.Unmarshal(r.Params[1], &download); err != nil { + return nil, errors.New("second optional parameter " + + " 'download' must be a bool: " + err.Error()) + } + optArgs = append(optArgs, download) + } + + return NewExportWatchingWalletCmd(r.Id, optArgs...) } // Id satisifies the Cmd interface by returning the ID of the command. @@ -292,20 +314,18 @@ func (cmd *ExportWatchingWalletCmd) Method() string { // MarshalJSON returns the JSON encoding of cmd. Part of the Cmd interface. func (cmd *ExportWatchingWalletCmd) MarshalJSON() ([]byte, error) { - // Fill a RawCmd and marshal. - raw := btcjson.RawCmd{ - Jsonrpc: "1.0", - Method: "exportwatchingwallet", - Id: cmd.id, - } - + params := make([]interface{}, 0, 2) if cmd.Account != "" || cmd.Download { - raw.Params = append(raw.Params, cmd.Account) + params = append(params, cmd.Account) } if cmd.Download { - raw.Params = append(raw.Params, cmd.Download) + params = append(params, cmd.Download) } + raw, err := btcjson.NewRawCmd(cmd.id, cmd.Method(), params) + if err != nil { + return nil, err + } return json.Marshal(raw) } @@ -372,17 +392,17 @@ func parseGetUnconfirmedBalanceCmd(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrWrongNumberOfParams } - if len(r.Params) == 0 { - // No optional args. - return NewGetUnconfirmedBalanceCmd(r.Id) + optArgs := make([]string, 0, 1) + if len(r.Params) > 0 { + var account string + if err := json.Unmarshal(r.Params[0], &account); err != nil { + return nil, errors.New("first optional parameter " + + " 'account' must be a string: " + err.Error()) + } + optArgs = append(optArgs, account) } - // One optional parameter for account. - account, ok := r.Params[0].(string) - if !ok { - return nil, errors.New("first parameter account must be a string") - } - return NewGetUnconfirmedBalanceCmd(r.Id, account) + return NewGetUnconfirmedBalanceCmd(r.Id, optArgs...) } // Id satisifies the Cmd interface by returning the ID of the command. @@ -402,17 +422,15 @@ func (cmd *GetUnconfirmedBalanceCmd) Method() string { // MarshalJSON returns the JSON encoding of cmd. Part of the Cmd interface. func (cmd *GetUnconfirmedBalanceCmd) MarshalJSON() ([]byte, error) { - // Fill a RawCmd and marshal. - raw := btcjson.RawCmd{ - Jsonrpc: "1.0", - Method: "getunconfirmedbalance", - Id: cmd.id, - } - + params := make([]interface{}, 0, 1) if cmd.Account != "" { - raw.Params = append(raw.Params, cmd.Account) + params = append(params, cmd.Account) } + raw, err := btcjson.NewRawCmd(cmd.id, cmd.Method(), params) + if err != nil { + return nil, err + } return json.Marshal(raw) } @@ -487,11 +505,9 @@ func (cmd *GetBestBlockCmd) Method() string { // MarshalJSON returns the JSON encoding of cmd. Part of the Cmd interface. func (cmd *GetBestBlockCmd) MarshalJSON() ([]byte, error) { - // Fill a RawCmd and marshal. - raw := btcjson.RawCmd{ - Jsonrpc: "1.0", - Method: "getbestblock", - Id: cmd.id, + raw, err := btcjson.NewRawCmd(cmd.id, cmd.Method(), []interface{}{}) + if err != nil { + return nil, err } return json.Marshal(raw) } @@ -547,15 +563,19 @@ func parseRecoverAddressesCmd(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrWrongNumberOfParams } - account, ok := r.Params[0].(string) - if !ok { - return nil, errors.New("first parameter account must be a string") + var account string + if err := json.Unmarshal(r.Params[0], &account); err != nil { + return nil, errors.New("first parameter 'account' must be a " + + "string: " + err.Error()) } - n, ok := r.Params[1].(float64) - if !ok { - return nil, errors.New("second parameter n must be a number") + + var n int + if err := json.Unmarshal(r.Params[1], &n); err != nil { + return nil, errors.New("second parameter 'n' must be an " + + "integer: " + err.Error()) } - return NewRecoverAddressesCmd(r.Id, account, int(n)), nil + + return NewRecoverAddressesCmd(r.Id, account, n), nil } // Id satisifies the Cmd interface by returning the ID of the command. @@ -575,17 +595,15 @@ func (cmd *RecoverAddressesCmd) Method() string { // MarshalJSON returns the JSON encoding of cmd. Part of the Cmd interface. func (cmd *RecoverAddressesCmd) MarshalJSON() ([]byte, error) { - // Fill a RawCmd and marshal. - raw := btcjson.RawCmd{ - Jsonrpc: "1.0", - Method: "recoveraddresses", - Id: cmd.id, - Params: []interface{}{ - cmd.Account, - cmd.N, - }, + params := []interface{}{ + cmd.Account, + cmd.N, } + raw, err := btcjson.NewRawCmd(cmd.id, cmd.Method(), params) + if err != nil { + return nil, err + } return json.Marshal(raw) } @@ -611,6 +629,22 @@ func (cmd *RecoverAddressesCmd) UnmarshalJSON(b []byte) error { return nil } +// OutPoint describes a transaction outpoint that will be marshalled to and +// from JSON. +type OutPoint struct { + Hash string `json:"hash"` + Index uint32 `json:"index"` +} + +// NewOutPointFromWire creates a new OutPoint from the OutPoint structure +// of the btcwire package. +func NewOutPointFromWire(op *btcwire.OutPoint) *OutPoint { + return &OutPoint{ + Hash: op.Hash.String(), + Index: op.Index, + } +} + // RescanCmd is a type handling custom marshaling and // unmarshaling of rescan JSON websocket extension // commands. @@ -618,7 +652,7 @@ type RescanCmd struct { id interface{} BeginBlock int32 Addresses []string - OutPoints []*btcwire.OutPoint + OutPoints []OutPoint EndBlock int64 // TODO: switch this and btcdb.AllShas to int32 } @@ -629,7 +663,7 @@ var _ btcjson.Cmd = &RescanCmd{} // arguments optArgs which may either be empty or a single upper // block height. func NewRescanCmd(id interface{}, begin int32, addresses []string, - outpoints []*btcwire.OutPoint, optArgs ...int64) (*RescanCmd, error) { + outpoints []OutPoint, optArgs ...int64) (*RescanCmd, error) { // Optional parameters set to their defaults. end := btcdb.AllShas @@ -658,60 +692,36 @@ func parseRescanCmd(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrWrongNumberOfParams } - begin, ok := r.Params[0].(float64) - if !ok { - return nil, errors.New("first parameter must be a number") + var begin int32 + if err := json.Unmarshal(r.Params[0], &begin); err != nil { + return nil, errors.New("first parameter 'begin' must be a " + + "32-bit integer: " + err.Error()) } - iaddrs, ok := r.Params[1].([]interface{}) - if !ok { - return nil, errors.New("second parameter must be a JSON array") - } - addresses := make([]string, 0, len(iaddrs)) - for _, addr := range iaddrs { - addrStr, ok := addr.(string) - if !ok { - return nil, errors.New("address is not a string") - } - addresses = append(addresses, addrStr) + var addresses []string + if err := json.Unmarshal(r.Params[1], &addresses); err != nil { + return nil, errors.New("second parameter 'addresses' must be " + + "an array of strings: " + err.Error()) } - ops, ok := r.Params[2].([]interface{}) - if !ok { - return nil, errors.New("third parameter must be a JSON array") - } - outpoints := make([]*btcwire.OutPoint, 0, len(ops)) - for i := range ops { - op, ok := ops[i].(map[string]interface{}) - if !ok { - return nil, errors.New("outpoint is not a JSON object") - } - txHashHexStr, ok := op["hash"].(string) - if !ok { - return nil, errors.New("outpoint hash is not a string") - } - txHash, err := btcwire.NewShaHashFromStr(txHashHexStr) - if err != nil { - return nil, errors.New("outpoint hash is not a valid hex string") - } - index, ok := op["index"].(float64) - if !ok { - return nil, errors.New("outpoint index is not a number") - } - outpoints = append(outpoints, btcwire.NewOutPoint(txHash, uint32(index))) + var outpoints []OutPoint + if err := json.Unmarshal(r.Params[2], &outpoints); err != nil { + return nil, errors.New("third parameter 'outpoints' must be " + + "an array of transaction outpoint JSON objects: " + + err.Error()) } - params := make([]int64, len(r.Params[3:])) - for i, val := range r.Params[3:] { - fval, ok := val.(float64) - if !ok { - return nil, errors.New("optional parameters must " + - "be be numbers") + optArgs := make([]int64, 0, 1) + if len(r.Params) > 3 { + var endblock int64 + if err := json.Unmarshal(r.Params[3], &endblock); err != nil { + return nil, errors.New("fourth optional parameter " + + " 'endblock' must be an integer: " + err.Error()) } - params[i] = int64(fval) + optArgs = append(optArgs, endblock) } - return NewRescanCmd(r.Id, int32(begin), addresses, outpoints, params...) + return NewRescanCmd(r.Id, begin, addresses, outpoints, optArgs...) } // Id satisifies the Cmd interface by returning the ID of the command. @@ -731,30 +741,18 @@ func (cmd *RescanCmd) Method() string { // MarshalJSON returns the JSON encoding of cmd. Part of the Cmd interface. func (cmd *RescanCmd) MarshalJSON() ([]byte, error) { - ops := make([]interface{}, 0, len(cmd.OutPoints)) - for _, op := range cmd.OutPoints { - ops = append(ops, map[string]interface{}{ - "hash": op.Hash.String(), - "index": float64(op.Index), - }) - } - - // Fill a RawCmd and marshal. - raw := btcjson.RawCmd{ - Jsonrpc: "1.0", - Method: "rescan", - Id: cmd.id, - Params: []interface{}{ - cmd.BeginBlock, - cmd.Addresses, - ops, - }, - } - + params := make([]interface{}, 3, 4) + params[0] = cmd.BeginBlock + params[1] = cmd.Addresses + params[2] = cmd.OutPoints if cmd.EndBlock != btcdb.AllShas { - raw.Params = append(raw.Params, cmd.EndBlock) + params = append(params, cmd.EndBlock) } + raw, err := btcjson.NewRawCmd(cmd.id, cmd.Method(), params) + if err != nil { + return nil, err + } return json.Marshal(raw) } @@ -824,13 +822,10 @@ func (cmd *NotifyBlocksCmd) Method() string { // MarshalJSON returns the JSON encoding of cmd. Part of the Cmd interface. func (cmd *NotifyBlocksCmd) MarshalJSON() ([]byte, error) { - // Fill a RawCmd and marshal. - raw := btcjson.RawCmd{ - Jsonrpc: "1.0", - Method: "notifyblocks", - Id: cmd.id, + raw, err := btcjson.NewRawCmd(cmd.id, cmd.Method(), []interface{}{}) + if err != nil { + return nil, err } - return json.Marshal(raw) } @@ -883,18 +878,10 @@ func parseNotifyNewTXsCmd(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrWrongNumberOfParams } - iaddrs, ok := r.Params[0].([]interface{}) - if !ok { - return nil, errors.New("first parameter must be a JSON array") - } - addresses := make([]string, len(iaddrs)) - for i := range iaddrs { - addr, ok := iaddrs[i].(string) - if !ok { - return nil, errors.New("first parameter must be an " + - "array of strings") - } - addresses[i] = addr + var addresses []string + if err := json.Unmarshal(r.Params[0], &addresses); err != nil { + return nil, errors.New("first parameter 'addresses' must be " + + "an array of strings: " + err.Error()) } return NewNotifyNewTXsCmd(r.Id, addresses), nil @@ -917,16 +904,14 @@ func (cmd *NotifyNewTXsCmd) Method() string { // MarshalJSON returns the JSON encoding of cmd. Part of the Cmd interface. func (cmd *NotifyNewTXsCmd) MarshalJSON() ([]byte, error) { - // Fill a RawCmd and marshal. - raw := btcjson.RawCmd{ - Jsonrpc: "1.0", - Method: "notifynewtxs", - Id: cmd.id, - Params: []interface{}{ - cmd.Addresses, - }, + params := []interface{}{ + cmd.Addresses, } + raw, err := btcjson.NewRawCmd(cmd.id, cmd.Method(), params) + if err != nil { + return nil, err + } return json.Marshal(raw) } @@ -986,17 +971,21 @@ func NewNotifyAllNewTXsCmd(id interface{}, optArgs ...bool) (*NotifyAllNewTXsCmd // satisifying the btcjson.Cmd interface. This is used when registering // the custom command with the btcjson parser. func parseNotifyAllNewTXsCmd(r *btcjson.RawCmd) (btcjson.Cmd, error) { - verbose := false - numParams := len(r.Params) - - if numParams > 0 { - if numParams > 1 { - return nil, btcjson.ErrWrongNumberOfParams - } - verbose = r.Params[0].(bool) + if len(r.Params) > 1 { + return nil, btcjson.ErrWrongNumberOfParams } - return NewNotifyAllNewTXsCmd(r.Id, verbose) + optArgs := make([]bool, 0, 1) + if len(r.Params) > 0 { + var verbose bool + if err := json.Unmarshal(r.Params[0], &verbose); err != nil { + return nil, errors.New("first optional parameter " + + "'verbose' must be a bool: " + err.Error()) + } + optArgs = append(optArgs, verbose) + } + + return NewNotifyAllNewTXsCmd(r.Id, optArgs...) } // Id satisifies the Cmd interface by returning the ID of the command. @@ -1016,16 +1005,14 @@ func (cmd *NotifyAllNewTXsCmd) Method() string { // MarshalJSON returns the JSON encoding of cmd. Part of the Cmd interface. func (cmd *NotifyAllNewTXsCmd) MarshalJSON() ([]byte, error) { - // Fill a RawCmd and marshal. - raw := btcjson.RawCmd{ - Jsonrpc: "1.0", - Method: "notifyallnewtxs", - Id: cmd.id, - Params: []interface{}{ - cmd.Verbose, - }, + params := []interface{}{ + cmd.Verbose, } + raw, err := btcjson.NewRawCmd(cmd.id, cmd.Method(), params) + if err != nil { + return nil, err + } return json.Marshal(raw) } @@ -1056,14 +1043,14 @@ func (cmd *NotifyAllNewTXsCmd) UnmarshalJSON(b []byte) error { // commands. type NotifySpentCmd struct { id interface{} - *btcwire.OutPoint + *OutPoint } // Enforce that NotifySpentCmd satisifies the btcjson.Cmd interface. var _ btcjson.Cmd = &NotifySpentCmd{} // NewNotifySpentCmd creates a new NotifySpentCmd. -func NewNotifySpentCmd(id interface{}, op *btcwire.OutPoint) *NotifySpentCmd { +func NewNotifySpentCmd(id interface{}, op *OutPoint) *NotifySpentCmd { return &NotifySpentCmd{ id: id, OutPoint: op, @@ -1074,29 +1061,17 @@ func NewNotifySpentCmd(id interface{}, op *btcwire.OutPoint) *NotifySpentCmd { // satisifying the btcjson.Cmd interface. This is used when registering // the custom command with the btcjson parser. func parseNotifySpentCmd(r *btcjson.RawCmd) (btcjson.Cmd, error) { - if len(r.Params) != 2 { + if len(r.Params) != 1 { return nil, btcjson.ErrWrongNumberOfParams } - hashStr, ok := r.Params[0].(string) - if !ok { - return nil, errors.New("first parameter must be a string") - } - hash, err := btcwire.NewShaHashFromStr(hashStr) - if err != nil { - return nil, errors.New("first parameter is not a valid " + - "hash string") - } - idx, ok := r.Params[1].(float64) - if !ok { - return nil, errors.New("second parameter is not a number") - } - if idx < 0 { - return nil, errors.New("second parameter cannot be negative") + var outpoint OutPoint + if err := json.Unmarshal(r.Params[0], &outpoint); err != nil { + return nil, errors.New("first parameter 'outpoint' must be a " + + "an outpoint JSON object: " + err.Error()) } - cmd := NewNotifySpentCmd(r.Id, btcwire.NewOutPoint(hash, uint32(idx))) - return cmd, nil + return NewNotifySpentCmd(r.Id, &outpoint), nil } // Id satisifies the Cmd interface by returning the ID of the command. @@ -1116,17 +1091,14 @@ func (cmd *NotifySpentCmd) Method() string { // MarshalJSON returns the JSON encoding of cmd. Part of the Cmd interface. func (cmd *NotifySpentCmd) MarshalJSON() ([]byte, error) { - // Fill a RawCmd and marshal. - raw := btcjson.RawCmd{ - Jsonrpc: "1.0", - Method: "notifyspent", - Id: cmd.id, - Params: []interface{}{ - cmd.OutPoint.Hash.String(), - cmd.OutPoint.Index, - }, + params := []interface{}{ + cmd.OutPoint, } + raw, err := btcjson.NewRawCmd(cmd.id, cmd.Method(), params) + if err != nil { + return nil, err + } return json.Marshal(raw) } @@ -1181,9 +1153,10 @@ func parseCreateEncryptedWalletCmd(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrWrongNumberOfParams } - passphrase, ok := r.Params[0].(string) - if !ok { - return nil, errors.New("first parameter is not a string") + var passphrase string + if err := json.Unmarshal(r.Params[0], &passphrase); err != nil { + return nil, errors.New("first parameter 'passphrase' must be " + + "a string: " + err.Error()) } return NewCreateEncryptedWalletCmd(r.Id, passphrase), nil @@ -1206,14 +1179,14 @@ func (cmd *CreateEncryptedWalletCmd) Method() string { // MarshalJSON returns the JSON encoding of cmd. Part of the Cmd interface. func (cmd *CreateEncryptedWalletCmd) MarshalJSON() ([]byte, error) { - // Fill a RawCmd and marshal. - raw := btcjson.RawCmd{ - Jsonrpc: "1.0", - Method: "createencryptedwallet", - Id: cmd.id, - Params: []interface{}{cmd.Passphrase}, + params := []interface{}{ + cmd.Passphrase, } + raw, err := btcjson.NewRawCmd(cmd.id, cmd.Method(), params) + if err != nil { + return nil, err + } return json.Marshal(raw) } @@ -1283,10 +1256,12 @@ func parseWalletIsLockedCmd(r *btcjson.RawCmd) (btcjson.Cmd, error) { return NewWalletIsLockedCmd(r.Id) } - account, ok := r.Params[0].(string) - if !ok { - return nil, errors.New("account must be a string") + var account string + if err := json.Unmarshal(r.Params[0], &account); err != nil { + return nil, errors.New("first parameter 'account' must be a " + + "string: " + err.Error()) } + return NewWalletIsLockedCmd(r.Id, account) } @@ -1307,18 +1282,15 @@ func (cmd *WalletIsLockedCmd) Method() string { // MarshalJSON returns the JSON encoding of cmd. Part of the Cmd interface. func (cmd *WalletIsLockedCmd) MarshalJSON() ([]byte, error) { - // Fill a RawCmd and marshal. - raw := btcjson.RawCmd{ - Jsonrpc: "1.0", - Method: "walletislocked", - Id: cmd.id, - Params: []interface{}{}, - } - + params := make([]interface{}, 0, 1) if cmd.Account != "" { - raw.Params = append(raw.Params, cmd.Account) + params = append(params, cmd.Account) } + raw, err := btcjson.NewRawCmd(cmd.id, cmd.Method(), params) + if err != nil { + return nil, err + } return json.Marshal(raw) } @@ -1386,30 +1358,23 @@ func parseListAddressTransactionsCmd(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrInvalidParams } - iaddrs, ok := r.Params[0].([]interface{}) - if !ok { - return nil, errors.New("first parameter must be a JSON array") + var addresses []string + if err := json.Unmarshal(r.Params[0], &addresses); err != nil { + return nil, errors.New("first parameter 'addresses' must be " + + "an array of strings: " + err.Error()) } - addresses := make([]string, len(iaddrs)) - for i := range iaddrs { - addr, ok := iaddrs[i].(string) - if !ok { - return nil, errors.New("first parameter must be an " + - "array of strings") + + optArgs := make([]string, 0, 1) + if len(r.Params) > 1 { + var account string + if err := json.Unmarshal(r.Params[1], &account); err != nil { + return nil, errors.New("second optional parameter " + + "'account' must be a string: " + err.Error()) } - addresses[i] = addr + optArgs = append(optArgs, account) } - if len(r.Params) == 1 { - // No optional parameters. - return NewListAddressTransactionsCmd(r.Id, addresses) - } - - account, ok := r.Params[1].(string) - if !ok { - return nil, errors.New("second parameter must be a string") - } - return NewListAddressTransactionsCmd(r.Id, addresses, account) + return NewListAddressTransactionsCmd(r.Id, addresses, optArgs...) } // Id satisifies the Cmd interface by returning the ID of the command. @@ -1429,20 +1394,16 @@ func (cmd *ListAddressTransactionsCmd) Method() string { // MarshalJSON returns the JSON encoding of cmd. Part of the Cmd interface. func (cmd *ListAddressTransactionsCmd) MarshalJSON() ([]byte, error) { - // Fill a RawCmd and marshal. - raw := btcjson.RawCmd{ - Jsonrpc: "1.0", - Method: cmd.Method(), - Id: cmd.id, - Params: []interface{}{ - cmd.Addresses, - }, - } - + params := make([]interface{}, 1, 2) + params[0] = cmd.Addresses if cmd.Account != "" { - raw.Params = append(raw.Params, cmd.Account) + params = append(params, cmd.Account) } + raw, err := btcjson.NewRawCmd(cmd.id, cmd.Method(), params) + if err != nil { + return nil, err + } return json.Marshal(raw) } @@ -1508,15 +1469,17 @@ func parseListAllTransactionsCmd(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrInvalidParams } - if len(r.Params) == 0 { - return NewListAllTransactionsCmd(r.Id) + optArgs := make([]string, 0, 1) + if len(r.Params) > 0 { + var account string + if err := json.Unmarshal(r.Params[0], &account); err != nil { + return nil, errors.New("first optional parameter " + + "'account' must be a string: " + err.Error()) + } + optArgs = append(optArgs, account) } - account, ok := r.Params[0].(string) - if !ok { - return nil, errors.New("account must be a string") - } - return NewListAllTransactionsCmd(r.Id, account) + return NewListAllTransactionsCmd(r.Id, optArgs...) } // Id satisifies the Cmd interface by returning the ID of the command. @@ -1536,18 +1499,15 @@ func (cmd *ListAllTransactionsCmd) Method() string { // MarshalJSON returns the JSON encoding of cmd. Part of the Cmd interface. func (cmd *ListAllTransactionsCmd) MarshalJSON() ([]byte, error) { - // Fill a RawCmd and marshal. - raw := btcjson.RawCmd{ - Jsonrpc: "1.0", - Method: "listalltransactions", - Id: cmd.id, - Params: []interface{}{}, - } - + params := make([]interface{}, 0, 1) if cmd.Account != "" { - raw.Params = append(raw.Params, cmd.Account) + params = append(params, cmd.Account) } + raw, err := btcjson.NewRawCmd(cmd.id, cmd.Method(), params) + if err != nil { + return nil, err + } return json.Marshal(raw) } @@ -1596,22 +1556,23 @@ func parseGetAddressBalanceCmd(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrInvalidParams } - address, ok := r.Params[0].(string) - if !ok { - return nil, errors.New("address must be a string") + var address string + if err := json.Unmarshal(r.Params[0], &address); err != nil { + return nil, errors.New("first parameter 'address' must be a " + + " string: " + err.Error()) } - if len(r.Params) == 1 { - // No optional params. - return NewGetAddressBalanceCmd(r.Id, address) + optArgs := make([]int, 0, 1) + if len(r.Params) > 1 { + var minConf int + if err := json.Unmarshal(r.Params[1], &minConf); err != nil { + return nil, errors.New("second optional parameter " + + " 'minconf' must be an integer: " + err.Error()) + } + optArgs = append(optArgs, minConf) } - // 1 optional param for minconf. - fminConf, ok := r.Params[1].(float64) - if !ok { - return nil, errors.New("first optional parameter minconf must be a number") - } - return NewGetAddressBalanceCmd(r.Id, address, int(fminConf)) + return NewGetAddressBalanceCmd(r.Id, address, optArgs...) } // NewGetAddressBalanceCmd creates a new GetAddressBalanceCmd. @@ -1653,20 +1614,16 @@ func (cmd *GetAddressBalanceCmd) Method() string { // MarshalJSON returns the JSON encoding of cmd. Part of the Cmd interface. func (cmd *GetAddressBalanceCmd) MarshalJSON() ([]byte, error) { - // Fill a RawCmd and marshal. - raw := btcjson.RawCmd{ - Jsonrpc: "1.0", - Method: "getaddressbalance", - Id: cmd.id, - Params: []interface{}{ - cmd.Address, - }, - } - + params := make([]interface{}, 1, 2) + params[0] = cmd.Address if cmd.Minconf != 1 { - raw.Params = append(raw.Params, cmd.Minconf) + params = append(params, cmd.Minconf) } + raw, err := btcjson.NewRawCmd(cmd.id, cmd.Method(), params) + if err != nil { + return nil, err + } return json.Marshal(raw) } diff --git a/cmds_test.go b/cmds_test.go index 7c249bc0..3325d4c1 100644 --- a/cmds_test.go +++ b/cmds_test.go @@ -8,7 +8,6 @@ package btcws import ( "github.com/conformal/btcdb" "github.com/conformal/btcjson" - "github.com/conformal/btcwire" "github.com/davecgh/go-spew/spew" "reflect" "testing" @@ -188,22 +187,20 @@ var cmdtests = []struct { { name: "notifyspent", f: func() (btcjson.Cmd, error) { - op := &btcwire.OutPoint{ - Hash: [...]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31}, + op := &OutPoint{ + Hash: "000102030405060708091011121314" + + "1516171819202122232425262728" + + "293031", Index: 1, } return NewNotifySpentCmd(float64(1), op), nil }, result: &NotifySpentCmd{ id: float64(1), - OutPoint: &btcwire.OutPoint{ - Hash: [...]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31}, + OutPoint: &OutPoint{ + Hash: "000102030405060708091011121314" + + "1516171819202122232425262728" + + "293031", Index: 1, }, }, @@ -212,12 +209,11 @@ var cmdtests = []struct { name: "rescan no optargs", f: func() (btcjson.Cmd, error) { addrs := []string{"17XhEvq9Nahdj7Xe1nv6oRe1tEmaHUuynH"} - ops := []*btcwire.OutPoint{ - &btcwire.OutPoint{ - Hash: [...]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31}, + ops := []OutPoint{ + { + Hash: "000102030405060708091011121314" + + "1516171819202122232425262728" + + "293031", Index: 1, }, } @@ -231,12 +227,11 @@ var cmdtests = []struct { id: float64(1), BeginBlock: 270000, Addresses: []string{"17XhEvq9Nahdj7Xe1nv6oRe1tEmaHUuynH"}, - OutPoints: []*btcwire.OutPoint{ - &btcwire.OutPoint{ - Hash: [...]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31}, + OutPoints: []OutPoint{ + { + Hash: "000102030405060708091011121314" + + "1516171819202122232425262728" + + "293031", Index: 1, }, }, @@ -247,12 +242,11 @@ var cmdtests = []struct { name: "rescan one optarg", f: func() (btcjson.Cmd, error) { addrs := []string{"17XhEvq9Nahdj7Xe1nv6oRe1tEmaHUuynH"} - ops := []*btcwire.OutPoint{ - &btcwire.OutPoint{ - Hash: [...]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31}, + ops := []OutPoint{ + { + Hash: "000102030405060708091011121314" + + "1516171819202122232425262728" + + "293031", Index: 1, }, } @@ -267,12 +261,11 @@ var cmdtests = []struct { id: float64(1), BeginBlock: 270000, Addresses: []string{"17XhEvq9Nahdj7Xe1nv6oRe1tEmaHUuynH"}, - OutPoints: []*btcwire.OutPoint{ - &btcwire.OutPoint{ - Hash: [...]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31}, + OutPoints: []OutPoint{ + { + Hash: "000102030405060708091011121314" + + "1516171819202122232425262728" + + "293031", Index: 1, }, }, diff --git a/notifications.go b/notifications.go index 99ddf508..8af72cef 100644 --- a/notifications.go +++ b/notifications.go @@ -91,10 +91,10 @@ func init() { // BlockDetails describes details of a tx in a block. type BlockDetails struct { - Height int32 - Hash string - Index int - Time int64 + Height int32 `json:"height"` + Hash string `json:"hash"` + Index int `json:"index"` + Time int64 `json:"time"` } // AccountBalanceNtfn is a type handling custom marshaling and @@ -131,17 +131,19 @@ func parseAccountBalanceNtfn(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrWrongNumberOfParams } - account, ok := r.Params[0].(string) - if !ok { - return nil, errors.New("first parameter account must be a string") + var account string + if err := json.Unmarshal(r.Params[0], &account); err != nil { + return nil, errors.New("first parameter 'account' must be a string: " + err.Error()) } - balance, ok := r.Params[1].(float64) - if !ok { - return nil, errors.New("second parameter balance must be a number") + + var balance float64 + if err := json.Unmarshal(r.Params[1], &balance); err != nil { + return nil, errors.New("second parameter 'balance' must be a number: " + err.Error()) } - confirmed, ok := r.Params[2].(bool) - if !ok { - return nil, errors.New("third parameter confirmed must be a boolean") + + var confirmed bool + if err := json.Unmarshal(r.Params[2], &confirmed); err != nil { + return nil, errors.New("third parameter 'confirmed' must be a bool: " + err.Error()) } return NewAccountBalanceNtfn(account, balance, confirmed), nil @@ -166,16 +168,18 @@ func (n *AccountBalanceNtfn) Method() string { // MarshalJSON returns the JSON encoding of n. Part of the btcjson.Cmd // interface. func (n *AccountBalanceNtfn) MarshalJSON() ([]byte, error) { - ntfn := btcjson.Message{ - Jsonrpc: "1.0", - Method: n.Method(), - Params: []interface{}{ - n.Account, - n.Balance, - n.Confirmed, - }, + params := []interface{}{ + n.Account, + n.Balance, + n.Confirmed, } - return json.Marshal(ntfn) + + // No ID for notifications. + raw, err := btcjson.NewRawCmd(nil, n.Method(), params) + if err != nil { + return nil, err + } + return json.Marshal(raw) } // UnmarshalJSON unmarshals the JSON encoding of n into n. Part of @@ -230,16 +234,17 @@ func parseBlockConnectedNtfn(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrWrongNumberOfParams } - hash, ok := r.Params[0].(string) - if !ok { - return nil, errors.New("first parameter hash must be a string") - } - fheight, ok := r.Params[1].(float64) - if !ok { - return nil, errors.New("second parameter height must be a number") + var hash string + if err := json.Unmarshal(r.Params[0], &hash); err != nil { + return nil, errors.New("first parameter 'hash' must be a string: " + err.Error()) } - return NewBlockConnectedNtfn(hash, int32(fheight)), nil + var height int32 + if err := json.Unmarshal(r.Params[1], &height); err != nil { + return nil, errors.New("second parameter 'height' must be a 32-bit integer: " + err.Error()) + } + + return NewBlockConnectedNtfn(hash, height), nil } // Id satisifies the btcjson.Cmd interface by returning nil for a @@ -261,15 +266,17 @@ func (n *BlockConnectedNtfn) Method() string { // MarshalJSON returns the JSON encoding of n. Part of the btcjson.Cmd // interface. func (n *BlockConnectedNtfn) MarshalJSON() ([]byte, error) { - ntfn := btcjson.Message{ - Jsonrpc: "1.0", - Method: n.Method(), - Params: []interface{}{ - n.Hash, - n.Height, - }, + params := []interface{}{ + n.Hash, + n.Height, } - return json.Marshal(ntfn) + + // No ID for notifications. + raw, err := btcjson.NewRawCmd(nil, n.Method(), params) + if err != nil { + return nil, err + } + return json.Marshal(raw) } // UnmarshalJSON unmarshals the JSON encoding of n into n. Part of @@ -324,16 +331,17 @@ func parseBlockDisconnectedNtfn(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrWrongNumberOfParams } - hash, ok := r.Params[0].(string) - if !ok { - return nil, errors.New("first parameter hash must be a string") - } - fheight, ok := r.Params[1].(float64) - if !ok { - return nil, errors.New("second parameter height must be a number") + var hash string + if err := json.Unmarshal(r.Params[0], &hash); err != nil { + return nil, errors.New("first parameter 'hash' must be a string: " + err.Error()) } - return NewBlockDisconnectedNtfn(hash, int32(fheight)), nil + var height int32 + if err := json.Unmarshal(r.Params[1], &height); err != nil { + return nil, errors.New("second parameter 'height' must be a 32-bit integer: " + err.Error()) + } + + return NewBlockDisconnectedNtfn(hash, height), nil } // Id satisifies the btcjson.Cmd interface by returning nil for a @@ -355,15 +363,17 @@ func (n *BlockDisconnectedNtfn) Method() string { // MarshalJSON returns the JSON encoding of n. Part of the btcjson.Cmd // interface. func (n *BlockDisconnectedNtfn) MarshalJSON() ([]byte, error) { - ntfn := btcjson.Message{ - Jsonrpc: "1.0", - Method: n.Method(), - Params: []interface{}{ - n.Hash, - n.Height, - }, + params := []interface{}{ + n.Hash, + n.Height, } - return json.Marshal(ntfn) + + // No ID for notifications. + raw, err := btcjson.NewRawCmd(nil, n.Method(), params) + if err != nil { + return nil, err + } + return json.Marshal(raw) } // UnmarshalJSON unmarshals the JSON encoding of n into n. Part of @@ -415,9 +425,9 @@ func parseBtcdConnectedNtfn(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrWrongNumberOfParams } - connected, ok := r.Params[0].(bool) - if !ok { - return nil, errors.New("first parameter connected is not a boolean") + var connected bool + if err := json.Unmarshal(r.Params[0], &connected); err != nil { + return nil, errors.New("first parameter 'connected' must be a bool: " + err.Error()) } return NewBtcdConnectedNtfn(connected), nil @@ -442,14 +452,16 @@ func (n *BtcdConnectedNtfn) Method() string { // MarshalJSON returns the JSON encoding of n. Part of the btcjson.Cmd // interface. func (n *BtcdConnectedNtfn) MarshalJSON() ([]byte, error) { - ntfn := btcjson.Message{ - Jsonrpc: "1.0", - Method: n.Method(), - Params: []interface{}{ - n.Connected, - }, + params := []interface{}{ + n.Connected, } - return json.Marshal(ntfn) + + // No ID for notifications. + raw, err := btcjson.NewRawCmd(nil, n.Method(), params) + if err != nil { + return nil, err + } + return json.Marshal(raw) } // UnmarshalJSON unmarshals the JSON encoding of n into n. Part of @@ -505,48 +517,22 @@ func parseRecvTxNtfn(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrWrongNumberOfParams } - hextx, ok := r.Params[0].(string) - if !ok { - return nil, errors.New("first parameter hextx must be a string") + var hextx string + if err := json.Unmarshal(r.Params[0], &hextx); err != nil { + return nil, errors.New("first parameter 'hextx' must be a " + + "string: " + err.Error()) } - ntfn := &RecvTxNtfn{HexTx: hextx} - + var blockDetails *BlockDetails if len(r.Params) > 1 { - details, ok := r.Params[1].(map[string]interface{}) - if !ok { - return nil, errors.New("second parameter must be a JSON object") - } - - height, ok := details["height"].(float64) - if !ok { - return nil, errors.New("unspecified block height") - } - - hash, ok := details["hash"].(string) - if !ok { - return nil, errors.New("unspecified block hash") - } - - index, ok := details["index"].(float64) - if !ok { - return nil, errors.New("unspecified block index") - } - - time, ok := details["time"].(float64) - if !ok { - return nil, errors.New("unspecified block time") - } - - ntfn.Block = &BlockDetails{ - Height: int32(height), - Hash: hash, - Index: int(index), - Time: int64(time), + if err := json.Unmarshal(r.Params[1], &blockDetails); err != nil { + return nil, errors.New("second optional parameter " + + "'details' must be a JSON oject of block " + + "details: " + err.Error()) } } - return ntfn, nil + return NewRecvTxNtfn(hextx, blockDetails), nil } // Id satisifies the btcjson.Cmd interface by returning nil for a @@ -568,25 +554,18 @@ func (n *RecvTxNtfn) Method() string { // MarshalJSON returns the JSON encoding of n. Part of the btcjson.Cmd // interface. func (n *RecvTxNtfn) MarshalJSON() ([]byte, error) { - params := []interface{}{n.HexTx} - + params := make([]interface{}, 1, 2) + params[0] = n.HexTx if n.Block != nil { - details := map[string]interface{}{ - "height": float64(n.Block.Height), - "hash": n.Block.Hash, - "index": float64(n.Block.Index), - "time": float64(n.Block.Time), - } - params = append(params, details) + params = append(params, n.Block) } - ntfn := btcjson.Message{ - Jsonrpc: "1.0", - Method: n.Method(), - Params: params, + // No ID for notifications. + raw, err := btcjson.NewRawCmd(nil, n.Method(), params) + if err != nil { + return nil, err } - - return json.Marshal(ntfn) + return json.Marshal(raw) } // UnmarshalJSON unmarshals the JSON encoding of n into n. Part of @@ -642,48 +621,22 @@ func parseRedeemingTxNtfn(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrWrongNumberOfParams } - hextx, ok := r.Params[0].(string) - if !ok { - return nil, errors.New("first parameter hextx must be a string") + var hextx string + if err := json.Unmarshal(r.Params[0], &hextx); err != nil { + return nil, errors.New("first parameter 'hextx' must be a " + + "string: " + err.Error()) } - ntfn := &RedeemingTxNtfn{HexTx: hextx} - + var blockDetails *BlockDetails if len(r.Params) > 1 { - details, ok := r.Params[1].(map[string]interface{}) - if !ok { - return nil, errors.New("second parameter must be a JSON object") - } - - height, ok := details["height"].(float64) - if !ok { - return nil, errors.New("unspecified block height") - } - - hash, ok := details["hash"].(string) - if !ok { - return nil, errors.New("unspecified block hash") - } - - index, ok := details["index"].(float64) - if !ok { - return nil, errors.New("unspecified block index") - } - - time, ok := details["time"].(float64) - if !ok { - return nil, errors.New("unspecified block time") - } - - ntfn.Block = &BlockDetails{ - Height: int32(height), - Hash: hash, - Index: int(index), - Time: int64(time), + if err := json.Unmarshal(r.Params[1], &blockDetails); err != nil { + return nil, errors.New("second optional parameter " + + "'details' must be a JSON oject of block " + + "details: " + err.Error()) } } - return ntfn, nil + return NewRedeemingTxNtfn(hextx, blockDetails), nil } // Id satisifies the btcjson.Cmd interface by returning nil for a @@ -705,25 +658,18 @@ func (n *RedeemingTxNtfn) Method() string { // MarshalJSON returns the JSON encoding of n. Part of the btcjson.Cmd // interface. func (n *RedeemingTxNtfn) MarshalJSON() ([]byte, error) { - params := []interface{}{n.HexTx} - + params := make([]interface{}, 1, 2) + params[0] = n.HexTx if n.Block != nil { - details := map[string]interface{}{ - "height": float64(n.Block.Height), - "hash": n.Block.Hash, - "index": float64(n.Block.Index), - "time": float64(n.Block.Time), - } - params = append(params, details) + params = append(params, n.Block) } - ntfn := btcjson.Message{ - Jsonrpc: "1.0", - Method: n.Method(), - Params: params, + // No ID for notifications. + raw, err := btcjson.NewRawCmd(nil, n.Method(), params) + if err != nil { + return nil, err } - - return json.Marshal(ntfn) + return json.Marshal(raw) } // UnmarshalJSON unmarshals the JSON encoding of n into n. Part of @@ -774,12 +720,13 @@ func parseRescanProgressNtfn(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrWrongNumberOfParams } - last, ok := r.Params[0].(float64) - if !ok { - return nil, errors.New("first parameter must be a number") + var last int32 + if err := json.Unmarshal(r.Params[0], &last); err != nil { + return nil, errors.New("first parameter 'last' must be a " + + "32-bit integer: " + err.Error()) } - return NewRescanProgressNtfn(int32(last)), nil + return NewRescanProgressNtfn(last), nil } // Id satisifies the btcjson.Cmd interface by returning nil for a @@ -801,12 +748,16 @@ func (n *RescanProgressNtfn) Method() string { // MarshalJSON returns the JSON encoding of n. Part of the btcjson.Cmd // interface. func (n *RescanProgressNtfn) MarshalJSON() ([]byte, error) { - ntfn := btcjson.Message{ - Jsonrpc: "1.0", - Method: n.Method(), - Params: []interface{}{n.LastProcessed}, + params := []interface{}{ + n.LastProcessed, } - return json.Marshal(ntfn) + + // No ID for notifications. + raw, err := btcjson.NewRawCmd(nil, n.Method(), params) + if err != nil { + return nil, err + } + return json.Marshal(raw) } // UnmarshalJSON unmarshals the JSON encoding of n into n. Part of @@ -861,13 +812,17 @@ func parseTxNtfn(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrWrongNumberOfParams } - account, ok := r.Params[0].(string) - if !ok { - return nil, errors.New("first parameter account must be a string") + var account string + if err := json.Unmarshal(r.Params[0], &account); err != nil { + return nil, errors.New("first parameter 'account' must be a " + + "string: " + err.Error()) } - details, ok := r.Params[1].(map[string]interface{}) - if !ok { - return nil, errors.New("second parameter details must be a JSON object") + + // TODO(davec): Object + var details map[string]interface{} + if err := json.Unmarshal(r.Params[1], &details); err != nil { + return nil, errors.New("second parameter 'details' must be a " + + "JSON object of transaction details: " + err.Error()) } return NewTxNtfn(account, details), nil @@ -892,15 +847,17 @@ func (n *TxNtfn) Method() string { // MarshalJSON returns the JSON encoding of n. Part of the btcjson.Cmd // interface. func (n *TxNtfn) MarshalJSON() ([]byte, error) { - ntfn := btcjson.Message{ - Jsonrpc: "1.0", - Method: n.Method(), - Params: []interface{}{ - n.Account, - n.Details, - }, + params := []interface{}{ + n.Account, + n.Details, } - return json.Marshal(ntfn) + + // No ID for notifications. + raw, err := btcjson.NewRawCmd(nil, n.Method(), params) + if err != nil { + return nil, err + } + return json.Marshal(raw) } // UnmarshalJSON unmarshals the JSON encoding of n into n. Part of @@ -958,13 +915,16 @@ func parseWalletLockStateNtfn(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrWrongNumberOfParams } - account, ok := r.Params[0].(string) - if !ok { - return nil, errors.New("first parameter account must be a string") + var account string + if err := json.Unmarshal(r.Params[0], &account); err != nil { + return nil, errors.New("first parameter 'account' must be a " + + "string: " + err.Error()) } - locked, ok := r.Params[1].(bool) - if !ok { - return nil, errors.New("second parameter locked must be a boolean") + + var locked bool + if err := json.Unmarshal(r.Params[1], &locked); err != nil { + return nil, errors.New("second parameter 'locked' must be a " + + "bool: " + err.Error()) } return NewWalletLockStateNtfn(account, locked), nil @@ -989,15 +949,17 @@ func (n *WalletLockStateNtfn) Method() string { // MarshalJSON returns the JSON encoding of n. Part of the btcjson.Cmd // interface. func (n *WalletLockStateNtfn) MarshalJSON() ([]byte, error) { - ntfn := btcjson.Message{ - Jsonrpc: "1.0", - Method: n.Method(), - Params: []interface{}{ - n.Account, - n.Locked, - }, + params := []interface{}{ + n.Account, + n.Locked, } - return json.Marshal(ntfn) + + // No ID for notifications. + raw, err := btcjson.NewRawCmd(nil, n.Method(), params) + if err != nil { + return nil, err + } + return json.Marshal(raw) } // UnmarshalJSON unmarshals the JSON encoding of n into n. Part of @@ -1052,16 +1014,19 @@ func parseAllTxNtfn(r *btcjson.RawCmd) (btcjson.Cmd, error) { return nil, btcjson.ErrWrongNumberOfParams } - txid, ok := r.Params[0].(string) - if !ok { - return nil, errors.New("first parameter txid must be a string") - } - famount, ok := r.Params[1].(float64) - if !ok { - return nil, errors.New("second parameter amount must be a number") + var txid string + if err := json.Unmarshal(r.Params[0], &txid); err != nil { + return nil, errors.New("first parameter 'txid' must be a " + + "string: " + err.Error()) } - return NewAllTxNtfn(txid, int64(famount)), nil + var amount int64 + if err := json.Unmarshal(r.Params[1], &amount); err != nil { + return nil, errors.New("second parameter 'amount' must be an " + + "integer: " + err.Error()) + } + + return NewAllTxNtfn(txid, amount), nil } // Id satisifies the btcjson.Cmd interface by returning nil for a @@ -1083,15 +1048,17 @@ func (n *AllTxNtfn) Method() string { // MarshalJSON returns the JSON encoding of n. Part of the btcjson.Cmd // interface. func (n *AllTxNtfn) MarshalJSON() ([]byte, error) { - ntfn := btcjson.Message{ - Jsonrpc: "1.0", - Method: n.Method(), - Params: []interface{}{ - n.TxID, - n.Amount, - }, + params := []interface{}{ + n.TxID, + n.Amount, } - return json.Marshal(ntfn) + + // No ID for notifications. + raw, err := btcjson.NewRawCmd(nil, n.Method(), params) + if err != nil { + return nil, err + } + return json.Marshal(raw) } // UnmarshalJSON unmarshals the JSON encoding of n into n. Part of @@ -1151,32 +1118,26 @@ func (n *AllVerboseTxNtfn) Method() string { // MarshalJSON returns the JSON encoding of n. Part of the btcjson.Cmd // interface. func (n *AllVerboseTxNtfn) MarshalJSON() ([]byte, error) { - ntfn := btcjson.Message{ - Jsonrpc: "1.0", - Method: n.Method(), - Params: []interface{}{ - n.RawTx, - }, + params := []interface{}{ + n.RawTx, } - return json.Marshal(ntfn) + + // No ID for notifications. + raw, err := btcjson.NewRawCmd(nil, n.Method(), params) + if err != nil { + return nil, err + } + return json.Marshal(raw) } func generateAllVerboseTxNtfn() btcjson.Cmd { return new(AllVerboseTxNtfn) } -type rawParamsCmd struct { - Jsonrpc string `json:"jsonrpc"` - Id interface{} `json:"id"` - Method string `json:"method"` - Params []*json.RawMessage `json:"params"` -} - // UnmarshalJSON unmarshals the JSON encoding of n into n. Part of // the btcjson.Cmd interface. func (n *AllVerboseTxNtfn) UnmarshalJSON(b []byte) error { - // Unmarshal into a custom rawParamsCmd - var r rawParamsCmd + var r btcjson.RawCmd if err := json.Unmarshal(b, &r); err != nil { return err } @@ -1190,7 +1151,7 @@ func (n *AllVerboseTxNtfn) UnmarshalJSON(b []byte) error { } var rawTx *btcjson.TxRawResult - if err := json.Unmarshal(*r.Params[0], &rawTx); err != nil { + if err := json.Unmarshal(r.Params[0], &rawTx); err != nil { return err } diff --git a/test_coverage.txt b/test_coverage.txt index 060d9df0..a27ce0d2 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,56 +1,6 @@ github.com/conformal/btcws/cmds.go init 100.00% (16/16) github.com/conformal/btcws/notifications.go init 100.00% (11/11) -github.com/conformal/btcws/cmds.go RescanCmd.MarshalJSON 100.00% (7/7) -github.com/conformal/btcws/notifications.go RedeemingTxNtfn.MarshalJSON 100.00% (6/6) -github.com/conformal/btcws/notifications.go RecvTxNtfn.MarshalJSON 100.00% (6/6) -github.com/conformal/btcws/cmds.go GetUnconfirmedBalanceCmd.MarshalJSON 100.00% (4/4) -github.com/conformal/btcws/cmds.go WalletIsLockedCmd.MarshalJSON 100.00% (4/4) -github.com/conformal/btcws/cmds.go ListAddressTransactionsCmd.MarshalJSON 100.00% (4/4) -github.com/conformal/btcws/cmds.go GetAddressBalanceCmd.MarshalJSON 100.00% (4/4) -github.com/conformal/btcws/cmds.go ListAllTransactionsCmd.MarshalJSON 100.00% (4/4) -github.com/conformal/btcws/notifications.go TxNtfn.MarshalJSON 100.00% (2/2) -github.com/conformal/btcws/cmds.go GetCurrentNetCmd.MarshalJSON 100.00% (2/2) -github.com/conformal/btcws/notifications.go WalletLockStateNtfn.MarshalJSON 100.00% (2/2) -github.com/conformal/btcws/notifications.go AllVerboseTxNtfn.MarshalJSON 100.00% (2/2) -github.com/conformal/btcws/notifications.go BlockDisconnectedNtfn.MarshalJSON 100.00% (2/2) -github.com/conformal/btcws/notifications.go AccountBalanceNtfn.MarshalJSON 100.00% (2/2) -github.com/conformal/btcws/cmds.go GetBestBlockCmd.MarshalJSON 100.00% (2/2) -github.com/conformal/btcws/notifications.go BlockConnectedNtfn.MarshalJSON 100.00% (2/2) -github.com/conformal/btcws/notifications.go RescanProgressNtfn.MarshalJSON 100.00% (2/2) -github.com/conformal/btcws/cmds.go CreateEncryptedWalletCmd.MarshalJSON 100.00% (2/2) -github.com/conformal/btcws/cmds.go NotifyNewTXsCmd.MarshalJSON 100.00% (2/2) -github.com/conformal/btcws/cmds.go NotifySpentCmd.MarshalJSON 100.00% (2/2) -github.com/conformal/btcws/notifications.go BtcdConnectedNtfn.MarshalJSON 100.00% (2/2) -github.com/conformal/btcws/notifications.go AllTxNtfn.MarshalJSON 100.00% (2/2) -github.com/conformal/btcws/cmds.go NotifyAllNewTXsCmd.MarshalJSON 100.00% (2/2) -github.com/conformal/btcws/notifications.go NewRedeemingTxNtfn 100.00% (1/1) -github.com/conformal/btcws/notifications.go RecvTxNtfn.Method 100.00% (1/1) -github.com/conformal/btcws/notifications.go NewRecvTxNtfn 100.00% (1/1) -github.com/conformal/btcws/notifications.go BtcdConnectedNtfn.Method 100.00% (1/1) -github.com/conformal/btcws/cmds.go RescanCmd.Id 100.00% (1/1) -github.com/conformal/btcws/notifications.go BtcdConnectedNtfn.Id 100.00% (1/1) -github.com/conformal/btcws/cmds.go RescanCmd.Method 100.00% (1/1) -github.com/conformal/btcws/notifications.go NewBtcdConnectedNtfn 100.00% (1/1) -github.com/conformal/btcws/notifications.go BlockDisconnectedNtfn.Method 100.00% (1/1) -github.com/conformal/btcws/notifications.go BlockDisconnectedNtfn.Id 100.00% (1/1) -github.com/conformal/btcws/notifications.go NewBlockDisconnectedNtfn 100.00% (1/1) -github.com/conformal/btcws/notifications.go BlockConnectedNtfn.Method 100.00% (1/1) -github.com/conformal/btcws/notifications.go BlockConnectedNtfn.Id 100.00% (1/1) -github.com/conformal/btcws/cmds.go NewNotifyNewTXsCmd 100.00% (1/1) -github.com/conformal/btcws/cmds.go NotifyNewTXsCmd.Id 100.00% (1/1) -github.com/conformal/btcws/notifications.go NewBlockConnectedNtfn 100.00% (1/1) -github.com/conformal/btcws/cmds.go NotifyNewTXsCmd.Method 100.00% (1/1) -github.com/conformal/btcws/cmds.go NotifyAllNewTXsCmd.Id 100.00% (1/1) -github.com/conformal/btcws/notifications.go AccountBalanceNtfn.Id 100.00% (1/1) -github.com/conformal/btcws/cmds.go NotifyAllNewTXsCmd.Method 100.00% (1/1) -github.com/conformal/btcws/notifications.go NewAccountBalanceNtfn 100.00% (1/1) -github.com/conformal/btcws/cmds.go NewNotifySpentCmd 100.00% (1/1) -github.com/conformal/btcws/notifications.go AccountBalanceNtfn.Method 100.00% (1/1) -github.com/conformal/btcws/cmds.go NotifySpentCmd.Id 100.00% (1/1) -github.com/conformal/btcws/cmds.go ListAllTransactionsCmd.Id 100.00% (1/1) -github.com/conformal/btcws/cmds.go NotifySpentCmd.Method 100.00% (1/1) -github.com/conformal/btcws/cmds.go GetUnconfirmedBalanceCmd.Id 100.00% (1/1) github.com/conformal/btcws/notifications.go AllVerboseTxNtfn.Method 100.00% (1/1) github.com/conformal/btcws/notifications.go AllVerboseTxNtfn.Id 100.00% (1/1) github.com/conformal/btcws/notifications.go NewAllVerboseTxNtfn 100.00% (1/1) @@ -60,135 +10,185 @@ github.com/conformal/btcws/notifications.go AllTxNtfn.Id 100.00% (1/1) github.com/conformal/btcws/cmds.go GetCurrentNetCmd.Id 100.00% (1/1) github.com/conformal/btcws/notifications.go NewAllTxNtfn 100.00% (1/1) github.com/conformal/btcws/cmds.go GetCurrentNetCmd.Method 100.00% (1/1) +github.com/conformal/btcws/cmds.go ListAddressTransactionsCmd.Id 100.00% (1/1) +github.com/conformal/btcws/notifications.go RecvTxNtfn.Id 100.00% (1/1) +github.com/conformal/btcws/cmds.go RescanCmd.Method 100.00% (1/1) +github.com/conformal/btcws/notifications.go BlockDisconnectedNtfn.Method 100.00% (1/1) +github.com/conformal/btcws/notifications.go BlockDisconnectedNtfn.Id 100.00% (1/1) +github.com/conformal/btcws/notifications.go NewBlockDisconnectedNtfn 100.00% (1/1) +github.com/conformal/btcws/notifications.go BlockConnectedNtfn.Method 100.00% (1/1) +github.com/conformal/btcws/notifications.go BlockConnectedNtfn.Id 100.00% (1/1) +github.com/conformal/btcws/notifications.go NewBlockConnectedNtfn 100.00% (1/1) +github.com/conformal/btcws/cmds.go NewNotifyNewTXsCmd 100.00% (1/1) +github.com/conformal/btcws/notifications.go AccountBalanceNtfn.Id 100.00% (1/1) +github.com/conformal/btcws/cmds.go NotifyNewTXsCmd.Id 100.00% (1/1) +github.com/conformal/btcws/notifications.go NewAccountBalanceNtfn 100.00% (1/1) +github.com/conformal/btcws/cmds.go NotifyNewTXsCmd.Method 100.00% (1/1) +github.com/conformal/btcws/notifications.go generateAllVerboseTxNtfn 100.00% (1/1) +github.com/conformal/btcws/cmds.go NotifyAllNewTXsCmd.Id 100.00% (1/1) +github.com/conformal/btcws/cmds.go NotifyAllNewTXsCmd.Method 100.00% (1/1) +github.com/conformal/btcws/cmds.go GetAddressBalanceCmd.Method 100.00% (1/1) +github.com/conformal/btcws/cmds.go NewNotifySpentCmd 100.00% (1/1) +github.com/conformal/btcws/notifications.go AccountBalanceNtfn.Method 100.00% (1/1) +github.com/conformal/btcws/cmds.go NotifySpentCmd.Id 100.00% (1/1) +github.com/conformal/btcws/cmds.go GetAddressBalanceCmd.Id 100.00% (1/1) +github.com/conformal/btcws/cmds.go NotifySpentCmd.Method 100.00% (1/1) +github.com/conformal/btcws/cmds.go NewCreateEncryptedWalletCmd 100.00% (1/1) +github.com/conformal/btcws/cmds.go CreateEncryptedWalletCmd.Id 100.00% (1/1) +github.com/conformal/btcws/cmds.go ListAllTransactionsCmd.Method 100.00% (1/1) +github.com/conformal/btcws/cmds.go CreateEncryptedWalletCmd.Method 100.00% (1/1) +github.com/conformal/btcws/cmds.go ListAllTransactionsCmd.Id 100.00% (1/1) +github.com/conformal/btcws/cmds.go WalletIsLockedCmd.Id 100.00% (1/1) +github.com/conformal/btcws/cmds.go WalletIsLockedCmd.Method 100.00% (1/1) +github.com/conformal/btcws/cmds.go ListAddressTransactionsCmd.Method 100.00% (1/1) github.com/conformal/btcws/notifications.go WalletLockStateNtfn.Method 100.00% (1/1) github.com/conformal/btcws/notifications.go WalletLockStateNtfn.Id 100.00% (1/1) github.com/conformal/btcws/notifications.go NewWalletLockStateNtfn 100.00% (1/1) github.com/conformal/btcws/notifications.go TxNtfn.Method 100.00% (1/1) github.com/conformal/btcws/notifications.go TxNtfn.Id 100.00% (1/1) github.com/conformal/btcws/notifications.go NewTxNtfn 100.00% (1/1) -github.com/conformal/btcws/cmds.go GetUnconfirmedBalanceCmd.Method 100.00% (1/1) +github.com/conformal/btcws/cmds.go GetUnconfirmedBalanceCmd.Id 100.00% (1/1) github.com/conformal/btcws/notifications.go RescanProgressNtfn.Method 100.00% (1/1) -github.com/conformal/btcws/cmds.go NewGetBestBlockCmd 100.00% (1/1) +github.com/conformal/btcws/cmds.go GetUnconfirmedBalanceCmd.Method 100.00% (1/1) github.com/conformal/btcws/notifications.go RescanProgressNtfn.Id 100.00% (1/1) -github.com/conformal/btcws/cmds.go GetBestBlockCmd.Id 100.00% (1/1) +github.com/conformal/btcws/cmds.go NewGetBestBlockCmd 100.00% (1/1) github.com/conformal/btcws/notifications.go NewRescanProgressNtfn 100.00% (1/1) +github.com/conformal/btcws/cmds.go GetBestBlockCmd.Id 100.00% (1/1) github.com/conformal/btcws/cmds.go GetBestBlockCmd.Method 100.00% (1/1) github.com/conformal/btcws/notifications.go RedeemingTxNtfn.Method 100.00% (1/1) github.com/conformal/btcws/notifications.go RedeemingTxNtfn.Id 100.00% (1/1) -github.com/conformal/btcws/cmds.go GetAddressBalanceCmd.Method 100.00% (1/1) -github.com/conformal/btcws/cmds.go CreateEncryptedWalletCmd.Id 100.00% (1/1) -github.com/conformal/btcws/cmds.go GetAddressBalanceCmd.Id 100.00% (1/1) -github.com/conformal/btcws/cmds.go CreateEncryptedWalletCmd.Method 100.00% (1/1) -github.com/conformal/btcws/cmds.go WalletIsLockedCmd.Id 100.00% (1/1) -github.com/conformal/btcws/cmds.go WalletIsLockedCmd.Method 100.00% (1/1) -github.com/conformal/btcws/cmds.go ListAllTransactionsCmd.Method 100.00% (1/1) -github.com/conformal/btcws/cmds.go ListAddressTransactionsCmd.Id 100.00% (1/1) -github.com/conformal/btcws/notifications.go RecvTxNtfn.Id 100.00% (1/1) -github.com/conformal/btcws/cmds.go ListAddressTransactionsCmd.Method 100.00% (1/1) -github.com/conformal/btcws/notifications.go generateAllVerboseTxNtfn 100.00% (1/1) -github.com/conformal/btcws/cmds.go NewCreateEncryptedWalletCmd 100.00% (1/1) -github.com/conformal/btcws/cmds.go parseListAllTransactionsCmd 87.50% (7/8) +github.com/conformal/btcws/notifications.go NewRedeemingTxNtfn 100.00% (1/1) +github.com/conformal/btcws/notifications.go RecvTxNtfn.Method 100.00% (1/1) +github.com/conformal/btcws/notifications.go NewRecvTxNtfn 100.00% (1/1) +github.com/conformal/btcws/notifications.go BtcdConnectedNtfn.Method 100.00% (1/1) +github.com/conformal/btcws/notifications.go BtcdConnectedNtfn.Id 100.00% (1/1) +github.com/conformal/btcws/notifications.go NewBtcdConnectedNtfn 100.00% (1/1) +github.com/conformal/btcws/cmds.go RescanCmd.Id 100.00% (1/1) +github.com/conformal/btcws/cmds.go RescanCmd.MarshalJSON 90.00% (9/10) +github.com/conformal/btcws/cmds.go parseListAllTransactionsCmd 88.89% (8/9) +github.com/conformal/btcws/notifications.go RecvTxNtfn.MarshalJSON 87.50% (7/8) +github.com/conformal/btcws/cmds.go ListAddressTransactionsCmd.MarshalJSON 87.50% (7/8) +github.com/conformal/btcws/notifications.go RedeemingTxNtfn.MarshalJSON 87.50% (7/8) +github.com/conformal/btcws/cmds.go GetAddressBalanceCmd.MarshalJSON 87.50% (7/8) +github.com/conformal/btcws/cmds.go ListAllTransactionsCmd.MarshalJSON 85.71% (6/7) github.com/conformal/btcws/cmds.go NewNotifyAllNewTXsCmd 85.71% (6/7) -github.com/conformal/btcws/cmds.go parseNotifyAllNewTXsCmd 85.71% (6/7) -github.com/conformal/btcws/cmds.go NewGetUnconfirmedBalanceCmd 83.33% (5/6) -github.com/conformal/btcws/cmds.go NewListAddressTransactionsCmd 83.33% (5/6) -github.com/conformal/btcws/cmds.go NewListAllTransactionsCmd 83.33% (5/6) +github.com/conformal/btcws/cmds.go WalletIsLockedCmd.MarshalJSON 85.71% (6/7) +github.com/conformal/btcws/cmds.go GetUnconfirmedBalanceCmd.MarshalJSON 85.71% (6/7) github.com/conformal/btcws/cmds.go NewWalletIsLockedCmd 83.33% (5/6) +github.com/conformal/btcws/cmds.go NewListAddressTransactionsCmd 83.33% (5/6) +github.com/conformal/btcws/cmds.go NewGetUnconfirmedBalanceCmd 83.33% (5/6) +github.com/conformal/btcws/cmds.go NewListAllTransactionsCmd 83.33% (5/6) github.com/conformal/btcws/cmds.go NewRescanCmd 83.33% (5/6) github.com/conformal/btcws/cmds.go NewGetAddressBalanceCmd 83.33% (5/6) -github.com/conformal/btcws/cmds.go parseListAddressTransactionsCmd 76.47% (13/17) -github.com/conformal/btcws/cmds.go parseNotifyNewTXsCmd 75.00% (9/12) -github.com/conformal/btcws/cmds.go parseGetUnconfirmedBalanceCmd 75.00% (6/8) +github.com/conformal/btcws/notifications.go WalletLockStateNtfn.MarshalJSON 80.00% (4/5) +github.com/conformal/btcws/cmds.go NotifyNewTXsCmd.MarshalJSON 80.00% (4/5) +github.com/conformal/btcws/notifications.go AllVerboseTxNtfn.MarshalJSON 80.00% (4/5) +github.com/conformal/btcws/notifications.go TxNtfn.MarshalJSON 80.00% (4/5) +github.com/conformal/btcws/notifications.go BlockDisconnectedNtfn.MarshalJSON 80.00% (4/5) +github.com/conformal/btcws/notifications.go RescanProgressNtfn.MarshalJSON 80.00% (4/5) +github.com/conformal/btcws/notifications.go AllTxNtfn.MarshalJSON 80.00% (4/5) +github.com/conformal/btcws/notifications.go BlockConnectedNtfn.MarshalJSON 80.00% (4/5) +github.com/conformal/btcws/cmds.go NotifyAllNewTXsCmd.MarshalJSON 80.00% (4/5) +github.com/conformal/btcws/notifications.go AccountBalanceNtfn.MarshalJSON 80.00% (4/5) +github.com/conformal/btcws/cmds.go CreateEncryptedWalletCmd.MarshalJSON 80.00% (4/5) +github.com/conformal/btcws/notifications.go BtcdConnectedNtfn.MarshalJSON 80.00% (4/5) +github.com/conformal/btcws/cmds.go NotifySpentCmd.MarshalJSON 80.00% (4/5) +github.com/conformal/btcws/cmds.go parseGetUnconfirmedBalanceCmd 77.78% (7/9) +github.com/conformal/btcws/cmds.go parseNotifyAllNewTXsCmd 77.78% (7/9) +github.com/conformal/btcws/cmds.go parseListAddressTransactionsCmd 75.00% (9/12) +github.com/conformal/btcws/cmds.go parseGetAddressBalanceCmd 75.00% (9/12) github.com/conformal/btcws/cmds.go parseWalletIsLockedCmd 75.00% (6/8) -github.com/conformal/btcws/cmds.go parseRescanCmd 74.36% (29/39) -github.com/conformal/btcws/notifications.go AllTxNtfn.UnmarshalJSON 72.73% (8/11) -github.com/conformal/btcws/cmds.go WalletIsLockedCmd.UnmarshalJSON 72.73% (8/11) -github.com/conformal/btcws/cmds.go ListAllTransactionsCmd.UnmarshalJSON 72.73% (8/11) -github.com/conformal/btcws/cmds.go parseGetAddressBalanceCmd 72.73% (8/11) -github.com/conformal/btcws/cmds.go CreateEncryptedWalletCmd.UnmarshalJSON 72.73% (8/11) +github.com/conformal/btcws/cmds.go GetCurrentNetCmd.MarshalJSON 75.00% (3/4) +github.com/conformal/btcws/cmds.go GetBestBlockCmd.MarshalJSON 75.00% (3/4) github.com/conformal/btcws/notifications.go WalletLockStateNtfn.UnmarshalJSON 72.73% (8/11) github.com/conformal/btcws/cmds.go GetCurrentNetCmd.UnmarshalJSON 72.73% (8/11) -github.com/conformal/btcws/notifications.go BlockDisconnectedNtfn.UnmarshalJSON 72.73% (8/11) -github.com/conformal/btcws/notifications.go RecvTxNtfn.UnmarshalJSON 72.73% (8/11) -github.com/conformal/btcws/cmds.go ListAddressTransactionsCmd.UnmarshalJSON 72.73% (8/11) -github.com/conformal/btcws/notifications.go BtcdConnectedNtfn.UnmarshalJSON 72.73% (8/11) -github.com/conformal/btcws/notifications.go BlockConnectedNtfn.UnmarshalJSON 72.73% (8/11) -github.com/conformal/btcws/cmds.go RescanCmd.UnmarshalJSON 72.73% (8/11) -github.com/conformal/btcws/cmds.go NotifySpentCmd.UnmarshalJSON 72.73% (8/11) -github.com/conformal/btcws/cmds.go GetAddressBalanceCmd.UnmarshalJSON 72.73% (8/11) +github.com/conformal/btcws/cmds.go ListAllTransactionsCmd.UnmarshalJSON 72.73% (8/11) github.com/conformal/btcws/notifications.go TxNtfn.UnmarshalJSON 72.73% (8/11) -github.com/conformal/btcws/cmds.go NotifyAllNewTXsCmd.UnmarshalJSON 72.73% (8/11) github.com/conformal/btcws/notifications.go RescanProgressNtfn.UnmarshalJSON 72.73% (8/11) +github.com/conformal/btcws/cmds.go NotifyAllNewTXsCmd.UnmarshalJSON 72.73% (8/11) github.com/conformal/btcws/cmds.go GetUnconfirmedBalanceCmd.UnmarshalJSON 72.73% (8/11) +github.com/conformal/btcws/cmds.go GetAddressBalanceCmd.UnmarshalJSON 72.73% (8/11) +github.com/conformal/btcws/cmds.go NotifyNewTXsCmd.UnmarshalJSON 72.73% (8/11) github.com/conformal/btcws/notifications.go RedeemingTxNtfn.UnmarshalJSON 72.73% (8/11) github.com/conformal/btcws/cmds.go GetBestBlockCmd.UnmarshalJSON 72.73% (8/11) -github.com/conformal/btcws/cmds.go NotifyNewTXsCmd.UnmarshalJSON 72.73% (8/11) +github.com/conformal/btcws/notifications.go RecvTxNtfn.UnmarshalJSON 72.73% (8/11) +github.com/conformal/btcws/cmds.go NotifySpentCmd.UnmarshalJSON 72.73% (8/11) +github.com/conformal/btcws/notifications.go BtcdConnectedNtfn.UnmarshalJSON 72.73% (8/11) github.com/conformal/btcws/notifications.go AccountBalanceNtfn.UnmarshalJSON 72.73% (8/11) -github.com/conformal/btcws/notifications.go parseRedeemingTxNtfn 69.23% (18/26) -github.com/conformal/btcws/notifications.go parseRecvTxNtfn 69.23% (18/26) -github.com/conformal/btcws/cmds.go parseNotifySpentCmd 66.67% (10/15) +github.com/conformal/btcws/notifications.go BlockConnectedNtfn.UnmarshalJSON 72.73% (8/11) +github.com/conformal/btcws/cmds.go WalletIsLockedCmd.UnmarshalJSON 72.73% (8/11) +github.com/conformal/btcws/cmds.go ListAddressTransactionsCmd.UnmarshalJSON 72.73% (8/11) +github.com/conformal/btcws/notifications.go AllTxNtfn.UnmarshalJSON 72.73% (8/11) +github.com/conformal/btcws/cmds.go CreateEncryptedWalletCmd.UnmarshalJSON 72.73% (8/11) +github.com/conformal/btcws/cmds.go RescanCmd.UnmarshalJSON 72.73% (8/11) +github.com/conformal/btcws/notifications.go BlockDisconnectedNtfn.UnmarshalJSON 72.73% (8/11) +github.com/conformal/btcws/cmds.go parseRescanCmd 72.22% (13/18) +github.com/conformal/btcws/notifications.go parseRecvTxNtfn 66.67% (8/12) github.com/conformal/btcws/notifications.go AllVerboseTxNtfn.UnmarshalJSON 66.67% (8/12) +github.com/conformal/btcws/notifications.go parseRedeemingTxNtfn 66.67% (8/12) +github.com/conformal/btcws/cmds.go parseNotifyNewTXsCmd 66.67% (4/6) +github.com/conformal/btcws/cmds.go parseNotifySpentCmd 66.67% (4/6) github.com/conformal/btcws/cmds.go parseCreateEncryptedWalletCmd 66.67% (4/6) github.com/conformal/btcws/cmds.go parseGetCurrentNetCmd 66.67% (2/3) github.com/conformal/btcws/cmds.go parseGetBestBlockCmd 66.67% (2/3) github.com/conformal/btcws/notifications.go parseAccountBalanceNtfn 64.29% (9/14) -github.com/conformal/btcws/notifications.go parseAllTxNtfn 63.64% (7/11) github.com/conformal/btcws/notifications.go parseWalletLockStateNtfn 63.64% (7/11) github.com/conformal/btcws/notifications.go parseTxNtfn 63.64% (7/11) github.com/conformal/btcws/notifications.go parseBlockDisconnectedNtfn 63.64% (7/11) github.com/conformal/btcws/notifications.go parseBlockConnectedNtfn 63.64% (7/11) -github.com/conformal/btcws/notifications.go parseBtcdConnectedNtfn 62.50% (5/8) +github.com/conformal/btcws/notifications.go parseAllTxNtfn 63.64% (7/11) github.com/conformal/btcws/notifications.go parseRescanProgressNtfn 62.50% (5/8) +github.com/conformal/btcws/notifications.go parseBtcdConnectedNtfn 62.50% (5/8) github.com/conformal/btcws/cmds.go NewExportWatchingWalletCmd 0.00% (0/15) -github.com/conformal/btcws/cmds.go NotifyBlocksCmd.UnmarshalJSON 0.00% (0/11) +github.com/conformal/btcws/cmds.go parseExportWatchingWalletCmd 0.00% (0/14) +github.com/conformal/btcws/cmds.go ExportWatchingWalletCmd.UnmarshalJSON 0.00% (0/11) github.com/conformal/btcws/cmds.go RecoverAddressesCmd.UnmarshalJSON 0.00% (0/11) github.com/conformal/btcws/cmds.go AuthenticateCmd.UnmarshalJSON 0.00% (0/11) -github.com/conformal/btcws/cmds.go ExportWatchingWalletCmd.UnmarshalJSON 0.00% (0/11) +github.com/conformal/btcws/cmds.go NotifyBlocksCmd.UnmarshalJSON 0.00% (0/11) +github.com/conformal/btcws/cmds.go ExportWatchingWalletCmd.MarshalJSON 0.00% (0/9) github.com/conformal/btcws/cmds.go parseRecoverAddressesCmd 0.00% (0/9) github.com/conformal/btcws/cmds.go parseAuthenticateCmd 0.00% (0/9) -github.com/conformal/btcws/cmds.go ExportWatchingWalletCmd.MarshalJSON 0.00% (0/6) +github.com/conformal/btcws/cmds.go RecoverAddressesCmd.MarshalJSON 0.00% (0/5) +github.com/conformal/btcws/cmds.go AuthenticateCmd.MarshalJSON 0.00% (0/5) +github.com/conformal/btcws/cmds.go NotifyBlocksCmd.MarshalJSON 0.00% (0/4) github.com/conformal/btcws/cmds.go parseNotifyBlocksCmd 0.00% (0/3) -github.com/conformal/btcws/cmds.go RecoverAddressesCmd.MarshalJSON 0.00% (0/2) -github.com/conformal/btcws/cmds.go NotifyBlocksCmd.MarshalJSON 0.00% (0/2) -github.com/conformal/btcws/cmds.go AuthenticateCmd.MarshalJSON 0.00% (0/2) -github.com/conformal/btcws/cmds.go GetUnconfirmedBalanceCmd.SetId 0.00% (0/1) +github.com/conformal/btcws/cmds.go ExportWatchingWalletCmd.SetId 0.00% (0/1) github.com/conformal/btcws/cmds.go NewNotifyBlocksCmd 0.00% (0/1) -github.com/conformal/btcws/cmds.go NotifyBlocksCmd.Id 0.00% (0/1) -github.com/conformal/btcws/cmds.go RescanCmd.SetId 0.00% (0/1) github.com/conformal/btcws/cmds.go NotifyBlocksCmd.Method 0.00% (0/1) -github.com/conformal/btcws/cmds.go NotifyBlocksCmd.SetId 0.00% (0/1) -github.com/conformal/btcws/cmds.go RecoverAddressesCmd.SetId 0.00% (0/1) -github.com/conformal/btcws/cmds.go RecoverAddressesCmd.Id 0.00% (0/1) -github.com/conformal/btcws/cmds.go NotifyNewTXsCmd.SetId 0.00% (0/1) -github.com/conformal/btcws/cmds.go NewRecoverAddressesCmd 0.00% (0/1) -github.com/conformal/btcws/cmds.go ListAddressTransactionsCmd.SetId 0.00% (0/1) -github.com/conformal/btcws/cmds.go GetBestBlockCmd.SetId 0.00% (0/1) +github.com/conformal/btcws/cmds.go RescanCmd.SetId 0.00% (0/1) github.com/conformal/btcws/cmds.go RecoverAddressesCmd.Method 0.00% (0/1) +github.com/conformal/btcws/cmds.go RecoverAddressesCmd.SetId 0.00% (0/1) +github.com/conformal/btcws/cmds.go NewAuthenticateCmd 0.00% (0/1) +github.com/conformal/btcws/cmds.go RecoverAddressesCmd.Id 0.00% (0/1) +github.com/conformal/btcws/cmds.go NewRecoverAddressesCmd 0.00% (0/1) +github.com/conformal/btcws/cmds.go GetBestBlockCmd.SetId 0.00% (0/1) +github.com/conformal/btcws/cmds.go NotifyNewTXsCmd.SetId 0.00% (0/1) github.com/conformal/btcws/cmds.go NotifyAllNewTXsCmd.SetId 0.00% (0/1) -github.com/conformal/btcws/cmds.go ExportWatchingWalletCmd.Id 0.00% (0/1) -github.com/conformal/btcws/cmds.go parseExportWatchingWalletCmd 0.00% (0/1) +github.com/conformal/btcws/cmds.go GetUnconfirmedBalanceCmd.SetId 0.00% (0/1) github.com/conformal/btcws/cmds.go GetAddressBalanceCmd.SetId 0.00% (0/1) +github.com/conformal/btcws/cmds.go ExportWatchingWalletCmd.Method 0.00% (0/1) +github.com/conformal/btcws/cmds.go ExportWatchingWalletCmd.Id 0.00% (0/1) +github.com/conformal/btcws/cmds.go NotifySpentCmd.SetId 0.00% (0/1) +github.com/conformal/btcws/cmds.go NotifyBlocksCmd.Id 0.00% (0/1) +github.com/conformal/btcws/cmds.go CreateEncryptedWalletCmd.SetId 0.00% (0/1) +github.com/conformal/btcws/cmds.go ListAllTransactionsCmd.SetId 0.00% (0/1) github.com/conformal/btcws/cmds.go GetCurrentNetCmd.SetId 0.00% (0/1) github.com/conformal/btcws/cmds.go WalletIsLockedCmd.SetId 0.00% (0/1) -github.com/conformal/btcws/cmds.go ListAllTransactionsCmd.SetId 0.00% (0/1) github.com/conformal/btcws/cmds.go AuthenticateCmd.Method 0.00% (0/1) github.com/conformal/btcws/cmds.go AuthenticateCmd.SetId 0.00% (0/1) github.com/conformal/btcws/cmds.go AuthenticateCmd.Id 0.00% (0/1) -github.com/conformal/btcws/cmds.go NewAuthenticateCmd 0.00% (0/1) -github.com/conformal/btcws/cmds.go CreateEncryptedWalletCmd.SetId 0.00% (0/1) -github.com/conformal/btcws/cmds.go ExportWatchingWalletCmd.Method 0.00% (0/1) -github.com/conformal/btcws/cmds.go ExportWatchingWalletCmd.SetId 0.00% (0/1) -github.com/conformal/btcws/cmds.go NotifySpentCmd.SetId 0.00% (0/1) -github.com/conformal/btcws/notifications.go TxNtfn.SetId 0.00% (0/0) -github.com/conformal/btcws/notifications.go BtcdConnectedNtfn.SetId 0.00% (0/0) -github.com/conformal/btcws/notifications.go RedeemingTxNtfn.SetId 0.00% (0/0) -github.com/conformal/btcws/notifications.go AllVerboseTxNtfn.SetId 0.00% (0/0) +github.com/conformal/btcws/cmds.go NotifyBlocksCmd.SetId 0.00% (0/1) +github.com/conformal/btcws/cmds.go ListAddressTransactionsCmd.SetId 0.00% (0/1) github.com/conformal/btcws/notifications.go AllTxNtfn.SetId 0.00% (0/0) github.com/conformal/btcws/notifications.go RescanProgressNtfn.SetId 0.00% (0/0) -github.com/conformal/btcws/notifications.go RecvTxNtfn.SetId 0.00% (0/0) +github.com/conformal/btcws/notifications.go TxNtfn.SetId 0.00% (0/0) +github.com/conformal/btcws/notifications.go RedeemingTxNtfn.SetId 0.00% (0/0) github.com/conformal/btcws/notifications.go WalletLockStateNtfn.SetId 0.00% (0/0) -github.com/conformal/btcws/notifications.go AccountBalanceNtfn.SetId 0.00% (0/0) github.com/conformal/btcws/notifications.go BlockConnectedNtfn.SetId 0.00% (0/0) +github.com/conformal/btcws/notifications.go BtcdConnectedNtfn.SetId 0.00% (0/0) github.com/conformal/btcws/notifications.go BlockDisconnectedNtfn.SetId 0.00% (0/0) -github.com/conformal/btcws ---------------------------------------- 67.18% (571/850) +github.com/conformal/btcws/notifications.go AllVerboseTxNtfn.SetId 0.00% (0/0) +github.com/conformal/btcws/notifications.go AccountBalanceNtfn.SetId 0.00% (0/0) +github.com/conformal/btcws/notifications.go RecvTxNtfn.SetId 0.00% (0/0) +github.com/conformal/btcws ---------------------------------------- 64.77% (568/877)