github.com/aidoskuneen/adk-node@v0.0.0-20220315131952-2e32567cb7f4/rpc/types.go (about)

     1  // Copyright 2021 The adkgo Authors
     2  // This file is part of the adkgo library (adapted for adkgo from go--ethereum v1.10.8).
     3  //
     4  // the adkgo library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // the adkgo library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the adkgo library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package rpc
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  	"math"
    24  	"strconv"
    25  	"strings"
    26  
    27  	"github.com/aidoskuneen/adk-node/common"
    28  	"github.com/aidoskuneen/adk-node/common/hexutil"
    29  )
    30  
    31  // API describes the set of methods offered over the RPC interface
    32  type API struct {
    33  	Namespace string      // namespace under which the rpc methods of Service are exposed
    34  	Version   string      // api version for DApp's
    35  	Service   interface{} // receiver instance which holds the methods
    36  	Public    bool        // indication if the methods must be considered safe for public use
    37  }
    38  
    39  // ServerCodec implements reading, parsing and writing RPC messages for the server side of
    40  // a RPC session. Implementations must be go-routine safe since the codec can be called in
    41  // multiple go-routines concurrently.
    42  type ServerCodec interface {
    43  	readBatch() (msgs []*jsonrpcMessage, isBatch bool, err error)
    44  	close()
    45  	jsonWriter
    46  }
    47  
    48  // jsonWriter can write JSON messages to its underlying connection.
    49  // Implementations must be safe for concurrent use.
    50  type jsonWriter interface {
    51  	writeJSON(context.Context, interface{}) error
    52  	// Closed returns a channel which is closed when the connection is closed.
    53  	closed() <-chan interface{}
    54  	// RemoteAddr returns the peer address of the connection.
    55  	remoteAddr() string
    56  }
    57  
    58  type BlockNumber int64
    59  
    60  const (
    61  	PendingBlockNumber  = BlockNumber(-2)
    62  	LatestBlockNumber   = BlockNumber(-1)
    63  	EarliestBlockNumber = BlockNumber(0)
    64  )
    65  
    66  // UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports:
    67  // - "latest", "earliest" or "pending" as string arguments
    68  // - the block number
    69  // Returned errors:
    70  // - an invalid block number error when the given argument isn't a known strings
    71  // - an out of range error when the given block number is either too little or too large
    72  func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
    73  	input := strings.TrimSpace(string(data))
    74  	if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' {
    75  		input = input[1 : len(input)-1]
    76  	}
    77  
    78  	switch input {
    79  	case "earliest":
    80  		*bn = EarliestBlockNumber
    81  		return nil
    82  	case "latest":
    83  		*bn = LatestBlockNumber
    84  		return nil
    85  	case "pending":
    86  		*bn = PendingBlockNumber
    87  		return nil
    88  	}
    89  
    90  	blckNum, err := hexutil.DecodeUint64(input)
    91  	if err != nil {
    92  		return err
    93  	}
    94  	if blckNum > math.MaxInt64 {
    95  		return fmt.Errorf("block number larger than int64")
    96  	}
    97  	*bn = BlockNumber(blckNum)
    98  	return nil
    99  }
   100  
   101  func (bn BlockNumber) Int64() int64 {
   102  	return (int64)(bn)
   103  }
   104  
   105  type BlockNumberOrHash struct {
   106  	BlockNumber      *BlockNumber `json:"blockNumber,omitempty"`
   107  	BlockHash        *common.Hash `json:"blockHash,omitempty"`
   108  	RequireCanonical bool         `json:"requireCanonical,omitempty"`
   109  }
   110  
   111  func (bnh *BlockNumberOrHash) UnmarshalJSON(data []byte) error {
   112  	type erased BlockNumberOrHash
   113  	e := erased{}
   114  	err := json.Unmarshal(data, &e)
   115  	if err == nil {
   116  		if e.BlockNumber != nil && e.BlockHash != nil {
   117  			return fmt.Errorf("cannot specify both BlockHash and BlockNumber, choose one or the other")
   118  		}
   119  		bnh.BlockNumber = e.BlockNumber
   120  		bnh.BlockHash = e.BlockHash
   121  		bnh.RequireCanonical = e.RequireCanonical
   122  		return nil
   123  	}
   124  	var input string
   125  	err = json.Unmarshal(data, &input)
   126  	if err != nil {
   127  		return err
   128  	}
   129  	switch input {
   130  	case "earliest":
   131  		bn := EarliestBlockNumber
   132  		bnh.BlockNumber = &bn
   133  		return nil
   134  	case "latest":
   135  		bn := LatestBlockNumber
   136  		bnh.BlockNumber = &bn
   137  		return nil
   138  	case "pending":
   139  		bn := PendingBlockNumber
   140  		bnh.BlockNumber = &bn
   141  		return nil
   142  	default:
   143  		if len(input) == 66 {
   144  			hash := common.Hash{}
   145  			err := hash.UnmarshalText([]byte(input))
   146  			if err != nil {
   147  				return err
   148  			}
   149  			bnh.BlockHash = &hash
   150  			return nil
   151  		} else {
   152  			blckNum, err := hexutil.DecodeUint64(input)
   153  			if err != nil {
   154  				return err
   155  			}
   156  			if blckNum > math.MaxInt64 {
   157  				return fmt.Errorf("blocknumber too high")
   158  			}
   159  			bn := BlockNumber(blckNum)
   160  			bnh.BlockNumber = &bn
   161  			return nil
   162  		}
   163  	}
   164  }
   165  
   166  func (bnh *BlockNumberOrHash) Number() (BlockNumber, bool) {
   167  	if bnh.BlockNumber != nil {
   168  		return *bnh.BlockNumber, true
   169  	}
   170  	return BlockNumber(0), false
   171  }
   172  
   173  func (bnh *BlockNumberOrHash) Hash() (common.Hash, bool) {
   174  	if bnh.BlockHash != nil {
   175  		return *bnh.BlockHash, true
   176  	}
   177  	return common.Hash{}, false
   178  }
   179  
   180  func BlockNumberOrHashWithNumber(blockNr BlockNumber) BlockNumberOrHash {
   181  	return BlockNumberOrHash{
   182  		BlockNumber:      &blockNr,
   183  		BlockHash:        nil,
   184  		RequireCanonical: false,
   185  	}
   186  }
   187  
   188  func BlockNumberOrHashWithHash(hash common.Hash, canonical bool) BlockNumberOrHash {
   189  	return BlockNumberOrHash{
   190  		BlockNumber:      nil,
   191  		BlockHash:        &hash,
   192  		RequireCanonical: canonical,
   193  	}
   194  }
   195  
   196  // DecimalOrHex unmarshals a non-negative decimal or hex parameter into a uint64.
   197  type DecimalOrHex uint64
   198  
   199  // UnmarshalJSON implements json.Unmarshaler.
   200  func (dh *DecimalOrHex) UnmarshalJSON(data []byte) error {
   201  	input := strings.TrimSpace(string(data))
   202  	if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' {
   203  		input = input[1 : len(input)-1]
   204  	}
   205  
   206  	value, err := strconv.ParseUint(input, 10, 64)
   207  	if err != nil {
   208  		value, err = hexutil.DecodeUint64(input)
   209  	}
   210  	if err != nil {
   211  		return err
   212  	}
   213  	*dh = DecimalOrHex(value)
   214  	return nil
   215  }