github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/rpcclient/rpc_test.go (about)

     1  package rpcclient
     2  
     3  import (
     4  	"context"
     5  	"encoding/base64"
     6  	"encoding/hex"
     7  	"encoding/json"
     8  	"fmt"
     9  	"math/big"
    10  	"net/http"
    11  	"net/http/httptest"
    12  	"strings"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/gorilla/websocket"
    17  	"github.com/nspcc-dev/neo-go/internal/testserdes"
    18  	"github.com/nspcc-dev/neo-go/pkg/config"
    19  	"github.com/nspcc-dev/neo-go/pkg/config/netmode"
    20  	"github.com/nspcc-dev/neo-go/pkg/core/block"
    21  	"github.com/nspcc-dev/neo-go/pkg/core/state"
    22  	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
    23  	"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
    24  	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
    25  	"github.com/nspcc-dev/neo-go/pkg/encoding/address"
    26  	"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
    27  	"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
    28  	"github.com/nspcc-dev/neo-go/pkg/io"
    29  	"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
    30  	"github.com/nspcc-dev/neo-go/pkg/services/rpcsrv/params"
    31  	"github.com/nspcc-dev/neo-go/pkg/smartcontract"
    32  	"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
    33  	"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
    34  	"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
    35  	"github.com/nspcc-dev/neo-go/pkg/util"
    36  	"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
    37  	"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
    38  	"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
    39  	"github.com/stretchr/testify/assert"
    40  	"github.com/stretchr/testify/require"
    41  )
    42  
    43  type rpcClientTestCase struct {
    44  	name           string
    45  	invoke         func(c *Client) (any, error)
    46  	fails          bool
    47  	serverResponse string
    48  	result         func(c *Client) any
    49  	check          func(t *testing.T, c *Client, result any)
    50  }
    51  
    52  const base64B1 = "AAAAAMSdeyVO3QCekJTbQ4D7YEEGFv2nXPd6CfO5Kn3htI8P9tVA4+VXLyyMG12BUj6qB3CZ+JIFwWCcDF+KBHH0VSjJICSkegEAAAAAAAAAAAAAAQAAAABouegejA5skHm0udEF6HinbT8iPwHGDEBg0hpK90iZlB4ZSCG7BOr7BsvPXGDax360lvqKeNFuzaGI1RYNH50/dhQLxocy90JdsIOyodd1sOJGEjZIt7ztDEAHc2avJzz6tK+FOQMIZO/FEEikJdLJX0+iZXFcsmDRpB7lo2wWMSQbcoTXNg7leuR0VeDsKJ+YdvCuTG5WbiqWDECa6Yjj+bK4te5KR5jdLF5kLt03csyozZcd/X7NPt89IsX01zpX8ec3e+B2qySJIOhEf3cK0i+5U5wyXiFcRI8xkxMMIQIQOn990BZVhZf3lg0nxRakOU/ZaLnmUVXrSwE+QEBAbgwhAqe8Vf6GhOARl2jRBLoweVvcyGYZ6GSt0mFWcj7Rhc1iDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIMIQPZDAffY+aQzneRLhCrUazJRLZoYCN7YIxPj4MJ5x7mmRRBntDcOgIAAgAAAMDYpwAAAAAADHlDAAAAAACwBAAAAWi56B6MDmyQebS50QXoeKdtPyI/AQBbCwIY3fUFDBTunqIsJ+NL0BSPxBCOCPdOj1BIsgwUaLnoHowObJB5tLnRBeh4p20/Ij8UwB8MCHRyYW5zZmVyDBT1Y+pAvCg9TQ4FxI6jBbPyoHNA70FifVtSOQHGDEC8InWg8rQHWjklRojobu7kn4r0xZY2xWYs15ggVX4PQyEHpNTU6vZHT2TXRdPXAOKHhgWAttO0oTvo+9VZAjIVDEBF0qvBMlvmYJIYLqSoCjhBykcSN78UXrBjO5BKL8BpHtejWCld1VT6Z7nYrEBLgySD6HeMcp/fa6vqHzU220e/DECXtm5AA1jy9GFA7t8U6a+1uPrQFk4Ufp0UyXsun0PvN0NdhrHc37xm8k9Z0dB85V/7WLtkMaLLyjVNVIKImC76kxMMIQIQOn990BZVhZf3lg0nxRakOU/ZaLnmUVXrSwE+QEBAbgwhAqe8Vf6GhOARl2jRBLoweVvcyGYZ6GSt0mFWcj7Rhc1iDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIMIQPZDAffY+aQzneRLhCrUazJRLZoYCN7YIxPj4MJ5x7mmRRBntDcOgADAAAAwNinAAAAAACsiEMAAAAAALAEAAABaLnoHowObJB5tLnRBeh4p20/Ij8BAF8LAwDodkgXAAAADBTunqIsJ+NL0BSPxBCOCPdOj1BIsgwUaLnoHowObJB5tLnRBeh4p20/Ij8UwB8MCHRyYW5zZmVyDBTPduKL0AYsSkeO41VhARMZ88+k0kFifVtSOQHGDEDgj/SQT84EbWRZ4ZKhyjJTuLwVPDgVlQO3CGmgacItvni9nziJvTxziZXBG/0Hqkv68ddS1EH94RtWlqLQWRCjDEAWZUeSQ8KskILSvoWPN3836xpg/TYzOGiFVoePv91CFnap4fRFxdbporBgnZ/sUsjFZ74U8f+r0riqtvkdMMyGDEDx5iho79oDVYOCwIDH3K1UeDjAT6Hq9YsD9SCfJSE1rRsAdJPh2StYxdh9Jah1lwGbW0U+Wu6zpbVFf5CS6fFckxMMIQIQOn990BZVhZf3lg0nxRakOU/ZaLnmUVXrSwE+QEBAbgwhAqe8Vf6GhOARl2jRBLoweVvcyGYZ6GSt0mFWcj7Rhc1iDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIMIQPZDAffY+aQzneRLhCrUazJRLZoYCN7YIxPj4MJ5x7mmRRBntDcOg=="
    53  
    54  const base64TxMoveNeo = "AAIAAADA2KcAAAAAAAx5QwAAAAAAsAQAAAFouegejA5skHm0udEF6HinbT8iPwEAWwsCGN31BQwU7p6iLCfjS9AUj8QQjgj3To9QSLIMFGi56B6MDmyQebS50QXoeKdtPyI/FMAfDAh0cmFuc2ZlcgwU9WPqQLwoPU0OBcSOowWz8qBzQO9BYn1bUjkBxgxAvCJ1oPK0B1o5JUaI6G7u5J+K9MWWNsVmLNeYIFV+D0MhB6TU1Or2R09k10XT1wDih4YFgLbTtKE76PvVWQIyFQxARdKrwTJb5mCSGC6kqAo4QcpHEje/FF6wYzuQSi/AaR7Xo1gpXdVU+me52KxAS4Mkg+h3jHKf32ur6h81NttHvwxAl7ZuQANY8vRhQO7fFOmvtbj60BZOFH6dFMl7Lp9D7zdDXYax3N+8ZvJPWdHQfOVf+1i7ZDGiy8o1TVSCiJgu+pMTDCECEDp/fdAWVYWX95YNJ8UWpDlP2Wi55lFV60sBPkBAQG4MIQKnvFX+hoTgEZdo0QS6MHlb3MhmGehkrdJhVnI+0YXNYgwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CDCED2QwH32PmkM53kS4Qq1GsyUS2aGAje2CMT4+DCece5pkUQZ7Q3Do="
    55  
    56  const b1Verbose = `{"size":1438,"nextblockhash":"0x34c20650683940a7af1881c2798e83acf9bf98aa226025af6c1d32b5530cc900","confirmations":15,"hash":"0x88c1cbf68695f73fb7b7d185c0037ffebdf032327488ebe65e0533d269e7de9b","version":0,"previousblockhash":"0x0f8fb4e17d2ab9f3097af75ca7fd16064160fb8043db94909e00dd4e257b9dc4","merkleroot":"0x2855f471048a5f0c9c60c10592f8997007aa3e52815d1b8c2c2f57e5e340d5f6","time":1626251469001,"nonce":"0","index":1,"nextconsensus":"NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq","primary":0,"witnesses":[{"invocation":"DEBg0hpK90iZlB4ZSCG7BOr7BsvPXGDax360lvqKeNFuzaGI1RYNH50/dhQLxocy90JdsIOyodd1sOJGEjZIt7ztDEAHc2avJzz6tK+FOQMIZO/FEEikJdLJX0+iZXFcsmDRpB7lo2wWMSQbcoTXNg7leuR0VeDsKJ+YdvCuTG5WbiqWDECa6Yjj+bK4te5KR5jdLF5kLt03csyozZcd/X7NPt89IsX01zpX8ec3e+B2qySJIOhEf3cK0i+5U5wyXiFcRI8x","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFEGe0Nw6"}],"tx":[{"hash":"0xf01080c50f3198f5a539c4a06d024f1b8bdc2a360a215fa7e2488f79a56d501a","size":488,"version":0,"nonce":2,"sender":"NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq","sysfee":"11000000","netfee":"4421900","validuntilblock":1200,"attributes":[],"signers":[{"account":"0x3f223f6da778e805d1b9b479906c0e8c1ee8b968","scopes":"CalledByEntry"}],"script":"CwIY3fUFDBTunqIsJ+NL0BSPxBCOCPdOj1BIsgwUaLnoHowObJB5tLnRBeh4p20/Ij8UwB8MCHRyYW5zZmVyDBT1Y+pAvCg9TQ4FxI6jBbPyoHNA70FifVtSOQ==","witnesses":[{"invocation":"DEC8InWg8rQHWjklRojobu7kn4r0xZY2xWYs15ggVX4PQyEHpNTU6vZHT2TXRdPXAOKHhgWAttO0oTvo+9VZAjIVDEBF0qvBMlvmYJIYLqSoCjhBykcSN78UXrBjO5BKL8BpHtejWCld1VT6Z7nYrEBLgySD6HeMcp/fa6vqHzU220e/DECXtm5AA1jy9GFA7t8U6a+1uPrQFk4Ufp0UyXsun0PvN0NdhrHc37xm8k9Z0dB85V/7WLtkMaLLyjVNVIKImC76","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFEGe0Nw6"}]},{"hash":"0xced32af656e144f6be5d7172ed37747831456cb3eeaac4ee964d0b479b45d3a8","size":492,"version":0,"nonce":3,"sender":"NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq","sysfee":"11000000","netfee":"4425900","validuntilblock":1200,"attributes":[],"signers":[{"account":"0x3f223f6da778e805d1b9b479906c0e8c1ee8b968","scopes":"CalledByEntry"}],"script":"CwMA6HZIFwAAAAwU7p6iLCfjS9AUj8QQjgj3To9QSLIMFGi56B6MDmyQebS50QXoeKdtPyI/FMAfDAh0cmFuc2ZlcgwUz3bii9AGLEpHjuNVYQETGfPPpNJBYn1bUjk=","witnesses":[{"invocation":"DEDgj/SQT84EbWRZ4ZKhyjJTuLwVPDgVlQO3CGmgacItvni9nziJvTxziZXBG/0Hqkv68ddS1EH94RtWlqLQWRCjDEAWZUeSQ8KskILSvoWPN3836xpg/TYzOGiFVoePv91CFnap4fRFxdbporBgnZ/sUsjFZ74U8f+r0riqtvkdMMyGDEDx5iho79oDVYOCwIDH3K1UeDjAT6Hq9YsD9SCfJSE1rRsAdJPh2StYxdh9Jah1lwGbW0U+Wu6zpbVFf5CS6fFc","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFEGe0Nw6"}]}]}`
    57  
    58  const base64Header1 = "AAAAAMSdeyVO3QCekJTbQ4D7YEEGFv2nXPd6CfO5Kn3htI8P9tVA4+VXLyyMG12BUj6qB3CZ+JIFwWCcDF+KBHH0VSjJICSkegEAAAAAAAAAAAAAAQAAAABouegejA5skHm0udEF6HinbT8iPwHGDEBg0hpK90iZlB4ZSCG7BOr7BsvPXGDax360lvqKeNFuzaGI1RYNH50/dhQLxocy90JdsIOyodd1sOJGEjZIt7ztDEAHc2avJzz6tK+FOQMIZO/FEEikJdLJX0+iZXFcsmDRpB7lo2wWMSQbcoTXNg7leuR0VeDsKJ+YdvCuTG5WbiqWDECa6Yjj+bK4te5KR5jdLF5kLt03csyozZcd/X7NPt89IsX01zpX8ec3e+B2qySJIOhEf3cK0i+5U5wyXiFcRI8xkxMMIQIQOn990BZVhZf3lg0nxRakOU/ZaLnmUVXrSwE+QEBAbgwhAqe8Vf6GhOARl2jRBLoweVvcyGYZ6GSt0mFWcj7Rhc1iDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIMIQPZDAffY+aQzneRLhCrUazJRLZoYCN7YIxPj4MJ5x7mmRRBntDcOg=="
    59  
    60  const header1Verbose = `{"hash":"0x88c1cbf68695f73fb7b7d185c0037ffebdf032327488ebe65e0533d269e7de9b","size":457,"version":0,"previousblockhash":"0x0f8fb4e17d2ab9f3097af75ca7fd16064160fb8043db94909e00dd4e257b9dc4","merkleroot":"0x2855f471048a5f0c9c60c10592f8997007aa3e52815d1b8c2c2f57e5e340d5f6","time":1626251469001,"index":1,"nextconsensus":"NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq","witnesses":[{"invocation":"DEBg0hpK90iZlB4ZSCG7BOr7BsvPXGDax360lvqKeNFuzaGI1RYNH50/dhQLxocy90JdsIOyodd1sOJGEjZIt7ztDEAHc2avJzz6tK+FOQMIZO/FEEikJdLJX0+iZXFcsmDRpB7lo2wWMSQbcoTXNg7leuR0VeDsKJ+YdvCuTG5WbiqWDECa6Yjj+bK4te5KR5jdLF5kLt03csyozZcd/X7NPt89IsX01zpX8ec3e+B2qySJIOhEf3cK0i+5U5wyXiFcRI8x","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFEGe0Nw6"}],"confirmations":15,"nextblockhash":"0x34c20650683940a7af1881c2798e83acf9bf98aa226025af6c1d32b5530cc900"}`
    61  
    62  const txMoveNeoVerbose = `{"blockhash":"0x88c1cbf68695f73fb7b7d185c0037ffebdf032327488ebe65e0533d269e7de9b","confirmations":15,"blocktime":1626251469001,"vmstate":"HALT","hash":"0xf01080c50f3198f5a539c4a06d024f1b8bdc2a360a215fa7e2488f79a56d501a","size":488,"version":0,"nonce":2,"sender":"NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq","sysfee":"11000000","netfee":"4421900","validuntilblock":1200,"attributes":[],"signers":[{"account":"0x3f223f6da778e805d1b9b479906c0e8c1ee8b968","scopes":"CalledByEntry"}],"script":"CwIY3fUFDBTunqIsJ+NL0BSPxBCOCPdOj1BIsgwUaLnoHowObJB5tLnRBeh4p20/Ij8UwB8MCHRyYW5zZmVyDBT1Y+pAvCg9TQ4FxI6jBbPyoHNA70FifVtSOQ==","witnesses":[{"invocation":"DEC8InWg8rQHWjklRojobu7kn4r0xZY2xWYs15ggVX4PQyEHpNTU6vZHT2TXRdPXAOKHhgWAttO0oTvo+9VZAjIVDEBF0qvBMlvmYJIYLqSoCjhBykcSN78UXrBjO5BKL8BpHtejWCld1VT6Z7nYrEBLgySD6HeMcp/fa6vqHzU220e/DECXtm5AA1jy9GFA7t8U6a+1uPrQFk4Ufp0UyXsun0PvN0NdhrHc37xm8k9Z0dB85V/7WLtkMaLLyjVNVIKImC76","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFEGe0Nw6"}]}`
    63  
    64  // getResultBlock1 returns data for block number 1 which is used by several tests.
    65  func getResultBlock1() *result.Block {
    66  	binB, err := base64.StdEncoding.DecodeString(base64B1)
    67  	if err != nil {
    68  		panic(err)
    69  	}
    70  	b := block.New(false)
    71  	err = testserdes.DecodeBinary(binB, b)
    72  	if err != nil {
    73  		panic(err)
    74  	}
    75  	b2Hash, err := util.Uint256DecodeStringLE("34c20650683940a7af1881c2798e83acf9bf98aa226025af6c1d32b5530cc900")
    76  	if err != nil {
    77  		panic(err)
    78  	}
    79  	return &result.Block{
    80  		Block: *b,
    81  		BlockMetadata: result.BlockMetadata{
    82  			Size:          1438,
    83  			NextBlockHash: &b2Hash,
    84  			Confirmations: 15,
    85  		},
    86  	}
    87  }
    88  
    89  func getTxMoveNeo() *result.TransactionOutputRaw {
    90  	b1 := getResultBlock1()
    91  	txBin, err := base64.StdEncoding.DecodeString(base64TxMoveNeo)
    92  	if err != nil {
    93  		panic(err)
    94  	}
    95  	tx, err := transaction.NewTransactionFromBytes(txBin)
    96  	if err != nil {
    97  		panic(err)
    98  	}
    99  	return &result.TransactionOutputRaw{
   100  		Transaction: *tx,
   101  		TransactionMetadata: result.TransactionMetadata{
   102  			Timestamp:     b1.Timestamp,
   103  			Blockhash:     b1.Block.Hash(),
   104  			Confirmations: int(b1.Confirmations),
   105  			VMState:       "HALT",
   106  		},
   107  	}
   108  }
   109  
   110  // rpcClientTestCases contains `serverResponse` json data fetched from examples
   111  // published in the official C# JSON-RPC API v2.10.3 reference
   112  // (see https://docs.neo.org/docs/en-us/reference/rpc/latest-version/api.html)
   113  var rpcClientTestCases = map[string][]rpcClientTestCase{
   114  	"getapplicationlog": {
   115  		{
   116  			name: "positive",
   117  			invoke: func(c *Client) (any, error) {
   118  				return c.GetApplicationLog(util.Uint256{}, nil)
   119  			},
   120  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"txid":"0x17145a039fca704fcdbeb46e6b210af98a1a9e5b9768e46ffc38f71c79ac2521","executions":[{"trigger":"Application","vmstate":"HALT","gasconsumed":"1","stack":[{"type":"Integer","value":"1"}],"notifications":[]}]}}`,
   121  			result: func(c *Client) any {
   122  				txHash, err := util.Uint256DecodeStringLE("17145a039fca704fcdbeb46e6b210af98a1a9e5b9768e46ffc38f71c79ac2521")
   123  				if err != nil {
   124  					panic(err)
   125  				}
   126  				return &result.ApplicationLog{
   127  					Container: txHash,
   128  					Executions: []state.Execution{
   129  						{
   130  							Trigger:     trigger.Application,
   131  							VMState:     vmstate.Halt,
   132  							GasConsumed: 1,
   133  							Stack:       []stackitem.Item{stackitem.NewBigInteger(big.NewInt(1))},
   134  							Events:      []state.NotificationEvent{},
   135  						},
   136  					},
   137  				}
   138  			},
   139  		},
   140  	},
   141  	"getbestblockhash": {
   142  		{
   143  			name: "positive",
   144  			invoke: func(c *Client) (any, error) {
   145  				return c.GetBestBlockHash()
   146  			},
   147  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":"0x773dd2dae4a9c9275290f89b56e67d7363ea4826dfd4fc13cc01cf73a44b0d0e"}`,
   148  			result: func(c *Client) any {
   149  				result, err := util.Uint256DecodeStringLE("773dd2dae4a9c9275290f89b56e67d7363ea4826dfd4fc13cc01cf73a44b0d0e")
   150  				if err != nil {
   151  					panic(err)
   152  				}
   153  				return result
   154  			},
   155  		},
   156  	},
   157  	"getblock": {
   158  		{
   159  			name: "byIndex_positive",
   160  			invoke: func(c *Client) (any, error) {
   161  				return c.GetBlockByIndex(1)
   162  			},
   163  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":"` + base64B1 + `"}`,
   164  			result: func(c *Client) any {
   165  				b := getResultBlock1()
   166  				return &b.Block
   167  			},
   168  		},
   169  		{
   170  			name: "byIndex_verbose_positive",
   171  			invoke: func(c *Client) (i any, err error) {
   172  				return c.GetBlockByIndexVerbose(1)
   173  			},
   174  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":` + b1Verbose + `}`,
   175  			result: func(c *Client) any {
   176  				res := getResultBlock1()
   177  				return res
   178  			},
   179  		},
   180  		{
   181  			name: "byHash_positive",
   182  			invoke: func(c *Client) (any, error) {
   183  				hash, err := util.Uint256DecodeStringLE("d151651e86680a7ecbc87babf3346a42e7bc9974414ce192c9c22ac4f2e9d043")
   184  				if err != nil {
   185  					panic(err)
   186  				}
   187  				return c.GetBlockByHash(hash)
   188  			},
   189  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":"` + base64B1 + `"}`,
   190  			result: func(c *Client) any {
   191  				b := getResultBlock1()
   192  				return &b.Block
   193  			},
   194  		},
   195  		{
   196  			name: "byHash_verbose_positive",
   197  			invoke: func(c *Client) (i any, err error) {
   198  				hash, err := util.Uint256DecodeStringLE("86fe1061140b2ea791b0739fb9732abc6e5e47de4927228a1ac41de3d93eb7cb")
   199  				if err != nil {
   200  					panic(err)
   201  				}
   202  				return c.GetBlockByHashVerbose(hash)
   203  			},
   204  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":` + b1Verbose + `}`,
   205  			result: func(c *Client) any {
   206  				res := getResultBlock1()
   207  				return res
   208  			},
   209  		},
   210  	},
   211  	"getblockcount": {
   212  		{
   213  			name: "positive",
   214  			invoke: func(c *Client) (any, error) {
   215  				return c.GetBlockCount()
   216  			},
   217  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":991991}`,
   218  			result: func(c *Client) any {
   219  				return uint32(991991)
   220  			},
   221  		},
   222  	},
   223  	"getblockhash": {
   224  		{
   225  			name: "positive",
   226  			invoke: func(c *Client) (any, error) {
   227  				return c.GetBlockHash(1)
   228  			},
   229  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":"0x4c1e879872344349067c3b1a30781eeb4f9040d3795db7922f513f6f9660b9b2"}`,
   230  			result: func(c *Client) any {
   231  				hash, err := util.Uint256DecodeStringLE("4c1e879872344349067c3b1a30781eeb4f9040d3795db7922f513f6f9660b9b2")
   232  				if err != nil {
   233  					panic(err)
   234  				}
   235  				return hash
   236  			},
   237  		},
   238  	},
   239  	"getblockheader": {
   240  		{
   241  			name: "positive",
   242  			invoke: func(c *Client) (any, error) {
   243  				hash, err := util.Uint256DecodeStringLE("68e4bd688b852e807eef13a0ff7da7b02223e359a35153667e88f9cb4a3b0801")
   244  				if err != nil {
   245  					panic(err)
   246  				}
   247  				return c.GetBlockHeader(hash)
   248  			},
   249  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":"` + base64Header1 + `"}`,
   250  			result: func(c *Client) any {
   251  				b := getResultBlock1()
   252  				return &b.Header
   253  			},
   254  		},
   255  		{
   256  			name: "verbose_positive",
   257  			invoke: func(c *Client) (i any, err error) {
   258  				hash, err := util.Uint256DecodeStringLE("cbb73ed9e31dc41a8a222749de475e6ebc2a73b99f73b091a72e0b146110fe86")
   259  				if err != nil {
   260  					panic(err)
   261  				}
   262  				return c.GetBlockHeaderVerbose(hash)
   263  			},
   264  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":` + header1Verbose + `}`,
   265  			result: func(c *Client) any {
   266  				b := getResultBlock1()
   267  				return &result.Header{
   268  					Header: b.Header,
   269  					BlockMetadata: result.BlockMetadata{
   270  						Size:          457,
   271  						NextBlockHash: b.NextBlockHash,
   272  						Confirmations: b.Confirmations,
   273  					},
   274  				}
   275  			},
   276  		},
   277  	},
   278  	"getblockheadercount": {
   279  		{
   280  			name: "positive",
   281  			invoke: func(c *Client) (any, error) {
   282  				return c.GetBlockHeaderCount()
   283  			},
   284  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":2021}`,
   285  			result: func(c *Client) any {
   286  				return uint32(2021)
   287  			},
   288  		},
   289  	},
   290  	"getblocksysfee": {
   291  		{
   292  			name: "positive",
   293  			invoke: func(c *Client) (any, error) {
   294  				return c.GetBlockSysFee(1)
   295  			},
   296  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":"195500"}`,
   297  			result: func(c *Client) any {
   298  				return fixedn.Fixed8FromInt64(195500)
   299  			},
   300  		},
   301  	},
   302  	"getcommittee": {
   303  		{
   304  			name: "positive",
   305  			invoke: func(c *Client) (any, error) {
   306  				return c.GetCommittee()
   307  			},
   308  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":["02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e"]}`,
   309  			result: func(c *Client) any {
   310  				member, err := keys.NewPublicKeyFromString("02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e")
   311  				if err != nil {
   312  					panic(fmt.Errorf("failed to decode public key: %w", err))
   313  				}
   314  				return keys.PublicKeys{member}
   315  			},
   316  		},
   317  	},
   318  	"getconnectioncount": {
   319  		{
   320  			name: "positive",
   321  			invoke: func(c *Client) (any, error) {
   322  				return c.GetConnectionCount()
   323  			},
   324  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":10}`,
   325  			result: func(c *Client) any {
   326  				return 10
   327  			},
   328  		},
   329  	},
   330  	"getcontractstate": {
   331  		{
   332  			name: "positive, by hash",
   333  			invoke: func(c *Client) (any, error) {
   334  				hash, err := util.Uint160DecodeStringLE("1b4357bff5a01bdf2a6581247cf9ed1e24629176")
   335  				if err != nil {
   336  					panic(err)
   337  				}
   338  				return c.GetContractStateByHash(hash)
   339  			},
   340  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"nef":{"magic":860243278,"compiler":"neo-go-3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":2512077441},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"features":{},"permissions":[],"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`,
   341  			result: func(c *Client) any {
   342  				script, err := base64.StdEncoding.DecodeString("VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==")
   343  				if err != nil {
   344  					panic(err)
   345  				}
   346  				m := manifest.NewManifest("Test")
   347  				cs := &state.Contract{
   348  					ContractBase: state.ContractBase{
   349  						ID:       0,
   350  						Hash:     hash.Hash160(script),
   351  						NEF:      newTestNEF(script),
   352  						Manifest: *m,
   353  					},
   354  				}
   355  				return cs
   356  			},
   357  		},
   358  		{
   359  			name: "positive, by address",
   360  			invoke: func(c *Client) (any, error) {
   361  				return c.GetContractStateByAddressOrName("NWiu5oejTu925aeL9Hc1LX8SvaJhE23h15")
   362  			},
   363  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"nef":{"magic":860243278,"compiler":"neo-go-3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":2512077441},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"features":{},"permissions":[],"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`,
   364  			result: func(c *Client) any {
   365  				script, err := base64.StdEncoding.DecodeString("VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==")
   366  				if err != nil {
   367  					panic(err)
   368  				}
   369  				m := manifest.NewManifest("Test")
   370  				cs := &state.Contract{
   371  					ContractBase: state.ContractBase{
   372  						ID:       0,
   373  						Hash:     hash.Hash160(script),
   374  						NEF:      newTestNEF(script),
   375  						Manifest: *m,
   376  					},
   377  				}
   378  				return cs
   379  			},
   380  		},
   381  		{
   382  			name: "positive, by id",
   383  			invoke: func(c *Client) (any, error) {
   384  				return c.GetContractStateByID(0)
   385  			},
   386  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"nef":{"magic":860243278,"compiler":"neo-go-3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":2512077441},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"features":{},"permissions":[],"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`,
   387  			result: func(c *Client) any {
   388  				script, err := base64.StdEncoding.DecodeString("VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==")
   389  				if err != nil {
   390  					panic(err)
   391  				}
   392  				m := manifest.NewManifest("Test")
   393  				cs := &state.Contract{
   394  					ContractBase: state.ContractBase{
   395  						ID:       0,
   396  						Hash:     hash.Hash160(script),
   397  						NEF:      newTestNEF(script),
   398  						Manifest: *m,
   399  					},
   400  				}
   401  				return cs
   402  			},
   403  		},
   404  	},
   405  	"getnep11balances": {
   406  		{
   407  			name: "positive",
   408  			invoke: func(c *Client) (any, error) {
   409  				hash, err := util.Uint160DecodeStringLE("1aada0032aba1ef6d1f07bbd8bec1d85f5380fb3")
   410  				if err != nil {
   411  					panic(err)
   412  				}
   413  				return c.GetNEP11Balances(hash)
   414  			},
   415  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"balance":[{"assethash":"a48b6e1291ba24211ad11bb90ae2a10bf1fcd5a8","symbol":"SOME","decimals":"42","name":"Contract","tokens":[{"tokenid":"abcdef","amount":"1","lastupdatedblock":251604}]}],"address":"NcEkNmgWmf7HQVQvzhxpengpnt4DXjmZLe"}}`,
   416  			result: func(c *Client) any {
   417  				hash, err := util.Uint160DecodeStringLE("a48b6e1291ba24211ad11bb90ae2a10bf1fcd5a8")
   418  				if err != nil {
   419  					panic(err)
   420  				}
   421  				return &result.NEP11Balances{
   422  					Balances: []result.NEP11AssetBalance{{
   423  						Asset:    hash,
   424  						Decimals: 42,
   425  						Name:     "Contract",
   426  						Symbol:   "SOME",
   427  						Tokens: []result.NEP11TokenBalance{{
   428  							ID:          "abcdef",
   429  							Amount:      "1",
   430  							LastUpdated: 251604,
   431  						}},
   432  					}},
   433  					Address: "NcEkNmgWmf7HQVQvzhxpengpnt4DXjmZLe",
   434  				}
   435  			},
   436  		},
   437  	},
   438  	"getnep17balances": {
   439  		{
   440  			name: "positive",
   441  			invoke: func(c *Client) (any, error) {
   442  				hash, err := util.Uint160DecodeStringLE("1aada0032aba1ef6d1f07bbd8bec1d85f5380fb3")
   443  				if err != nil {
   444  					panic(err)
   445  				}
   446  				return c.GetNEP17Balances(hash)
   447  			},
   448  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"balance":[{"assethash":"a48b6e1291ba24211ad11bb90ae2a10bf1fcd5a8","symbol":"N17","decimals":"8","name":"Token","amount":"50000000000","lastupdatedblock":251604}],"address":"AY6eqWjsUFCzsVELG7yG72XDukKvC34p2w"}}`,
   449  			result: func(c *Client) any {
   450  				hash, err := util.Uint160DecodeStringLE("a48b6e1291ba24211ad11bb90ae2a10bf1fcd5a8")
   451  				if err != nil {
   452  					panic(err)
   453  				}
   454  				return &result.NEP17Balances{
   455  					Balances: []result.NEP17Balance{{
   456  						Asset:       hash,
   457  						Decimals:    8,
   458  						Name:        "Token",
   459  						Symbol:      "N17",
   460  						Amount:      "50000000000",
   461  						LastUpdated: 251604,
   462  					}},
   463  					Address: "AY6eqWjsUFCzsVELG7yG72XDukKvC34p2w",
   464  				}
   465  			},
   466  		},
   467  	},
   468  	"getnep11properties": {
   469  		{
   470  			name: "positive",
   471  			invoke: func(c *Client) (any, error) {
   472  				hash, err := util.Uint160DecodeStringLE("1aada0032aba1ef6d1f07bbd8bec1d85f5380fb3")
   473  				if err != nil {
   474  					panic(err)
   475  				}
   476  				return c.GetNEP11Properties(hash, []byte("abcdef"))
   477  			}, // NcEkNmgWmf7HQVQvzhxpengpnt4DXjmZLe
   478  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"name":"sometoken","field1":"c29tZXRoaW5n","field2":null}}`,
   479  			result: func(c *Client) any {
   480  				return map[string]any{
   481  					"name":   "sometoken",
   482  					"field1": []byte("something"),
   483  					"field2": nil,
   484  				}
   485  			},
   486  		},
   487  	},
   488  	"getnep11transfers": {
   489  		{
   490  			name: "positive",
   491  			invoke: func(c *Client) (any, error) {
   492  				hash, err := address.StringToUint160("NcEkNmgWmf7HQVQvzhxpengpnt4DXjmZLe")
   493  				if err != nil {
   494  					panic(err)
   495  				}
   496  				return c.GetNEP11Transfers(hash, nil, nil, nil, nil)
   497  			},
   498  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"sent":[],"received":[{"timestamp":1555651816,"assethash":"600c4f5200db36177e3e8a09e9f18e2fc7d12a0f","transferaddress":"NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP","amount":"1","tokenid":"abcdef","blockindex":436036,"transfernotifyindex":0,"txhash":"df7683ece554ecfb85cf41492c5f143215dd43ef9ec61181a28f922da06aba58"}],"address":"NcEkNmgWmf7HQVQvzhxpengpnt4DXjmZLe"}}`,
   499  			result: func(c *Client) any {
   500  				assetHash, err := util.Uint160DecodeStringLE("600c4f5200db36177e3e8a09e9f18e2fc7d12a0f")
   501  				if err != nil {
   502  					panic(err)
   503  				}
   504  				txHash, err := util.Uint256DecodeStringLE("df7683ece554ecfb85cf41492c5f143215dd43ef9ec61181a28f922da06aba58")
   505  				if err != nil {
   506  					panic(err)
   507  				}
   508  				return &result.NEP11Transfers{
   509  					Sent: []result.NEP11Transfer{},
   510  					Received: []result.NEP11Transfer{
   511  						{
   512  							Timestamp:   1555651816,
   513  							Asset:       assetHash,
   514  							Address:     "NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP",
   515  							Amount:      "1",
   516  							ID:          "abcdef",
   517  							Index:       436036,
   518  							NotifyIndex: 0,
   519  							TxHash:      txHash,
   520  						},
   521  					},
   522  					Address: "NcEkNmgWmf7HQVQvzhxpengpnt4DXjmZLe",
   523  				}
   524  			},
   525  		},
   526  	},
   527  	"getnep17transfers": {
   528  		{
   529  			name: "positive",
   530  			invoke: func(c *Client) (any, error) {
   531  				hash, err := address.StringToUint160("NcEkNmgWmf7HQVQvzhxpengpnt4DXjmZLe")
   532  				if err != nil {
   533  					panic(err)
   534  				}
   535  				return c.GetNEP17Transfers(hash, nil, nil, nil, nil)
   536  			},
   537  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"sent":[],"received":[{"timestamp":1555651816,"assethash":"600c4f5200db36177e3e8a09e9f18e2fc7d12a0f","transferaddress":"AYwgBNMepiv5ocGcyNT4mA8zPLTQ8pDBis","amount":"1000000","blockindex":436036,"transfernotifyindex":0,"txhash":"df7683ece554ecfb85cf41492c5f143215dd43ef9ec61181a28f922da06aba58"}],"address":"NcEkNmgWmf7HQVQvzhxpengpnt4DXjmZLe"}}`,
   538  			result: func(c *Client) any {
   539  				assetHash, err := util.Uint160DecodeStringLE("600c4f5200db36177e3e8a09e9f18e2fc7d12a0f")
   540  				if err != nil {
   541  					panic(err)
   542  				}
   543  				txHash, err := util.Uint256DecodeStringLE("df7683ece554ecfb85cf41492c5f143215dd43ef9ec61181a28f922da06aba58")
   544  				if err != nil {
   545  					panic(err)
   546  				}
   547  				return &result.NEP17Transfers{
   548  					Sent: []result.NEP17Transfer{},
   549  					Received: []result.NEP17Transfer{
   550  						{
   551  							Timestamp:   1555651816,
   552  							Asset:       assetHash,
   553  							Address:     "AYwgBNMepiv5ocGcyNT4mA8zPLTQ8pDBis",
   554  							Amount:      "1000000",
   555  							Index:       436036,
   556  							NotifyIndex: 0,
   557  							TxHash:      txHash,
   558  						},
   559  					},
   560  					Address: "NcEkNmgWmf7HQVQvzhxpengpnt4DXjmZLe",
   561  				}
   562  			},
   563  		},
   564  	},
   565  	"getpeers": {
   566  		{
   567  			name: "positive",
   568  			invoke: func(c *Client) (any, error) {
   569  				return c.GetPeers()
   570  			},
   571  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"unconnected":[{"address":"172.200.0.1","port":20333}],"connected":[{"address":"127.0.0.1","port":20335}],"bad":[{"address":"172.200.0.254","port":20332}]}}`,
   572  			result: func(c *Client) any {
   573  
   574  				return &result.GetPeers{
   575  					Unconnected: result.Peers{
   576  						{
   577  							Address: "172.200.0.1",
   578  							Port:    20333,
   579  						},
   580  					},
   581  					Connected: result.Peers{
   582  						{
   583  							Address: "127.0.0.1",
   584  							Port:    20335,
   585  						},
   586  					},
   587  					Bad: result.Peers{
   588  						{
   589  							Address: "172.200.0.254",
   590  							Port:    20332,
   591  						},
   592  					},
   593  				}
   594  			},
   595  		},
   596  	},
   597  	"getrawmempool": {
   598  		{
   599  			name: "positive",
   600  			invoke: func(c *Client) (any, error) {
   601  				return c.GetRawMemPool()
   602  			},
   603  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":["0x9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e"]}`,
   604  			result: func(c *Client) any {
   605  				hash, err := util.Uint256DecodeStringLE("9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e")
   606  				if err != nil {
   607  					panic(err)
   608  				}
   609  				return []util.Uint256{hash}
   610  			},
   611  		},
   612  	},
   613  	"getrawtransaction": {
   614  		{
   615  			name: "positive",
   616  			invoke: func(c *Client) (i any, err error) {
   617  				hash, err := util.Uint256DecodeStringLE("f5fbd303799f24ba247529d7544d4276cca54ea79f4b98095f2b0557313c5275")
   618  				if err != nil {
   619  					panic(err)
   620  				}
   621  				return c.GetRawTransaction(hash)
   622  			},
   623  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":"` + base64TxMoveNeo + `"}`,
   624  			result: func(c *Client) any {
   625  				tx := getTxMoveNeo()
   626  				return &tx.Transaction
   627  			},
   628  		},
   629  		{
   630  			name: "verbose_positive",
   631  			invoke: func(c *Client) (any, error) {
   632  				hash, err := util.Uint256DecodeStringLE("f5fbd303799f24ba247529d7544d4276cca54ea79f4b98095f2b0557313c5275")
   633  				if err != nil {
   634  					panic(err)
   635  				}
   636  				out, err := c.GetRawTransactionVerbose(hash)
   637  				if err != nil {
   638  					return nil, err
   639  				}
   640  				out.Transaction.FeePerByte() // set fee per byte
   641  				return out, nil
   642  			},
   643  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":` + txMoveNeoVerbose + `}`,
   644  			result: func(c *Client) any {
   645  				return getTxMoveNeo()
   646  			},
   647  		},
   648  	},
   649  	"getstateroot": {
   650  		{
   651  			name: "positive, by height",
   652  			invoke: func(c *Client) (any, error) {
   653  				return c.GetStateRootByHeight(5)
   654  			},
   655  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"version":0,"index":5,"roothash":"0x65d19151694321e70c6d184b37a2bcf7af4a2c60c099af332a4f7815e3670686","witnesses":[]}}`,
   656  			result: func(c *Client) any {
   657  				h, err := util.Uint256DecodeStringLE("65d19151694321e70c6d184b37a2bcf7af4a2c60c099af332a4f7815e3670686")
   658  				if err != nil {
   659  					panic(err)
   660  				}
   661  				return &state.MPTRoot{
   662  					Version: 0,
   663  					Index:   5,
   664  					Root:    h,
   665  					Witness: []transaction.Witness{},
   666  				}
   667  			},
   668  		},
   669  		{
   670  			name: "positive, by hash",
   671  			invoke: func(c *Client) (any, error) {
   672  				hash, err := util.Uint256DecodeStringLE("86fe1061140b2ea791b0739fb9732abc6e5e47de4927228a1ac41de3d93eb7cb")
   673  				if err != nil {
   674  					panic(err)
   675  				}
   676  				return c.GetStateRootByBlockHash(hash)
   677  			},
   678  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"version":0,"index":5,"roothash":"0x65d19151694321e70c6d184b37a2bcf7af4a2c60c099af332a4f7815e3670686","witnesses":[]}}`,
   679  			result: func(c *Client) any {
   680  				h, _ := util.Uint256DecodeStringLE("65d19151694321e70c6d184b37a2bcf7af4a2c60c099af332a4f7815e3670686")
   681  				return &state.MPTRoot{
   682  					Version: 0,
   683  					Index:   5,
   684  					Root:    h,
   685  					Witness: []transaction.Witness{},
   686  				}
   687  			},
   688  		},
   689  	},
   690  	"getstate": {
   691  		{
   692  			name: "positive",
   693  			invoke: func(c *Client) (any, error) {
   694  				root, _ := util.Uint256DecodeStringLE("252e9d73d49c95c7618d40650da504e05183a1b2eed0685e42c360413c329170")
   695  				cHash, _ := util.Uint160DecodeStringLE("5c9e40a12055c6b9e3f72271c9779958c842135d")
   696  				return c.GetState(root, cHash, []byte("testkey"))
   697  			},
   698  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":"dGVzdHZhbHVl"}`,
   699  			result: func(c *Client) any {
   700  				return []byte("testvalue")
   701  			},
   702  		},
   703  	},
   704  	"getproof": {
   705  		{
   706  			name: "positive",
   707  			invoke: func(c *Client) (any, error) {
   708  				root, _ := util.Uint256DecodeStringLE("272002b11a6a39035c719defec3e4e6a8d1f4ae37a995b44734911413fcc2ba5")
   709  				cHash, _ := util.Uint160DecodeStringLE("cc5e4edd9f5f8dba8bb65734541df7a1c081c67b")
   710  				key := []byte{10}
   711  				return c.GetProof(root, cHash, key)
   712  			},
   713  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":"Bfn///8KBiQBAQ8DogBnMdiiPTEW05A6bJPmQ2TNVpuca/nB1rJRdQX7R4SyAAQEBAQEBAQDHvo5Rc9v\u002BWSpfsnMXM75ku\u002BZjvbLJhWXn/lh6L\u002B1yB0EA4k\u002Bsx4f7IgmdHNm3wRMpj5kTU4l0gChSGppo5p5wZyWA2\u002BKSFn16W6tRrGSfJob\u002BgqJukLcNDk0DBFYW2wIS2/NAzkugdLfZRXHOLqq5XJr89ElzlqyXU1o9D87l9YOcXjGBAQEA7oDTOxuU4iMAKPuhn5eJjzsM56bQrx3uORa8LKm42oDBCkBBg8PDw8PDwN96s39UOSCwMJmMQZzNjfNAPCbRRyke1B4VRKqOZ0NHlIAA2woQ13XO4Ug2aQ/cW4WBricVcUVqobFUU0dnRPtfIHeAxuYERXsV6HwdGjW\u002BhtpM0FEkw/mllbH5pyhn\u002BBx4r8wBAQEBAQEBAQEBAQEBAQEJAEBCgPXvpMqBogTeGhXjtFY4Rsn9bY/PgNX0l4iYOHMzUBQQgQCAugD"}`,
   714  			result: func(c *Client) any {
   715  				b, _ := base64.StdEncoding.DecodeString("Bfn///8KBiQBAQ8DogBnMdiiPTEW05A6bJPmQ2TNVpuca/nB1rJRdQX7R4SyAAQEBAQEBAQDHvo5Rc9v\u002BWSpfsnMXM75ku\u002BZjvbLJhWXn/lh6L\u002B1yB0EA4k\u002Bsx4f7IgmdHNm3wRMpj5kTU4l0gChSGppo5p5wZyWA2\u002BKSFn16W6tRrGSfJob\u002BgqJukLcNDk0DBFYW2wIS2/NAzkugdLfZRXHOLqq5XJr89ElzlqyXU1o9D87l9YOcXjGBAQEA7oDTOxuU4iMAKPuhn5eJjzsM56bQrx3uORa8LKm42oDBCkBBg8PDw8PDwN96s39UOSCwMJmMQZzNjfNAPCbRRyke1B4VRKqOZ0NHlIAA2woQ13XO4Ug2aQ/cW4WBricVcUVqobFUU0dnRPtfIHeAxuYERXsV6HwdGjW\u002BhtpM0FEkw/mllbH5pyhn\u002BBx4r8wBAQEBAQEBAQEBAQEBAQEJAEBCgPXvpMqBogTeGhXjtFY4Rsn9bY/PgNX0l4iYOHMzUBQQgQCAugD")
   716  				proof := &result.ProofWithKey{}
   717  				r := io.NewBinReaderFromBuf(b)
   718  				proof.DecodeBinary(r)
   719  				return proof
   720  			},
   721  		},
   722  		{
   723  			name: "not found",
   724  			invoke: func(c *Client) (any, error) {
   725  				root, _ := util.Uint256DecodeStringLE("272002b11a6a39035c719defec3e4e6a8d1f4ae37a995b44734911413fcc2ba5")
   726  				cHash, _ := util.Uint160DecodeStringLE("cc5e4edd9f5f8dba8bb65734541df7a1c081c67b")
   727  				key := []byte{01}
   728  				return c.GetProof(root, cHash, key)
   729  			},
   730  			serverResponse: `{"id":1,"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error","data":"failed to get proof: item not found"}}`,
   731  			fails:          true,
   732  		},
   733  	},
   734  	"verifyproof": {
   735  		{
   736  			name: "positive",
   737  			invoke: func(c *Client) (any, error) {
   738  				root, _ := util.Uint256DecodeStringLE("272002b11a6a39035c719defec3e4e6a8d1f4ae37a995b44734911413fcc2ba5")
   739  				b, _ := base64.StdEncoding.DecodeString("Bfn///8KBiQBAQ8DogBnMdiiPTEW05A6bJPmQ2TNVpuca/nB1rJRdQX7R4SyAAQEBAQEBAQDHvo5Rc9v\u002BWSpfsnMXM75ku\u002BZjvbLJhWXn/lh6L\u002B1yB0EA4k\u002Bsx4f7IgmdHNm3wRMpj5kTU4l0gChSGppo5p5wZyWA2\u002BKSFn16W6tRrGSfJob\u002BgqJukLcNDk0DBFYW2wIS2/NAzkugdLfZRXHOLqq5XJr89ElzlqyXU1o9D87l9YOcXjGBAQEA7oDTOxuU4iMAKPuhn5eJjzsM56bQrx3uORa8LKm42oDBCkBBg8PDw8PDwN96s39UOSCwMJmMQZzNjfNAPCbRRyke1B4VRKqOZ0NHlIAA2woQ13XO4Ug2aQ/cW4WBricVcUVqobFUU0dnRPtfIHeAxuYERXsV6HwdGjW\u002BhtpM0FEkw/mllbH5pyhn\u002BBx4r8wBAQEBAQEBAQEBAQEBAQEJAEBCgPXvpMqBogTeGhXjtFY4Rsn9bY/PgNX0l4iYOHMzUBQQgQCAugD")
   740  				proof := &result.ProofWithKey{}
   741  				r := io.NewBinReaderFromBuf(b)
   742  				proof.DecodeBinary(r)
   743  				return c.VerifyProof(root, proof)
   744  			},
   745  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":"6AM="}`,
   746  			result: func(c *Client) any {
   747  				return bigint.ToPreallocatedBytes(big.NewInt(1000), nil)
   748  			},
   749  		},
   750  		{
   751  			name: "fail",
   752  			invoke: func(c *Client) (any, error) {
   753  				root, _ := util.Uint256DecodeStringLE("272002b11a6a39035c719defec3e4e6a8d1f4ae37a995b44734911413fcc2ba5")
   754  				b, _ := base64.StdEncoding.DecodeString("Bfn///8KBiQBAQ8DogBnMdiiPTEW05A6bJPmQ2TNVpuca/nB1rJRdQX7R4SyAAQEBAQEBAQDHvo5Rc9v\u002BWSpfsnMXM75ku\u002BZjvbLJhWXn/lh6L\u002B1yB0EA4k\u002Bsx4f7IgmdHNm3wRMpj5kTU4l0gChSGppo5p5wZyWA2\u002BKSFn16W6tRrGSfJob\u002BgqJukLcNDk0DBFYW2wIS2/NAzkugdLfZRXHOLqq5XJr89ElzlqyXU1o9D87l9YOcXjGBAQEA7oDTOxuU4iMAKPuhn5eJjzsM56bQrx3uORa8LKm42oDBCkBBg8PDw8PDwN96s39UOSCwMJmMQZzNjfNAPCbRRyke1B4VRKqOZ0NHlIAA2woQ13XO4Ug2aQ/cW4WBricVcUVqobFUU0dnRPtfIHeAxuYERXsV6HwdGjW\u002BhtpM0FEkw/mllbH5pyhn\u002BBx4r8wBAQEBAQEBAQEBAQEBAQEJAEBCgPXvpMqBogTeGhXjtFY4Rsn9bY/PgNX0l4iYOHMzUBQQgQCAugD")
   755  				proof := &result.ProofWithKey{}
   756  				r := io.NewBinReaderFromBuf(b)
   757  				proof.DecodeBinary(r)
   758  				return c.VerifyProof(root, proof)
   759  			},
   760  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":"invalid"}`,
   761  			fails:          true,
   762  		},
   763  	},
   764  	"findstates": {
   765  		{
   766  			name: "positive",
   767  			invoke: func(c *Client) (any, error) {
   768  				root, _ := util.Uint256DecodeStringLE("252e9d73d49c95c7618d40650da504e05183a1b2eed0685e42c360413c329170")
   769  				cHash, _ := util.Uint160DecodeStringLE("5c9e40a12055c6b9e3f72271c9779958c842135d")
   770  				count := 1
   771  				return c.FindStates(root, cHash, []byte("aa"), []byte("aa00"), &count)
   772  			},
   773  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"results":[{"key":"YWExMA==","value":"djI="}],"firstProof":"CAEAAABhYTEwCXIAA5KNHjQ1+LFX4lQBLjMAhaLtTJnfuI86O7WnNdlshsYWBAQEBAQEBAQDTzD7MJp2KW6E8BNVjjjgZMTAjI/GI3ZrTmR2UUOtSeIEBAQEBAPKPqb0qnb4Ywz6gqpNKCUNQsfBmAnKc5p3dxokSQRpwgRSAAQDPplG1wee4KOfkehaF94R5uoKSgvQL1j5gkFTN4ywYaIEBAOhOyI39MZfoKc940g57XeqwRnxh7P62fKjnfEtBzQxHQQEBAQEBAQEBAQEBCkBBgAAAAAAAAM6A1UrwFYZAEMfe6go3jX25xz2sHsovQ2UO/UHqZZOXLIABAOwg7pkXyaTR85yQIvYnoGaG/OVRLRHOj+nhZnXb6dVtAQEBAPnciBUp3uspLQTajKTlAxgrNe+3tlqlbwlNRkz0eNmhQMzoMcWOFi9nCyn+eM5lA6Pq67DxzTQDlHljh8g8kRtJAPq9hxzTgreK0qDTavsethixguZYfV7wDmKfumMglnoqQQEBAQEBAM1x2dVBdf5BJ0Xvw2qqhvpKqxdHb8/HMFWiXkJj1uAAQQEJgEDAQYBA5kV2WLkgey9C5z6gZT69VLKcEuwyY8P853rNtGhT3NeUgAEBAQDiX59K9PuJ5RE7Z1uj7q/QJ8FGf8avLdWM7hwmWkVH2gEBAQEBAQEBAQEBAQD1SubX5XhFHcUOWdUzg1bXmDwWJwt+wpU3FOdFkU1PXBSAAQDHCzfEQyqwOO263EE6HER1vWDrwz8JiEHEOXfZ3kX7NYEBAQDEH++Hy8wBcniKuWVevaAwzHCh60kzncU30E5fDC3gJsEBAQEBAQEBAQEBCUBAgMAA1wt18LbxMKdYcJ+nEDMMWZbRsu550l8HGhcYhpl6DjSBAICdjI=","truncated":true}}`,
   774  			result: func(c *Client) any {
   775  				proofB, _ := base64.StdEncoding.DecodeString("CAEAAABhYTEwCXIAA5KNHjQ1+LFX4lQBLjMAhaLtTJnfuI86O7WnNdlshsYWBAQEBAQEBAQDTzD7MJp2KW6E8BNVjjjgZMTAjI/GI3ZrTmR2UUOtSeIEBAQEBAPKPqb0qnb4Ywz6gqpNKCUNQsfBmAnKc5p3dxokSQRpwgRSAAQDPplG1wee4KOfkehaF94R5uoKSgvQL1j5gkFTN4ywYaIEBAOhOyI39MZfoKc940g57XeqwRnxh7P62fKjnfEtBzQxHQQEBAQEBAQEBAQEBCkBBgAAAAAAAAM6A1UrwFYZAEMfe6go3jX25xz2sHsovQ2UO/UHqZZOXLIABAOwg7pkXyaTR85yQIvYnoGaG/OVRLRHOj+nhZnXb6dVtAQEBAPnciBUp3uspLQTajKTlAxgrNe+3tlqlbwlNRkz0eNmhQMzoMcWOFi9nCyn+eM5lA6Pq67DxzTQDlHljh8g8kRtJAPq9hxzTgreK0qDTavsethixguZYfV7wDmKfumMglnoqQQEBAQEBAM1x2dVBdf5BJ0Xvw2qqhvpKqxdHb8/HMFWiXkJj1uAAQQEJgEDAQYBA5kV2WLkgey9C5z6gZT69VLKcEuwyY8P853rNtGhT3NeUgAEBAQDiX59K9PuJ5RE7Z1uj7q/QJ8FGf8avLdWM7hwmWkVH2gEBAQEBAQEBAQEBAQD1SubX5XhFHcUOWdUzg1bXmDwWJwt+wpU3FOdFkU1PXBSAAQDHCzfEQyqwOO263EE6HER1vWDrwz8JiEHEOXfZ3kX7NYEBAQDEH++Hy8wBcniKuWVevaAwzHCh60kzncU30E5fDC3gJsEBAQEBAQEBAQEBCUBAgMAA1wt18LbxMKdYcJ+nEDMMWZbRsu550l8HGhcYhpl6DjSBAICdjI=")
   776  				proof := &result.ProofWithKey{}
   777  				r := io.NewBinReaderFromBuf(proofB)
   778  				proof.DecodeBinary(r)
   779  				return result.FindStates{
   780  					Results:    []result.KeyValue{{Key: []byte("aa10"), Value: []byte("v2")}},
   781  					FirstProof: proof,
   782  					Truncated:  true,
   783  				}
   784  			},
   785  		},
   786  	},
   787  	"findstorage": {
   788  		{
   789  			name: "positive by hash",
   790  			invoke: func(c *Client) (any, error) {
   791  				cHash, _ := util.Uint160DecodeStringLE("5c9e40a12055c6b9e3f72271c9779958c842135d")
   792  				start := 1
   793  				return c.FindStorageByHash(cHash, []byte("aa"), &start)
   794  			},
   795  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"results":[{"key":"YWExMA==","value":"djI="}],"truncated":true, "next": 1}}`,
   796  			result: func(c *Client) any {
   797  				return result.FindStorage{
   798  					Results:   []result.KeyValue{{Key: []byte("aa10"), Value: []byte("v2")}},
   799  					Truncated: true,
   800  					Next:      1,
   801  				}
   802  			},
   803  		},
   804  		{
   805  			name: "positive by ID",
   806  			invoke: func(c *Client) (any, error) {
   807  				start := 1
   808  				return c.FindStorageByID(1, []byte("aa"), &start)
   809  			},
   810  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"results":[{"key":"YWExMA==","value":"djI="}],"truncated":true, "next": 1}}`,
   811  			result: func(c *Client) any {
   812  				return result.FindStorage{
   813  					Results:   []result.KeyValue{{Key: []byte("aa10"), Value: []byte("v2")}},
   814  					Truncated: true,
   815  					Next:      1,
   816  				}
   817  			},
   818  		},
   819  	},
   820  	"findstoragehistoric": {
   821  		{
   822  			name: "positive by hash",
   823  			invoke: func(c *Client) (any, error) {
   824  				root, _ := util.Uint256DecodeStringLE("252e9d73d49c95c7618d40650da504e05183a1b2eed0685e42c360413c329170")
   825  				cHash, _ := util.Uint160DecodeStringLE("5c9e40a12055c6b9e3f72271c9779958c842135d")
   826  				start := 1
   827  				return c.FindStorageByHashHistoric(root, cHash, []byte("aa"), &start)
   828  			},
   829  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"results":[{"key":"YWExMA==","value":"djI="}],"truncated":true, "next": 1}}`,
   830  			result: func(c *Client) any {
   831  				return result.FindStorage{
   832  					Results:   []result.KeyValue{{Key: []byte("aa10"), Value: []byte("v2")}},
   833  					Truncated: true,
   834  					Next:      1,
   835  				}
   836  			},
   837  		},
   838  		{
   839  			name: "positive by ID",
   840  			invoke: func(c *Client) (any, error) {
   841  				root, _ := util.Uint256DecodeStringLE("252e9d73d49c95c7618d40650da504e05183a1b2eed0685e42c360413c329170")
   842  				start := 1
   843  				return c.FindStorageByIDHistoric(root, 1, []byte("aa"), &start)
   844  			},
   845  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"results":[{"key":"YWExMA==","value":"djI="}],"truncated":true, "next": 1}}`,
   846  			result: func(c *Client) any {
   847  				return result.FindStorage{
   848  					Results:   []result.KeyValue{{Key: []byte("aa10"), Value: []byte("v2")}},
   849  					Truncated: true,
   850  					Next:      1,
   851  				}
   852  			},
   853  		},
   854  	},
   855  	"getstateheight": {
   856  		{
   857  			name: "positive",
   858  			invoke: func(c *Client) (any, error) {
   859  				return c.GetStateHeight()
   860  			},
   861  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"localrootindex":11646,"validatedrootindex":11645}}`,
   862  			result: func(c *Client) any {
   863  				return &result.StateHeight{
   864  					Local:     11646,
   865  					Validated: 11645,
   866  				}
   867  			},
   868  		},
   869  	},
   870  	"getstorage": {
   871  		{
   872  			name: "by hash, positive",
   873  			invoke: func(c *Client) (any, error) {
   874  				hash, err := util.Uint160DecodeStringLE("03febccf81ac85e3d795bc5cbd4e84e907812aa3")
   875  				if err != nil {
   876  					panic(err)
   877  				}
   878  				key, err := hex.DecodeString("5065746572")
   879  				if err != nil {
   880  					panic(err)
   881  				}
   882  				return c.GetStorageByHash(hash, key)
   883  			},
   884  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":"TGlu"}`,
   885  			result: func(c *Client) any {
   886  				value, err := hex.DecodeString("4c696e")
   887  				if err != nil {
   888  					panic(err)
   889  				}
   890  				return value
   891  			},
   892  		},
   893  		{
   894  			name: "by ID, positive",
   895  			invoke: func(c *Client) (any, error) {
   896  				key, err := hex.DecodeString("5065746572")
   897  				if err != nil {
   898  					panic(err)
   899  				}
   900  				return c.GetStorageByID(-1, key)
   901  			},
   902  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":"TGlu"}`,
   903  			result: func(c *Client) any {
   904  				value, err := hex.DecodeString("4c696e")
   905  				if err != nil {
   906  					panic(err)
   907  				}
   908  				return value
   909  			},
   910  		},
   911  	},
   912  	"getstoragehistoric": {
   913  		{
   914  			name: "by hash, positive",
   915  			invoke: func(c *Client) (any, error) {
   916  				root, _ := util.Uint256DecodeStringLE("252e9d73d49c95c7618d40650da504e05183a1b2eed0685e42c360413c329170")
   917  				hash, err := util.Uint160DecodeStringLE("03febccf81ac85e3d795bc5cbd4e84e907812aa3")
   918  				if err != nil {
   919  					panic(err)
   920  				}
   921  				key, err := hex.DecodeString("5065746572")
   922  				if err != nil {
   923  					panic(err)
   924  				}
   925  				return c.GetStorageByHashHistoric(root, hash, key)
   926  			},
   927  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":"TGlu"}`,
   928  			result: func(c *Client) any {
   929  				value, err := hex.DecodeString("4c696e")
   930  				if err != nil {
   931  					panic(err)
   932  				}
   933  				return value
   934  			},
   935  		},
   936  		{
   937  			name: "by ID, positive",
   938  			invoke: func(c *Client) (any, error) {
   939  				root, _ := util.Uint256DecodeStringLE("252e9d73d49c95c7618d40650da504e05183a1b2eed0685e42c360413c329170")
   940  				key, err := hex.DecodeString("5065746572")
   941  				if err != nil {
   942  					panic(err)
   943  				}
   944  				return c.GetStorageByIDHistoric(root, -1, key)
   945  			},
   946  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":"TGlu"}`,
   947  			result: func(c *Client) any {
   948  				value, err := hex.DecodeString("4c696e")
   949  				if err != nil {
   950  					panic(err)
   951  				}
   952  				return value
   953  			},
   954  		},
   955  	},
   956  	"gettransactionheight": {
   957  		{
   958  			name: "positive",
   959  			invoke: func(c *Client) (any, error) {
   960  				hash, err := util.Uint256DecodeStringLE("cb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2")
   961  				if err != nil {
   962  					panic(err)
   963  				}
   964  				return c.GetTransactionHeight(hash)
   965  			},
   966  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":1}`,
   967  			result: func(c *Client) any {
   968  				return uint32(1)
   969  			},
   970  		},
   971  	},
   972  	"getunclaimedgas": {
   973  		{
   974  			name: "positive",
   975  			invoke: func(c *Client) (any, error) {
   976  				return c.GetUnclaimedGas("NMipL5VsNoLUBUJKPKLhxaEbPQVCZnyJyB")
   977  			},
   978  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"address":"NMipL5VsNoLUBUJKPKLhxaEbPQVCZnyJyB","unclaimed":"897299680935"}}`,
   979  			result: func(c *Client) any {
   980  				addr, err := address.StringToUint160("NMipL5VsNoLUBUJKPKLhxaEbPQVCZnyJyB")
   981  				if err != nil {
   982  					panic(fmt.Errorf("failed to parse UnclaimedGas address: %w", err))
   983  				}
   984  				return result.UnclaimedGas{
   985  					Address:   addr,
   986  					Unclaimed: *big.NewInt(897299680935),
   987  				}
   988  			},
   989  		},
   990  	},
   991  	"getcandidates": {
   992  		{
   993  			name: "positive",
   994  			invoke: func(c *Client) (any, error) {
   995  				return c.GetCandidates()
   996  			},
   997  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":[{"publickey":"02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2","votes":"0","active":true},{"publickey":"02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e","votes":"0","active":true},{"publickey":"03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699","votes":"0","active":true},{"publickey":"02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62","votes":"0","active":true}]}`,
   998  			result:         func(c *Client) any { return []result.Candidate{} },
   999  			check: func(t *testing.T, c *Client, uns any) {
  1000  				res, ok := uns.([]result.Candidate)
  1001  				require.True(t, ok)
  1002  				assert.Equal(t, 4, len(res))
  1003  			},
  1004  		},
  1005  	},
  1006  	"getvalidators": {
  1007  		{
  1008  			name: "positive",
  1009  			invoke: func(c *Client) (any, error) {
  1010  				return c.GetNextBlockValidators()
  1011  			},
  1012  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":[{"publickey":"02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2","votes":"0","active":true},{"publickey":"02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e","votes":"0","active":true},{"publickey":"03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699","votes":"0","active":true},{"publickey":"02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62","votes":"0","active":true}]}`,
  1013  			result:         func(c *Client) any { return []result.Validator{} },
  1014  			check: func(t *testing.T, c *Client, uns any) {
  1015  				res, ok := uns.([]result.Validator)
  1016  				require.True(t, ok)
  1017  				assert.Equal(t, 4, len(res))
  1018  			},
  1019  		},
  1020  	},
  1021  	"getversion": {
  1022  		{
  1023  			name: "positive",
  1024  			invoke: func(c *Client) (any, error) {
  1025  				return c.GetVersion()
  1026  			},
  1027  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"tcpport":20332,"wsport":20342,"nonce":2153672787,"useragent":"/NEO-GO:0.73.1-pre-273-ge381358/", "protocol": {"network": 2, "hardforks": {}}, "rpc": {"maxiteratorresultitems": 100, "sessionenabled": true}}`,
  1028  			result: func(c *Client) any {
  1029  				return &result.Version{
  1030  					TCPPort:   uint16(20332),
  1031  					WSPort:    uint16(20342),
  1032  					Nonce:     2153672787,
  1033  					UserAgent: "/NEO-GO:0.73.1-pre-273-ge381358/",
  1034  					Protocol: result.Protocol{
  1035  						Network:   netmode.UnitTestNet,
  1036  						Hardforks: map[config.Hardfork]uint32{},
  1037  					},
  1038  					RPC: result.RPC{
  1039  						MaxIteratorResultItems: 100,
  1040  						SessionEnabled:         true,
  1041  					},
  1042  				}
  1043  			},
  1044  		},
  1045  	},
  1046  	"invokefunction": {
  1047  		{
  1048  			name: "positive, by scripthash",
  1049  			invoke: func(c *Client) (any, error) {
  1050  				hash, err := util.Uint160DecodeStringLE("91b83e96f2a7c4fdf0c1688441ec61986c7cae26")
  1051  				if err != nil {
  1052  					panic(err)
  1053  				}
  1054  				contr, err := util.Uint160DecodeStringLE("af7c7328eee5a275a3bcaee2bf0cf662b5e739be")
  1055  				if err != nil {
  1056  					panic(err)
  1057  				}
  1058  				return c.InvokeFunction(contr, "balanceOf", []smartcontract.Parameter{
  1059  					{
  1060  						Type:  smartcontract.Hash160Type,
  1061  						Value: hash,
  1062  					},
  1063  				}, []transaction.Signer{{
  1064  					Account: util.Uint160{1, 2, 3},
  1065  				}})
  1066  			},
  1067  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"script":"FCaufGyYYexBhGjB8P3Ep/KWPriRUcEJYmFsYW5jZU9mZ74557Vi9gy/4q68o3Wi5e4oc3yv","state":"HALT","gasconsumed":"31100000","stack":[{"type":"ByteString","value":"JivsCEQy"}],"tx":"AAgAAACAlpgAAAAAAAIEEwAAAAAAsAQAAAGqis+FnU/kArNOZz8hVoIXlqSI6wEAVwHoAwwUqorPhZ1P5AKzTmc/IVaCF5akiOsMFOeetm08E0pKd27oB9LluEbdpP2wE8AMCHRyYW5zZmVyDBTnnrZtPBNKSndu6AfS5bhG3aT9sEFifVtSOAFCDEDYNAh3TUvYsZrocFYdBvJ0Trdnj1jRuQzy9Q6YroP2Cwgk4v7q3vbeZBikz8Q7vB+RbDPsWUy+ZiqdkkeG4XoUKQwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CC0GVRA14"}}`,
  1068  			result: func(c *Client) any {
  1069  				return &result.Invoke{}
  1070  			},
  1071  			check: func(t *testing.T, c *Client, uns any) {
  1072  				res, ok := uns.(*result.Invoke)
  1073  				require.True(t, ok)
  1074  				bytes, err := hex.DecodeString("262bec084432")
  1075  				if err != nil {
  1076  					panic(err)
  1077  				}
  1078  				script, err := base64.StdEncoding.DecodeString("FCaufGyYYexBhGjB8P3Ep/KWPriRUcEJYmFsYW5jZU9mZ74557Vi9gy/4q68o3Wi5e4oc3yv")
  1079  				if err != nil {
  1080  					panic(err)
  1081  				}
  1082  				assert.Equal(t, "HALT", res.State)
  1083  				assert.Equal(t, int64(31100000), res.GasConsumed)
  1084  				assert.Equal(t, script, res.Script)
  1085  				assert.Equal(t, []stackitem.Item{stackitem.NewByteArray(bytes)}, res.Stack)
  1086  				assert.NotNil(t, res.Transaction)
  1087  			},
  1088  		},
  1089  		{
  1090  			name: "positive, FAULT state",
  1091  			invoke: func(c *Client) (any, error) {
  1092  				hash, err := util.Uint160DecodeStringLE("91b83e96f2a7c4fdf0c1688441ec61986c7cae26")
  1093  				if err != nil {
  1094  					panic(err)
  1095  				}
  1096  				contr, err := util.Uint160DecodeStringLE("af7c7328eee5a275a3bcaee2bf0cf662b5e739be")
  1097  				if err != nil {
  1098  					panic(err)
  1099  				}
  1100  				return c.InvokeFunction(contr, "balanceOf", []smartcontract.Parameter{
  1101  					{
  1102  						Type:  smartcontract.Hash160Type,
  1103  						Value: hash,
  1104  					},
  1105  				}, []transaction.Signer{{
  1106  					Account: util.Uint160{1, 2, 3},
  1107  				}})
  1108  			},
  1109  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"script":"FCaufGyYYexBhGjB8P3Ep/KWPriRUcEJYmFsYW5jZU9mZ74557Vi9gy/4q68o3Wi5e4oc3yv","state":"FAULT","gasconsumed":"31100000","stack":[{"type":"ByteString","value":"JivsCEQy"}],"tx":"AAgAAACAlpgAAAAAAAIEEwAAAAAAsAQAAAGqis+FnU/kArNOZz8hVoIXlqSI6wEAVwHoAwwUqorPhZ1P5AKzTmc/IVaCF5akiOsMFOeetm08E0pKd27oB9LluEbdpP2wE8AMCHRyYW5zZmVyDBTnnrZtPBNKSndu6AfS5bhG3aT9sEFifVtSOAFCDEDYNAh3TUvYsZrocFYdBvJ0Trdnj1jRuQzy9Q6YroP2Cwgk4v7q3vbeZBikz8Q7vB+RbDPsWUy+ZiqdkkeG4XoUKQwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CC0GVRA14","exception":"gas limit exceeded"}}`,
  1110  			result: func(c *Client) any {
  1111  				return &result.Invoke{}
  1112  			},
  1113  			check: func(t *testing.T, c *Client, uns any) {
  1114  				res, ok := uns.(*result.Invoke)
  1115  				require.True(t, ok)
  1116  				bytes, err := hex.DecodeString("262bec084432")
  1117  				if err != nil {
  1118  					panic(err)
  1119  				}
  1120  				script, err := base64.StdEncoding.DecodeString("FCaufGyYYexBhGjB8P3Ep/KWPriRUcEJYmFsYW5jZU9mZ74557Vi9gy/4q68o3Wi5e4oc3yv")
  1121  				if err != nil {
  1122  					panic(err)
  1123  				}
  1124  				assert.Equal(t, "FAULT", res.State)
  1125  				assert.Equal(t, int64(31100000), res.GasConsumed)
  1126  				assert.Equal(t, script, res.Script)
  1127  				assert.Equal(t, []stackitem.Item{stackitem.NewByteArray(bytes)}, res.Stack)
  1128  				assert.NotNil(t, res.Transaction)
  1129  			},
  1130  		},
  1131  	},
  1132  	"invokescript": {
  1133  		{
  1134  			name: "positive",
  1135  			invoke: func(c *Client) (any, error) {
  1136  				script, err := base64.StdEncoding.DecodeString("AARuYW1lZyQFjl4bYAiEfNZicoVJCIqe6CGR")
  1137  				if err != nil {
  1138  					panic(err)
  1139  				}
  1140  				return c.InvokeScript(script, []transaction.Signer{{
  1141  					Account: util.Uint160{1, 2, 3},
  1142  				}})
  1143  			},
  1144  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"script":"AARuYW1lZyQFjl4bYAiEfNZicoVJCIqe6CGR","state":"HALT","gasconsumed":"16100000","stack":[{"type":"ByteString","value":"TkVQNSBHQVM="}],"tx":null}}`,
  1145  			result: func(c *Client) any {
  1146  				bytes, err := hex.DecodeString("4e45503520474153")
  1147  				if err != nil {
  1148  					panic(err)
  1149  				}
  1150  				script, err := base64.StdEncoding.DecodeString("AARuYW1lZyQFjl4bYAiEfNZicoVJCIqe6CGR")
  1151  				if err != nil {
  1152  					panic(err)
  1153  				}
  1154  				return &result.Invoke{
  1155  					State:       "HALT",
  1156  					GasConsumed: 16100000,
  1157  					Script:      script,
  1158  					Stack:       []stackitem.Item{stackitem.NewByteArray(bytes)},
  1159  				}
  1160  			},
  1161  		},
  1162  	},
  1163  	"invokecontractverify": {
  1164  		{
  1165  			name: "positive",
  1166  			invoke: func(c *Client) (any, error) {
  1167  				contr, err := util.Uint160DecodeStringLE("af7c7328eee5a275a3bcaee2bf0cf662b5e739be")
  1168  				if err != nil {
  1169  					panic(err)
  1170  				}
  1171  				return c.InvokeContractVerify(contr, nil, []transaction.Signer{{Account: util.Uint160{1, 2, 3}}}, transaction.Witness{InvocationScript: []byte{1, 2, 3}})
  1172  			},
  1173  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"script":"FCaufGyYYexBhGjB8P3Ep/KWPriRUcEJYmFsYW5jZU9mZ74557Vi9gy/4q68o3Wi5e4oc3yv","state":"HALT","gasconsumed":"31100000","stack":[{"type":"ByteString","value":"JivsCEQy"}],"tx":"AAgAAACAlpgAAAAAAAIEEwAAAAAAsAQAAAGqis+FnU/kArNOZz8hVoIXlqSI6wEAVwHoAwwUqorPhZ1P5AKzTmc/IVaCF5akiOsMFOeetm08E0pKd27oB9LluEbdpP2wE8AMCHRyYW5zZmVyDBTnnrZtPBNKSndu6AfS5bhG3aT9sEFifVtSOAFCDEDYNAh3TUvYsZrocFYdBvJ0Trdnj1jRuQzy9Q6YroP2Cwgk4v7q3vbeZBikz8Q7vB+RbDPsWUy+ZiqdkkeG4XoUKQwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CC0GVRA14"}}`,
  1174  			result: func(c *Client) any {
  1175  				return &result.Invoke{}
  1176  			},
  1177  			check: func(t *testing.T, c *Client, uns any) {
  1178  				res, ok := uns.(*result.Invoke)
  1179  				require.True(t, ok)
  1180  				bytes, err := hex.DecodeString("262bec084432")
  1181  				if err != nil {
  1182  					panic(err)
  1183  				}
  1184  				script, err := base64.StdEncoding.DecodeString("FCaufGyYYexBhGjB8P3Ep/KWPriRUcEJYmFsYW5jZU9mZ74557Vi9gy/4q68o3Wi5e4oc3yv")
  1185  				if err != nil {
  1186  					panic(err)
  1187  				}
  1188  				assert.Equal(t, "HALT", res.State)
  1189  				assert.Equal(t, int64(31100000), res.GasConsumed)
  1190  				assert.Equal(t, script, res.Script)
  1191  				assert.Equal(t, []stackitem.Item{stackitem.NewByteArray(bytes)}, res.Stack)
  1192  				assert.NotNil(t, res.Transaction)
  1193  			},
  1194  		},
  1195  		{
  1196  			name: "bad witness number",
  1197  			invoke: func(c *Client) (any, error) {
  1198  				return c.InvokeContractVerify(util.Uint160{}, nil, []transaction.Signer{{}}, []transaction.Witness{{}, {}}...)
  1199  			},
  1200  			fails: true,
  1201  		},
  1202  	},
  1203  	"sendrawtransaction": {
  1204  		{
  1205  			name: "positive",
  1206  			invoke: func(c *Client) (any, error) {
  1207  				return c.SendRawTransaction(transaction.New([]byte{byte(opcode.PUSH1)}, 0))
  1208  			},
  1209  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"hash":"0x72159b0cf1221110daad6e1df6ef4ff03012173b63c86910bd7134deb659c875"}}`,
  1210  			result: func(c *Client) any {
  1211  				h, err := util.Uint256DecodeStringLE("72159b0cf1221110daad6e1df6ef4ff03012173b63c86910bd7134deb659c875")
  1212  				if err != nil {
  1213  					panic(fmt.Errorf("can't decode `sendrawtransaction` result hash: %w", err))
  1214  				}
  1215  				return h
  1216  			},
  1217  		},
  1218  	},
  1219  	"submitblock": {
  1220  		{
  1221  			name: "positive",
  1222  			invoke: func(c *Client) (any, error) {
  1223  				return c.SubmitBlock(block.Block{
  1224  					Header:       block.Header{},
  1225  					Transactions: nil,
  1226  					Trimmed:      false,
  1227  				})
  1228  			},
  1229  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"hash":"0x1bdea8f80eb5bd97fade38d5e7fb93b02c9d3e01394e9f4324218132293f7ea6"}}`,
  1230  			result: func(c *Client) any {
  1231  				h, err := util.Uint256DecodeStringLE("1bdea8f80eb5bd97fade38d5e7fb93b02c9d3e01394e9f4324218132293f7ea6")
  1232  				if err != nil {
  1233  					panic(fmt.Errorf("can't decode `submitblock` result hash: %w", err))
  1234  				}
  1235  				return h
  1236  			},
  1237  		},
  1238  	},
  1239  	"validateaddress": {
  1240  		{
  1241  			name: "positive",
  1242  			invoke: func(c *Client) (any, error) {
  1243  				return nil, c.ValidateAddress("AQVh2pG732YvtNaxEGkQUei3YA4cvo7d2i")
  1244  			},
  1245  			serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"address":"AQVh2pG732YvtNaxEGkQUei3YA4cvo7d2i","isvalid":true}}`,
  1246  			result: func(c *Client) any {
  1247  				// no error expected
  1248  				return nil
  1249  			},
  1250  		},
  1251  	},
  1252  	"getrawnotarytransaction": {
  1253  		{
  1254  			name: "positive",
  1255  			invoke: func(c *Client) (any, error) {
  1256  				hash, err := util.Uint256DecodeStringLE("ad1c2875de823a54188949490e2d68580fd070fcc5ff409609f478d23d12355f")
  1257  				if err != nil {
  1258  					panic(err)
  1259  				}
  1260  				return c.GetRawNotaryTransaction(hash)
  1261  			},
  1262  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":"AAMAAAAAAAAAAAAAAAAAAAAAAAAAewAAAAHunqIsJ+NL0BSPxBCOCPdOj1BIsgABIgEBQAEDAQQHAwMGCQ=="}`,
  1263  			result: func(c *Client) any {
  1264  				return &transaction.Transaction{}
  1265  			},
  1266  			check: func(t *testing.T, c *Client, uns any) {
  1267  				res, ok := uns.(*transaction.Transaction)
  1268  				require.True(t, ok)
  1269  				assert.NotNil(t, res)
  1270  				expectHash, err := util.Uint256DecodeStringLE("ad1c2875de823a54188949490e2d68580fd070fcc5ff409609f478d23d12355f")
  1271  				require.NoError(t, err)
  1272  				assert.Equal(t, expectHash, res.Hash())
  1273  			},
  1274  		},
  1275  		{
  1276  			name: "positive verbose",
  1277  			invoke: func(c *Client) (any, error) {
  1278  				hash, err := util.Uint256DecodeStringLE("ad1c2875de823a54188949490e2d68580fd070fcc5ff409609f478d23d12355f")
  1279  				if err != nil {
  1280  					panic(err)
  1281  				}
  1282  				return c.GetRawNotaryTransactionVerbose(hash)
  1283  			},
  1284  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0xad1c2875de823a54188949490e2d68580fd070fcc5ff409609f478d23d12355f","size":61,"version":0,"nonce":3,"sender":"Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn","sysfee":"0","netfee":"0","validuntilblock":123,"attributes":[{"nkeys":1,"type":"NotaryAssisted"}],"signers":[{"account":"0xb248508f4ef7088e10c48f14d04be3272ca29eee","scopes":"None"}],"script":"QA==","witnesses":[{"invocation":"AQQH","verification":"AwYJ"}]}}`,
  1285  			result: func(c *Client) any {
  1286  				return &transaction.Transaction{}
  1287  			},
  1288  			check: func(t *testing.T, c *Client, uns any) {
  1289  				res, ok := uns.(*transaction.Transaction)
  1290  				require.True(t, ok)
  1291  				assert.NotNil(t, res)
  1292  				expectHash, err := util.Uint256DecodeStringLE("ad1c2875de823a54188949490e2d68580fd070fcc5ff409609f478d23d12355f")
  1293  				require.NoError(t, err)
  1294  				assert.Equal(t, expectHash, res.Hash())
  1295  			},
  1296  		},
  1297  	},
  1298  	"getrawnotarypool": {
  1299  		{
  1300  			name: "empty pool",
  1301  			invoke: func(c *Client) (any, error) {
  1302  				return c.GetRawNotaryPool()
  1303  			},
  1304  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":{}}`,
  1305  			result: func(c *Client) any {
  1306  				return &result.RawNotaryPool{
  1307  					Hashes: map[util.Uint256][]util.Uint256{},
  1308  				}
  1309  			},
  1310  		},
  1311  		{
  1312  			name: "nonempty pool",
  1313  			invoke: func(c *Client) (any, error) {
  1314  				return c.GetRawNotaryPool()
  1315  			},
  1316  			serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hashes":{"0xd86b5346e9bbe6dba845cc4192fa716535a3d05c4f2084431edc99dc3862a299":["0xbb0b2f1d5539dd776637f00e5011d97921a1400d3a63c02977a38446180c6d7c"]}}}`,
  1317  			result: func(c *Client) any {
  1318  				return &result.RawNotaryPool{
  1319  					Hashes: map[util.Uint256][]util.Uint256{},
  1320  				}
  1321  			},
  1322  			check: func(t *testing.T, c *Client, uns any) {
  1323  				res, ok := uns.(*result.RawNotaryPool)
  1324  				require.True(t, ok)
  1325  				mainHash, err := util.Uint256DecodeStringLE("d86b5346e9bbe6dba845cc4192fa716535a3d05c4f2084431edc99dc3862a299")
  1326  				require.NoError(t, err, "can't decode `mainHash` result hash")
  1327  				fallbackHash, err := util.Uint256DecodeStringLE("bb0b2f1d5539dd776637f00e5011d97921a1400d3a63c02977a38446180c6d7c")
  1328  				require.NoError(t, err, "can't decode `fallbackHash` result hash")
  1329  				fallbacks, ok := res.Hashes[mainHash]
  1330  				require.True(t, ok)
  1331  				assert.Equal(t, fallbacks[0], fallbackHash)
  1332  			},
  1333  		},
  1334  	},
  1335  }
  1336  
  1337  type rpcClientErrorCase struct {
  1338  	name   string
  1339  	invoke func(c *Client) (any, error)
  1340  }
  1341  
  1342  var rpcClientErrorCases = map[string][]rpcClientErrorCase{
  1343  	`{"jsonrpc":"2.0","id":1,"result":{"name":"name","bad":42}}`: {
  1344  		{
  1345  			name: "getnep11properties_unmarshalling_error",
  1346  			invoke: func(c *Client) (any, error) {
  1347  				return c.GetNEP11Properties(util.Uint160{}, []byte{})
  1348  			},
  1349  		},
  1350  	},
  1351  	`{"jsonrpc":"2.0","id":1,"result":{"name":100500,"good":"c29tZXRoaW5n"}}`: {
  1352  		{
  1353  			name: "getnep11properties_unmarshalling_error",
  1354  			invoke: func(c *Client) (any, error) {
  1355  				return c.GetNEP11Properties(util.Uint160{}, []byte{})
  1356  			},
  1357  		},
  1358  	},
  1359  	`{"jsonrpc":"2.0","id":1,"result":"not-a-hex-string"}`: {
  1360  		{
  1361  			name: "getblock_not_a_hex_response",
  1362  			invoke: func(c *Client) (any, error) {
  1363  				return c.GetBlockByIndex(1)
  1364  			},
  1365  		},
  1366  		{
  1367  			name: "getblockheader_not_a_hex_response",
  1368  			invoke: func(c *Client) (any, error) {
  1369  				hash, err := util.Uint256DecodeStringLE("e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c")
  1370  				if err != nil {
  1371  					panic(err)
  1372  				}
  1373  				return c.GetBlockHeader(hash)
  1374  			},
  1375  		},
  1376  		{
  1377  			name: "getrawtransaction_not_a_hex_response",
  1378  			invoke: func(c *Client) (any, error) {
  1379  				hash, err := util.Uint256DecodeStringLE("e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c")
  1380  				if err != nil {
  1381  					panic(err)
  1382  				}
  1383  				return c.GetRawTransaction(hash)
  1384  			},
  1385  		},
  1386  		{
  1387  			name: "getstoragebyhash_not_a_hex_response",
  1388  			invoke: func(c *Client) (any, error) {
  1389  				hash, err := util.Uint160DecodeStringLE("03febccf81ac85e3d795bc5cbd4e84e907812aa3")
  1390  				if err != nil {
  1391  					panic(err)
  1392  				}
  1393  				key, err := hex.DecodeString("5065746572")
  1394  				if err != nil {
  1395  					panic(err)
  1396  				}
  1397  				return c.GetStorageByHash(hash, key)
  1398  			},
  1399  		},
  1400  		{
  1401  			name: "getstoragebyid_not_a_hex_response",
  1402  			invoke: func(c *Client) (any, error) {
  1403  				key, err := hex.DecodeString("5065746572")
  1404  				if err != nil {
  1405  					panic(err)
  1406  				}
  1407  				return c.GetStorageByID(-1, key)
  1408  			},
  1409  		},
  1410  	},
  1411  	`{"jsonrpc":"2.0","id":1,"result":"01"}`: {
  1412  		{
  1413  			name: "getblock_decodebin_error",
  1414  			invoke: func(c *Client) (any, error) {
  1415  				return c.GetBlockByIndex(1)
  1416  			},
  1417  		},
  1418  		{
  1419  			name: "getheader_decodebin_err",
  1420  			invoke: func(c *Client) (any, error) {
  1421  				hash, err := util.Uint256DecodeStringLE("e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c")
  1422  				if err != nil {
  1423  					panic(err)
  1424  				}
  1425  				return c.GetBlockHeader(hash)
  1426  			},
  1427  		},
  1428  		{
  1429  			name: "getrawtransaction_decodebin_err",
  1430  			invoke: func(c *Client) (any, error) {
  1431  				hash, err := util.Uint256DecodeStringLE("e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c")
  1432  				if err != nil {
  1433  					panic(err)
  1434  				}
  1435  				return c.GetRawTransaction(hash)
  1436  			},
  1437  		},
  1438  	},
  1439  	`{"jsonrpc":"2.0","id":1,"result":false}`: {
  1440  		{
  1441  			name: "sendrawtransaction_bad_server_answer",
  1442  			invoke: func(c *Client) (any, error) {
  1443  				return c.SendRawTransaction(transaction.New([]byte{byte(opcode.PUSH1)}, 0))
  1444  			},
  1445  		},
  1446  		{
  1447  			name: "submitblock_bad_server_answer",
  1448  			invoke: func(c *Client) (any, error) {
  1449  				return c.SubmitBlock(block.Block{
  1450  					Header:       block.Header{},
  1451  					Transactions: nil,
  1452  					Trimmed:      false,
  1453  				})
  1454  			},
  1455  		},
  1456  		{
  1457  			name: "validateaddress_bad_server_answer",
  1458  			invoke: func(c *Client) (any, error) {
  1459  				return nil, c.ValidateAddress("AQVh2pG732YvtNaxEGkQUei3YA4cvo7d2i")
  1460  			},
  1461  		},
  1462  	},
  1463  	`{"id":1,"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params"}}`: {
  1464  		{
  1465  			name: "getapplicationlog_invalid_params_error",
  1466  			invoke: func(c *Client) (any, error) {
  1467  				return c.GetApplicationLog(util.Uint256{}, nil)
  1468  			},
  1469  		},
  1470  		{
  1471  			name: "getbestblockhash_invalid_params_error",
  1472  			invoke: func(c *Client) (any, error) {
  1473  				return c.GetBestBlockHash()
  1474  			},
  1475  		},
  1476  		{
  1477  			name: "getblock_byindex_invalid_params_error",
  1478  			invoke: func(c *Client) (any, error) {
  1479  				return c.GetBlockByIndex(1)
  1480  			},
  1481  		},
  1482  		{
  1483  			name: "getblock_byindex_verbose_invalid_params_error",
  1484  			invoke: func(c *Client) (any, error) {
  1485  				return c.GetBlockByIndexVerbose(1)
  1486  			},
  1487  		},
  1488  		{
  1489  			name: "getblock_byhash_invalid_params_error",
  1490  			invoke: func(c *Client) (any, error) {
  1491  				return c.GetBlockByHash(util.Uint256{})
  1492  			},
  1493  		},
  1494  		{
  1495  			name: "getblock_byhash_verbose_invalid_params_error",
  1496  			invoke: func(c *Client) (any, error) {
  1497  				return c.GetBlockByHashVerbose(util.Uint256{})
  1498  			},
  1499  		},
  1500  		{
  1501  			name: "getblockhash_invalid_params_error",
  1502  			invoke: func(c *Client) (any, error) {
  1503  				return c.GetBlockHash(0)
  1504  			},
  1505  		},
  1506  		{
  1507  			name: "getblockheader_invalid_params_error",
  1508  			invoke: func(c *Client) (any, error) {
  1509  				return c.GetBlockHeader(util.Uint256{})
  1510  			},
  1511  		},
  1512  		{
  1513  			name: "getblockheader_verbose_invalid_params_error",
  1514  			invoke: func(c *Client) (any, error) {
  1515  				return c.GetBlockHeaderVerbose(util.Uint256{})
  1516  			},
  1517  		},
  1518  		{
  1519  			name: "getblocksysfee_invalid_params_error",
  1520  			invoke: func(c *Client) (any, error) {
  1521  				return c.GetBlockSysFee(1)
  1522  			},
  1523  		},
  1524  		{
  1525  			name: "getconnectioncount_invalid_params_error",
  1526  			invoke: func(c *Client) (any, error) {
  1527  				return c.GetConnectionCount()
  1528  			},
  1529  		},
  1530  		{
  1531  			name: "getcontractstate_invalid_params_error",
  1532  			invoke: func(c *Client) (any, error) {
  1533  				return c.GetContractStateByHash(util.Uint160{})
  1534  			},
  1535  		},
  1536  		{
  1537  			name: "getnep11balances_invalid_params_error",
  1538  			invoke: func(c *Client) (any, error) {
  1539  				return c.GetNEP11Balances(util.Uint160{})
  1540  			},
  1541  		},
  1542  		{
  1543  			name: "getnep17balances_invalid_params_error",
  1544  			invoke: func(c *Client) (any, error) {
  1545  				return c.GetNEP17Balances(util.Uint160{})
  1546  			},
  1547  		},
  1548  		{
  1549  			name: "getnep11properties_invalid_params_error",
  1550  			invoke: func(c *Client) (any, error) {
  1551  				return c.GetNEP11Properties(util.Uint160{}, []byte{})
  1552  			},
  1553  		},
  1554  		{
  1555  			name: "getnep11transfers_invalid_params_error",
  1556  			invoke: func(c *Client) (any, error) {
  1557  				return c.GetNEP11Transfers(util.Uint160{}, nil, nil, nil, nil)
  1558  			},
  1559  		},
  1560  		{
  1561  			name: "getnep17transfers_invalid_params_error",
  1562  			invoke: func(c *Client) (any, error) {
  1563  				return c.GetNEP17Transfers(util.Uint160{}, nil, nil, nil, nil)
  1564  			},
  1565  		},
  1566  		{
  1567  			name: "getnep17transfers_invalid_params_error 2",
  1568  			invoke: func(c *Client) (any, error) {
  1569  				var stop uint64
  1570  				return c.GetNEP17Transfers(util.Uint160{}, nil, &stop, nil, nil)
  1571  			},
  1572  		},
  1573  		{
  1574  			name: "getnep17transfers_invalid_params_error 3",
  1575  			invoke: func(c *Client) (any, error) {
  1576  				var start uint64
  1577  				var limit int
  1578  				return c.GetNEP17Transfers(util.Uint160{}, &start, nil, &limit, nil)
  1579  			},
  1580  		},
  1581  		{
  1582  			name: "getnep17transfers_invalid_params_error 4",
  1583  			invoke: func(c *Client) (any, error) {
  1584  				var start, stop uint64
  1585  				var page int
  1586  				return c.GetNEP17Transfers(util.Uint160{}, &start, &stop, nil, &page)
  1587  			},
  1588  		},
  1589  		{
  1590  			name: "getrawtransaction_invalid_params_error",
  1591  			invoke: func(c *Client) (any, error) {
  1592  				return c.GetRawTransaction(util.Uint256{})
  1593  			},
  1594  		},
  1595  		{
  1596  			name: "getrawtransaction_verbose_invalid_params_error",
  1597  			invoke: func(c *Client) (any, error) {
  1598  				return c.GetRawTransactionVerbose(util.Uint256{})
  1599  			},
  1600  		},
  1601  		{
  1602  			name: "getstoragebyhash_invalid_params_error",
  1603  			invoke: func(c *Client) (any, error) {
  1604  				return c.GetStorageByHash(util.Uint160{}, []byte{})
  1605  			},
  1606  		},
  1607  		{
  1608  			name: "getstoragebyid_invalid_params_error",
  1609  			invoke: func(c *Client) (any, error) {
  1610  				return c.GetStorageByID(-1, []byte{})
  1611  			},
  1612  		},
  1613  		{
  1614  			name: "gettransactionheight_invalid_params_error",
  1615  			invoke: func(c *Client) (any, error) {
  1616  				return c.GetTransactionHeight(util.Uint256{})
  1617  			},
  1618  		},
  1619  		{
  1620  			name: "getunclaimedgas_invalid_params_error",
  1621  			invoke: func(c *Client) (any, error) {
  1622  				return c.GetUnclaimedGas("")
  1623  			},
  1624  		},
  1625  		{
  1626  			name: "invokefunction_invalid_params_error",
  1627  			invoke: func(c *Client) (any, error) {
  1628  				return c.InvokeFunction(util.Uint160{}, "", []smartcontract.Parameter{}, nil)
  1629  			},
  1630  		},
  1631  		{
  1632  			name: "invokescript_invalid_params_error",
  1633  			invoke: func(c *Client) (any, error) {
  1634  				return c.InvokeScript([]byte{}, nil)
  1635  			},
  1636  		},
  1637  		{
  1638  			name: "sendrawtransaction_invalid_params_error",
  1639  			invoke: func(c *Client) (any, error) {
  1640  				return c.SendRawTransaction(&transaction.Transaction{})
  1641  			},
  1642  		},
  1643  		{
  1644  			name: "submitblock_invalid_params_error",
  1645  			invoke: func(c *Client) (any, error) {
  1646  				return c.SubmitBlock(block.Block{})
  1647  			},
  1648  		},
  1649  		{
  1650  			name: "validateaddress_invalid_params_error",
  1651  			invoke: func(c *Client) (any, error) {
  1652  				return nil, c.ValidateAddress("")
  1653  			},
  1654  		},
  1655  	},
  1656  	`{}`: {
  1657  		{
  1658  			name: "getapplicationlog_unmarshalling_error",
  1659  			invoke: func(c *Client) (any, error) {
  1660  				return c.GetApplicationLog(util.Uint256{}, nil)
  1661  			},
  1662  		},
  1663  		{
  1664  			name: "getbestblockhash_unmarshalling_error",
  1665  			invoke: func(c *Client) (any, error) {
  1666  				return c.GetBestBlockHash()
  1667  			},
  1668  		},
  1669  		{
  1670  			name: "getblock_byindex_unmarshalling_error",
  1671  			invoke: func(c *Client) (any, error) {
  1672  				return c.GetBlockByIndex(1)
  1673  			},
  1674  		},
  1675  		{
  1676  			name: "getblock_byindex_verbose_unmarshalling_error",
  1677  			invoke: func(c *Client) (any, error) {
  1678  				return c.GetBlockByIndexVerbose(1)
  1679  			},
  1680  		},
  1681  		{
  1682  			name: "getblock_byhash_unmarshalling_error",
  1683  			invoke: func(c *Client) (any, error) {
  1684  				return c.GetBlockByHash(util.Uint256{})
  1685  			},
  1686  		},
  1687  		{
  1688  			name: "getblock_byhash_verbose_unmarshalling_error",
  1689  			invoke: func(c *Client) (any, error) {
  1690  				return c.GetBlockByHashVerbose(util.Uint256{})
  1691  			},
  1692  		},
  1693  		{
  1694  			name: "getblockcount_unmarshalling_error",
  1695  			invoke: func(c *Client) (any, error) {
  1696  				return c.GetBlockCount()
  1697  			},
  1698  		},
  1699  		{
  1700  			name: "getblockhash_unmarshalling_error",
  1701  			invoke: func(c *Client) (any, error) {
  1702  				return c.GetBlockHash(1)
  1703  			},
  1704  		},
  1705  		{
  1706  			name: "getblockheader_unmarshalling_error",
  1707  			invoke: func(c *Client) (any, error) {
  1708  				return c.GetBlockHeader(util.Uint256{})
  1709  			},
  1710  		},
  1711  		{
  1712  			name: "getblockheader_verbose_unmarshalling_error",
  1713  			invoke: func(c *Client) (any, error) {
  1714  				return c.GetBlockHeaderVerbose(util.Uint256{})
  1715  			},
  1716  		},
  1717  		{
  1718  			name: "getblocksysfee_unmarshalling_error",
  1719  			invoke: func(c *Client) (any, error) {
  1720  				return c.GetBlockSysFee(1)
  1721  			},
  1722  		},
  1723  		{
  1724  			name: "getcommittee_unmarshalling_error",
  1725  			invoke: func(c *Client) (any, error) {
  1726  				return c.GetCommittee()
  1727  			},
  1728  		},
  1729  		{
  1730  			name: "getconnectioncount_unmarshalling_error",
  1731  			invoke: func(c *Client) (any, error) {
  1732  				return c.GetConnectionCount()
  1733  			},
  1734  		},
  1735  		{
  1736  			name: "getcontractstate_unmarshalling_error",
  1737  			invoke: func(c *Client) (any, error) {
  1738  				return c.GetContractStateByHash(util.Uint160{})
  1739  			},
  1740  		},
  1741  		{
  1742  			name: "getnep11balances_unmarshalling_error",
  1743  			invoke: func(c *Client) (any, error) {
  1744  				return c.GetNEP11Balances(util.Uint160{})
  1745  			},
  1746  		},
  1747  		{
  1748  			name: "getnep17balances_unmarshalling_error",
  1749  			invoke: func(c *Client) (any, error) {
  1750  				return c.GetNEP17Balances(util.Uint160{})
  1751  			},
  1752  		},
  1753  		{
  1754  			name: "getnep11transfers_unmarshalling_error",
  1755  			invoke: func(c *Client) (any, error) {
  1756  				return c.GetNEP11Transfers(util.Uint160{}, nil, nil, nil, nil)
  1757  			},
  1758  		},
  1759  		{
  1760  			name: "getnep17transfers_unmarshalling_error",
  1761  			invoke: func(c *Client) (any, error) {
  1762  				return c.GetNEP17Transfers(util.Uint160{}, nil, nil, nil, nil)
  1763  			},
  1764  		},
  1765  		{
  1766  			name: "getpeers_unmarshalling_error",
  1767  			invoke: func(c *Client) (any, error) {
  1768  				return c.GetPeers()
  1769  			},
  1770  		},
  1771  		{
  1772  			name: "getrawmempool_unmarshalling_error",
  1773  			invoke: func(c *Client) (any, error) {
  1774  				return c.GetRawMemPool()
  1775  			},
  1776  		},
  1777  		{
  1778  			name: "getrawtransaction_unmarshalling_error",
  1779  			invoke: func(c *Client) (any, error) {
  1780  				return c.GetRawTransaction(util.Uint256{})
  1781  			},
  1782  		},
  1783  		{
  1784  			name: "getrawtransaction_verbose_unmarshalling_error",
  1785  			invoke: func(c *Client) (any, error) {
  1786  				return c.GetRawTransactionVerbose(util.Uint256{})
  1787  			},
  1788  		},
  1789  		{
  1790  			name: "getstoragebyhash_unmarshalling_error",
  1791  			invoke: func(c *Client) (any, error) {
  1792  				return c.GetStorageByHash(util.Uint160{}, []byte{})
  1793  			},
  1794  		},
  1795  		{
  1796  			name: "getstoragebyid_unmarshalling_error",
  1797  			invoke: func(c *Client) (any, error) {
  1798  				return c.GetStorageByID(-1, []byte{})
  1799  			},
  1800  		},
  1801  		{
  1802  			name: "gettransactionheight_unmarshalling_error",
  1803  			invoke: func(c *Client) (any, error) {
  1804  				return c.GetTransactionHeight(util.Uint256{})
  1805  			},
  1806  		},
  1807  		{
  1808  			name: "getunclaimedgas_unmarshalling_error",
  1809  			invoke: func(c *Client) (any, error) {
  1810  				return c.GetUnclaimedGas("")
  1811  			},
  1812  		},
  1813  		{
  1814  			name: "getcandidates_unmarshalling_error",
  1815  			invoke: func(c *Client) (any, error) {
  1816  				return c.GetCandidates()
  1817  			},
  1818  		},
  1819  		{
  1820  			name: "getvalidators_unmarshalling_error",
  1821  			invoke: func(c *Client) (any, error) {
  1822  				return c.GetNextBlockValidators()
  1823  			},
  1824  		},
  1825  		{
  1826  			name: "invokefunction_unmarshalling_error",
  1827  			invoke: func(c *Client) (any, error) {
  1828  				return c.InvokeFunction(util.Uint160{}, "", []smartcontract.Parameter{}, nil)
  1829  			},
  1830  		},
  1831  		{
  1832  			name: "invokescript_unmarshalling_error",
  1833  			invoke: func(c *Client) (any, error) {
  1834  				return c.InvokeScript([]byte{}, nil)
  1835  			},
  1836  		},
  1837  		{
  1838  			name: "sendrawtransaction_unmarshalling_error",
  1839  			invoke: func(c *Client) (any, error) {
  1840  				return c.SendRawTransaction(transaction.New([]byte{byte(opcode.PUSH1)}, 0))
  1841  			},
  1842  		},
  1843  		{
  1844  			name: "submitblock_unmarshalling_error",
  1845  			invoke: func(c *Client) (any, error) {
  1846  				return c.SubmitBlock(block.Block{
  1847  					Header:       block.Header{},
  1848  					Transactions: nil,
  1849  					Trimmed:      false,
  1850  				})
  1851  			},
  1852  		},
  1853  		{
  1854  			name: "validateaddress_unmarshalling_error",
  1855  			invoke: func(c *Client) (any, error) {
  1856  				return nil, c.ValidateAddress("")
  1857  			},
  1858  		},
  1859  	},
  1860  }
  1861  
  1862  func TestRPCClients(t *testing.T) {
  1863  	t.Run("Client", func(t *testing.T) {
  1864  		testRPCClient(t, func(ctx context.Context, endpoint string, opts Options) (*Client, error) {
  1865  			c, err := New(ctx, endpoint, opts)
  1866  			require.NoError(t, err)
  1867  			c.getNextRequestID = getTestRequestID
  1868  			require.NoError(t, c.Init())
  1869  			return c, nil
  1870  		})
  1871  	})
  1872  	t.Run("WSClient", func(t *testing.T) {
  1873  		testRPCClient(t, func(ctx context.Context, endpoint string, opts Options) (*Client, error) {
  1874  			wsc, err := NewWS(ctx, httpURLtoWS(endpoint), WSOptions{Options: opts})
  1875  			require.NoError(t, err)
  1876  			wsc.getNextRequestID = getTestRequestID
  1877  			require.NoError(t, wsc.Init())
  1878  			return &wsc.Client, nil
  1879  		})
  1880  	})
  1881  }
  1882  
  1883  func testRPCClient(t *testing.T, newClient func(context.Context, string, Options) (*Client, error)) {
  1884  	for method, testBatch := range rpcClientTestCases {
  1885  		t.Run(method, func(t *testing.T) {
  1886  			for _, testCase := range testBatch {
  1887  				t.Run(testCase.name, func(t *testing.T) {
  1888  					srv := initTestServer(t, testCase.serverResponse)
  1889  
  1890  					endpoint := srv.URL
  1891  					opts := Options{}
  1892  					c, err := newClient(context.TODO(), endpoint, opts)
  1893  					if err != nil {
  1894  						t.Fatal(err)
  1895  					}
  1896  					c.getNextRequestID = getTestRequestID
  1897  
  1898  					actual, err := testCase.invoke(c)
  1899  					if testCase.fails {
  1900  						assert.Error(t, err)
  1901  					} else {
  1902  						assert.NoError(t, err)
  1903  
  1904  						expected := testCase.result(c)
  1905  						if testCase.check == nil {
  1906  							assert.Equal(t, expected, actual)
  1907  						} else {
  1908  							testCase.check(t, c, actual)
  1909  						}
  1910  					}
  1911  				})
  1912  			}
  1913  		})
  1914  	}
  1915  	for serverResponse, testBatch := range rpcClientErrorCases {
  1916  		srv := initTestServer(t, serverResponse)
  1917  
  1918  		endpoint := srv.URL
  1919  		opts := Options{}
  1920  		for _, testCase := range testBatch {
  1921  			t.Run(testCase.name, func(t *testing.T) {
  1922  				c, err := newClient(context.TODO(), endpoint, opts)
  1923  				if err != nil {
  1924  					t.Fatal(err)
  1925  				}
  1926  				c.getNextRequestID = getTestRequestID
  1927  				_, err = testCase.invoke(c)
  1928  				assert.Error(t, err)
  1929  			})
  1930  		}
  1931  	}
  1932  }
  1933  
  1934  func httpURLtoWS(url string) string {
  1935  	return "ws" + strings.TrimPrefix(url, "http") + "/ws"
  1936  }
  1937  
  1938  func initTestServer(t *testing.T, resp string) *httptest.Server {
  1939  	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
  1940  		if req.URL.Path == "/ws" && req.Method == "GET" {
  1941  			var upgrader = websocket.Upgrader{}
  1942  			ws, err := upgrader.Upgrade(w, req, nil)
  1943  			require.NoError(t, err)
  1944  			for {
  1945  				err = ws.SetReadDeadline(time.Now().Add(5 * time.Second))
  1946  				require.NoError(t, err)
  1947  				_, p, err := ws.ReadMessage()
  1948  				if err != nil {
  1949  					break
  1950  				}
  1951  				r := params.NewIn()
  1952  				err = json.Unmarshal(p, r)
  1953  				if err != nil {
  1954  					t.Fatalf("Cannot decode request body: %s", req.Body)
  1955  				}
  1956  				response := wrapInitResponse(r, resp)
  1957  				err = ws.SetWriteDeadline(time.Now().Add(5 * time.Second))
  1958  				require.NoError(t, err)
  1959  				err = ws.WriteMessage(1, []byte(response))
  1960  				if err != nil {
  1961  					break
  1962  				}
  1963  			}
  1964  			ws.Close()
  1965  			return
  1966  		}
  1967  		r := params.NewRequest()
  1968  		err := r.DecodeData(req.Body)
  1969  		if err != nil {
  1970  			t.Fatalf("Cannot decode request body: %s", req.Body)
  1971  		}
  1972  		requestHandler(t, r.In, w, resp)
  1973  	}))
  1974  
  1975  	t.Cleanup(srv.Close)
  1976  
  1977  	return srv
  1978  }
  1979  
  1980  func requestHandler(t *testing.T, r *params.In, w http.ResponseWriter, resp string) {
  1981  	w.Header().Set("Content-Type", "application/json; charset=utf-8")
  1982  	response := wrapInitResponse(r, resp)
  1983  	_, err := w.Write([]byte(response))
  1984  	if err != nil {
  1985  		t.Fatalf("Error writing response: %s", err.Error())
  1986  	}
  1987  }
  1988  
  1989  func wrapInitResponse(r *params.In, resp string) string {
  1990  	var response string
  1991  	switch r.Method {
  1992  	case "getversion":
  1993  		response = `{"id":1,"jsonrpc":"2.0","result":{"protocol":{"network":42},"tcpport":20332,"wsport":20342,"nonce":2153672787,"useragent":"/NEO-GO:0.73.1-pre-273-ge381358/", "rpc": {"maxiteratorresultitems": 100, "sessionenabled": true}}}`
  1994  	case "getnativecontracts":
  1995  		response = `{"jsonrpc":"2.0","id":1,"result":[{"id":-1,"hash":"0xfffdc93764dbaddd97c48f252a53ea4643faa3fd","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1110259869},"manifest":{"name":"ContractManagement","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"deploy","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"}],"returntype":"Array","offset":0,"safe":false},{"name":"deploy","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Array","offset":7,"safe":false},{"name":"destroy","parameters":[],"returntype":"Void","offset":14,"safe":false},{"name":"getContract","parameters":[{"name":"hash","type":"Hash160"}],"returntype":"Array","offset":21,"safe":true},{"name":"getMinimumDeploymentFee","parameters":[],"returntype":"Integer","offset":28,"safe":true},{"name":"setMinimumDeploymentFee","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":35,"safe":false},{"name":"update","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"}],"returntype":"Void","offset":42,"safe":false},{"name":"update","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Void","offset":49,"safe":false}],"events":[{"name":"Deploy","parameters":[{"name":"Hash","type":"Hash160"}]},{"name":"Update","parameters":[{"name":"Hash","type":"Hash160"}]},{"name":"Destroy","parameters":[{"name":"Hash","type":"Hash160"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null},"updatehistory":[0]},{"id":-2,"hash":"0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1325686241},"manifest":{"name":"StdLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"atoi","parameters":[{"name":"value","type":"String"}],"returntype":"Integer","offset":0,"safe":true},{"name":"atoi","parameters":[{"name":"value","type":"String"},{"name":"base","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"base58CheckDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":14,"safe":true},{"name":"base58CheckEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":21,"safe":true},{"name":"base58Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":28,"safe":true},{"name":"base58Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":35,"safe":true},{"name":"base64Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"base64Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":49,"safe":true},{"name":"deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"Any","offset":56,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"}],"returntype":"String","offset":63,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"},{"name":"base","type":"Integer"}],"returntype":"String","offset":70,"safe":true},{"name":"jsonDeserialize","parameters":[{"name":"json","type":"ByteArray"}],"returntype":"Any","offset":77,"safe":true},{"name":"jsonSerialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":84,"safe":true},{"name":"memoryCompare","parameters":[{"name":"str1","type":"ByteArray"},{"name":"str2","type":"ByteArray"}],"returntype":"Integer","offset":91,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"}],"returntype":"Integer","offset":98,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"}],"returntype":"Integer","offset":105,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"},{"name":"backward","type":"Boolean"}],"returntype":"Integer","offset":112,"safe":true},{"name":"serialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":119,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"}],"returntype":"Array","offset":126,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"},{"name":"removeEmptyEntries","type":"Boolean"}],"returntype":"Array","offset":133,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null},"updatehistory":[0]},{"id":-3,"hash":"0x726cb6e0cd8628a1350a611384688911ab75f51b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dA","checksum":1592866325},"manifest":{"name":"CryptoLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"ripemd160","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":0,"safe":true},{"name":"sha256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":7,"safe":true},{"name":"verifyWithECDsa","parameters":[{"name":"message","type":"ByteArray"},{"name":"pubkey","type":"ByteArray"},{"name":"signature","type":"ByteArray"},{"name":"curve","type":"Integer"}],"returntype":"Boolean","offset":14,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null},"updatehistory":[0]},{"id":-4,"hash":"0xda65b600f7124ce6c79950c1772a36403104f2be","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dA","checksum":529571427},"manifest":{"name":"LedgerContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"currentHash","parameters":[],"returntype":"Hash256","offset":0,"safe":true},{"name":"currentIndex","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getBlock","parameters":[{"name":"indexOrHash","type":"ByteArray"}],"returntype":"Array","offset":14,"safe":true},{"name":"getTransaction","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":21,"safe":true},{"name":"getTransactionFromBlock","parameters":[{"name":"blockIndexOrHash","type":"ByteArray"},{"name":"txIndex","type":"Integer"}],"returntype":"Array","offset":28,"safe":true},{"name":"getTransactionHeight","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":35,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null},"updatehistory":[0]},{"id":-5,"hash":"0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":588003825},"manifest":{"name":"NeoToken","groups":[],"features":{},"supportedstandards":["NEP-17"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getAccountState","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Array","offset":14,"safe":true},{"name":"getCandidates","parameters":[],"returntype":"Array","offset":21,"safe":true},{"name":"getCommittee","parameters":[],"returntype":"Array","offset":28,"safe":true},{"name":"getGasPerBlock","parameters":[],"returntype":"Integer","offset":35,"safe":true},{"name":"getNextBlockValidators","parameters":[],"returntype":"Array","offset":42,"safe":true},{"name":"getRegisterPrice","parameters":[],"returntype":"Integer","offset":49,"safe":true},{"name":"registerCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":56,"safe":false},{"name":"setGasPerBlock","parameters":[{"name":"gasPerBlock","type":"Integer"}],"returntype":"Void","offset":63,"safe":false},{"name":"setRegisterPrice","parameters":[{"name":"registerPrice","type":"Integer"}],"returntype":"Void","offset":70,"safe":false},{"name":"symbol","parameters":[],"returntype":"String","offset":77,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":84,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":91,"safe":false},{"name":"unclaimedGas","parameters":[{"name":"account","type":"Hash160"},{"name":"end","type":"Integer"}],"returntype":"Integer","offset":98,"safe":true},{"name":"unregisterCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":105,"safe":false},{"name":"vote","parameters":[{"name":"account","type":"Hash160"},{"name":"voteTo","type":"PublicKey"}],"returntype":"Boolean","offset":112,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null},"updatehistory":[0]},{"id":-6,"hash":"0xd2a4cff31913016155e38e474a2c06d08be276cf","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2663858513},"manifest":{"name":"GasToken","groups":[],"features":{},"supportedstandards":["NEP-17"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"symbol","parameters":[],"returntype":"String","offset":14,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":21,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":28,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null},"updatehistory":[0]},{"id":-7,"hash":"0xcc5e4edd9f5f8dba8bb65734541df7a1c081c67b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dA","checksum":3443651689},"manifest":{"name":"PolicyContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"blockAccount","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":0,"safe":false},{"name":"getExecFeeFactor","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getFeePerByte","parameters":[],"returntype":"Integer","offset":14,"safe":true},{"name":"getStoragePrice","parameters":[],"returntype":"Integer","offset":21,"safe":true},{"name":"isBlocked","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":28,"safe":true},{"name":"setExecFeeFactor","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":35,"safe":false},{"name":"setFeePerByte","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":42,"safe":false},{"name":"setStoragePrice","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":49,"safe":false},{"name":"unblockAccount","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":56,"safe":false}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null},"updatehistory":[0]},{"id":-8,"hash":"0x49cf4e5378ffcd4dec034fd98a174c5491e395e2","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0A=","checksum":983638438},"manifest":{"name":"RoleManagement","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"designateAsRole","parameters":[{"name":"role","type":"Integer"},{"name":"nodes","type":"Array"}],"returntype":"Void","offset":0,"safe":false},{"name":"getDesignatedByRole","parameters":[{"name":"role","type":"Integer"},{"name":"index","type":"Integer"}],"returntype":"Array","offset":7,"safe":true}],"events":[{"name":"Designation","parameters":[{"name":"Role","type":"Integer"},{"name":"BlockIndex","type":"Integer"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null},"updatehistory":[0]},{"id":-9,"hash":"0xfe924b7cfe89ddd271abaf7210a80a7e11178758","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2663858513},"manifest":{"name":"OracleContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"finish","parameters":[],"returntype":"Void","offset":0,"safe":false},{"name":"getPrice","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"request","parameters":[{"name":"url","type":"String"},{"name":"filter","type":"String"},{"name":"callback","type":"String"},{"name":"userData","type":"Any"},{"name":"gasForResponse","type":"Integer"}],"returntype":"Void","offset":14,"safe":false},{"name":"setPrice","parameters":[{"name":"price","type":"Integer"}],"returntype":"Void","offset":21,"safe":false},{"name":"verify","parameters":[],"returntype":"Boolean","offset":28,"safe":true}],"events":[{"name":"OracleRequest","parameters":[{"name":"Id","type":"Integer"},{"name":"RequestContract","type":"Hash160"},{"name":"Url","type":"String"},{"name":"Filter","type":"String"}]},{"name":"OracleResponse","parameters":[{"name":"Id","type":"Integer"},{"name":"OriginalTx","type":"Hash256"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null},"updatehistory":[0]}]}`
  1996  	case "getcontractstate":
  1997  		p := params.Params(r.RawParams)
  1998  		name, _ := p.Value(0).GetString()
  1999  		switch name {
  2000  		case "NeoToken":
  2001  			response = `{"id":1,"jsonrpc":"2.0","result":{"id":-1,"script":"DANORU9Ba2d4Cw==","manifest":{"name":"NEO","abi":{"hash":"0xde5f57d430d3dece511cf975a8d37848cb9e0525","methods":[{"name":"name","offset":0,"parameters":null,"returntype":"String"},{"name":"symbol","offset":0,"parameters":null,"returntype":"String"},{"name":"decimals","offset":0,"parameters":null,"returntype":"Integer"},{"name":"totalSupply","offset":0,"parameters":null,"returntype":"Integer"},{"name":"balanceOf","offset":0,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer"},{"name":"transfer","offset":0,"parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}],"returntype":"Boolean"},{"name":"onPersist","offset":0,"parameters":null,"returntype":"Void"},{"name":"postPersist","offset":0,"parameters":null,"returntype":"Void"},{"name":"unclaimedGas","offset":0,"parameters":[{"name":"account","type":"Hash160"},{"name":"end","type":"Integer"}],"returntype":"Integer"},{"name":"registerCandidate","offset":0,"parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean"},{"name":"unregisterCandidate","offset":0,"parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean"},{"name":"vote","offset":0,"parameters":[{"name":"account","type":"Hash160"},{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean"},{"name":"getCandidates","offset":0,"parameters":null,"returntype":"Array"},{"name":"getДommittee","offset":0,"parameters":null,"returntype":"Array"},{"name":"getNextBlockValidators","offset":0,"parameters":null,"returntype":"Array"},{"name":"getGasPerBlock","offset":0,"parameters":null,"returntype":"Integer"},{"name":"setGasPerBlock","offset":0,"parameters":[{"name":"gasPerBlock","type":"Integer"}],"returntype":"Boolean"}],"events":[{"name":"Transfer","parameters":null}]},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":["NEP-5"],"trusts":[],"safemethods":["name","symbol","decimals","totalSupply","balanceOf","unclaimedGas","getCandidates","getДommittee","getNextBlockValidators"],"extra":null},"hash":"0xde5f57d430d3dece511cf975a8d37848cb9e0525"}}`
  2002  		case "GasToken":
  2003  			response = `{"id":1,"jsonrpc":"2.0","result":{"id":-2,"script":"DANHQVNBa2d4Cw==","manifest":{"name":"GAS","abi":{"hash":"0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc","methods":[{"name":"name","offset":0,"parameters":null,"returntype":"String"},{"name":"symbol","offset":0,"parameters":null,"returntype":"String"},{"name":"decimals","offset":0,"parameters":null,"returntype":"Integer"},{"name":"totalSupply","offset":0,"parameters":null,"returntype":"Integer"},{"name":"balanceOf","offset":0,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer"},{"name":"transfer","offset":0,"parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}],"returntype":"Boolean"},{"name":"onPersist","offset":0,"parameters":null,"returntype":"Void"},{"name":"postPersist","offset":0,"parameters":null,"returntype":"Void"}],"events":[{"name":"Transfer","parameters":null}]},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":["NEP-5"],"trusts":[],"safemethods":["name","symbol","decimals","totalSupply","balanceOf"],"extra":null},"hash":"0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"}}`
  2004  		case "PolicyContract":
  2005  			response = `{"id":1,"jsonrpc":"2.0","result":{"id":-3,"updatecounter":0,"hash":"0xac593e6183643940a9193f87c64ccf55ef19c529","script":"DAZQb2xpY3lBGvd7Zw==","manifest":{"name":"Policy","abi":{"methods":[{"name":"getMaxTransactionsPerBlock","offset":0,"parameters":null,"returntype":"Integer"},{"name":"getMaxBlockSize","offset":0,"parameters":null,"returntype":"Integer"},{"name":"getFeePerByte","offset":0,"parameters":null,"returntype":"Integer"},{"name":"isBlocked","offset":0,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean"},{"name":"getMaxBlockSystemFee","offset":0,"parameters":null,"returntype":"Integer"},{"name":"setMaxBlockSize","offset":0,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Boolean"},{"name":"setMaxTransactionsPerBlock","offset":0,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Boolean"},{"name":"setFeePerByte","offset":0,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Boolean"},{"name":"setMaxBlockSystemFee","offset":0,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Boolean"},{"name":"blockAccount","offset":0,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean"},{"name":"unblockAccount","offset":0,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean"}],"events":[]},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"safemethods":["getMaxTransactionsPerBlock","getMaxBlockSize","getFeePerByte","isBlocked","getMaxBlockSystemFee"],"extra":null}}}`
  2006  		default:
  2007  			response = resp
  2008  		}
  2009  	default:
  2010  		response = resp
  2011  	}
  2012  	return response
  2013  }
  2014  
  2015  func TestUninitedClient(t *testing.T) {
  2016  	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
  2017  		r := params.NewRequest()
  2018  		err := r.DecodeData(req.Body)
  2019  		require.NoErrorf(t, err, "Cannot decode request body: %s", req.Body)
  2020  		// request handler already have `getversion` response wrapper
  2021  		requestHandler(t, r.In, w, "")
  2022  	}))
  2023  	t.Cleanup(srv.Close)
  2024  	endpoint := srv.URL
  2025  	opts := Options{}
  2026  
  2027  	c, err := New(context.TODO(), endpoint, opts)
  2028  	require.NoError(t, err)
  2029  	c.getNextRequestID = getTestRequestID
  2030  
  2031  	_, err = c.GetBlockByIndex(0)
  2032  	require.Error(t, err)
  2033  	_, err = c.GetBlockByIndexVerbose(0)
  2034  	require.Error(t, err)
  2035  	_, err = c.GetBlockHeader(util.Uint256{})
  2036  	require.Error(t, err)
  2037  	_, err = c.GetRawTransaction(util.Uint256{})
  2038  	require.Error(t, err)
  2039  	_, err = c.GetRawTransactionVerbose(util.Uint256{})
  2040  	require.Error(t, err)
  2041  }
  2042  
  2043  func newTestNEF(script []byte) nef.File {
  2044  	var ne nef.File
  2045  	ne.Header.Magic = nef.Magic
  2046  	ne.Header.Compiler = "neo-go-3.0"
  2047  	ne.Script = script
  2048  	ne.Checksum = ne.CalculateChecksum()
  2049  	return ne
  2050  }
  2051  
  2052  func getTestRequestID() uint64 {
  2053  	return 1
  2054  }