package rpc import ( "bytes" "encoding/hex" "encoding/json" "fmt" "github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/util" "github.com/pkg/errors" ) type ( // Param represents a param either passed to // the server or to send to a server using // the client. Param struct { Type paramType Value interface{} } paramType int // FuncParam represents a function argument parameter used in the // invokefunction RPC method. FuncParam struct { Type StackParamType `json:"type"` Value Param `json:"value"` } ) const ( defaultT paramType = iota stringT numberT arrayT funcParamT ) func (p Param) String() string { return fmt.Sprintf("%v", p.Value) } // GetString returns string value of the parameter. func (p Param) GetString() (string, error) { str, ok := p.Value.(string) if !ok { return "", errors.New("not a string") } return str, nil } // GetInt returns int value of te parameter. func (p Param) GetInt() (int, error) { i, ok := p.Value.(int) if !ok { return 0, errors.New("not an integer") } return i, nil } // GetArray returns a slice of Params stored in the parameter. func (p Param) GetArray() ([]Param, error) { a, ok := p.Value.([]Param) if !ok { return nil, errors.New("not an array") } return a, nil } // GetUint256 returns Uint256 value of the parameter. func (p Param) GetUint256() (util.Uint256, error) { s, err := p.GetString() if err != nil { return util.Uint256{}, err } return util.Uint256DecodeReverseString(s) } // GetUint160FromHex returns Uint160 value of the parameter encoded in hex. func (p Param) GetUint160FromHex() (util.Uint160, error) { s, err := p.GetString() if err != nil { return util.Uint160{}, err } scriptHashLE, err := util.Uint160DecodeString(s) if err != nil { return util.Uint160{}, err } return util.Uint160DecodeBytes(scriptHashLE.BytesReverse()) } // GetUint160FromAddress returns Uint160 value of the parameter that was // supplied as an address. func (p Param) GetUint160FromAddress() (util.Uint160, error) { s, err := p.GetString() if err != nil { return util.Uint160{}, err } return crypto.Uint160DecodeAddress(s) } // GetFuncParam returns current parameter as a function call parameter. func (p Param) GetFuncParam() (FuncParam, error) { fp, ok := p.Value.(FuncParam) if !ok { return FuncParam{}, errors.New("not a function parameter") } return fp, nil } // GetBytesHex returns []byte value of the parameter if // it is a hex-encoded string. func (p Param) GetBytesHex() ([]byte, error) { s, err := p.GetString() if err != nil { return nil, err } return hex.DecodeString(s) } // UnmarshalJSON implements json.Unmarshaler interface. func (p *Param) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err == nil { p.Type = stringT p.Value = s return nil } var num float64 if err := json.Unmarshal(data, &num); err == nil { p.Type = numberT p.Value = int(num) return nil } r := bytes.NewReader(data) jd := json.NewDecoder(r) jd.DisallowUnknownFields() var fp FuncParam if err := jd.Decode(&fp); err == nil { p.Type = funcParamT p.Value = fp return nil } var ps []Param if err := json.Unmarshal(data, &ps); err == nil { p.Type = arrayT p.Value = ps return nil } return errors.New("unknown type") }