lbcd/notifications.go

257 lines
6.6 KiB
Go

// Copyright (c) 2013 Conformal Systems LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcws
import (
"encoding/json"
"errors"
"github.com/conformal/btcjson"
)
var (
// ErrNtfnUnexpected describes an error where an unexpected
// notification is received when unmarshaling into a concrete
// Notification variable.
ErrNtfnUnexpected = errors.New("notification unexpected")
// ErrNtfnNotFound describes an error where a parser does not
// handle unmarshaling a notification.
ErrNtfnNotFound = errors.New("notification not found")
)
const (
// BlockConnectedNtfnId is the id of the btcd blockconnected
// notification.
BlockConnectedNtfnId = "btcd:blockconnected"
// BlockDisconnectedNtfnId is the id of the btcd blockdisconnected
// notification.
BlockDisconnectedNtfnId = "btcd:blockdisconnected"
//TxMinedNtfnId is the id of the btcd txmined notification.
TxMinedNtfnId = "btcd:txmined"
)
type newNtfnFn func() Notification
func newBlockConnectedNtfn() Notification {
return &BlockConnectedNtfn{}
}
func newBlockDisconnectedNtfn() Notification {
return &BlockDisconnectedNtfn{}
}
func newTxMinedNtfn() Notification {
return &TxMinedNtfn{}
}
var newNtfnFns = map[string]newNtfnFn{
BlockConnectedNtfnId: newBlockConnectedNtfn,
BlockDisconnectedNtfnId: newBlockDisconnectedNtfn,
TxMinedNtfnId: newTxMinedNtfn,
}
// ParseMarshaledNtfn attempts to unmarshal a marshaled notification
// into the notification described by id.
func ParseMarshaledNtfn(id string, b []byte) (Notification, error) {
if newFn, ok := newNtfnFns[id]; ok {
n := newFn()
if err := n.UnmarshalJSON(b); err != nil {
return nil, err
}
return n, nil
}
return nil, ErrNtfnNotFound
}
// Notification is an interface implemented by all notification types.
type Notification interface {
json.Marshaler
json.Unmarshaler
Id() interface{}
}
// BlockConnectedNtfn is a type handling custom marshaling and
// unmarshaling of blockconnected JSON websocket notifications.
type BlockConnectedNtfn struct {
Hash string `json:"hash"`
Height int32 `json:"height"`
}
type blockConnectedResult BlockConnectedNtfn
// Enforce that BlockConnectedNtfn satisfies the Notification interface.
var _ Notification = &BlockConnectedNtfn{}
// NewBlockConnectedNtfn creates a new BlockConnectedNtfn.
func NewBlockConnectedNtfn(hash string, height int32) *BlockConnectedNtfn {
return &BlockConnectedNtfn{
Hash: hash,
Height: height,
}
}
// Id satisifies the Notification interface by returning the id of the
// notification.
func (n *BlockConnectedNtfn) Id() interface{} {
return BlockConnectedNtfnId
}
// MarshalJSON returns the JSON encoding of n. Part of the Notification
// interface.
func (n *BlockConnectedNtfn) MarshalJSON() ([]byte, error) {
id := n.Id()
reply := btcjson.Reply{
Result: *n,
Id: &id,
}
return json.Marshal(reply)
}
// UnmarshalJSON unmarshals the JSON encoding of n into n. Part of
// the Notification interface.
func (n *BlockConnectedNtfn) UnmarshalJSON(b []byte) error {
var ntfn struct {
Result blockConnectedResult `json:"result"`
Error *btcjson.Error `json:"error"`
Id interface{} `json:"id"`
}
if err := json.Unmarshal(b, &ntfn); err != nil {
return err
}
// Notification IDs must match expected.
if n.Id() != ntfn.Id {
return ErrNtfnUnexpected
}
*n = BlockConnectedNtfn(ntfn.Result)
return nil
}
// BlockDisconnectedNtfn is a type handling custom marshaling and
// unmarshaling of blockdisconnected JSON websocket notifications.
type BlockDisconnectedNtfn struct {
Hash string `json:"hash"`
Height int32 `json:"height"`
}
type blockDisconnectedResult BlockDisconnectedNtfn
// Enforce that BlockDisconnectedNtfn satisfies the Notification interface.
var _ Notification = &BlockDisconnectedNtfn{}
// NewBlockDisconnectedNtfn creates a new BlockConnectedNtfn.
func NewBlockDisconnectedNtfn(hash string, height int32) *BlockDisconnectedNtfn {
return &BlockDisconnectedNtfn{
Hash: hash,
Height: height,
}
}
// Id satisifies the Notification interface by returning the id of the
// notification.
func (n *BlockDisconnectedNtfn) Id() interface{} {
return BlockDisconnectedNtfnId
}
// MarshalJSON returns the JSON encoding of n. Part of the Notification
// interface.
func (n *BlockDisconnectedNtfn) MarshalJSON() ([]byte, error) {
id := n.Id()
reply := btcjson.Reply{
Result: *n,
Id: &id,
}
return json.Marshal(reply)
}
// UnmarshalJSON unmarshals the JSON encoding of n into n. Part of
// the Notification interface.
func (n *BlockDisconnectedNtfn) UnmarshalJSON(b []byte) error {
var ntfn struct {
Result blockDisconnectedResult `json:"result"`
Error *btcjson.Error `json:"error"`
Id interface{} `json:"id"`
}
if err := json.Unmarshal(b, &ntfn); err != nil {
return err
}
// Notification IDs must match expected.
if n.Id() != ntfn.Id {
return ErrNtfnUnexpected
}
*n = BlockDisconnectedNtfn(ntfn.Result)
return nil
}
// TxMinedNtfn is a type handling custom marshaling and
// unmarshaling of txmined JSON websocket notifications.
type TxMinedNtfn struct {
TxID string `json:"txid"`
BlockHash string `json:"blockhash"`
BlockHeight int32 `json:"blockheight"`
BlockTime int64 `json:"blocktime"`
Index int `json:"index"`
}
type txMinedResult TxMinedNtfn
// Enforce that TxMinedNtfn satisfies the Notification interface.
var _ Notification = &TxMinedNtfn{}
// NewTxMinedNtfn creates a new TxMinedNtfn.
func NewTxMinedNtfn(txid, blockhash string, blockheight int32,
blocktime int64, index int) *TxMinedNtfn {
return &TxMinedNtfn{
TxID: txid,
BlockHash: blockhash,
BlockHeight: blockheight,
BlockTime: blocktime,
Index: index,
}
}
// Id satisifies the Notification interface by returning the id of the
// notification.
func (n *TxMinedNtfn) Id() interface{} {
return TxMinedNtfnId
}
// MarshalJSON returns the JSON encoding of n. Part of the Notification
// interface.
func (n *TxMinedNtfn) MarshalJSON() ([]byte, error) {
id := n.Id()
reply := btcjson.Reply{
Result: *n,
Id: &id,
}
return json.Marshal(reply)
}
// UnmarshalJSON unmarshals the JSON encoding of n into n. Part of
// the Notification interface.
func (n *TxMinedNtfn) UnmarshalJSON(b []byte) error {
var ntfn struct {
Result txMinedResult `json:"result"`
Error *btcjson.Error `json:"error"`
Id interface{} `json:"id"`
}
if err := json.Unmarshal(b, &ntfn); err != nil {
return err
}
// Notification IDs must match expected.
if n.Id() != ntfn.Id {
return ErrNtfnUnexpected
}
*n = TxMinedNtfn(ntfn.Result)
return nil
}