rpc, cli: remove Network from RPC client and cli

This commit is contained in:
Anna Shaleva 2020-10-14 18:13:20 +03:00
parent 474d2dfb65
commit 590be7a58d
16 changed files with 206 additions and 80 deletions

View file

@ -17,7 +17,7 @@ func TestRegisterCandidate(t *testing.T) {
e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "nep5", "multitransfer",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet,
"--from", validatorAddr,
"neo:"+validatorPriv.Address()+":10",
@ -26,7 +26,7 @@ func TestRegisterCandidate(t *testing.T) {
e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "candidate", "register",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet,
"--address", validatorPriv.Address())
e.checkTxPersisted(t)
@ -40,7 +40,7 @@ func TestRegisterCandidate(t *testing.T) {
t.Run("Vote", func(t *testing.T) {
e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "candidate", "vote",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet,
"--address", validatorPriv.Address(),
"--candidate", hex.EncodeToString(validatorPriv.PublicKey().Bytes()))
@ -55,7 +55,7 @@ func TestRegisterCandidate(t *testing.T) {
e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "candidate", "unregister",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet,
"--address", validatorPriv.Address())
e.checkTxPersisted(t)

View file

@ -40,7 +40,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
e.In.WriteString("one\r")
e.Run(t, "neo-go", "contract", "deploy",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--address", validatorAddr,
"--in", nefName, "--manifest", manifestName)
@ -53,7 +53,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
e.In.WriteString("one\r")
e.Run(t, "neo-go", "contract", "testinvokefunction",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
h.StringLE(), "getValue")
res := new(result.Invoke)
@ -84,7 +84,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
e.In.WriteString("one\r")
e.Run(t, "neo-go", "contract", "invokefunction",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--address", validatorAddr,
h.StringLE(), "update",
"bytes:"+hex.EncodeToString(realNef.Script),
@ -94,7 +94,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
e.In.WriteString("one\r")
e.Run(t, "neo-go", "contract", "testinvokefunction",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
hash.Hash160(realNef.Script).StringLE(), "getValue")
res := new(result.Invoke)

View file

@ -53,7 +53,7 @@ func TestSignMultisigTx(t *testing.T) {
// Transfer funds to the multisig.
e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "nep5", "multitransfer",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet,
"--from", validatorAddr,
"neo:"+multisigAddr+":4",
@ -68,14 +68,14 @@ func TestSignMultisigTx(t *testing.T) {
defer os.Remove(txPath)
e.In.WriteString("pass\r")
e.Run(t, "neo-go", "wallet", "nep5", "transfer",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", wallet1Path, "--from", multisigAddr,
"--to", priv.Address(), "--token", "neo", "--amount", "1",
"--out", txPath)
e.In.WriteString("pass\r")
e.Run(t, "neo-go", "wallet", "multisig", "sign",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", wallet2Path, "--address", multisigAddr,
"--in", txPath, "--out", txPath)
e.checkTxPersisted(t)
@ -88,7 +88,7 @@ func TestSignMultisigTx(t *testing.T) {
t.Run("via invokefunction", func(t *testing.T) {
e.In.WriteString("pass\r")
e.Run(t, "neo-go", "contract", "invokefunction",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", wallet1Path, "--address", multisigAddr,
"--out", txPath,
client.NeoContractHash.StringLE(), "transfer",
@ -99,7 +99,7 @@ func TestSignMultisigTx(t *testing.T) {
e.In.WriteString("pass\r")
e.Run(t, "neo-go", "wallet", "multisig", "sign",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", wallet2Path, "--address", multisigAddr,
"--in", txPath, "--out", txPath)
e.checkTxPersisted(t)

View file

@ -109,7 +109,6 @@ func TestNEP5Transfer(t *testing.T) {
defer e.Close(t)
args := []string{
"neo-go", "wallet", "nep5", "transfer",
"--unittest",
"--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", validatorWallet,
"--from", validatorAddr,
@ -141,7 +140,7 @@ func TestNEP5MultiTransfer(t *testing.T) {
defer e.Close(t)
args := []string{
"neo-go", "wallet", "nep5", "multitransfer",
"--unittest", "--rpc-endpoint", "http://" + e.RPC.Addr,
"--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", validatorWallet,
"--from", validatorAddr,
"neo:" + privs[0].Address() + ":42",

View file

@ -34,10 +34,6 @@ var RPC = []cli.Flag{
Name: "timeout, s",
Usage: "Timeout for the operation (10 seconds by default)",
},
cli.BoolFlag{Name: "privnet, p"},
cli.BoolFlag{Name: "mainnet, m"},
cli.BoolFlag{Name: "testnet, t"},
cli.BoolFlag{Name: "unittest", Hidden: true},
}
var errNoEndpoint = errors.New("no RPC endpoint specified, use option '--" + RPCEndpointFlag + "' or '-r'")
@ -73,7 +69,11 @@ func GetRPCClient(gctx context.Context, ctx *cli.Context) (*client.Client, cli.E
if len(endpoint) == 0 {
return nil, cli.NewExitError(errNoEndpoint, 1)
}
c, err := client.New(gctx, endpoint, client.Options{Network: GetNetwork(ctx)})
c, err := client.New(gctx, endpoint, client.Options{})
if err != nil {
return nil, cli.NewExitError(err, 1)
}
err = c.Init()
if err != nil {
return nil, cli.NewExitError(err, 1)
}

View file

@ -2,10 +2,13 @@ package options
import (
"flag"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/stretchr/testify/require"
"github.com/urfave/cli"
)
@ -56,6 +59,17 @@ func TestGetTimeoutContext(t *testing.T) {
}
func TestGetRPCClient(t *testing.T) {
// need test server for proper client.Init() handling
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
response := `{"id":1,"jsonrpc":"2.0","result":{"magic":42,"tcpport":20332,"wsport":20342,"nonce":2153672787,"useragent":"/NEO-GO:0.73.1-pre-273-ge381358/"}}`
_, err := w.Write([]byte(response))
if err != nil {
t.Fatalf("Error writing response: %s", err.Error())
}
}))
defer srv.Close()
t.Run("no endpoint", func(t *testing.T) {
set := flag.NewFlagSet("flagSet", flag.ExitOnError)
ctx := cli.NewContext(cli.NewApp(), set, nil)
@ -66,7 +80,7 @@ func TestGetRPCClient(t *testing.T) {
t.Run("success", func(t *testing.T) {
set := flag.NewFlagSet("flagSet", flag.ExitOnError)
set.String(RPCEndpointFlag, "http://localhost:50333", "")
set.String(RPCEndpointFlag, srv.URL, "")
ctx := cli.NewContext(cli.NewApp(), set, nil)
gctx, _ := GetTimeoutContext(ctx)
_, ec := GetRPCClient(gctx, ctx)

View file

@ -487,6 +487,9 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
if err != nil {
return err
}
if err = c.Init(); err != nil {
return err
}
resp, err = c.InvokeFunction(script, operation, params, cosigners)
if err != nil {

View file

@ -176,7 +176,7 @@ func TestClaimGas(t *testing.T) {
balanceBefore := e.Chain.GetUtilityTokenBalance(validatorHash)
e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "claim",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet,
"--address", validatorAddr)
tx, end := e.checkTxPersisted(t)
@ -195,7 +195,7 @@ func TestImportDeployed(t *testing.T) {
e.In.WriteString("one\r")
e.Run(t, "neo-go", "contract", "deploy",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--address", validatorAddr,
"--in", "testdata/verify.nef", "--manifest", "testdata/verify.manifest.json")
@ -217,7 +217,7 @@ func TestImportDeployed(t *testing.T) {
e.In.WriteString("acc\rpass\rpass\r")
e.Run(t, "neo-go", "wallet", "import-deployed",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", walletPath, "--wif", priv.WIF(),
"--contract", h.StringLE())
@ -232,7 +232,7 @@ func TestImportDeployed(t *testing.T) {
t.Run("Sign", func(t *testing.T) {
e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "nep5", "multitransfer",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--from", validatorAddr,
"neo:"+contractAddr+":10",
"gas:"+contractAddr+":10")
@ -243,7 +243,7 @@ func TestImportDeployed(t *testing.T) {
e.In.WriteString("pass\r")
e.Run(t, "neo-go", "wallet", "nep5", "transfer",
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", walletPath, "--from", contractAddr,
"--to", privTo.Address(), "--token", "neo", "--amount", "1")
e.checkTxPersisted(t)

View file

@ -29,6 +29,8 @@ const (
type Client struct {
cli *http.Client
endpoint *url.URL
network netmode.Magic
initDone bool
ctx context.Context
opts Options
requestF func(*request.Raw) (*response.Raw, error)
@ -46,7 +48,6 @@ type Options struct {
CACert string
DialTimeout time.Duration
RequestTimeout time.Duration
Network netmode.Magic
}
// cache stores cache values for the RPC client methods
@ -61,7 +62,8 @@ type calculateValidUntilBlockCache struct {
expiresAt uint32
}
// New returns a new Client ready to use.
// New returns a new Client ready to use. You should call Init method to
// initialize network magic the client is operating on.
func New(ctx context.Context, endpoint string, opts Options) (*Client, error) {
url, err := url.Parse(endpoint)
if err != nil {
@ -99,6 +101,19 @@ func New(ctx context.Context, endpoint string, opts Options) (*Client, error) {
return cl, nil
}
// Init sets magic of the network client connected to. This method should be called
// before any transaction-, header- or block-related requests in order to deserialize
// responses properly.
func (c *Client) Init() error {
version, err := c.GetVersion()
if err != nil {
return fmt.Errorf("failed to get network magic: %w", err)
}
c.network = version.Magic
c.initDone = true
return nil
}
func (c *Client) performRequest(method string, p request.RawParams, v interface{}) error {
var r = request.Raw{
JSONRPC: request.JSONRPCVersion,

View file

@ -5,14 +5,13 @@ import (
"fmt"
"os"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
)
func Example() {
endpoint := "http://seed5.bridgeprotocol.io:10332"
opts := client.Options{Network: netmode.MainNet}
opts := client.Options{}
c, err := client.New(context.TODO(), endpoint, opts)
if err != nil {

View file

@ -152,7 +152,8 @@ func (c *Client) CreateNEP5MultiTransferTx(acc *wallet.Account, gas int64, recip
}
// CreateTxFromScript creates transaction and properly sets cosigners and NetworkFee.
// If sysFee <= 0, it is determined via result of `invokescript` RPC.
// If sysFee <= 0, it is determined via result of `invokescript` RPC. You should
// initialize network magic with Init before calling CreateTxFromScript.
func (c *Client) CreateTxFromScript(script []byte, acc *wallet.Account, sysFee, netFee int64,
cosigners ...transaction.Signer) (*transaction.Transaction, error) {
from, err := address.StringToUint160(acc.Address)
@ -172,7 +173,10 @@ func (c *Client) CreateTxFromScript(script []byte, acc *wallet.Account, sysFee,
sysFee = result.GasConsumed
}
tx := transaction.New(c.opts.Network, script, sysFee)
if !c.initDone {
return nil, errNetworkNotInitialized
}
tx := transaction.New(c.GetNetwork(), script, sysFee)
tx.Signers = signers
tx.ValidUntilBlock, err = c.CalculateValidUntilBlock()

View file

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/fee"
@ -20,6 +21,8 @@ import (
"github.com/nspcc-dev/neo-go/pkg/wallet"
)
var errNetworkNotInitialized = errors.New("RPC client network is not initialized")
// GetApplicationLog returns the contract log based on the specified txid.
func (c *Client) GetApplicationLog(hash util.Uint256) (*state.AppExecResult, error) {
var (
@ -50,12 +53,14 @@ func (c *Client) GetBlockCount() (uint32, error) {
return resp, nil
}
// GetBlockByIndex returns a block by its height.
// GetBlockByIndex returns a block by its height. You should initialize network magic
// with Init before calling GetBlockByIndex.
func (c *Client) GetBlockByIndex(index uint32) (*block.Block, error) {
return c.getBlock(request.NewRawParams(index))
}
// GetBlockByHash returns a block by its hash.
// GetBlockByHash returns a block by its hash. You should initialize network magic
// with Init before calling GetBlockByHash.
func (c *Client) GetBlockByHash(hash util.Uint256) (*block.Block, error) {
return c.getBlock(request.NewRawParams(hash.StringLE()))
}
@ -66,6 +71,9 @@ func (c *Client) getBlock(params request.RawParams) (*block.Block, error) {
err error
b *block.Block
)
if !c.initDone {
return nil, errNetworkNotInitialized
}
if err = c.performRequest("getblock", params, &resp); err != nil {
return nil, err
}
@ -74,7 +82,7 @@ func (c *Client) getBlock(params request.RawParams) (*block.Block, error) {
return nil, err
}
r := io.NewBinReaderFromBuf(blockBytes)
b = block.New(c.opts.Network)
b = block.New(c.GetNetwork())
b.DecodeBinary(r)
if r.Err != nil {
return nil, r.Err
@ -83,14 +91,14 @@ func (c *Client) getBlock(params request.RawParams) (*block.Block, error) {
}
// GetBlockByIndexVerbose returns a block wrapper with additional metadata by
// its height.
// its height. You should initialize network magic with Init before calling GetBlockByIndexVerbose.
// NOTE: to get transaction.ID and transaction.Size, use t.Hash() and io.GetVarSize(t) respectively.
func (c *Client) GetBlockByIndexVerbose(index uint32) (*result.Block, error) {
return c.getBlockVerbose(request.NewRawParams(index, 1))
}
// GetBlockByHashVerbose returns a block wrapper with additional metadata by
// its hash.
// its hash. You should initialize network magic with Init before calling GetBlockByHashVerbose.
func (c *Client) GetBlockByHashVerbose(hash util.Uint256) (*result.Block, error) {
return c.getBlockVerbose(request.NewRawParams(hash.StringLE(), 1))
}
@ -100,7 +108,10 @@ func (c *Client) getBlockVerbose(params request.RawParams) (*result.Block, error
resp = &result.Block{}
err error
)
resp.Network = c.opts.Network
if !c.initDone {
return nil, errNetworkNotInitialized
}
resp.Network = c.GetNetwork()
if err = c.performRequest("getblock", params, resp); err != nil {
return nil, err
}
@ -120,13 +131,17 @@ func (c *Client) GetBlockHash(index uint32) (util.Uint256, error) {
}
// GetBlockHeader returns the corresponding block header information from serialized hex string
// according to the specified script hash.
// according to the specified script hash. You should initialize network magic
// // with Init before calling GetBlockHeader.
func (c *Client) GetBlockHeader(hash util.Uint256) (*block.Header, error) {
var (
params = request.NewRawParams(hash.StringLE())
resp string
h *block.Header
)
if !c.initDone {
return nil, errNetworkNotInitialized
}
if err := c.performRequest("getblockheader", params, &resp); err != nil {
return nil, err
}
@ -136,7 +151,7 @@ func (c *Client) GetBlockHeader(hash util.Uint256) (*block.Header, error) {
}
r := io.NewBinReaderFromBuf(headerBytes)
h = new(block.Header)
h.Network = c.opts.Network
h.Network = c.GetNetwork()
h.DecodeBinary(r)
if r.Err != nil {
return nil, r.Err
@ -271,13 +286,17 @@ func (c *Client) GetRawMemPool() ([]util.Uint256, error) {
return *resp, nil
}
// GetRawTransaction returns a transaction by hash.
// GetRawTransaction returns a transaction by hash. You should initialize network magic
// with Init before calling GetRawTransaction.
func (c *Client) GetRawTransaction(hash util.Uint256) (*transaction.Transaction, error) {
var (
params = request.NewRawParams(hash.StringLE())
resp string
err error
)
if !c.initDone {
return nil, errNetworkNotInitialized
}
if err = c.performRequest("getrawtransaction", params, &resp); err != nil {
return nil, err
}
@ -285,7 +304,7 @@ func (c *Client) GetRawTransaction(hash util.Uint256) (*transaction.Transaction,
if err != nil {
return nil, err
}
tx, err := transaction.NewTransactionFromBytes(c.opts.Network, txBytes)
tx, err := transaction.NewTransactionFromBytes(c.GetNetwork(), txBytes)
if err != nil {
return nil, err
}
@ -293,7 +312,8 @@ func (c *Client) GetRawTransaction(hash util.Uint256) (*transaction.Transaction,
}
// GetRawTransactionVerbose returns a transaction wrapper with additional
// metadata by transaction's hash.
// metadata by transaction's hash. You should initialize network magic
// with Init before calling GetRawTransactionVerbose.
// NOTE: to get transaction.ID and transaction.Size, use t.Hash() and io.GetVarSize(t) respectively.
func (c *Client) GetRawTransactionVerbose(hash util.Uint256) (*result.TransactionOutputRaw, error) {
var (
@ -301,7 +321,10 @@ func (c *Client) GetRawTransactionVerbose(hash util.Uint256) (*result.Transactio
resp = &result.TransactionOutputRaw{}
err error
)
resp.Network = c.opts.Network
if !c.initDone {
return nil, errNetworkNotInitialized
}
resp.Network = c.GetNetwork()
if err = c.performRequest("getrawtransaction", params, resp); err != nil {
return nil, err
}
@ -569,3 +592,8 @@ func (c *Client) AddNetworkFee(tx *transaction.Transaction, extraFee int64, accs
tx.NetworkFee += int64(size)*fee + extraFee
return nil
}
// GetNetwork returns the network magic of the RPC node client connected to.
func (c *Client) GetNetwork() netmode.Magic {
return c.network
}

View file

@ -4,6 +4,7 @@ import (
"context"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"math/big"
"net/http"
@ -1247,12 +1248,6 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{
return c.GetNextBlockValidators()
},
},
{
name: "getversion_unmarshalling_error",
invoke: func(c *Client) (interface{}, error) {
return c.GetVersion()
},
},
{
name: "invokefunction_unmarshalling_error",
invoke: func(c *Client) (interface{}, error) {
@ -1293,13 +1288,17 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{
func TestRPCClients(t *testing.T) {
t.Run("Client", func(t *testing.T) {
testRPCClient(t, func(ctx context.Context, endpoint string, opts Options) (*Client, error) {
return New(ctx, endpoint, opts)
c, err := New(ctx, endpoint, opts)
require.NoError(t, err)
require.NoError(t, c.Init())
return c, nil
})
})
t.Run("WSClient", func(t *testing.T) {
testRPCClient(t, func(ctx context.Context, endpoint string, opts Options) (*Client, error) {
wsc, err := NewWS(ctx, httpURLtoWS(endpoint), opts)
require.NoError(t, err)
require.NoError(t, wsc.Init())
return &wsc.Client, nil
})
})
@ -1314,7 +1313,7 @@ func testRPCClient(t *testing.T, newClient func(context.Context, string, Options
defer srv.Close()
endpoint := srv.URL
opts := Options{Network: netmode.UnitTestNet}
opts := Options{}
c, err := newClient(context.TODO(), endpoint, opts)
if err != nil {
t.Fatal(err)
@ -1338,7 +1337,7 @@ func testRPCClient(t *testing.T, newClient func(context.Context, string, Options
defer srv.Close()
endpoint := srv.URL
opts := Options{Network: netmode.UnitTestNet}
opts := Options{}
c, err := newClient(context.TODO(), endpoint, opts)
if err != nil {
t.Fatal(err)
@ -1365,12 +1364,24 @@ func initTestServer(t *testing.T, resp string) *httptest.Server {
require.NoError(t, err)
for {
ws.SetReadDeadline(time.Now().Add(2 * time.Second))
_, _, err = ws.ReadMessage()
_, p, err := ws.ReadMessage()
if err != nil {
break
}
r := request.NewIn()
err = json.Unmarshal(p, r)
if err != nil {
t.Fatalf("Cannot decode request body: %s", req.Body)
}
var response string
switch r.Method {
case "getversion":
response = `{"id":1,"jsonrpc":"2.0","result":{"magic":42,"tcpport":20332,"wsport":20342,"nonce":2153672787,"useragent":"/NEO-GO:0.73.1-pre-273-ge381358/"}}`
default:
response = resp
}
ws.SetWriteDeadline(time.Now().Add(2 * time.Second))
err = ws.WriteMessage(1, []byte(resp))
err = ws.WriteMessage(1, []byte(response))
if err != nil {
break
}
@ -1378,16 +1389,27 @@ func initTestServer(t *testing.T, resp string) *httptest.Server {
ws.Close()
return
}
requestHandler(t, w, resp)
r := request.NewIn()
err := r.DecodeData(req.Body)
if err != nil {
t.Fatalf("Cannot decode request body: %s", req.Body)
}
requestHandler(t, r.Method, w, resp)
}))
return srv
}
func requestHandler(t *testing.T, w http.ResponseWriter, resp string) {
func requestHandler(t *testing.T, method string, w http.ResponseWriter, resp string) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
_, err := w.Write([]byte(resp))
var response string
switch method {
case "getversion":
response = `{"id":1,"jsonrpc":"2.0","result":{"magic":42,"tcpport":20332,"wsport":20342,"nonce":2153672787,"useragent":"/NEO-GO:0.73.1-pre-273-ge381358/"}}`
default:
response = resp
}
_, err := w.Write([]byte(response))
if err != nil {
t.Fatalf("Error writing response: %s", err.Error())
}
@ -1412,10 +1434,8 @@ func TestCalculateValidUntilBlock(t *testing.T) {
case "getnextblockvalidators":
getValidatorsCalled++
response = `{"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}]}`
default:
t.Fatalf("Bad request method: %s", r.Method)
}
requestHandler(t, w, response)
requestHandler(t, r.Method, w, response)
}))
defer srv.Close()
@ -1425,6 +1445,7 @@ func TestCalculateValidUntilBlock(t *testing.T) {
if err != nil {
t.Fatal(err)
}
require.NoError(t, c.Init())
validUntilBlock, err := c.CalculateValidUntilBlock()
assert.NoError(t, err)
@ -1439,3 +1460,32 @@ func TestCalculateValidUntilBlock(t *testing.T) {
assert.Equal(t, 2, getBlockCountCalled)
assert.Equal(t, 1, getValidatorsCalled)
}
func TestGetNetwork(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
// request handler already have `getversion` response wrapper
requestHandler(t, "getversion", w, "")
}))
defer srv.Close()
endpoint := srv.URL
opts := Options{}
t.Run("bad", func(t *testing.T) {
c, err := New(context.TODO(), endpoint, opts)
if err != nil {
t.Fatal(err)
}
// network was not initialised
require.Equal(t, netmode.Magic(0), c.GetNetwork())
require.Equal(t, false, c.initDone)
})
t.Run("good", func(t *testing.T) {
c, err := New(context.TODO(), endpoint, opts)
if err != nil {
t.Fatal(err)
}
require.NoError(t, c.Init())
require.Equal(t, netmode.UnitTestNet, c.GetNetwork())
})
}

View file

@ -69,6 +69,8 @@ const (
// NewWS returns a new WSClient ready to use (with established websocket
// connection). You need to use websocket URL for it like `ws://1.2.3.4/ws`.
// You should call Init method to initialize network magic the client is
// operating on.
func NewWS(ctx context.Context, endpoint string, opts Options) (*WSClient, error) {
cl, err := New(ctx, endpoint, opts)
if err != nil {
@ -137,9 +139,9 @@ readloop:
var val interface{}
switch event {
case response.BlockEventID:
val = block.New(c.opts.Network)
val = block.New(c.GetNetwork())
case response.TransactionEventID:
val = &transaction.Transaction{Network: c.opts.Network}
val = &transaction.Transaction{Network: c.GetNetwork()}
case response.NotificationEventID:
val = new(state.NotificationEvent)
case response.ExecutionEventID:

View file

@ -18,7 +18,7 @@ import (
func TestWSClientClose(t *testing.T) {
srv := initTestServer(t, "")
defer srv.Close()
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{Network: netmode.UnitTestNet})
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{})
require.NoError(t, err)
wsc.Close()
}
@ -43,8 +43,9 @@ func TestWSClientSubscription(t *testing.T) {
t.Run(name, func(t *testing.T) {
srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "result": "55aaff00"}`)
defer srv.Close()
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{Network: netmode.UnitTestNet})
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{})
require.NoError(t, err)
require.NoError(t, wsc.Init())
id, err := f(wsc)
require.NoError(t, err)
require.Equal(t, "55aaff00", id)
@ -56,8 +57,9 @@ func TestWSClientSubscription(t *testing.T) {
t.Run(name, func(t *testing.T) {
srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "error":{"code":-32602,"message":"Invalid Params"}}`)
defer srv.Close()
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{Network: netmode.UnitTestNet})
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{})
require.NoError(t, err)
require.NoError(t, wsc.Init())
_, err = f(wsc)
require.Error(t, err)
})
@ -105,8 +107,9 @@ func TestWSClientUnsubscription(t *testing.T) {
t.Run(name, func(t *testing.T) {
srv := initTestServer(t, rc.response)
defer srv.Close()
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{Network: netmode.UnitTestNet})
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{})
require.NoError(t, err)
require.NoError(t, wsc.Init())
rc.code(t, wsc)
})
}
@ -139,8 +142,9 @@ func TestWSClientEvents(t *testing.T) {
}
}))
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{Network: netmode.UnitTestNet})
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{})
require.NoError(t, err)
wsc.network = netmode.UnitTestNet
for range events {
select {
case _, ok = <-wsc.Notifications:
@ -162,8 +166,9 @@ func TestWSExecutionVMStateCheck(t *testing.T) {
// Will answer successfully if request slips through.
srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "result": "55aaff00"}`)
defer srv.Close()
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{Network: netmode.UnitTestNet})
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{})
require.NoError(t, err)
require.NoError(t, wsc.Init())
filter := "NONE"
_, err = wsc.SubscribeForTransactionExecutions(&filter)
require.Error(t, err)
@ -326,8 +331,9 @@ func TestWSFilteredSubscriptions(t *testing.T) {
}
}))
defer srv.Close()
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{Network: netmode.UnitTestNet})
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{})
require.NoError(t, err)
wsc.network = netmode.UnitTestNet
c.clientCode(t, wsc)
wsc.Close()
})
@ -339,11 +345,12 @@ func TestNewWS(t *testing.T) {
defer srv.Close()
t.Run("good", func(t *testing.T) {
_, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{Network: netmode.UnitTestNet})
c, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{})
require.NoError(t, err)
require.NoError(t, c.Init())
})
t.Run("bad URL", func(t *testing.T) {
_, err := NewWS(context.TODO(), strings.Trim(srv.URL, "http://"), Options{Network: netmode.UnitTestNet})
_, err := NewWS(context.TODO(), strings.Trim(srv.URL, "http://"), Options{})
require.Error(t, err)
})
}

View file

@ -5,7 +5,6 @@ import (
"encoding/hex"
"testing"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/fee"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
@ -25,8 +24,9 @@ func TestClient_NEP5(t *testing.T) {
defer chain.Close()
defer rpcSrv.Shutdown()
c, err := client.New(context.Background(), httpSrv.URL, client.Options{Network: netmode.UnitTestNet})
c, err := client.New(context.Background(), httpSrv.URL, client.Options{})
require.NoError(t, err)
require.NoError(t, c.Init())
h, err := util.Uint160DecodeStringLE(testContractHash)
require.NoError(t, err)
@ -72,8 +72,9 @@ func TestAddNetworkFee(t *testing.T) {
defer chain.Close()
defer rpcSrv.Shutdown()
c, err := client.New(context.Background(), httpSrv.URL, client.Options{Network: testchain.Network()})
c, err := client.New(context.Background(), httpSrv.URL, client.Options{})
require.NoError(t, err)
require.NoError(t, c.Init())
getAccounts := func(t *testing.T, n int) []*wallet.Account {
accs := make([]*wallet.Account, n)
@ -199,8 +200,9 @@ func TestSignAndPushInvocationTx(t *testing.T) {
defer chain.Close()
defer rpcSrv.Shutdown()
c, err := client.New(context.Background(), httpSrv.URL, client.Options{Network: testchain.Network()})
c, err := client.New(context.Background(), httpSrv.URL, client.Options{})
require.NoError(t, err)
require.NoError(t, c.Init())
priv := testchain.PrivateKey(0)
acc, err := wallet.NewAccountFromWIF(priv.WIF())
@ -222,8 +224,9 @@ func TestPing(t *testing.T) {
chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t)
defer chain.Close()
c, err := client.New(context.Background(), httpSrv.URL, client.Options{Network: testchain.Network()})
c, err := client.New(context.Background(), httpSrv.URL, client.Options{})
require.NoError(t, err)
require.NoError(t, c.Init())
require.NoError(t, c.Ping())
require.NoError(t, rpcSrv.Shutdown())
@ -236,8 +239,9 @@ func TestCreateTxFromScript(t *testing.T) {
defer chain.Close()
defer rpcSrv.Shutdown()
c, err := client.New(context.Background(), httpSrv.URL, client.Options{Network: testchain.Network()})
c, err := client.New(context.Background(), httpSrv.URL, client.Options{})
require.NoError(t, err)
require.NoError(t, c.Init())
priv := testchain.PrivateKey(0)
acc, err := wallet.NewAccountFromWIF(priv.WIF())
@ -265,8 +269,9 @@ func TestCreateNEP5TransferTx(t *testing.T) {
defer chain.Close()
defer rpcSrv.Shutdown()
c, err := client.New(context.Background(), httpSrv.URL, client.Options{Network: testchain.Network()})
c, err := client.New(context.Background(), httpSrv.URL, client.Options{})
require.NoError(t, err)
require.NoError(t, c.Init())
priv := testchain.PrivateKeyByID(0)
acc, err := wallet.NewAccountFromWIF(priv.WIF())