blockbook/bchain/coins/btc/codec.go

91 lines
1.7 KiB
Go

package btc
import (
"encoding/json"
"errors"
"reflect"
)
type RPCMarshaler interface {
Marshal(v interface{}) ([]byte, error)
}
type JSONMarshalerV2 struct{}
func (JSONMarshalerV2) Marshal(v interface{}) ([]byte, error) {
d, err := json.Marshal(v)
if err != nil {
return nil, err
}
return d, nil
}
var InvalidValue = errors.New("Invalid value to marshal")
type JSONMarshalerV1 struct{}
func (JSONMarshalerV1) Marshal(v interface{}) ([]byte, error) {
u := cmdUntypedParams{}
switch v := v.(type) {
case *CmdGetBlock:
var t bool
if v.Params.Verbosity > 0 {
t = true
}
u.Method = v.Method
u.Params = append(u.Params, v.Params.BlockHash)
u.Params = append(u.Params, t)
case *CmdGetRawTransaction:
var n int
if v.Params.Verbose {
n = 1
}
u.Method = v.Method
u.Params = append(u.Params, v.Params.Txid)
u.Params = append(u.Params, n)
default:
{
v := reflect.ValueOf(v).Elem()
f := v.FieldByName("Method")
if !f.IsValid() || f.Kind() != reflect.String {
return nil, InvalidValue
}
u.Method = f.String()
f = v.FieldByName("Params")
if f.IsValid() {
var arr []interface{}
switch f.Kind() {
case reflect.Slice:
arr = make([]interface{}, f.Len())
for i := 0; i < f.Len(); i++ {
arr[i] = f.Index(i).Interface()
}
case reflect.Struct:
arr = make([]interface{}, f.NumField())
for i := 0; i < f.NumField(); i++ {
arr[i] = f.Field(i).Interface()
}
default:
return nil, InvalidValue
}
u.Params = arr
}
}
}
d, err := json.Marshal(u)
if err != nil {
return nil, err
}
return d, nil
}
type cmdUntypedParams struct {
Method string `json:"method"`
Params []interface{} `json:"params,omitempty"`
}