mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-23 03:41:34 +00:00
rpc, cli: remove Network from RPC client and cli
This commit is contained in:
parent
474d2dfb65
commit
590be7a58d
16 changed files with 206 additions and 80 deletions
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
Loading…
Reference in a new issue