Added commands to support notifyallnewtxs
Sending NotifyAllNewTXsCmd will register websocket client to receive notifications on all new transactions. Once registered the client will receive either AllTxNtfn or AllVerboseTxNtfn based on the required verbose field in the NotifyAllNewTXsCmd.
This commit is contained in:
parent
3cba42282e
commit
07c403efd0
4 changed files with 313 additions and 0 deletions
86
cmds.go
86
cmds.go
|
@ -43,6 +43,8 @@ func init() {
|
|||
`TODO(jrick) fillmein`)
|
||||
btcjson.RegisterCustomCmd("notifynewtxs", parseNotifyNewTXsCmd,
|
||||
`TODO(jrick) fillmein`)
|
||||
btcjson.RegisterCustomCmd("notifyallnewtxs", parseNotifyAllNewTXsCmd,
|
||||
`TODO(flam) fillmein`)
|
||||
btcjson.RegisterCustomCmd("notifyspent", parseNotifySpentCmd,
|
||||
`TODO(jrick) fillmein`)
|
||||
btcjson.RegisterCustomCmd("recoveraddresses", parseRecoverAddressesCmd,
|
||||
|
@ -902,6 +904,90 @@ func (cmd *NotifyNewTXsCmd) UnmarshalJSON(b []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// NotifyAllNewTXsCmd is a type handling custom marshaling and
|
||||
// unmarshaling of notifynewtxs JSON websocket extension
|
||||
// commands.
|
||||
type NotifyAllNewTXsCmd struct {
|
||||
id interface{}
|
||||
Verbose bool
|
||||
}
|
||||
|
||||
// Enforce that NotifyAllNewTXsCmd satisifies the btcjson.Cmd interface.
|
||||
var _ btcjson.Cmd = &NotifyAllNewTXsCmd{}
|
||||
|
||||
// NewNotifyAllNewTXsCmd creates a new NotifyAllNewTXsCmd.
|
||||
func NewNotifyAllNewTXsCmd(id interface{}, verbose bool) *NotifyAllNewTXsCmd {
|
||||
return &NotifyAllNewTXsCmd{
|
||||
id: id,
|
||||
Verbose: verbose,
|
||||
}
|
||||
}
|
||||
|
||||
// parseNotifyAllNewTXsCmd parses a NotifyAllNewTXsCmd into a concrete type
|
||||
// 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) {
|
||||
if len(r.Params) != 1 {
|
||||
return nil, btcjson.ErrWrongNumberOfParams
|
||||
}
|
||||
|
||||
verbose := r.Params[0].(bool)
|
||||
|
||||
return NewNotifyAllNewTXsCmd(r.Id, verbose), nil
|
||||
}
|
||||
|
||||
// Id satisifies the Cmd interface by returning the ID of the command.
|
||||
func (cmd *NotifyAllNewTXsCmd) Id() interface{} {
|
||||
return cmd.id
|
||||
}
|
||||
|
||||
// SetId satisifies the Cmd interface by setting the ID of the command.
|
||||
func (cmd *NotifyAllNewTXsCmd) SetId(id interface{}) {
|
||||
cmd.id = id
|
||||
}
|
||||
|
||||
// Method satisfies the Cmd interface by returning the RPC method.
|
||||
func (cmd *NotifyAllNewTXsCmd) Method() string {
|
||||
return "notifyallnewtxs"
|
||||
}
|
||||
|
||||
// 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,
|
||||
},
|
||||
}
|
||||
|
||||
return json.Marshal(raw)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals the JSON encoding of cmd into cmd. Part of
|
||||
// the Cmd interface.
|
||||
func (cmd *NotifyAllNewTXsCmd) UnmarshalJSON(b []byte) error {
|
||||
// Unmarshal into a RawCmd.
|
||||
var r btcjson.RawCmd
|
||||
if err := json.Unmarshal(b, &r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newCmd, err := parseNotifyAllNewTXsCmd(&r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
concreteCmd, ok := newCmd.(*NotifyAllNewTXsCmd)
|
||||
if !ok {
|
||||
return btcjson.ErrInternal
|
||||
}
|
||||
*cmd = *concreteCmd
|
||||
return nil
|
||||
}
|
||||
|
||||
// NotifySpentCmd is a type handling custom marshaling and
|
||||
// unmarshaling of notifyspent JSON websocket extension
|
||||
// commands.
|
||||
|
|
12
cmds_test.go
12
cmds_test.go
|
@ -173,6 +173,18 @@ var cmdtests = []struct {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "notifyallnewtxs",
|
||||
f: func() (btcjson.Cmd, error) {
|
||||
return NewNotifyAllNewTXsCmd(
|
||||
float64(1),
|
||||
true), nil
|
||||
},
|
||||
result: &NotifyAllNewTXsCmd{
|
||||
id: float64(1),
|
||||
Verbose: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "notifyspent",
|
||||
f: func() (btcjson.Cmd, error) {
|
||||
|
|
184
notifications.go
184
notifications.go
|
@ -38,6 +38,14 @@ const (
|
|||
// processedtx notification.
|
||||
ProcessedTxNtfnMethod = "processedtx"
|
||||
|
||||
// AllTxNtfnMethod is the method of the btcd alltx
|
||||
// notification
|
||||
AllTxNtfnMethod = "alltx"
|
||||
|
||||
// AllVerboseTxNtfnMethod is the method of the btcd
|
||||
// allverbosetx notifications.
|
||||
AllVerboseTxNtfnMethod = "allverbosetx"
|
||||
|
||||
// TxMinedNtfnMethod is the method of the btcd txmined
|
||||
// notification.
|
||||
TxMinedNtfnMethod = "txmined"
|
||||
|
@ -75,6 +83,10 @@ func init() {
|
|||
`TODO(jrick) fillmein`)
|
||||
btcjson.RegisterCustomCmd(WalletLockStateNtfnMethod,
|
||||
parseWalletLockStateNtfn, `TODO(jrick) fillmein`)
|
||||
btcjson.RegisterCustomCmd(AllTxNtfnMethod,
|
||||
parseAllTxNtfn, `TODO(flam) fillmein`)
|
||||
btcjson.RegisterCustomCmdGenerator(AllVerboseTxNtfnMethod,
|
||||
generateAllVerboseTxNtfn)
|
||||
}
|
||||
|
||||
// AccountBalanceNtfn is a type handling custom marshaling and
|
||||
|
@ -1015,3 +1027,175 @@ func (n *WalletLockStateNtfn) UnmarshalJSON(b []byte) error {
|
|||
*n = *concreteNtfn
|
||||
return nil
|
||||
}
|
||||
|
||||
// AllTxNtfn is a type handling custom marshaling and
|
||||
// unmarshaling of txmined JSON websocket notifications.
|
||||
type AllTxNtfn struct {
|
||||
TxID string
|
||||
Amount int64
|
||||
}
|
||||
|
||||
// Enforce that AllTxNtfn satisifies the btcjson.Cmd interface.
|
||||
var _ btcjson.Cmd = &AllTxNtfn{}
|
||||
|
||||
// NewAllTxNtfn creates a new AllTxNtfn.
|
||||
func NewAllTxNtfn(txid string, amount int64) *AllTxNtfn {
|
||||
return &AllTxNtfn{
|
||||
TxID: txid,
|
||||
Amount: amount,
|
||||
}
|
||||
}
|
||||
|
||||
// parseAllTxNtfn parses a RawCmd into a concrete type satisifying
|
||||
// the btcjson.Cmd interface. This is used when registering the notification
|
||||
// with the btcjson parser.
|
||||
func parseAllTxNtfn(r *btcjson.RawCmd) (btcjson.Cmd, error) {
|
||||
if r.Id != nil {
|
||||
return nil, ErrNotANtfn
|
||||
}
|
||||
|
||||
if len(r.Params) != 2 {
|
||||
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")
|
||||
}
|
||||
|
||||
return NewAllTxNtfn(txid, int64(famount)), nil
|
||||
}
|
||||
|
||||
// Id satisifies the btcjson.Cmd interface by returning nil for a
|
||||
// notification ID.
|
||||
func (n *AllTxNtfn) Id() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetId is implemented to satisify the btcjson.Cmd interface. The
|
||||
// notification id is not modified.
|
||||
func (n *AllTxNtfn) SetId(id interface{}) {}
|
||||
|
||||
// Method satisifies the btcjson.Cmd interface by returning the method
|
||||
// of the notification.
|
||||
func (n *AllTxNtfn) Method() string {
|
||||
return AllTxNtfnMethod
|
||||
}
|
||||
|
||||
// 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,
|
||||
},
|
||||
}
|
||||
return json.Marshal(ntfn)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals the JSON encoding of n into n. Part of
|
||||
// the btcjson.Cmd interface.
|
||||
func (n *AllTxNtfn) UnmarshalJSON(b []byte) error {
|
||||
// Unmarshal into a RawCmd.
|
||||
var r btcjson.RawCmd
|
||||
if err := json.Unmarshal(b, &r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newNtfn, err := parseAllTxNtfn(&r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
concreteNtfn, ok := newNtfn.(*AllTxNtfn)
|
||||
if !ok {
|
||||
return btcjson.ErrInternal
|
||||
}
|
||||
*n = *concreteNtfn
|
||||
return nil
|
||||
}
|
||||
|
||||
// AllVerboseTxNtfn is a type handling custom marshaling and
|
||||
// unmarshaling of txmined JSON websocket notifications.
|
||||
type AllVerboseTxNtfn struct {
|
||||
RawTx *btcjson.TxRawResult
|
||||
}
|
||||
|
||||
// Enforce that AllTxNtfn satisifies the btcjson.Cmd interface.
|
||||
var _ btcjson.Cmd = &AllVerboseTxNtfn{}
|
||||
|
||||
// NewAllVerboseTxNtfn creates a new AllVerboseTxNtfn.
|
||||
func NewAllVerboseTxNtfn(rawTx *btcjson.TxRawResult) *AllVerboseTxNtfn {
|
||||
return &AllVerboseTxNtfn{
|
||||
RawTx: rawTx,
|
||||
}
|
||||
}
|
||||
|
||||
// Id satisifies the btcjson.Cmd interface by returning nil for a
|
||||
// notification ID.
|
||||
func (n *AllVerboseTxNtfn) Id() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetId is implemented to satisify the btcjson.Cmd interface. The
|
||||
// notification id is not modified.
|
||||
func (n *AllVerboseTxNtfn) SetId(id interface{}) {}
|
||||
|
||||
// Method satisifies the btcjson.Cmd interface by returning the method
|
||||
// of the notification.
|
||||
func (n *AllVerboseTxNtfn) Method() string {
|
||||
return AllVerboseTxNtfnMethod
|
||||
}
|
||||
|
||||
// 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,
|
||||
},
|
||||
}
|
||||
return json.Marshal(ntfn)
|
||||
}
|
||||
|
||||
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
|
||||
if err := json.Unmarshal(b, &r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(r.Params) != 1 {
|
||||
return btcjson.ErrWrongNumberOfParams
|
||||
}
|
||||
|
||||
var rawTx *btcjson.TxRawResult
|
||||
if err := json.Unmarshal(*r.Params[0], &rawTx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*n = *NewAllVerboseTxNtfn(rawTx)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -154,6 +154,37 @@ var ntfntests = []struct {
|
|||
Locked: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "alltx",
|
||||
f: func() btcjson.Cmd {
|
||||
return btcws.NewAllTxNtfn(
|
||||
"062f2b5f7d28c787e0f3aee382132241cd590efb7b83bd2c7f506de5aa4ef275",
|
||||
34567765)
|
||||
},
|
||||
result: &btcws.AllTxNtfn{
|
||||
TxID: "062f2b5f7d28c787e0f3aee382132241cd590efb7b83bd2c7f506de5aa4ef275",
|
||||
Amount: 34567765,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "allverbosetx",
|
||||
f: func() btcjson.Cmd {
|
||||
return btcws.NewAllVerboseTxNtfn(&btcjson.TxRawResult{
|
||||
Hex: "01000000010cdf900074a3622499a2f28f44a94476f27a8900a2bdd60e042754b6cab09741000000008a473044022012e11012fad1eb21ba1c82deb8da98778b08e714b72f281293064528343fae0502204294d7520f469f9673087a55395de0ce0e9074dce236db9fe7f30013b5fd00b90141047b6ff7832b4a763666e5481a0bd9eedb656d9f882d215c16fe9563d7b191cd67b2a41601a853a9f9d92773ae6f912ef451a089148e510623759cf55c408efdefffffffff02f4063f00000000001976a914b269e0ceec5d5b5e192cf580ae42341e0f79b0b588aca8c84b02000000001976a91439233c0d43a1411e547c60bad8985bae3530b6af88ac00000000",
|
||||
Txid: "0cfeb968fb5d0f6b9a2a1de37c0607a1964dd3e335f203377cec90e03b20869e",
|
||||
Version: 0x1,
|
||||
LockTime: 0x0,
|
||||
})
|
||||
},
|
||||
result: &btcws.AllVerboseTxNtfn{
|
||||
RawTx: &btcjson.TxRawResult{
|
||||
Hex: "01000000010cdf900074a3622499a2f28f44a94476f27a8900a2bdd60e042754b6cab09741000000008a473044022012e11012fad1eb21ba1c82deb8da98778b08e714b72f281293064528343fae0502204294d7520f469f9673087a55395de0ce0e9074dce236db9fe7f30013b5fd00b90141047b6ff7832b4a763666e5481a0bd9eedb656d9f882d215c16fe9563d7b191cd67b2a41601a853a9f9d92773ae6f912ef451a089148e510623759cf55c408efdefffffffff02f4063f00000000001976a914b269e0ceec5d5b5e192cf580ae42341e0f79b0b588aca8c84b02000000001976a91439233c0d43a1411e547c60bad8985bae3530b6af88ac00000000",
|
||||
Txid: "0cfeb968fb5d0f6b9a2a1de37c0607a1964dd3e335f203377cec90e03b20869e",
|
||||
Version: 0x1,
|
||||
LockTime: 0x0,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestNtfns(t *testing.T) {
|
||||
|
|
Loading…
Add table
Reference in a new issue