mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-25 23:42:23 +00:00
cli: add historic abilities for all invoking commands
Notice that we can't do this for balance commands (unless we change the interface in some manner) because they use getnepXXbalances. Fixes #2620.
This commit is contained in:
parent
4403a95ae6
commit
d2d190913b
5 changed files with 194 additions and 62 deletions
|
@ -602,6 +602,39 @@ func TestContract_TestInvokeScript(t *testing.T) {
|
|||
"--rpc-endpoint", "http://123456789",
|
||||
"--in", goodNef)
|
||||
})
|
||||
t.Run("good", func(t *testing.T) {
|
||||
e.Run(t, "neo-go", "contract", "testinvokescript",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
||||
"--in", goodNef)
|
||||
})
|
||||
t.Run("good with hashed signer", func(t *testing.T) {
|
||||
e.Run(t, "neo-go", "contract", "testinvokescript",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
||||
"--in", goodNef, "--", util.Uint160{1, 2, 3}.StringLE())
|
||||
})
|
||||
t.Run("good with addressed signer", func(t *testing.T) {
|
||||
e.Run(t, "neo-go", "contract", "testinvokescript",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
||||
"--in", goodNef, "--", address.Uint160ToString(util.Uint160{1, 2, 3}))
|
||||
})
|
||||
t.Run("historic, invalid", func(t *testing.T) {
|
||||
e.RunWithError(t, "neo-go", "contract", "testinvokescript",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
||||
"--historic", "bad",
|
||||
"--in", goodNef)
|
||||
})
|
||||
t.Run("historic, index", func(t *testing.T) {
|
||||
e.Run(t, "neo-go", "contract", "testinvokescript",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
||||
"--historic", "0",
|
||||
"--in", goodNef)
|
||||
})
|
||||
t.Run("historic, hash", func(t *testing.T) {
|
||||
e.Run(t, "neo-go", "contract", "testinvokescript",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
||||
"--historic", e.Chain.GetHeaderHash(0).StringLE(),
|
||||
"--in", goodNef)
|
||||
})
|
||||
}
|
||||
|
||||
func TestComlileAndInvokeFunction(t *testing.T) {
|
||||
|
@ -618,16 +651,6 @@ func TestComlileAndInvokeFunction(t *testing.T) {
|
|||
"--config", "testdata/deploy/neo-go.yml",
|
||||
"--out", nefName, "--manifest", manifestName)
|
||||
|
||||
// Check that it is possible to invoke before deploy.
|
||||
// This doesn't make much sense, because every method has an offset
|
||||
// which is contained in the manifest. This should be either removed or refactored.
|
||||
e.Run(t, "neo-go", "contract", "testinvokescript",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
||||
"--in", nefName, "--", util.Uint160{1, 2, 3}.StringLE())
|
||||
e.Run(t, "neo-go", "contract", "testinvokescript",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
||||
"--in", nefName, "--", address.Uint160ToString(util.Uint160{1, 2, 3}))
|
||||
|
||||
tmp := t.TempDir()
|
||||
configPath := filepath.Join(tmp, "config.yaml")
|
||||
cfg := config.Wallet{
|
||||
|
@ -689,11 +712,14 @@ func TestComlileAndInvokeFunction(t *testing.T) {
|
|||
|
||||
e.Run(t, cmd...)
|
||||
|
||||
res := new(result.Invoke)
|
||||
require.NoError(t, json.Unmarshal(e.Out.Bytes(), res))
|
||||
require.Equal(t, vmstate.Halt.String(), res.State, res.FaultException)
|
||||
require.Len(t, res.Stack, 1)
|
||||
require.Equal(t, []byte("on create|sub create"), res.Stack[0].Value())
|
||||
checkGetValueOut := func(str string) {
|
||||
res := new(result.Invoke)
|
||||
require.NoError(t, json.Unmarshal(e.Out.Bytes(), res))
|
||||
require.Equal(t, vmstate.Halt.String(), res.State, res.FaultException)
|
||||
require.Len(t, res.Stack, 1)
|
||||
require.Equal(t, []byte(str), res.Stack[0].Value())
|
||||
}
|
||||
checkGetValueOut("on create|sub create")
|
||||
|
||||
// deploy verification contract
|
||||
hVerify := deployVerifyContract(t, e)
|
||||
|
@ -866,6 +892,12 @@ func TestComlileAndInvokeFunction(t *testing.T) {
|
|||
})
|
||||
})
|
||||
|
||||
var (
|
||||
hashBeforeUpdate util.Uint256
|
||||
indexBeforeUpdate uint32
|
||||
indexAfterUpdate uint32
|
||||
stateBeforeUpdate util.Uint256
|
||||
)
|
||||
t.Run("Update", func(t *testing.T) {
|
||||
nefName := filepath.Join(tmpDir, "updated.nef")
|
||||
manifestName := filepath.Join(tmpDir, "updated.manifest.json")
|
||||
|
@ -884,6 +916,11 @@ func TestComlileAndInvokeFunction(t *testing.T) {
|
|||
rawManifest, err := os.ReadFile(manifestName)
|
||||
require.NoError(t, err)
|
||||
|
||||
indexBeforeUpdate = e.Chain.BlockHeight()
|
||||
hashBeforeUpdate = e.Chain.CurrentHeaderHash()
|
||||
mptBeforeUpdate, err := e.Chain.GetStateRoot(indexBeforeUpdate)
|
||||
require.NoError(t, err)
|
||||
stateBeforeUpdate = mptBeforeUpdate.Root
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, "neo-go", "contract", "invokefunction",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
||||
|
@ -895,16 +932,40 @@ func TestComlileAndInvokeFunction(t *testing.T) {
|
|||
)
|
||||
e.checkTxPersisted(t, "Sent invocation transaction ")
|
||||
|
||||
indexAfterUpdate = e.Chain.BlockHeight()
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, "neo-go", "contract", "testinvokefunction",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
||||
h.StringLE(), "getValue")
|
||||
|
||||
res := new(result.Invoke)
|
||||
require.NoError(t, json.Unmarshal(e.Out.Bytes(), res))
|
||||
require.Equal(t, vmstate.Halt.String(), res.State)
|
||||
require.Len(t, res.Stack, 1)
|
||||
require.Equal(t, []byte("on update|sub update"), res.Stack[0].Value())
|
||||
checkGetValueOut("on update|sub update")
|
||||
})
|
||||
t.Run("historic", func(t *testing.T) {
|
||||
t.Run("bad ref", func(t *testing.T) {
|
||||
e.RunWithError(t, "neo-go", "contract", "testinvokefunction",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
||||
"--historic", "bad",
|
||||
h.StringLE(), "getValue")
|
||||
})
|
||||
for name, ref := range map[string]string{
|
||||
"by index": strconv.FormatUint(uint64(indexBeforeUpdate), 10),
|
||||
"by block hash": hashBeforeUpdate.StringLE(),
|
||||
"by state hash": stateBeforeUpdate.StringLE(),
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
e.Run(t, "neo-go", "contract", "testinvokefunction",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
||||
"--historic", ref,
|
||||
h.StringLE(), "getValue")
|
||||
})
|
||||
checkGetValueOut("on create|sub create")
|
||||
}
|
||||
t.Run("updated historic", func(t *testing.T) {
|
||||
e.Run(t, "neo-go", "contract", "testinvokefunction",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
||||
"--historic", strconv.FormatUint(uint64(indexAfterUpdate), 10),
|
||||
h.StringLE(), "getValue")
|
||||
checkGetValueOut("on update|sub update")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -161,6 +161,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
|
|||
}
|
||||
|
||||
tokenID := mint(t)
|
||||
var hashBeforeTransfer = e.Chain.CurrentHeaderHash()
|
||||
|
||||
// check the balance
|
||||
cmdCheckBalance := []string{"neo-go", "wallet", "nep11", "balance",
|
||||
|
@ -358,6 +359,24 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
|
|||
// check balance after transfer
|
||||
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
|
||||
checkBalanceResult(t, nftOwnerAddr)
|
||||
|
||||
// historic calls still remember the good old days.
|
||||
cmdOwnerOf = append(cmdOwnerOf, "--historic", hashBeforeTransfer.StringLE())
|
||||
e.Run(t, cmdOwnerOf...)
|
||||
e.checkNextLine(t, nftOwnerAddr)
|
||||
|
||||
cmdTokensOf = append(cmdTokensOf, "--historic", hashBeforeTransfer.StringLE())
|
||||
e.Run(t, cmdTokensOf...)
|
||||
require.Equal(t, hex.EncodeToString(tokenID), e.getNextLine(t))
|
||||
|
||||
cmdTokens = append(cmdTokens, "--historic", hashBeforeTransfer.StringLE())
|
||||
e.Run(t, cmdTokens...)
|
||||
require.Equal(t, hex.EncodeToString(tokenID), e.getNextLine(t))
|
||||
|
||||
// this one is not affected by transfer, but anyway
|
||||
cmdProperties = append(cmdProperties, "--historic", hashBeforeTransfer.StringLE())
|
||||
e.Run(t, cmdProperties...)
|
||||
require.Equal(t, fmt.Sprintf(`{"name":"HASHY %s"}`, base64.StdEncoding.EncodeToString(tokenID)), e.getNextLine(t))
|
||||
}
|
||||
|
||||
func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
|
||||
|
|
|
@ -6,10 +6,14 @@ package options
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
|
@ -42,7 +46,14 @@ var RPC = []cli.Flag{
|
|||
},
|
||||
}
|
||||
|
||||
// Historic is a flag for commands that can perform historic invocations.
|
||||
var Historic = cli.StringFlag{
|
||||
Name: "historic",
|
||||
Usage: "Use historic state (height, block hash or state root hash)",
|
||||
}
|
||||
|
||||
var errNoEndpoint = errors.New("no RPC endpoint specified, use option '--" + RPCEndpointFlag + "' or '-r'")
|
||||
var errInvalidHistoric = errors.New("invalid 'historic' parameter, neither a block number, nor a block/state hash")
|
||||
|
||||
// GetNetwork examines Context's flags and returns the appropriate network. It
|
||||
// defaults to PrivNet if no flags are given.
|
||||
|
@ -85,3 +96,35 @@ func GetRPCClient(gctx context.Context, ctx *cli.Context) (*rpcclient.Client, cl
|
|||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// GetInvoker returns an invoker using the given RPC client, context and signers.
|
||||
// It parses "--historic" parameter to adjust it.
|
||||
func GetInvoker(c *rpcclient.Client, ctx *cli.Context, signers []transaction.Signer) (*invoker.Invoker, cli.ExitCoder) {
|
||||
historic := ctx.String("historic")
|
||||
if historic == "" {
|
||||
return invoker.New(c, signers), nil
|
||||
}
|
||||
if index, err := strconv.ParseUint(historic, 10, 32); err == nil {
|
||||
return invoker.NewHistoricAtHeight(uint32(index), c, signers), nil
|
||||
}
|
||||
if u256, err := util.Uint256DecodeStringLE(historic); err == nil {
|
||||
// Might as well be a block hash, but it makes no practical difference.
|
||||
return invoker.NewHistoricWithState(u256, c, signers), nil
|
||||
}
|
||||
return nil, cli.NewExitError(errInvalidHistoric, 1)
|
||||
}
|
||||
|
||||
// GetRPCWithInvoker combines GetRPCClient with GetInvoker for cases where it's
|
||||
// appropriate to do so.
|
||||
func GetRPCWithInvoker(gctx context.Context, ctx *cli.Context, signers []transaction.Signer) (*rpcclient.Client, *invoker.Invoker, cli.ExitCoder) {
|
||||
c, err := GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
inv, err := GetInvoker(c, ctx, signers)
|
||||
if err != nil {
|
||||
c.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
return c, inv, err
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/management"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
|
@ -110,8 +111,11 @@ func NewCommands() []cli.Command {
|
|||
Name: "in, i",
|
||||
Usage: "Input location of the .nef file that needs to be invoked",
|
||||
},
|
||||
options.Historic,
|
||||
}
|
||||
testInvokeScriptFlags = append(testInvokeScriptFlags, options.RPC...)
|
||||
testInvokeFunctionFlags := []cli.Flag{options.Historic}
|
||||
testInvokeFunctionFlags = append(testInvokeFunctionFlags, options.RPC...)
|
||||
invokeFunctionFlags := []cli.Flag{
|
||||
walletFlag,
|
||||
walletConfigFlag,
|
||||
|
@ -213,7 +217,7 @@ func NewCommands() []cli.Command {
|
|||
{
|
||||
Name: "testinvokefunction",
|
||||
Usage: "invoke deployed contract on the blockchain (test mode)",
|
||||
UsageText: "neo-go contract testinvokefunction -r endpoint scripthash [method] [arguments...] [--] [signers...]",
|
||||
UsageText: "neo-go contract testinvokefunction -r endpoint [--historic index/hash] scripthash [method] [arguments...] [--] [signers...]",
|
||||
Description: `Executes given (as a script hash) deployed script with the given method,
|
||||
arguments and signers (sender is not included by default). If no method is given
|
||||
"" is passed to the script, if no arguments are given, an empty array is
|
||||
|
@ -328,12 +332,12 @@ func NewCommands() []cli.Command {
|
|||
`CustomContracts:1011120009070e030d0f0e020d0c06050e030c02:0x1211100009070e030d0f0e020d0c06050e030c02'
|
||||
`,
|
||||
Action: testInvokeFunction,
|
||||
Flags: options.RPC,
|
||||
Flags: testInvokeFunctionFlags,
|
||||
},
|
||||
{
|
||||
Name: "testinvokescript",
|
||||
Usage: "Invoke compiled AVM code in NEF format on the blockchain (test mode, not creating a transaction for it)",
|
||||
UsageText: "neo-go contract testinvokescript -r endpoint -i input.nef [signers...]",
|
||||
UsageText: "neo-go contract testinvokescript -r endpoint -i input.nef [--historic index/hash] [signers...]",
|
||||
Description: `Executes given compiled AVM instructions in NEF format with the given set of
|
||||
signers not included sender by default. See testinvokefunction documentation
|
||||
for the details about parameters.
|
||||
|
@ -608,8 +612,9 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
|
|||
err error
|
||||
exitErr *cli.ExitError
|
||||
operation string
|
||||
params = make([]smartcontract.Parameter, 0)
|
||||
params []interface{}
|
||||
paramsStart = 1
|
||||
scParams []smartcontract.Parameter
|
||||
cosigners []transaction.Signer
|
||||
cosignersOffset = 0
|
||||
)
|
||||
|
@ -629,10 +634,14 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
|
|||
paramsStart++
|
||||
|
||||
if len(args) > paramsStart {
|
||||
cosignersOffset, params, err = cmdargs.ParseParams(args[paramsStart:], true)
|
||||
cosignersOffset, scParams, err = cmdargs.ParseParams(args[paramsStart:], true)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
params = make([]interface{}, len(scParams))
|
||||
for i := range scParams {
|
||||
params[i] = scParams[i]
|
||||
}
|
||||
}
|
||||
|
||||
cosignersStart := paramsStart + cosignersOffset
|
||||
|
@ -656,13 +665,14 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
|
|||
return invokeWithArgs(ctx, acc, w, script, operation, params, cosigners)
|
||||
}
|
||||
|
||||
func invokeWithArgs(ctx *cli.Context, acc *wallet.Account, wall *wallet.Wallet, script util.Uint160, operation string, params []smartcontract.Parameter, cosigners []transaction.Signer) error {
|
||||
func invokeWithArgs(ctx *cli.Context, acc *wallet.Account, wall *wallet.Wallet, script util.Uint160, operation string, params []interface{}, cosigners []transaction.Signer) error {
|
||||
var (
|
||||
err error
|
||||
gas, sysgas fixedn.Fixed8
|
||||
signersAccounts []actor.SignerAccount
|
||||
resp *result.Invoke
|
||||
signAndPush = acc != nil
|
||||
inv *invoker.Invoker
|
||||
act *actor.Actor
|
||||
)
|
||||
if signAndPush {
|
||||
|
@ -685,12 +695,15 @@ func invokeWithArgs(ctx *cli.Context, acc *wallet.Account, wall *wallet.Wallet,
|
|||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to create RPC actor: %w", err), 1)
|
||||
}
|
||||
inv = &act.Invoker
|
||||
} else {
|
||||
inv, err = options.GetInvoker(c, ctx, cosigners)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
out := ctx.String("out")
|
||||
// It's a bit easier to keep this as is (not using invoker.Invoker)
|
||||
// during transition period. Mostly because of the need to convert params
|
||||
// to []interface{}.
|
||||
resp, err = c.InvokeFunction(script, operation, params, cosigners)
|
||||
resp, err = inv.Call(script, operation, params...)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
@ -781,12 +794,12 @@ func testInvokeScript(ctx *cli.Context) error {
|
|||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
defer cancel()
|
||||
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
_, inv, err := options.GetRPCWithInvoker(gctx, ctx, signers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := c.InvokeScript(nefFile.Script, signers)
|
||||
resp, err := inv.Run(nefFile.Script)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
@ -922,16 +935,8 @@ func contractDeploy(ctx *cli.Context) error {
|
|||
return cli.NewExitError(fmt.Errorf("failed to read manifest file: %w", err), 1)
|
||||
}
|
||||
|
||||
appCallParams := []smartcontract.Parameter{
|
||||
{
|
||||
Type: smartcontract.ByteArrayType,
|
||||
Value: f,
|
||||
},
|
||||
{
|
||||
Type: smartcontract.ByteArrayType,
|
||||
Value: manifestBytes,
|
||||
},
|
||||
}
|
||||
var appCallParams = []interface{}{f, manifestBytes}
|
||||
|
||||
signOffset, data, err := cmdargs.ParseParams(ctx.Args(), true)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("unable to parse 'data' parameter: %w", err), 1)
|
||||
|
|
|
@ -13,7 +13,6 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep11"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
|
@ -116,50 +115,55 @@ func newNEP11Commands() []cli.Command {
|
|||
{
|
||||
Name: "properties",
|
||||
Usage: "print properties of NEP-11 token",
|
||||
UsageText: "properties --rpc-endpoint <node> --timeout <time> --token <hash> --id <token-id>",
|
||||
UsageText: "properties --rpc-endpoint <node> [--timeout <time>] --token <hash> --id <token-id> [--historic <block/hash>]",
|
||||
Action: printNEP11Properties,
|
||||
Flags: append([]cli.Flag{
|
||||
tokenAddressFlag,
|
||||
tokenID,
|
||||
options.Historic,
|
||||
}, options.RPC...),
|
||||
},
|
||||
{
|
||||
Name: "ownerOf",
|
||||
Usage: "print owner of non-divisible NEP-11 token with the specified ID",
|
||||
UsageText: "ownerOf --rpc-endpoint <node> --timeout <time> --token <hash> --id <token-id>",
|
||||
UsageText: "ownerOf --rpc-endpoint <node> [--timeout <time>] --token <hash> --id <token-id> [--historic <block/hash>]",
|
||||
Action: printNEP11NDOwner,
|
||||
Flags: append([]cli.Flag{
|
||||
tokenAddressFlag,
|
||||
tokenID,
|
||||
options.Historic,
|
||||
}, options.RPC...),
|
||||
},
|
||||
{
|
||||
Name: "ownerOfD",
|
||||
Usage: "print set of owners of divisible NEP-11 token with the specified ID (" + maxIters + " will be printed at max)",
|
||||
UsageText: "ownerOfD --rpc-endpoint <node> --timeout <time> --token <hash> --id <token-id>",
|
||||
UsageText: "ownerOfD --rpc-endpoint <node> [--timeout <time>] --token <hash> --id <token-id> [--historic <block/hash>]",
|
||||
Action: printNEP11DOwner,
|
||||
Flags: append([]cli.Flag{
|
||||
tokenAddressFlag,
|
||||
tokenID,
|
||||
options.Historic,
|
||||
}, options.RPC...),
|
||||
},
|
||||
{
|
||||
Name: "tokensOf",
|
||||
Usage: "print list of tokens IDs for the specified NFT owner (" + maxIters + " will be printed at max)",
|
||||
UsageText: "tokensOf --rpc-endpoint <node> --timeout <time> --token <hash> --address <addr>",
|
||||
UsageText: "tokensOf --rpc-endpoint <node> [--timeout <time>] --token <hash> --address <addr> [--historic <block/hash>]",
|
||||
Action: printNEP11TokensOf,
|
||||
Flags: append([]cli.Flag{
|
||||
tokenAddressFlag,
|
||||
ownerAddressFlag,
|
||||
options.Historic,
|
||||
}, options.RPC...),
|
||||
},
|
||||
{
|
||||
Name: "tokens",
|
||||
Usage: "print list of tokens IDs minted by the specified NFT (optional method; " + maxIters + " will be printed at max)",
|
||||
UsageText: "tokens --rpc-endpoint <node> --timeout <time> --token <hash>",
|
||||
UsageText: "tokens --rpc-endpoint <node> [--timeout <time>] --token <hash> [--historic <block/hash>]",
|
||||
Action: printNEP11Tokens,
|
||||
Flags: append([]cli.Flag{
|
||||
tokenAddressFlag,
|
||||
options.Historic,
|
||||
}, options.RPC...),
|
||||
},
|
||||
}
|
||||
|
@ -256,13 +260,13 @@ func printNEP11Owner(ctx *cli.Context, divisible bool) error {
|
|||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
defer cancel()
|
||||
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
_, inv, err := options.GetRPCWithInvoker(gctx, ctx, nil)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return err
|
||||
}
|
||||
|
||||
if divisible {
|
||||
n11 := nep11.NewDivisibleReader(invoker.New(c, nil), tokenHash.Uint160())
|
||||
n11 := nep11.NewDivisibleReader(inv, tokenHash.Uint160())
|
||||
result, err := n11.OwnerOfExpanded(tokenIDBytes, config.DefaultMaxIteratorResultItems)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Sprintf("failed to call NEP-11 divisible `ownerOf` method: %s", err.Error()), 1)
|
||||
|
@ -271,7 +275,7 @@ func printNEP11Owner(ctx *cli.Context, divisible bool) error {
|
|||
fmt.Fprintln(ctx.App.Writer, address.Uint160ToString(h))
|
||||
}
|
||||
} else {
|
||||
n11 := nep11.NewNonDivisibleReader(invoker.New(c, nil), tokenHash.Uint160())
|
||||
n11 := nep11.NewNonDivisibleReader(inv, tokenHash.Uint160())
|
||||
result, err := n11.OwnerOf(tokenIDBytes)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Sprintf("failed to call NEP-11 non-divisible `ownerOf` method: %s", err.Error()), 1)
|
||||
|
@ -297,12 +301,12 @@ func printNEP11TokensOf(ctx *cli.Context) error {
|
|||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
defer cancel()
|
||||
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
_, inv, err := options.GetRPCWithInvoker(gctx, ctx, nil)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return err
|
||||
}
|
||||
|
||||
n11 := nep11.NewBaseReader(invoker.New(c, nil), tokenHash.Uint160())
|
||||
n11 := nep11.NewBaseReader(inv, tokenHash.Uint160())
|
||||
result, err := n11.TokensOfExpanded(acc.Uint160(), config.DefaultMaxIteratorResultItems)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Sprintf("failed to call NEP-11 `tokensOf` method: %s", err.Error()), 1)
|
||||
|
@ -327,12 +331,12 @@ func printNEP11Tokens(ctx *cli.Context) error {
|
|||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
defer cancel()
|
||||
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
_, inv, err := options.GetRPCWithInvoker(gctx, ctx, nil)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return err
|
||||
}
|
||||
|
||||
n11 := nep11.NewBaseReader(invoker.New(c, nil), tokenHash.Uint160())
|
||||
n11 := nep11.NewBaseReader(inv, tokenHash.Uint160())
|
||||
result, err := n11.TokensExpanded(config.DefaultMaxIteratorResultItems)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Sprintf("failed to call optional NEP-11 `tokens` method: %s", err.Error()), 1)
|
||||
|
@ -366,12 +370,12 @@ func printNEP11Properties(ctx *cli.Context) error {
|
|||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
defer cancel()
|
||||
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
_, inv, err := options.GetRPCWithInvoker(gctx, ctx, nil)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return err
|
||||
}
|
||||
|
||||
n11 := nep11.NewBaseReader(invoker.New(c, nil), tokenHash.Uint160())
|
||||
n11 := nep11.NewBaseReader(inv, tokenHash.Uint160())
|
||||
result, err := n11.Properties(tokenIDBytes)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Sprintf("failed to call NEP-11 `properties` method: %s", err.Error()), 1)
|
||||
|
|
Loading…
Reference in a new issue