mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-25 03:47:18 +00:00
cli: upgrade urfave lib to v2
Close #3097 Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
This commit is contained in:
parent
b32e568d21
commit
acde7bd0de
39 changed files with 980 additions and 693 deletions
|
@ -12,7 +12,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/cli/vm"
|
||||
"github.com/nspcc-dev/neo-go/cli/wallet"
|
||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func versionPrinter(c *cli.Context) {
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -138,16 +138,16 @@ const (
|
|||
|
||||
// GetSignersFromContext returns signers parsed from context args starting
|
||||
// from the specified offset.
|
||||
func GetSignersFromContext(ctx *cli.Context, offset int) ([]transaction.Signer, *cli.ExitError) {
|
||||
func GetSignersFromContext(ctx *cli.Context, offset int) ([]transaction.Signer, cli.ExitCoder) {
|
||||
args := ctx.Args()
|
||||
var (
|
||||
signers []transaction.Signer
|
||||
err error
|
||||
)
|
||||
if args.Present() && len(args) > offset {
|
||||
signers, err = ParseSigners(args[offset:])
|
||||
if args.Present() && args.Len() > offset {
|
||||
signers, err = ParseSigners(args.Slice()[offset:])
|
||||
if err != nil {
|
||||
return nil, cli.NewExitError(err, 1)
|
||||
return nil, cli.Exit(err, 1)
|
||||
}
|
||||
}
|
||||
return signers, nil
|
||||
|
@ -230,7 +230,7 @@ func parseCosigner(c string) (transaction.Signer, error) {
|
|||
}
|
||||
|
||||
// GetDataFromContext returns data parameter from context args.
|
||||
func GetDataFromContext(ctx *cli.Context) (int, any, *cli.ExitError) {
|
||||
func GetDataFromContext(ctx *cli.Context) (int, any, cli.ExitCoder) {
|
||||
var (
|
||||
data any
|
||||
offset int
|
||||
|
@ -239,17 +239,17 @@ func GetDataFromContext(ctx *cli.Context) (int, any, *cli.ExitError) {
|
|||
)
|
||||
args := ctx.Args()
|
||||
if args.Present() {
|
||||
offset, params, err = ParseParams(args, true)
|
||||
offset, params, err = ParseParams(args.Slice(), true)
|
||||
if err != nil {
|
||||
return offset, nil, cli.NewExitError(fmt.Errorf("unable to parse 'data' parameter: %w", err), 1)
|
||||
return offset, nil, cli.Exit(fmt.Errorf("unable to parse 'data' parameter: %w", err), 1)
|
||||
}
|
||||
if len(params) > 1 {
|
||||
return offset, nil, cli.NewExitError("'data' should be represented as a single parameter", 1)
|
||||
return offset, nil, cli.Exit("'data' should be represented as a single parameter", 1)
|
||||
}
|
||||
if len(params) != 0 {
|
||||
data, err = smartcontract.ExpandParameterToEmitable(params[0])
|
||||
if err != nil {
|
||||
return offset, nil, cli.NewExitError(fmt.Sprintf("failed to convert 'data' to emitable type: %s", err.Error()), 1)
|
||||
return offset, nil, cli.Exit(fmt.Sprintf("failed to convert 'data' to emitable type: %s", err.Error()), 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,9 +258,9 @@ func GetDataFromContext(ctx *cli.Context) (int, any, *cli.ExitError) {
|
|||
|
||||
// EnsureNone returns an error if there are any positional arguments present.
|
||||
// It can be used to check for them in commands that don't accept arguments.
|
||||
func EnsureNone(ctx *cli.Context) *cli.ExitError {
|
||||
func EnsureNone(ctx *cli.Context) cli.ExitCoder {
|
||||
if ctx.Args().Present() {
|
||||
return cli.NewExitError("additional arguments given while this command expects none", 1)
|
||||
return cli.Exit(fmt.Errorf("additional arguments given while this command expects none"), 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// Address is a wrapper for a Uint160 with flag.Value methods.
|
||||
|
@ -16,11 +16,15 @@ type Address struct {
|
|||
Value util.Uint160
|
||||
}
|
||||
|
||||
// AddressFlag is a flag with type string.
|
||||
// AddressFlag is a flag with type Uint160.
|
||||
type AddressFlag struct {
|
||||
Name string
|
||||
Usage string
|
||||
Value Address
|
||||
Aliases []string
|
||||
Required bool
|
||||
Hidden bool
|
||||
Action func(*cli.Context, string) error
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -37,7 +41,7 @@ func (a Address) String() string {
|
|||
func (a *Address) Set(s string) error {
|
||||
addr, err := ParseAddress(s)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
a.IsSet = true
|
||||
a.Value = addr
|
||||
|
@ -63,9 +67,9 @@ func (f AddressFlag) IsSet() bool {
|
|||
// (for usage defaults).
|
||||
func (f AddressFlag) String() string {
|
||||
var names []string
|
||||
eachName(f.Name, func(name string) {
|
||||
for _, name := range f.Names() {
|
||||
names = append(names, getNameHelp(name))
|
||||
})
|
||||
}
|
||||
|
||||
return strings.Join(names, ", ") + "\t" + f.Usage
|
||||
}
|
||||
|
@ -77,17 +81,57 @@ func getNameHelp(name string) string {
|
|||
return fmt.Sprintf("--%s value", name)
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f AddressFlag) GetName() string {
|
||||
return f.Name
|
||||
// Names returns the names of the flag.
|
||||
func (f AddressFlag) Names() []string {
|
||||
return cli.FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether the flag is required.
|
||||
func (f AddressFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false.
|
||||
func (f AddressFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false.
|
||||
func (f AddressFlag) TakesValue() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// GetUsage returns the usage string for the flag.
|
||||
func (f AddressFlag) GetUsage() string {
|
||||
return f.Usage
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment.
|
||||
// Ignores errors.
|
||||
func (f AddressFlag) Apply(set *flag.FlagSet) {
|
||||
eachName(f.Name, func(name string) {
|
||||
func (f AddressFlag) Apply(set *flag.FlagSet) error {
|
||||
for _, name := range f.Names() {
|
||||
set.Var(&f.Value, name, f.Usage)
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set.
|
||||
func (f AddressFlag) RunAction(c *cli.Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, address.Uint160ToString(f.Value.Value))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetValue returns the flags value as string representation.
|
||||
func (f AddressFlag) GetValue() string {
|
||||
return address.Uint160ToString(f.Value.Value)
|
||||
}
|
||||
|
||||
// Get returns the flag’s value in the given Context.
|
||||
func (f AddressFlag) Get(ctx *cli.Context) Address {
|
||||
adr := ctx.Generic(f.Name).(*Address)
|
||||
return *adr
|
||||
}
|
||||
|
||||
// ParseAddress parses a Uint160 from either an LE string or an address.
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func TestParseAddress(t *testing.T) {
|
||||
|
@ -109,22 +110,102 @@ func TestAddress_getNameHelp(t *testing.T) {
|
|||
require.Equal(t, "--flag value", getNameHelp("flag"))
|
||||
}
|
||||
|
||||
func TestAddressFlag_GetName(t *testing.T) {
|
||||
func TestAddressFlag_Names(t *testing.T) {
|
||||
flag := AddressFlag{
|
||||
Name: "my flag",
|
||||
Name: "flag",
|
||||
Aliases: []string{"my"},
|
||||
}
|
||||
|
||||
require.Equal(t, "my flag", flag.GetName())
|
||||
require.Equal(t, []string{"flag", "my"}, flag.Names())
|
||||
}
|
||||
|
||||
func TestAddress(t *testing.T) {
|
||||
f := flag.NewFlagSet("", flag.ContinueOnError)
|
||||
f.SetOutput(io.Discard) // don't pollute test output
|
||||
addr := AddressFlag{Name: "addr, a"}
|
||||
addr.Apply(f)
|
||||
addr := AddressFlag{Name: "addr", Aliases: []string{"a"}}
|
||||
err := addr.Apply(f)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Parse([]string{"--addr", "NRHkiY2hLy5ypD32CKZtL6pNwhbFMqDEhR"}))
|
||||
require.Equal(t, "NRHkiY2hLy5ypD32CKZtL6pNwhbFMqDEhR", f.Lookup("a").Value.String())
|
||||
require.NoError(t, f.Parse([]string{"-a", "NRHkiY2hLy5ypD32CKZtL6pNwhbFMqDEhR"}))
|
||||
require.Equal(t, "NRHkiY2hLy5ypD32CKZtL6pNwhbFMqDEhR", f.Lookup("a").Value.String())
|
||||
require.Error(t, f.Parse([]string{"--addr", "kek"}))
|
||||
}
|
||||
|
||||
func TestAddressFlag_IsRequired(t *testing.T) {
|
||||
flag := AddressFlag{Required: true}
|
||||
require.True(t, flag.IsRequired())
|
||||
|
||||
flag.Required = false
|
||||
require.False(t, flag.IsRequired())
|
||||
}
|
||||
|
||||
func TestAddressFlag_IsVisible(t *testing.T) {
|
||||
flag := AddressFlag{Hidden: false}
|
||||
require.True(t, flag.IsVisible())
|
||||
|
||||
flag.Hidden = true
|
||||
require.False(t, flag.IsVisible())
|
||||
}
|
||||
|
||||
func TestAddressFlag_TakesValue(t *testing.T) {
|
||||
flag := AddressFlag{}
|
||||
require.True(t, flag.TakesValue())
|
||||
}
|
||||
|
||||
func TestAddressFlag_GetUsage(t *testing.T) {
|
||||
flag := AddressFlag{Usage: "Specify the address"}
|
||||
require.Equal(t, "Specify the address", flag.GetUsage())
|
||||
}
|
||||
|
||||
func TestAddressFlag_GetValue(t *testing.T) {
|
||||
addrValue := util.Uint160{1, 2, 3}
|
||||
flag := AddressFlag{Value: Address{IsSet: true, Value: addrValue}}
|
||||
expectedStr := address.Uint160ToString(addrValue)
|
||||
require.Equal(t, expectedStr, flag.GetValue())
|
||||
}
|
||||
|
||||
func TestAddressFlag_Get(t *testing.T) {
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", flag.ContinueOnError)
|
||||
ctx := cli.NewContext(app, set, nil)
|
||||
|
||||
flag := AddressFlag{
|
||||
Name: "testAddress",
|
||||
Value: Address{Value: util.Uint160{1, 2, 3}, IsSet: false},
|
||||
}
|
||||
|
||||
set.Var(&flag.Value, "testAddress", "test usage")
|
||||
require.NoError(t, set.Set("testAddress", address.Uint160ToString(util.Uint160{3, 2, 1})))
|
||||
|
||||
expected := flag.Get(ctx)
|
||||
require.True(t, expected.IsSet)
|
||||
require.Equal(t, util.Uint160{3, 2, 1}, expected.Value)
|
||||
}
|
||||
|
||||
func TestAddressFlag_RunAction(t *testing.T) {
|
||||
called := false
|
||||
action := func(ctx *cli.Context, s string) error {
|
||||
called = true
|
||||
require.Equal(t, address.Uint160ToString(util.Uint160{1, 2, 3}), s)
|
||||
return nil
|
||||
}
|
||||
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", flag.ContinueOnError)
|
||||
ctx := cli.NewContext(app, set, nil)
|
||||
|
||||
flag := AddressFlag{
|
||||
Action: action,
|
||||
Value: Address{IsSet: true, Value: util.Uint160{4, 5, 6}},
|
||||
}
|
||||
|
||||
expected := address.Uint160ToString(util.Uint160{1, 2, 3})
|
||||
set.Var(&flag.Value, "testAddress", "test usage")
|
||||
require.NoError(t, set.Set("testAddress", expected))
|
||||
require.Equal(t, expected, flag.GetValue())
|
||||
|
||||
err := flag.RunAction(ctx)
|
||||
require.NoError(t, err)
|
||||
require.True(t, called)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// Fixed8 is a wrapper for a Uint160 with flag.Value methods.
|
||||
|
@ -18,6 +18,10 @@ type Fixed8Flag struct {
|
|||
Name string
|
||||
Usage string
|
||||
Value Fixed8
|
||||
Aliases []string
|
||||
Required bool
|
||||
Hidden bool
|
||||
Action func(*cli.Context, string) error
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -34,7 +38,7 @@ func (a Fixed8) String() string {
|
|||
func (a *Fixed8) Set(s string) error {
|
||||
f, err := fixedn.Fixed8FromString(s)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
a.Value = f
|
||||
return nil
|
||||
|
@ -45,31 +49,75 @@ func (a *Fixed8) Fixed8() fixedn.Fixed8 {
|
|||
return a.Value
|
||||
}
|
||||
|
||||
// IsSet checks if flag was set to a non-default value.
|
||||
func (f Fixed8Flag) IsSet() bool {
|
||||
return f.Value.Value != 0
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults).
|
||||
func (f Fixed8Flag) String() string {
|
||||
var names []string
|
||||
eachName(f.Name, func(name string) {
|
||||
for _, name := range f.Names() {
|
||||
names = append(names, getNameHelp(name))
|
||||
})
|
||||
|
||||
}
|
||||
return strings.Join(names, ", ") + "\t" + f.Usage
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f Fixed8Flag) GetName() string {
|
||||
return f.Name
|
||||
// Names returns the names of the flag.
|
||||
func (f Fixed8Flag) Names() []string {
|
||||
return cli.FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether the flag is required.
|
||||
func (f Fixed8Flag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false.
|
||||
func (f Fixed8Flag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// TakesValue returns true if the flag takes a value, otherwise false.
|
||||
func (f Fixed8Flag) TakesValue() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// GetUsage returns the usage string for the flag.
|
||||
func (f Fixed8Flag) GetUsage() string {
|
||||
return f.Usage
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment.
|
||||
// Ignores errors.
|
||||
func (f Fixed8Flag) Apply(set *flag.FlagSet) {
|
||||
eachName(f.Name, func(name string) {
|
||||
func (f Fixed8Flag) Apply(set *flag.FlagSet) error {
|
||||
for _, name := range f.Names() {
|
||||
set.Var(&f.Value, name, f.Usage)
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Fixed8FromContext returns a parsed util.Fixed8 value provided flag name.
|
||||
func Fixed8FromContext(ctx *cli.Context, name string) fixedn.Fixed8 {
|
||||
return ctx.Generic(name).(*Fixed8).Value
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set.
|
||||
func (f Fixed8Flag) RunAction(c *cli.Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, f.Value.Value.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetValue returns the flags value as string representation.
|
||||
func (f Fixed8Flag) GetValue() string {
|
||||
return f.Value.Value.String()
|
||||
}
|
||||
|
||||
// Get returns the flag’s value in the given Context.
|
||||
func (f Fixed8Flag) Get(ctx *cli.Context) Fixed8 {
|
||||
adr := ctx.Generic(f.Name).(*Fixed8)
|
||||
return *adr
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func TestFixed8_String(t *testing.T) {
|
||||
|
@ -45,22 +46,83 @@ func TestFixed8Flag_String(t *testing.T) {
|
|||
require.Equal(t, "--myFlag value\tGas amount", flag.String())
|
||||
}
|
||||
|
||||
func TestFixed8Flag_GetName(t *testing.T) {
|
||||
func TestFixed8Flag_Names(t *testing.T) {
|
||||
flag := Fixed8Flag{
|
||||
Name: "myFlag",
|
||||
}
|
||||
|
||||
require.Equal(t, "myFlag", flag.GetName())
|
||||
require.Equal(t, []string{"myFlag"}, flag.Names())
|
||||
}
|
||||
|
||||
func TestFixed8(t *testing.T) {
|
||||
f := flag.NewFlagSet("", flag.ContinueOnError)
|
||||
f.SetOutput(io.Discard) // don't pollute test output
|
||||
gas := Fixed8Flag{Name: "gas, g"}
|
||||
gas.Apply(f)
|
||||
gas := Fixed8Flag{Name: "gas", Aliases: []string{"g"}, Usage: "Gas amount", Value: Fixed8{Value: 0}, Required: true, Hidden: false, Action: nil}
|
||||
err := gas.Apply(f)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Parse([]string{"--gas", "0.123"}))
|
||||
require.Equal(t, "0.123", f.Lookup("g").Value.String())
|
||||
require.NoError(t, f.Parse([]string{"-g", "0.456"}))
|
||||
require.Equal(t, "0.456", f.Lookup("g").Value.String())
|
||||
require.Error(t, f.Parse([]string{"--gas", "kek"}))
|
||||
}
|
||||
|
||||
func TestFixed8Flag_Get(t *testing.T) {
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", flag.ContinueOnError)
|
||||
ctx := cli.NewContext(app, set, nil)
|
||||
flag := Fixed8Flag{
|
||||
Name: "testFlag",
|
||||
}
|
||||
fixedFlag := Fixed8{Value: fixedn.Fixed8(123)}
|
||||
set.Var(&fixedFlag, "testFlag", "test usage")
|
||||
require.NoError(t, set.Set("testFlag", "0.00000321"))
|
||||
expected := flag.Get(ctx)
|
||||
require.Equal(t, fixedn.Fixed8(321), expected.Value)
|
||||
}
|
||||
|
||||
func TestFixed8Flag_GetValue(t *testing.T) {
|
||||
f := Fixed8Flag{Value: Fixed8{Value: fixedn.Fixed8(123)}}
|
||||
require.Equal(t, "0.00000123", f.GetValue())
|
||||
require.True(t, f.TakesValue())
|
||||
}
|
||||
|
||||
func TestFixed8Flag_RunAction(t *testing.T) {
|
||||
called := false
|
||||
action := func(ctx *cli.Context, s string) error {
|
||||
called = true
|
||||
require.Equal(t, "0.00000123", s)
|
||||
return nil
|
||||
}
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", flag.ContinueOnError)
|
||||
ctx := cli.NewContext(app, set, nil)
|
||||
f := Fixed8Flag{
|
||||
Action: action,
|
||||
Value: Fixed8{Value: fixedn.Fixed8(123)},
|
||||
}
|
||||
err := f.RunAction(ctx)
|
||||
require.NoError(t, err)
|
||||
require.True(t, called)
|
||||
}
|
||||
|
||||
func TestFixed8Flag_GetUsage(t *testing.T) {
|
||||
f := Fixed8Flag{Usage: "Use this flag to specify gas amount"}
|
||||
require.Equal(t, "Use this flag to specify gas amount", f.GetUsage())
|
||||
}
|
||||
|
||||
func TestFixed8Flag_IsVisible(t *testing.T) {
|
||||
f := Fixed8Flag{Hidden: false}
|
||||
require.True(t, f.IsVisible())
|
||||
|
||||
f.Hidden = true
|
||||
require.False(t, f.IsVisible())
|
||||
}
|
||||
|
||||
func TestFixed8Flag_IsRequired(t *testing.T) {
|
||||
f := Fixed8Flag{Required: false}
|
||||
require.False(t, f.IsRequired())
|
||||
|
||||
f.Required = true
|
||||
require.True(t, f.IsRequired())
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
package flags
|
||||
|
||||
import "strings"
|
||||
|
||||
func eachName(longName string, fn func(string)) {
|
||||
parts := strings.Split(longName, ",")
|
||||
for _, name := range parts {
|
||||
name = strings.Trim(name, " ")
|
||||
fn(name)
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package flags
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestEachName(t *testing.T) {
|
||||
expected := "*one*two*three"
|
||||
actual := ""
|
||||
|
||||
eachName(" one,two ,three", func(s string) {
|
||||
actual += "*" + s
|
||||
})
|
||||
require.Equal(t, expected, actual)
|
||||
}
|
|
@ -21,14 +21,13 @@ func TestNEP17Balance(t *testing.T) {
|
|||
e := testcli.NewExecutor(t, true)
|
||||
|
||||
args := []string{
|
||||
"neo-go", "wallet", "nep17", "multitransfer",
|
||||
"neo-go", "wallet", "nep17", "multitransfer", "--force",
|
||||
"--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
|
||||
"--wallet", testcli.ValidatorWallet,
|
||||
"--from", testcli.ValidatorAddr,
|
||||
"GAS:" + testcli.TestWalletMultiAccount1 + ":1",
|
||||
"NEO:" + testcli.TestWalletMultiAccount1 + ":10",
|
||||
"GAS:" + testcli.TestWalletMultiAccount3 + ":3",
|
||||
"--force",
|
||||
}
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, args...)
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/cli/options"
|
||||
"github.com/nspcc-dev/neo-go/internal/testcli"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func TestGetRPCClient(t *testing.T) {
|
||||
|
|
|
@ -26,7 +26,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"golang.org/x/term"
|
||||
|
@ -47,65 +47,87 @@ const (
|
|||
const RPCEndpointFlag = "rpc-endpoint"
|
||||
|
||||
// Wallet is a set of flags used for wallet operations.
|
||||
var Wallet = []cli.Flag{cli.StringFlag{
|
||||
Name: "wallet, w",
|
||||
var Wallet = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "wallet",
|
||||
Aliases: []string{"w"},
|
||||
Usage: "Wallet to use to get the key for transaction signing; conflicts with --wallet-config flag",
|
||||
}, cli.StringFlag{
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "wallet-config",
|
||||
Usage: "Path to wallet config to use to get the key for transaction signing; conflicts with --wallet flag"},
|
||||
Usage: "Path to wallet config to use to get the key for transaction signing; conflicts with --wallet flag",
|
||||
},
|
||||
}
|
||||
|
||||
// Network is a set of flags for choosing the network to operate on
|
||||
// (privnet/mainnet/testnet).
|
||||
var Network = []cli.Flag{
|
||||
cli.BoolFlag{Name: "privnet, p", Usage: "Use private network configuration (if --config-file option is not specified)"},
|
||||
cli.BoolFlag{Name: "mainnet, m", Usage: "Use mainnet network configuration (if --config-file option is not specified)"},
|
||||
cli.BoolFlag{Name: "testnet, t", Usage: "Use testnet network configuration (if --config-file option is not specified)"},
|
||||
cli.BoolFlag{Name: "unittest", Hidden: true},
|
||||
&cli.BoolFlag{
|
||||
Name: "privnet",
|
||||
Aliases: []string{"p"},
|
||||
Usage: "Use private network configuration (if --config-file option is not specified)",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "mainnet",
|
||||
Aliases: []string{"m"},
|
||||
Usage: "Use mainnet network configuration (if --config-file option is not specified)",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "testnet",
|
||||
Aliases: []string{"t"},
|
||||
Usage: "Use testnet network configuration (if --config-file option is not specified)",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "unittest",
|
||||
Hidden: true,
|
||||
},
|
||||
}
|
||||
|
||||
// RPC is a set of flags used for RPC connections (endpoint and timeout).
|
||||
var RPC = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: RPCEndpointFlag + ", r",
|
||||
&cli.StringFlag{
|
||||
Name: RPCEndpointFlag,
|
||||
Aliases: []string{"r"},
|
||||
Usage: "RPC node address",
|
||||
},
|
||||
cli.DurationFlag{
|
||||
Name: "timeout, s",
|
||||
&cli.DurationFlag{
|
||||
Name: "timeout",
|
||||
Aliases: []string{"s"},
|
||||
Value: DefaultTimeout,
|
||||
Usage: "Timeout for the operation",
|
||||
},
|
||||
}
|
||||
|
||||
// Historic is a flag for commands that can perform historic invocations.
|
||||
var Historic = cli.StringFlag{
|
||||
var Historic = &cli.StringFlag{
|
||||
Name: "historic",
|
||||
Usage: "Use historic state (height, block hash or state root hash)",
|
||||
}
|
||||
|
||||
// Config is a flag for commands that use node configuration.
|
||||
var Config = cli.StringFlag{
|
||||
var Config = &cli.StringFlag{
|
||||
Name: "config-path",
|
||||
Usage: "Path to directory with per-network configuration files (may be overridden by --config-file option for the configuration file)",
|
||||
}
|
||||
|
||||
// ConfigFile is a flag for commands that use node configuration and provide
|
||||
// path to the specific config file instead of config path.
|
||||
var ConfigFile = cli.StringFlag{
|
||||
var ConfigFile = &cli.StringFlag{
|
||||
Name: "config-file",
|
||||
Usage: "Path to the node configuration file (overrides --config-path option)",
|
||||
}
|
||||
|
||||
// RelativePath is a flag for commands that use node configuration and provide
|
||||
// a prefix to all relative paths in config files.
|
||||
var RelativePath = cli.StringFlag{
|
||||
var RelativePath = &cli.StringFlag{
|
||||
Name: "relative-path",
|
||||
Usage: "Prefix to all relative paths in the node configuration file",
|
||||
}
|
||||
|
||||
// Debug is a flag for commands that allow node in debug mode usage.
|
||||
var Debug = cli.BoolFlag{
|
||||
Name: "debug, d",
|
||||
var Debug = &cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Aliases: []string{"d"},
|
||||
Usage: "Enable debug logging (LOTS of output, overrides configuration)",
|
||||
}
|
||||
|
||||
|
@ -146,15 +168,15 @@ func GetTimeoutContext(ctx *cli.Context) (context.Context, func()) {
|
|||
func GetRPCClient(gctx context.Context, ctx *cli.Context) (*rpcclient.Client, cli.ExitCoder) {
|
||||
endpoint := ctx.String(RPCEndpointFlag)
|
||||
if len(endpoint) == 0 {
|
||||
return nil, cli.NewExitError(errNoEndpoint, 1)
|
||||
return nil, cli.Exit(errNoEndpoint, 1)
|
||||
}
|
||||
c, err := rpcclient.New(gctx, endpoint, rpcclient.Options{})
|
||||
if err != nil {
|
||||
return nil, cli.NewExitError(err, 1)
|
||||
return nil, cli.Exit(err, 1)
|
||||
}
|
||||
err = c.Init()
|
||||
if err != nil {
|
||||
return nil, cli.NewExitError(err, 1)
|
||||
return nil, cli.Exit(err, 1)
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
@ -173,7 +195,7 @@ func GetInvoker(c *rpcclient.Client, ctx *cli.Context, signers []transaction.Sig
|
|||
// 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)
|
||||
return nil, cli.Exit(errInvalidHistoric, 1)
|
||||
}
|
||||
|
||||
// GetRPCWithInvoker combines GetRPCClient with GetInvoker for cases where it's
|
||||
|
@ -314,7 +336,7 @@ func GetRPCWithActor(gctx context.Context, ctx *cli.Context, signers []actor.Sig
|
|||
a, actorErr := actor.New(c, signers)
|
||||
if actorErr != nil {
|
||||
c.Close()
|
||||
return nil, nil, cli.NewExitError(fmt.Errorf("failed to create Actor: %w", actorErr), 1)
|
||||
return nil, nil, cli.Exit(fmt.Errorf("failed to create Actor: %w", actorErr), 1)
|
||||
}
|
||||
return c, a, nil
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func TestGetNetwork(t *testing.T) {
|
||||
|
|
|
@ -22,21 +22,22 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// NewCommands returns 'query' command.
|
||||
func NewCommands() []cli.Command {
|
||||
func NewCommands() []*cli.Command {
|
||||
queryTxFlags := append([]cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "verbose, v",
|
||||
&cli.BoolFlag{
|
||||
Name: "verbose",
|
||||
Aliases: []string{"v"},
|
||||
Usage: "Output full tx info and execution logs",
|
||||
},
|
||||
}, options.RPC...)
|
||||
return []cli.Command{{
|
||||
return []*cli.Command{{
|
||||
Name: "query",
|
||||
Usage: "Query data from RPC node",
|
||||
Subcommands: []cli.Command{
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "candidates",
|
||||
Usage: "Get candidates and votes",
|
||||
|
@ -61,14 +62,14 @@ func NewCommands() []cli.Command {
|
|||
{
|
||||
Name: "tx",
|
||||
Usage: "Query transaction status",
|
||||
UsageText: "neo-go query tx <hash> -r endpoint [-s timeout] [-v]",
|
||||
UsageText: "neo-go query tx -r endpoint [-s timeout] [-v] <hash>",
|
||||
Action: queryTx,
|
||||
Flags: queryTxFlags,
|
||||
},
|
||||
{
|
||||
Name: "voter",
|
||||
Usage: "Print NEO holder account state",
|
||||
UsageText: "neo-go query voter <address> -r endpoint [-s timeout]",
|
||||
UsageText: "neo-go query voter -r endpoint [-s timeout] <address>",
|
||||
Action: queryVoter,
|
||||
Flags: options.RPC,
|
||||
},
|
||||
|
@ -77,16 +78,16 @@ func NewCommands() []cli.Command {
|
|||
}
|
||||
|
||||
func queryTx(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
args := ctx.Args().Slice()
|
||||
if len(args) == 0 {
|
||||
return cli.NewExitError("Transaction hash is missing", 1)
|
||||
return cli.Exit("Transaction hash is missing", 1)
|
||||
} else if len(args) > 1 {
|
||||
return cli.NewExitError("only one transaction hash is accepted", 1)
|
||||
return cli.Exit("only one transaction hash is accepted", 1)
|
||||
}
|
||||
|
||||
txHash, err := util.Uint256DecodeStringLE(strings.TrimPrefix(args[0], "0x"))
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Sprintf("Invalid tx hash: %s", args[0]), 1)
|
||||
return cli.Exit(fmt.Sprintf("Invalid tx hash: %s", args[0]), 1)
|
||||
}
|
||||
|
||||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
|
@ -94,25 +95,25 @@ func queryTx(ctx *cli.Context) error {
|
|||
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
txOut, err := c.GetRawTransactionVerbose(txHash)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
var res *result.ApplicationLog
|
||||
if !txOut.Blockhash.Equals(util.Uint256{}) {
|
||||
res, err = c.GetApplicationLog(txHash, nil)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
}
|
||||
|
||||
err = DumpApplicationLog(ctx, res, &txOut.Transaction, &txOut.TransactionMetadata, ctx.Bool("verbose"))
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -179,16 +180,16 @@ func queryCandidates(ctx *cli.Context) error {
|
|||
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
vals, err := c.GetCandidates()
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
comm, err := c.GetCommittee()
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
sort.Slice(vals, func(i, j int) bool {
|
||||
|
@ -225,12 +226,12 @@ func queryCommittee(ctx *cli.Context) error {
|
|||
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
comm, err := c.GetCommittee()
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
for _, k := range comm {
|
||||
|
@ -251,12 +252,12 @@ func queryHeight(ctx *cli.Context) error {
|
|||
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
blockCount, err := c.GetBlockCount()
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
blockHeight := blockCount - 1 // GetBlockCount returns block count (including 0), not the highest block index.
|
||||
|
||||
|
@ -271,16 +272,16 @@ func queryHeight(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
func queryVoter(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
args := ctx.Args().Slice()
|
||||
if len(args) == 0 {
|
||||
return cli.NewExitError("No address specified", 1)
|
||||
return cli.Exit("No address specified", 1)
|
||||
} else if len(args) > 1 {
|
||||
return cli.NewExitError("this command only accepts one address", 1)
|
||||
return cli.Exit("this command only accepts one address", 1)
|
||||
}
|
||||
|
||||
addr, err := flags.ParseAddress(args[0])
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Sprintf("wrong address: %s", args[0]), 1)
|
||||
return cli.Exit(fmt.Sprintf("wrong address: %s", args[0]), 1)
|
||||
}
|
||||
|
||||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
|
@ -294,14 +295,14 @@ func queryVoter(ctx *cli.Context) error {
|
|||
|
||||
st, err := neoToken.GetAccountState(addr)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
if st == nil {
|
||||
st = new(state.NEOBalance)
|
||||
}
|
||||
dec, err := neoToken.Decimals()
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to get decimals: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to get decimals: %w", err), 1)
|
||||
}
|
||||
voted := "null"
|
||||
if st.VoteTo != nil {
|
||||
|
|
|
@ -27,13 +27,13 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/services/oracle"
|
||||
"github.com/nspcc-dev/neo-go/pkg/services/rpcsrv"
|
||||
"github.com/nspcc-dev/neo-go/pkg/services/stateroot"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
// NewCommands returns 'node' command.
|
||||
func NewCommands() []cli.Command {
|
||||
func NewCommands() []*cli.Command {
|
||||
cfgFlags := []cli.Flag{options.Config, options.ConfigFile, options.RelativePath}
|
||||
cfgFlags = append(cfgFlags, options.Network...)
|
||||
var cfgWithCountFlags = make([]cli.Flag, len(cfgFlags))
|
||||
|
@ -41,47 +41,52 @@ func NewCommands() []cli.Command {
|
|||
cfgFlags = append(cfgFlags, options.Debug)
|
||||
|
||||
cfgWithCountFlags = append(cfgWithCountFlags,
|
||||
cli.UintFlag{
|
||||
Name: "count, c",
|
||||
&cli.UintFlag{
|
||||
Name: "count",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "Number of blocks to be processed (default or 0: all chain)",
|
||||
},
|
||||
)
|
||||
var cfgCountOutFlags = make([]cli.Flag, len(cfgWithCountFlags))
|
||||
copy(cfgCountOutFlags, cfgWithCountFlags)
|
||||
cfgCountOutFlags = append(cfgCountOutFlags,
|
||||
cli.UintFlag{
|
||||
Name: "start, s",
|
||||
Usage: "Block number to start from (default: 0)",
|
||||
&cli.UintFlag{
|
||||
Name: "start",
|
||||
Aliases: []string{"s"},
|
||||
Usage: "Block number to start from",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "out, o",
|
||||
&cli.StringFlag{
|
||||
Name: "out",
|
||||
Aliases: []string{"o"},
|
||||
Usage: "Output file (stdout if not given)",
|
||||
},
|
||||
)
|
||||
var cfgCountInFlags = make([]cli.Flag, len(cfgWithCountFlags))
|
||||
copy(cfgCountInFlags, cfgWithCountFlags)
|
||||
cfgCountInFlags = append(cfgCountInFlags,
|
||||
cli.StringFlag{
|
||||
Name: "in, i",
|
||||
&cli.StringFlag{
|
||||
Name: "in",
|
||||
Aliases: []string{"i"},
|
||||
Usage: "Input file (stdin if not given)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "dump",
|
||||
Usage: "Directory for storing JSON dumps",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "incremental, n",
|
||||
&cli.BoolFlag{
|
||||
Name: "incremental",
|
||||
Aliases: []string{"n"},
|
||||
Usage: "Use if dump is incremental",
|
||||
},
|
||||
)
|
||||
var cfgHeightFlags = make([]cli.Flag, len(cfgFlags)+1)
|
||||
copy(cfgHeightFlags, cfgFlags)
|
||||
cfgHeightFlags[len(cfgHeightFlags)-1] = cli.UintFlag{
|
||||
cfgHeightFlags[len(cfgHeightFlags)-1] = &cli.UintFlag{
|
||||
Name: "height",
|
||||
Usage: "Height of the state to reset DB to",
|
||||
Required: true,
|
||||
}
|
||||
return []cli.Command{
|
||||
return []*cli.Command{
|
||||
{
|
||||
Name: "node",
|
||||
Usage: "Start a NeoGo node",
|
||||
|
@ -92,7 +97,7 @@ func NewCommands() []cli.Command {
|
|||
{
|
||||
Name: "db",
|
||||
Usage: "Database manipulations",
|
||||
Subcommands: []cli.Command{
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "dump",
|
||||
Usage: "Dump blocks (starting with block #1) to the file",
|
||||
|
@ -134,7 +139,7 @@ func newGraceContext() context.Context {
|
|||
func initBCWithMetrics(cfg config.Config, log *zap.Logger) (*core.Blockchain, *metrics.Service, *metrics.Service, error) {
|
||||
chain, _, err := initBlockChain(cfg, log)
|
||||
if err != nil {
|
||||
return nil, nil, nil, cli.NewExitError(err, 1)
|
||||
return nil, nil, nil, cli.Exit(err, 1)
|
||||
}
|
||||
prometheus := metrics.NewPrometheusService(cfg.ApplicationConfiguration.Prometheus, log)
|
||||
pprof := metrics.NewPprofService(cfg.ApplicationConfiguration.Pprof, log)
|
||||
|
@ -142,11 +147,11 @@ func initBCWithMetrics(cfg config.Config, log *zap.Logger) (*core.Blockchain, *m
|
|||
go chain.Run()
|
||||
err = prometheus.Start()
|
||||
if err != nil {
|
||||
return nil, nil, nil, cli.NewExitError(fmt.Errorf("failed to start Prometheus service: %w", err), 1)
|
||||
return nil, nil, nil, cli.Exit(fmt.Errorf("failed to start Prometheus service: %w", err), 1)
|
||||
}
|
||||
err = pprof.Start()
|
||||
if err != nil {
|
||||
return nil, nil, nil, cli.NewExitError(fmt.Errorf("failed to start Pprof service: %w", err), 1)
|
||||
return nil, nil, nil, cli.Exit(fmt.Errorf("failed to start Pprof service: %w", err), 1)
|
||||
}
|
||||
|
||||
return chain, prometheus, pprof, nil
|
||||
|
@ -158,11 +163,11 @@ func dumpDB(ctx *cli.Context) error {
|
|||
}
|
||||
cfg, err := options.GetConfigFromContext(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
log, _, logCloser, err := options.HandleLoggingParams(ctx.Bool("debug"), cfg.ApplicationConfiguration)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
if logCloser != nil {
|
||||
defer func() { _ = logCloser() }()
|
||||
|
@ -174,7 +179,7 @@ func dumpDB(ctx *cli.Context) error {
|
|||
if out := ctx.String("out"); out != "" {
|
||||
outStream, err = os.Create(out)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
}
|
||||
defer outStream.Close()
|
||||
|
@ -192,7 +197,7 @@ func dumpDB(ctx *cli.Context) error {
|
|||
|
||||
chainCount := chain.BlockHeight() + 1
|
||||
if start+count > chainCount {
|
||||
return cli.NewExitError(fmt.Errorf("chain is not that high (%d) to dump %d blocks starting from %d", chainCount-1, count, start), 1)
|
||||
return cli.Exit(fmt.Errorf("chain is not that high (%d) to dump %d blocks starting from %d", chainCount-1, count, start), 1)
|
||||
}
|
||||
if count == 0 {
|
||||
count = chainCount - start
|
||||
|
@ -203,7 +208,7 @@ func dumpDB(ctx *cli.Context) error {
|
|||
writer.WriteU32LE(count)
|
||||
err = chaindump.Dump(chain, writer, start, count)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err.Error(), 1)
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -218,7 +223,7 @@ func restoreDB(ctx *cli.Context) error {
|
|||
}
|
||||
log, _, logCloser, err := options.HandleLoggingParams(ctx.Bool("debug"), cfg.ApplicationConfiguration)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
if logCloser != nil {
|
||||
defer func() { _ = logCloser() }()
|
||||
|
@ -229,7 +234,7 @@ func restoreDB(ctx *cli.Context) error {
|
|||
if in := ctx.String("in"); in != "" {
|
||||
inStream, err = os.Open(in)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
}
|
||||
defer inStream.Close()
|
||||
|
@ -254,7 +259,7 @@ func restoreDB(ctx *cli.Context) error {
|
|||
if ctx.Bool("incremental") {
|
||||
start = reader.ReadU32LE()
|
||||
if chain.BlockHeight()+1 < start {
|
||||
return cli.NewExitError(fmt.Errorf("expected height: %d, dump starts at %d",
|
||||
return cli.Exit(fmt.Errorf("expected height: %d, dump starts at %d",
|
||||
chain.BlockHeight()+1, start), 1)
|
||||
}
|
||||
}
|
||||
|
@ -266,10 +271,10 @@ func restoreDB(ctx *cli.Context) error {
|
|||
|
||||
var allBlocks = reader.ReadU32LE()
|
||||
if reader.Err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
if skip+count > allBlocks {
|
||||
return cli.NewExitError(fmt.Errorf("input file has only %d blocks, can't read %d starting from %d", allBlocks, count, skip), 1)
|
||||
return cli.Exit(fmt.Errorf("input file has only %d blocks, can't read %d starting from %d", allBlocks, count, skip), 1)
|
||||
}
|
||||
if count == 0 {
|
||||
count = allBlocks - skip
|
||||
|
@ -320,7 +325,7 @@ func restoreDB(ctx *cli.Context) error {
|
|||
|
||||
err = chaindump.Restore(chain, reader, skip, count, f)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -331,29 +336,29 @@ func resetDB(ctx *cli.Context) error {
|
|||
}
|
||||
cfg, err := options.GetConfigFromContext(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
h := uint32(ctx.Uint("height"))
|
||||
|
||||
log, _, logCloser, err := options.HandleLoggingParams(ctx.Bool("debug"), cfg.ApplicationConfiguration)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
if logCloser != nil {
|
||||
defer func() { _ = logCloser() }()
|
||||
}
|
||||
chain, store, err := initBlockChain(cfg, log)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to create Blockchain instance: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to create Blockchain instance: %w", err), 1)
|
||||
}
|
||||
|
||||
err = chain.Reset(h)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to reset chain state to height %d: %w", h, err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to reset chain state to height %d: %w", h, err), 1)
|
||||
}
|
||||
err = store.Close()
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to close the DB: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to close the DB: %w", err), 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -442,12 +447,12 @@ func startServer(ctx *cli.Context) error {
|
|||
|
||||
cfg, err := options.GetConfigFromContext(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
var logDebug = ctx.Bool("debug")
|
||||
log, logLevel, logCloser, err := options.HandleLoggingParams(logDebug, cfg.ApplicationConfiguration)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
if logCloser != nil {
|
||||
defer func() { _ = logCloser() }()
|
||||
|
@ -458,12 +463,12 @@ func startServer(ctx *cli.Context) error {
|
|||
|
||||
serverConfig, err := network.NewServerConfig(cfg)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
chain, prometheus, pprof, err := initBCWithMetrics(cfg, log)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer func() {
|
||||
pprof.ShutDown()
|
||||
|
@ -473,26 +478,26 @@ func startServer(ctx *cli.Context) error {
|
|||
|
||||
serv, err := network.NewServer(serverConfig, chain, chain.GetStateSyncModule(), log)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to create network server: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to create network server: %w", err), 1)
|
||||
}
|
||||
srMod := chain.GetStateModule().(*corestate.Module) // Take full responsibility here.
|
||||
sr, err := stateroot.New(serverConfig.StateRootCfg, srMod, log, chain, serv.BroadcastExtensible)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't initialize StateRoot service: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't initialize StateRoot service: %w", err), 1)
|
||||
}
|
||||
serv.AddExtensibleService(sr, stateroot.Category, sr.OnPayload)
|
||||
|
||||
oracleSrv, err := mkOracle(cfg.ApplicationConfiguration.Oracle, cfg.ProtocolConfiguration.Magic, chain, serv, log)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
dbftSrv, err := mkConsensus(cfg.ApplicationConfiguration.Consensus, serverConfig.TimePerBlock, chain, serv, log)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
p2pNotary, err := mkP2PNotary(cfg.ApplicationConfiguration.P2PNotary, chain, serv, log)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
errChan := make(chan error)
|
||||
rpcServer := rpcsrv.New(chain, cfg.ApplicationConfiguration.RPC, serv, oracleSrv, log, errChan)
|
||||
|
@ -640,7 +645,7 @@ Main:
|
|||
}
|
||||
|
||||
if shutdownErr != nil {
|
||||
return cli.NewExitError(shutdownErr, 1)
|
||||
return cli.Exit(shutdownErr, 1)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -650,7 +655,7 @@ Main:
|
|||
func initBlockChain(cfg config.Config, log *zap.Logger) (*core.Blockchain, storage.Store, error) {
|
||||
store, err := storage.NewStore(cfg.ApplicationConfiguration.DBConfiguration)
|
||||
if err != nil {
|
||||
return nil, nil, cli.NewExitError(fmt.Errorf("could not initialize storage: %w", err), 1)
|
||||
return nil, nil, cli.Exit(fmt.Errorf("could not initialize storage: %w", err), 1)
|
||||
}
|
||||
|
||||
chain, err := core.NewBlockchain(store, cfg.Blockchain(), log)
|
||||
|
@ -663,7 +668,7 @@ func initBlockChain(cfg config.Config, log *zap.Logger) (*core.Blockchain, stora
|
|||
errArgs = append(errArgs, closeErr)
|
||||
}
|
||||
|
||||
return nil, nil, cli.NewExitError(fmt.Errorf(errText, errArgs...), 1)
|
||||
return nil, nil, cli.Exit(fmt.Errorf(errText, errArgs...), 1)
|
||||
}
|
||||
return chain, store, nil
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/storage/dbconfig"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
|
|
|
@ -9,32 +9,35 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/binding"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/rpcbinding"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var generatorFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
&cli.StringFlag{
|
||||
Name: "config",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "Configuration file to use",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "manifest, m",
|
||||
&cli.StringFlag{
|
||||
Name: "manifest",
|
||||
Aliases: []string{"m"},
|
||||
Required: true,
|
||||
Usage: "Read contract manifest (*.manifest.json) file",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "out, o",
|
||||
&cli.StringFlag{
|
||||
Name: "out",
|
||||
Aliases: []string{"o"},
|
||||
Required: true,
|
||||
Usage: "Output of the compiled wrapper",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "hash",
|
||||
Usage: "Smart-contract hash. If not passed, the wrapper will be designed for dynamic hash usage",
|
||||
},
|
||||
}
|
||||
|
||||
var generateWrapperCmd = cli.Command{
|
||||
var generateWrapperCmd = &cli.Command{
|
||||
Name: "generate-wrapper",
|
||||
Usage: "Generate wrapper to use in other contracts",
|
||||
UsageText: "neo-go contract generate-wrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]",
|
||||
|
@ -48,7 +51,7 @@ var generateWrapperCmd = cli.Command{
|
|||
Flags: generatorFlags,
|
||||
}
|
||||
|
||||
var generateRPCWrapperCmd = cli.Command{
|
||||
var generateRPCWrapperCmd = &cli.Command{
|
||||
Name: "generate-rpcwrapper",
|
||||
Usage: "Generate RPC wrapper to use for data reads",
|
||||
UsageText: "neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]",
|
||||
|
@ -76,23 +79,23 @@ func contractGenerateSomething(ctx *cli.Context, cb func(binding.Config) error)
|
|||
if hStr := ctx.String("hash"); len(hStr) != 0 {
|
||||
h, err = util.Uint160DecodeStringLE(strings.TrimPrefix(hStr, "0x"))
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid contract hash: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("invalid contract hash: %w", err), 1)
|
||||
}
|
||||
}
|
||||
m, _, err := readManifest(ctx.String("manifest"), h)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't read contract manifest: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't read contract manifest: %w", err), 1)
|
||||
}
|
||||
|
||||
cfg := binding.NewConfig()
|
||||
if cfgPath := ctx.String("config"); cfgPath != "" {
|
||||
bs, err := os.ReadFile(cfgPath)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't read config file: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't read config file: %w", err), 1)
|
||||
}
|
||||
err = yaml.Unmarshal(bs, &cfg)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't parse config file: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't parse config file: %w", err), 1)
|
||||
}
|
||||
}
|
||||
cfg.Manifest = m
|
||||
|
@ -100,7 +103,7 @@ func contractGenerateSomething(ctx *cli.Context, cb func(binding.Config) error)
|
|||
|
||||
f, err := os.Create(ctx.String("out"))
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't create output file: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't create output file: %w", err), 1)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
|
@ -108,7 +111,7 @@ func contractGenerateSomething(ctx *cli.Context, cb func(binding.Config) error)
|
|||
|
||||
err = cb(cfg)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("error during generation: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("error during generation: %w", err), 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
|
@ -125,7 +125,7 @@ func TestGenerate(t *testing.T) {
|
|||
0xCA, 0xFE, 0xBA, 0xBE, 0xDE, 0xAD, 0xBE, 0xEF, 0x03, 0x04,
|
||||
}
|
||||
app := cli.NewApp()
|
||||
app.Commands = []cli.Command{generateWrapperCmd}
|
||||
app.Commands = []*cli.Command{generateWrapperCmd}
|
||||
|
||||
rawCfg := `package: wrapper
|
||||
hash: ` + h.StringLE() + `
|
||||
|
@ -351,7 +351,7 @@ func TestGenerateValidPackageName(t *testing.T) {
|
|||
0xCA, 0xFE, 0xBA, 0xBE, 0xDE, 0xAD, 0xBE, 0xEF, 0x03, 0x04,
|
||||
}
|
||||
app := cli.NewApp()
|
||||
app.Commands = []cli.Command{generateWrapperCmd, generateRPCWrapperCmd}
|
||||
app.Commands = []*cli.Command{generateWrapperCmd, generateRPCWrapperCmd}
|
||||
require.NoError(t, app.Run([]string{"", "generate-wrapper",
|
||||
"--manifest", manifestFile,
|
||||
"--out", outFile,
|
||||
|
@ -432,7 +432,7 @@ const rewriteExpectedOutputs = false
|
|||
func TestGenerateRPCBindings(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
app := cli.NewApp()
|
||||
app.Commands = []cli.Command{generateWrapperCmd, generateRPCWrapperCmd}
|
||||
app.Commands = []*cli.Command{generateWrapperCmd, generateRPCWrapperCmd}
|
||||
|
||||
var checkBinding = func(manifest string, hash string, good string) {
|
||||
t.Run(manifest, func(t *testing.T) {
|
||||
|
@ -549,7 +549,7 @@ func TestAssistedRPCBindings(t *testing.T) {
|
|||
|
||||
func TestGenerate_Errors(t *testing.T) {
|
||||
app := cli.NewApp()
|
||||
app.Commands = []cli.Command{generateWrapperCmd}
|
||||
app.Commands = []*cli.Command{generateWrapperCmd}
|
||||
app.ExitErrHandler = func(*cli.Context, error) {}
|
||||
|
||||
checkError := func(t *testing.T, msg string, args ...string) {
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func manifestAddGroup(ctx *cli.Context) error {
|
||||
|
@ -22,25 +22,25 @@ func manifestAddGroup(ctx *cli.Context) error {
|
|||
}
|
||||
sender, err := flags.ParseAddress(ctx.String("sender"))
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid sender: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("invalid sender: %w", err), 1)
|
||||
}
|
||||
|
||||
nf, _, err := readNEFFile(ctx.String("nef"))
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't read NEF file: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't read NEF file: %w", err), 1)
|
||||
}
|
||||
|
||||
mPath := ctx.String("manifest")
|
||||
m, _, err := readManifest(mPath, util.Uint160{})
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't read contract manifest: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't read contract manifest: %w", err), 1)
|
||||
}
|
||||
|
||||
h := state.CreateContractHash(sender, nf.Checksum, m.Name)
|
||||
|
||||
gAcc, w, err := options.GetAccFromContext(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't get account to sign group with: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't get account to sign group with: %w", err), 1)
|
||||
}
|
||||
defer w.Close()
|
||||
|
||||
|
@ -64,12 +64,12 @@ func manifestAddGroup(ctx *cli.Context) error {
|
|||
|
||||
rawM, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't marshal manifest: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't marshal manifest: %w", err), 1)
|
||||
}
|
||||
|
||||
err = os.WriteFile(mPath, rawM, os.ModePerm)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't write manifest file: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't write manifest file: %w", err), 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -27,13 +27,17 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// addressFlagName is a flag name used for address-related operations. It should be
|
||||
// the same within the smartcontract package, thus, use this constant.
|
||||
const addressFlagName = "address, a"
|
||||
// addressFlagName and addressFlagAlias are a flag name and its alias
|
||||
// used for address-related operations. It should be the same within
|
||||
// the smartcontract package, thus, use this constant.
|
||||
const (
|
||||
addressFlagName = "address"
|
||||
addressFlagAlias = "a"
|
||||
)
|
||||
|
||||
var (
|
||||
errNoInput = errors.New("no input file was found, specify an input file with the '--in or -i' flag")
|
||||
|
@ -43,8 +47,9 @@ var (
|
|||
errNoScriptHash = errors.New("no smart contract hash was provided, specify one as the first argument")
|
||||
errNoSmartContractName = errors.New("no name was provided, specify the '--name or -n' flag")
|
||||
errFileExist = errors.New("A file with given smart-contract name already exists")
|
||||
addressFlag = flags.AddressFlag{
|
||||
addressFlag = &flags.AddressFlag{
|
||||
Name: addressFlagName,
|
||||
Aliases: []string{addressFlagAlias},
|
||||
Usage: "Address to use as transaction signee (and gas source)",
|
||||
}
|
||||
)
|
||||
|
@ -74,10 +79,11 @@ func RuntimeNotify(args []any) {
|
|||
)
|
||||
|
||||
// NewCommands returns 'contract' command.
|
||||
func NewCommands() []cli.Command {
|
||||
func NewCommands() []*cli.Command {
|
||||
testInvokeScriptFlags := []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "in, i",
|
||||
&cli.StringFlag{
|
||||
Name: "in",
|
||||
Aliases: []string{"i"},
|
||||
Usage: "Input location of the .nef file that needs to be invoked",
|
||||
},
|
||||
options.Historic,
|
||||
|
@ -96,37 +102,43 @@ func NewCommands() []cli.Command {
|
|||
invokeFunctionFlags = append(invokeFunctionFlags, options.Wallet...)
|
||||
invokeFunctionFlags = append(invokeFunctionFlags, options.RPC...)
|
||||
deployFlags := append(invokeFunctionFlags, []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "in, i",
|
||||
&cli.StringFlag{
|
||||
Name: "in",
|
||||
Aliases: []string{"i"},
|
||||
Usage: "Input file for the smart contract (*.nef)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "manifest, m",
|
||||
&cli.StringFlag{
|
||||
Name: "manifest",
|
||||
Aliases: []string{"m"},
|
||||
Usage: "Manifest input file (*.manifest.json)",
|
||||
},
|
||||
}...)
|
||||
manifestAddGroupFlags := append([]cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "sender, s",
|
||||
&cli.StringFlag{
|
||||
Name: "sender",
|
||||
Aliases: []string{"s"},
|
||||
Usage: "Deploy transaction sender",
|
||||
},
|
||||
flags.AddressFlag{
|
||||
&flags.AddressFlag{
|
||||
Name: addressFlagName, // use the same name for handler code unification.
|
||||
Aliases: []string{addressFlagAlias},
|
||||
Usage: "Account to sign group with",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "nef, n",
|
||||
&cli.StringFlag{
|
||||
Name: "nef",
|
||||
Aliases: []string{"n"},
|
||||
Usage: "Path to the NEF file",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "manifest, m",
|
||||
&cli.StringFlag{
|
||||
Name: "manifest",
|
||||
Aliases: []string{"m"},
|
||||
Usage: "Path to the manifest",
|
||||
},
|
||||
}, options.Wallet...)
|
||||
return []cli.Command{{
|
||||
return []*cli.Command{{
|
||||
Name: "contract",
|
||||
Usage: "Compile - debug - deploy smart contracts",
|
||||
Subcommands: []cli.Command{
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "compile",
|
||||
Usage: "Compile a smart contract to a .nef file",
|
||||
|
@ -141,47 +153,53 @@ func NewCommands() []cli.Command {
|
|||
`,
|
||||
Action: contractCompile,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "in, i",
|
||||
&cli.StringFlag{
|
||||
Name: "in",
|
||||
Aliases: []string{"i"},
|
||||
Usage: "Input file for the smart contract to be compiled (*.go file or directory)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "out, o",
|
||||
&cli.StringFlag{
|
||||
Name: "out",
|
||||
Aliases: []string{"o"},
|
||||
Usage: "Output of the compiled contract",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "verbose, v",
|
||||
&cli.BoolFlag{
|
||||
Name: "verbose",
|
||||
Aliases: []string{"v"},
|
||||
Usage: "Print out additional information after a compiling",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "debug, d",
|
||||
&cli.StringFlag{
|
||||
Name: "debug",
|
||||
Aliases: []string{"d"},
|
||||
Usage: "Emit debug info in a separate file",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "manifest, m",
|
||||
&cli.StringFlag{
|
||||
Name: "manifest",
|
||||
Aliases: []string{"m"},
|
||||
Usage: "Emit contract manifest (*.manifest.json) file into separate file using configuration input file (*.yml)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
&cli.StringFlag{
|
||||
Name: "config",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "Configuration input file (*.yml)",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
&cli.BoolFlag{
|
||||
Name: "no-standards",
|
||||
Usage: "Do not check compliance with supported standards",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
&cli.BoolFlag{
|
||||
Name: "no-events",
|
||||
Usage: "Do not check emitted events with the manifest",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
&cli.BoolFlag{
|
||||
Name: "no-permissions",
|
||||
Usage: "Do not check if invoked contracts are allowed in manifest",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
&cli.BoolFlag{
|
||||
Name: "guess-eventtypes",
|
||||
Usage: "Guess event types for smart-contract bindings configuration from the code usages",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "bindings",
|
||||
Usage: "Output file for smart-contract bindings configuration",
|
||||
},
|
||||
|
@ -254,12 +272,14 @@ func NewCommands() []cli.Command {
|
|||
UsageText: "neo-go contract init -n name [--skip-details]",
|
||||
Action: initSmartContract,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "name, n",
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Aliases: []string{"n"},
|
||||
Usage: "Name of the smart-contract to be initialized",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "skip-details, skip",
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-details",
|
||||
Aliases: []string{"skip"},
|
||||
Usage: "Skip filling in the projects and contract details",
|
||||
},
|
||||
},
|
||||
|
@ -270,12 +290,14 @@ func NewCommands() []cli.Command {
|
|||
UsageText: "neo-go contract inspect -i file [-c]",
|
||||
Action: inspect,
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "compile, c",
|
||||
&cli.BoolFlag{
|
||||
Name: "compile",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "Compile input file (it should be go code then)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "in, i",
|
||||
&cli.StringFlag{
|
||||
Name: "in",
|
||||
Aliases: []string{"i"},
|
||||
Usage: "Input file of the program (either .go or .nef)",
|
||||
},
|
||||
},
|
||||
|
@ -286,16 +308,18 @@ func NewCommands() []cli.Command {
|
|||
UsageText: "neo-go contract calc-hash -i nef -m manifest -s address",
|
||||
Action: calcHash,
|
||||
Flags: []cli.Flag{
|
||||
flags.AddressFlag{
|
||||
Name: "sender, s",
|
||||
&flags.AddressFlag{
|
||||
Name: "sender",
|
||||
Aliases: []string{"s"},
|
||||
Usage: "Sender script hash or address",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "in",
|
||||
Usage: "Path to NEF file",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "manifest, m",
|
||||
&cli.StringFlag{
|
||||
Name: "manifest",
|
||||
Aliases: []string{"m"},
|
||||
Usage: "Path to manifest file",
|
||||
},
|
||||
},
|
||||
|
@ -303,7 +327,7 @@ func NewCommands() []cli.Command {
|
|||
{
|
||||
Name: "manifest",
|
||||
Usage: "Manifest-related commands",
|
||||
Subcommands: []cli.Command{
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "add-group",
|
||||
Usage: "Adds group to the manifest",
|
||||
|
@ -324,12 +348,12 @@ func initSmartContract(ctx *cli.Context) error {
|
|||
}
|
||||
contractName := ctx.String("name")
|
||||
if contractName == "" {
|
||||
return cli.NewExitError(errNoSmartContractName, 1)
|
||||
return cli.Exit(errNoSmartContractName, 1)
|
||||
}
|
||||
|
||||
// Check if the file already exists, if yes, exit
|
||||
if _, err := os.Stat(contractName); err == nil {
|
||||
return cli.NewExitError(errFileExist, 1)
|
||||
return cli.Exit(errFileExist, 1)
|
||||
}
|
||||
|
||||
basePath := contractName
|
||||
|
@ -338,7 +362,7 @@ func initSmartContract(ctx *cli.Context) error {
|
|||
|
||||
// create base directory
|
||||
if err := os.Mkdir(basePath, os.ModePerm); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
m := ProjectConfig{
|
||||
|
@ -363,10 +387,10 @@ func initSmartContract(ctx *cli.Context) error {
|
|||
}
|
||||
b, err := yaml.Marshal(m)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(basePath, "neo-go.yml"), b, 0644); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
ver := ModVersion
|
||||
|
@ -382,12 +406,12 @@ require (
|
|||
github.com/nspcc-dev/neo-go/pkg/interop ` + ver + `
|
||||
)`)
|
||||
if err := os.WriteFile(filepath.Join(basePath, "go.mod"), gm, 0644); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
data := []byte(fmt.Sprintf(smartContractTmpl, contractName))
|
||||
if err := os.WriteFile(filepath.Join(basePath, fileName), data, 0644); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
fmt.Fprintf(ctx.App.Writer, "Successfully initialized smart contract [%s]\n", contractName)
|
||||
|
@ -401,7 +425,7 @@ func contractCompile(ctx *cli.Context) error {
|
|||
}
|
||||
src := ctx.String("in")
|
||||
if len(src) == 0 {
|
||||
return cli.NewExitError(errNoInput, 1)
|
||||
return cli.Exit(errNoInput, 1)
|
||||
}
|
||||
manifestFile := ctx.String("manifest")
|
||||
confFile := ctx.String("config")
|
||||
|
@ -409,7 +433,7 @@ func contractCompile(ctx *cli.Context) error {
|
|||
out := ctx.String("out")
|
||||
bindings := ctx.String("bindings")
|
||||
if len(confFile) == 0 && (len(manifestFile) != 0 || len(debugFile) != 0 || len(bindings) != 0) {
|
||||
return cli.NewExitError(errNoConfFile, 1)
|
||||
return cli.Exit(errNoConfFile, 1)
|
||||
}
|
||||
autocomplete := len(manifestFile) == 0 &&
|
||||
len(confFile) == 0 &&
|
||||
|
@ -419,7 +443,7 @@ func contractCompile(ctx *cli.Context) error {
|
|||
var root string
|
||||
fileInfo, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to stat source file or directory: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to stat source file or directory: %w", err), 1)
|
||||
}
|
||||
if fileInfo.IsDir() {
|
||||
base := filepath.Base(fileInfo.Name())
|
||||
|
@ -470,7 +494,7 @@ func contractCompile(ctx *cli.Context) error {
|
|||
|
||||
result, err := compiler.CompileAndSave(src, o)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
if ctx.Bool("verbose") {
|
||||
fmt.Fprintln(ctx.App.Writer, hex.EncodeToString(result))
|
||||
|
@ -485,33 +509,33 @@ func calcHash(ctx *cli.Context) error {
|
|||
}
|
||||
sender := ctx.Generic("sender").(*flags.Address)
|
||||
if !sender.IsSet {
|
||||
return cli.NewExitError("sender is not set", 1)
|
||||
return cli.Exit("sender is not set", 1)
|
||||
}
|
||||
|
||||
p := ctx.String("in")
|
||||
if p == "" {
|
||||
return cli.NewExitError(errors.New("no .nef file was provided"), 1)
|
||||
return cli.Exit(errors.New("no .nef file was provided"), 1)
|
||||
}
|
||||
mpath := ctx.String("manifest")
|
||||
if mpath == "" {
|
||||
return cli.NewExitError(errors.New("no manifest file provided"), 1)
|
||||
return cli.Exit(errors.New("no manifest file provided"), 1)
|
||||
}
|
||||
f, err := os.ReadFile(p)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't read .nef file: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't read .nef file: %w", err), 1)
|
||||
}
|
||||
nefFile, err := nef.FileFromBytes(f)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't unmarshal .nef file: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't unmarshal .nef file: %w", err), 1)
|
||||
}
|
||||
manifestBytes, err := os.ReadFile(mpath)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to read manifest file: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to read manifest file: %w", err), 1)
|
||||
}
|
||||
m := &manifest.Manifest{}
|
||||
err = json.Unmarshal(manifestBytes, m)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to restore manifest file: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to restore manifest file: %w", err), 1)
|
||||
}
|
||||
fmt.Fprintln(ctx.App.Writer, "Contract hash:", state.CreateContractHash(sender.Uint160(), nefFile.Checksum, m.Name).StringLE())
|
||||
return nil
|
||||
|
@ -528,7 +552,7 @@ func invokeFunction(ctx *cli.Context) error {
|
|||
func invokeInternal(ctx *cli.Context, signAndPush bool) error {
|
||||
var (
|
||||
err error
|
||||
exitErr *cli.ExitError
|
||||
exitErr cli.ExitCoder
|
||||
operation string
|
||||
params []any
|
||||
paramsStart = 1
|
||||
|
@ -539,22 +563,23 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
|
|||
|
||||
args := ctx.Args()
|
||||
if !args.Present() {
|
||||
return cli.NewExitError(errNoScriptHash, 1)
|
||||
return cli.Exit(errNoScriptHash, 1)
|
||||
}
|
||||
script, err := flags.ParseAddress(args[0])
|
||||
argsSlice := args.Slice()
|
||||
script, err := flags.ParseAddress(argsSlice[0])
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("incorrect script hash: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("incorrect script hash: %w", err), 1)
|
||||
}
|
||||
if len(args) <= 1 {
|
||||
return cli.NewExitError(errNoMethod, 1)
|
||||
if len(argsSlice) <= 1 {
|
||||
return cli.Exit(errNoMethod, 1)
|
||||
}
|
||||
operation = args[1]
|
||||
operation = argsSlice[1]
|
||||
paramsStart++
|
||||
|
||||
if len(args) > paramsStart {
|
||||
cosignersOffset, scParams, err = cmdargs.ParseParams(args[paramsStart:], true)
|
||||
if len(argsSlice) > paramsStart {
|
||||
cosignersOffset, scParams, err = cmdargs.ParseParams(argsSlice[paramsStart:], true)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
params = make([]any, len(scParams))
|
||||
for i := range scParams {
|
||||
|
@ -575,7 +600,7 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
|
|||
if signAndPush {
|
||||
acc, w, err = options.GetAccFromContext(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer w.Close()
|
||||
}
|
||||
|
@ -595,7 +620,7 @@ func invokeWithArgs(ctx *cli.Context, acc *wallet.Account, wall *wallet.Wallet,
|
|||
if signAndPush {
|
||||
signersAccounts, err = cmdargs.GetSignersAccounts(acc, wall, cosigners, transaction.None)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid signers: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("invalid signers: %w", err), 1)
|
||||
}
|
||||
}
|
||||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
|
@ -615,12 +640,12 @@ func invokeWithArgs(ctx *cli.Context, acc *wallet.Account, wall *wallet.Wallet,
|
|||
out := ctx.String("out")
|
||||
resp, err = inv.Call(script, operation, params...)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
if resp.State != "HALT" {
|
||||
errText := fmt.Sprintf("Warning: %s VM state returned from the RPC node: %s", resp.State, resp.FaultException)
|
||||
if !signAndPush {
|
||||
return cli.NewExitError(errText, 1)
|
||||
return cli.Exit(errText, 1)
|
||||
}
|
||||
|
||||
action := "send"
|
||||
|
@ -630,25 +655,25 @@ func invokeWithArgs(ctx *cli.Context, acc *wallet.Account, wall *wallet.Wallet,
|
|||
process = "Saving"
|
||||
}
|
||||
if !ctx.Bool("force") {
|
||||
return cli.NewExitError(errText+".\nUse --force flag to "+action+" the transaction anyway.", 1)
|
||||
return cli.Exit(errText+".\nUse --force flag to "+action+" the transaction anyway.", 1)
|
||||
}
|
||||
fmt.Fprintln(ctx.App.Writer, errText+".\n"+process+" transaction...")
|
||||
}
|
||||
if !signAndPush {
|
||||
b, err := json.MarshalIndent(resp, "", " ")
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
fmt.Fprintln(ctx.App.Writer, string(b))
|
||||
return nil
|
||||
}
|
||||
if len(resp.Script) == 0 {
|
||||
return cli.NewExitError(errors.New("no script returned from the RPC node"), 1)
|
||||
return cli.Exit(errors.New("no script returned from the RPC node"), 1)
|
||||
}
|
||||
tx, err := act.MakeUnsignedUncheckedRun(resp.Script, resp.GasConsumed, nil)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to create tx: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to create tx: %w", err), 1)
|
||||
}
|
||||
return txctx.SignAndSend(ctx, act, acc, tx)
|
||||
}
|
||||
|
@ -656,16 +681,16 @@ func invokeWithArgs(ctx *cli.Context, acc *wallet.Account, wall *wallet.Wallet,
|
|||
func testInvokeScript(ctx *cli.Context) error {
|
||||
src := ctx.String("in")
|
||||
if len(src) == 0 {
|
||||
return cli.NewExitError(errNoInput, 1)
|
||||
return cli.Exit(errNoInput, 1)
|
||||
}
|
||||
|
||||
b, err := os.ReadFile(src)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
nefFile, err := nef.FileFromBytes(b)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to restore .nef file: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to restore .nef file: %w", err), 1)
|
||||
}
|
||||
|
||||
signers, exitErr := cmdargs.GetSignersFromContext(ctx, 0)
|
||||
|
@ -683,12 +708,12 @@ func testInvokeScript(ctx *cli.Context) error {
|
|||
|
||||
resp, err := inv.Run(nefFile.Script)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
b, err = json.MarshalIndent(resp, "", " ")
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
fmt.Fprintln(ctx.App.Writer, string(b))
|
||||
|
@ -715,7 +740,7 @@ func inspect(ctx *cli.Context) error {
|
|||
in := ctx.String("in")
|
||||
compile := ctx.Bool("compile")
|
||||
if len(in) == 0 {
|
||||
return cli.NewExitError(errNoInput, 1)
|
||||
return cli.Exit(errNoInput, 1)
|
||||
}
|
||||
var (
|
||||
b []byte
|
||||
|
@ -724,16 +749,16 @@ func inspect(ctx *cli.Context) error {
|
|||
if compile {
|
||||
b, err = compiler.Compile(in, nil)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to compile: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to compile: %w", err), 1)
|
||||
}
|
||||
} else {
|
||||
f, err := os.ReadFile(in)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to read .nef file: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to read .nef file: %w", err), 1)
|
||||
}
|
||||
nefFile, err := nef.FileFromBytes(f)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to restore .nef file: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to restore .nef file: %w", err), 1)
|
||||
}
|
||||
b = nefFile.Script
|
||||
}
|
||||
|
@ -748,22 +773,22 @@ func inspect(ctx *cli.Context) error {
|
|||
func contractDeploy(ctx *cli.Context) error {
|
||||
nefFile, f, err := readNEFFile(ctx.String("in"))
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
m, manifestBytes, err := readManifest(ctx.String("manifest"), util.Uint160{})
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to read manifest file: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to read manifest file: %w", err), 1)
|
||||
}
|
||||
|
||||
var appCallParams = []any{f, manifestBytes}
|
||||
|
||||
signOffset, data, err := cmdargs.ParseParams(ctx.Args(), true)
|
||||
signOffset, data, err := cmdargs.ParseParams(ctx.Args().Slice(), true)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("unable to parse 'data' parameter: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("unable to parse 'data' parameter: %w", err), 1)
|
||||
}
|
||||
if len(data) > 1 {
|
||||
return cli.NewExitError("'data' should be represented as a single parameter", 1)
|
||||
return cli.Exit("'data' should be represented as a single parameter", 1)
|
||||
}
|
||||
if len(data) != 0 {
|
||||
appCallParams = append(appCallParams, data[0])
|
||||
|
@ -771,7 +796,7 @@ func contractDeploy(ctx *cli.Context) error {
|
|||
|
||||
acc, w, err := options.GetAccFromContext(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't get sender address: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't get sender address: %w", err), 1)
|
||||
}
|
||||
defer w.Close()
|
||||
sender := acc.ScriptHash()
|
||||
|
@ -801,12 +826,12 @@ func ParseContractConfig(confFile string) (ProjectConfig, error) {
|
|||
conf := ProjectConfig{}
|
||||
confBytes, err := os.ReadFile(confFile)
|
||||
if err != nil {
|
||||
return conf, cli.NewExitError(err, 1)
|
||||
return conf, cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
err = yaml.Unmarshal(confBytes, &conf)
|
||||
if err != nil {
|
||||
return conf, cli.NewExitError(fmt.Errorf("bad config: %w", err), 1)
|
||||
return conf, cli.Exit(fmt.Errorf("bad config: %w", err), 1)
|
||||
}
|
||||
return conf, nil
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
|
|
|
@ -16,32 +16,34 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
// GasFlag is a flag used for the additional network fee.
|
||||
GasFlag = flags.Fixed8Flag{
|
||||
Name: "gas, g",
|
||||
GasFlag = &flags.Fixed8Flag{
|
||||
Name: "gas",
|
||||
Aliases: []string{"g"},
|
||||
Usage: "Network fee to add to the transaction (prioritizing it)",
|
||||
}
|
||||
// SysGasFlag is a flag used for the additional system fee.
|
||||
SysGasFlag = flags.Fixed8Flag{
|
||||
Name: "sysgas, e",
|
||||
SysGasFlag = &flags.Fixed8Flag{
|
||||
Name: "sysgas",
|
||||
Aliases: []string{"e"},
|
||||
Usage: "System fee to add to the transaction (compensating for execution)",
|
||||
}
|
||||
// OutFlag is a flag used for file output.
|
||||
OutFlag = cli.StringFlag{
|
||||
OutFlag = &cli.StringFlag{
|
||||
Name: "out",
|
||||
Usage: "File (JSON) to put signature context with a transaction to",
|
||||
}
|
||||
// ForceFlag is a flag used to force transaction send.
|
||||
ForceFlag = cli.BoolFlag{
|
||||
ForceFlag = &cli.BoolFlag{
|
||||
Name: "force",
|
||||
Usage: "Do not ask for a confirmation (and ignore errors)",
|
||||
}
|
||||
// AwaitFlag is a flag used to wait for the transaction to be included in a block.
|
||||
AwaitFlag = cli.BoolFlag{
|
||||
AwaitFlag = &cli.BoolFlag{
|
||||
Name: "await",
|
||||
Usage: "Wait for the transaction to be included in a block",
|
||||
}
|
||||
|
@ -71,7 +73,7 @@ func SignAndSend(ctx *cli.Context, act *actor.Actor, acc *wallet.Account, tx *tr
|
|||
promptTime := time.Now()
|
||||
err := input.ConfirmTx(ctx.App.Writer, tx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
waitTime := time.Since(promptTime)
|
||||
// Compensate for confirmation waiting.
|
||||
|
@ -83,17 +85,17 @@ func SignAndSend(ctx *cli.Context, act *actor.Actor, acc *wallet.Account, tx *tr
|
|||
)
|
||||
resTx, vub, err = act.SignAndSend(tx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
if ctx.Bool("await") {
|
||||
aer, err = act.Wait(resTx, vub, err)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to await transaction %s: %w", resTx.StringLE(), err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to await transaction %s: %w", resTx.StringLE(), err), 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
DumpTransactionInfo(ctx.App.Writer, tx.Hash(), aer)
|
||||
|
|
|
@ -16,20 +16,20 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/waiter"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func cancelTx(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
args := ctx.Args().Slice()
|
||||
if len(args) == 0 {
|
||||
return cli.NewExitError("transaction hash is missing", 1)
|
||||
return cli.Exit("transaction hash is missing", 1)
|
||||
} else if len(args) > 1 {
|
||||
return cli.NewExitError("only one transaction hash is accepted", 1)
|
||||
return cli.Exit("only one transaction hash is accepted", 1)
|
||||
}
|
||||
|
||||
txHash, err := util.Uint256DecodeStringLE(strings.TrimPrefix(args[0], "0x"))
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Sprintf("invalid tx hash: %s", args[0]), 1)
|
||||
return cli.Exit(fmt.Sprintf("invalid tx hash: %s", args[0]), 1)
|
||||
}
|
||||
|
||||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
|
@ -37,13 +37,13 @@ func cancelTx(ctx *cli.Context) error {
|
|||
|
||||
acc, w, err := options.GetAccFromContext(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to get account from context to sign the conflicting transaction: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to get account from context to sign the conflicting transaction: %w", err), 1)
|
||||
}
|
||||
defer w.Close()
|
||||
|
||||
signers, err := cmdargs.GetSignersAccounts(acc, w, nil, transaction.CalledByEntry)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid signers: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("invalid signers: %w", err), 1)
|
||||
}
|
||||
c, a, exitErr := options.GetRPCWithActor(gctx, ctx, signers)
|
||||
if exitErr != nil {
|
||||
|
@ -52,11 +52,11 @@ func cancelTx(ctx *cli.Context) error {
|
|||
|
||||
mainTx, _ := c.GetRawTransactionVerbose(txHash)
|
||||
if mainTx != nil && !mainTx.Blockhash.Equals(util.Uint256{}) {
|
||||
return cli.NewExitError(fmt.Errorf("target transaction %s is accepted at block %s", txHash, mainTx.Blockhash.StringLE()), 1)
|
||||
return cli.Exit(fmt.Errorf("target transaction %s is accepted at block %s", txHash, mainTx.Blockhash.StringLE()), 1)
|
||||
}
|
||||
|
||||
if mainTx != nil && !mainTx.HasSigner(acc.ScriptHash()) {
|
||||
return cli.NewExitError(fmt.Errorf("account %s is not a signer of the conflicting transaction", acc.Address), 1)
|
||||
return cli.Exit(fmt.Errorf("account %s is not a signer of the conflicting transaction", acc.Address), 1)
|
||||
}
|
||||
|
||||
resHash, resVub, err := a.SendTunedRun([]byte{byte(opcode.RET)}, []transaction.Attribute{{Type: transaction.ConflictsT, Value: &transaction.Conflicts{Hash: txHash}}}, func(r *result.Invoke, t *transaction.Transaction) error {
|
||||
|
@ -74,7 +74,7 @@ func cancelTx(ctx *cli.Context) error {
|
|||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to send conflicting transaction: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to send conflicting transaction: %w", err), 1)
|
||||
}
|
||||
var res *state.AppExecResult
|
||||
if ctx.Bool("await") {
|
||||
|
@ -82,19 +82,19 @@ func cancelTx(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
if errors.Is(err, waiter.ErrTxNotAccepted) {
|
||||
if mainTx == nil {
|
||||
return cli.NewExitError(fmt.Errorf("neither target nor conflicting transaction is accepted before the current height %d (ValidUntilBlock value of conlicting transaction). Main transaction is unknown to the provided RPC node, thus still has chances to be accepted, you may try cancellation again", resVub), 1)
|
||||
return cli.Exit(fmt.Errorf("neither target nor conflicting transaction is accepted before the current height %d (ValidUntilBlock value of conlicting transaction). Main transaction is unknown to the provided RPC node, thus still has chances to be accepted, you may try cancellation again", resVub), 1)
|
||||
}
|
||||
fmt.Fprintf(ctx.App.Writer, "Neither target nor conflicting transaction is accepted before the current height %d (ValidUntilBlock value of both target and conflicting transactions). Main transaction is not valid anymore, cancellation is successful\n", resVub)
|
||||
return nil
|
||||
}
|
||||
return cli.NewExitError(fmt.Errorf("failed to await target/ conflicting transaction %s/ %s: %w", txHash.StringLE(), resHash.StringLE(), err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to await target/ conflicting transaction %s/ %s: %w", txHash.StringLE(), resHash.StringLE(), err), 1)
|
||||
}
|
||||
if txHash.Equals(res.Container) {
|
||||
tx, err := c.GetRawTransactionVerbose(txHash)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("target transaction %s is accepted", txHash), 1)
|
||||
return cli.Exit(fmt.Errorf("target transaction %s is accepted", txHash), 1)
|
||||
}
|
||||
return cli.NewExitError(fmt.Errorf("target transaction %s is accepted at block %s", txHash, tx.Blockhash.StringLE()), 1)
|
||||
return cli.Exit(fmt.Errorf("target transaction %s is accepted at block %s", txHash, tx.Blockhash.StringLE()), 1)
|
||||
}
|
||||
fmt.Fprintln(ctx.App.Writer, "Conflicting transaction accepted")
|
||||
}
|
||||
|
|
|
@ -11,27 +11,28 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/cli/txctx"
|
||||
vmcli "github.com/nspcc-dev/neo-go/cli/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// NewCommands returns util commands for neo-go CLI.
|
||||
func NewCommands() []cli.Command {
|
||||
func NewCommands() []*cli.Command {
|
||||
txDumpFlags := append([]cli.Flag{}, options.RPC...)
|
||||
txSendFlags := append(txDumpFlags, txctx.AwaitFlag)
|
||||
txCancelFlags := append([]cli.Flag{
|
||||
flags.AddressFlag{
|
||||
Name: "address, a",
|
||||
&flags.AddressFlag{
|
||||
Name: "address",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Address to use as conflicting transaction signee (and gas source)",
|
||||
},
|
||||
txctx.GasFlag,
|
||||
txctx.AwaitFlag,
|
||||
}, options.RPC...)
|
||||
txCancelFlags = append(txCancelFlags, options.Wallet...)
|
||||
return []cli.Command{
|
||||
return []*cli.Command{
|
||||
{
|
||||
Name: "util",
|
||||
Usage: "Various helper commands",
|
||||
Subcommands: []cli.Command{
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "convert",
|
||||
Usage: "Convert provided argument into other possible formats",
|
||||
|
@ -44,7 +45,7 @@ func NewCommands() []cli.Command {
|
|||
{
|
||||
Name: "sendtx",
|
||||
Usage: "Send complete transaction stored in a context file",
|
||||
UsageText: "sendtx [-r <endpoint>] <file.in> [--await]",
|
||||
UsageText: "sendtx [-r <endpoint>] [--await] <file.in>",
|
||||
Description: `Sends the transaction from the given context file to the given RPC node if it's
|
||||
completely signed and ready. This command expects a ContractParametersContext
|
||||
JSON file for input, it can't handle binary (or hex- or base64-encoded)
|
||||
|
@ -57,7 +58,7 @@ func NewCommands() []cli.Command {
|
|||
{
|
||||
Name: "canceltx",
|
||||
Usage: "Cancel transaction by sending conflicting transaction",
|
||||
UsageText: "canceltx <txid> -r <endpoint> --wallet <wallet> [--account <account>] [--wallet-config <path>] [--gas <gas>] [--await]",
|
||||
UsageText: "canceltx -r <endpoint> --wallet <wallet> [--account <account>] [--wallet-config <path>] [--gas <gas>] [--await] <txid>",
|
||||
Description: `Aims to prevent a transaction from being added to the blockchain by dispatching a more
|
||||
prioritized conflicting transaction to the specified RPC node. The input for this command should
|
||||
be the transaction hash. If another account is not specified, the conflicting transaction is
|
||||
|
@ -90,14 +91,15 @@ func NewCommands() []cli.Command {
|
|||
{
|
||||
Name: "ops",
|
||||
Usage: "Pretty-print VM opcodes of the given base64- or hex- encoded script (base64 is checked first). If the input file is specified, then the script is taken from the file.",
|
||||
UsageText: "ops <base64/hex-encoded script> [-i path-to-file] [--hex]",
|
||||
UsageText: "ops [-i path-to-file] [--hex] <base64/hex-encoded script>",
|
||||
Action: handleOps,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "in, i",
|
||||
&cli.StringFlag{
|
||||
Name: "in",
|
||||
Aliases: []string{"i"},
|
||||
Usage: "Input file containing base64- or hex- encoded script representation",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
&cli.BoolFlag{
|
||||
Name: "hex",
|
||||
Usage: "Use hex encoding and do not check base64",
|
||||
},
|
||||
|
@ -109,9 +111,9 @@ func NewCommands() []cli.Command {
|
|||
}
|
||||
|
||||
func handleParse(ctx *cli.Context) error {
|
||||
res, err := vmcli.Parse(ctx.Args())
|
||||
res, err := vmcli.Parse(ctx.Args().Slice())
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
fmt.Fprint(ctx.App.Writer, res)
|
||||
return nil
|
||||
|
@ -127,21 +129,21 @@ func handleOps(ctx *cli.Context) error {
|
|||
if len(in) != 0 {
|
||||
b, err := os.ReadFile(in)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to read file: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to read file: %w", err), 1)
|
||||
}
|
||||
s = string(b)
|
||||
} else {
|
||||
if !ctx.Args().Present() {
|
||||
return cli.NewExitError("missing script", 1)
|
||||
return cli.Exit("missing script", 1)
|
||||
}
|
||||
s = ctx.Args()[0]
|
||||
s = ctx.Args().Slice()[0]
|
||||
}
|
||||
b, err = base64.StdEncoding.DecodeString(s)
|
||||
if err != nil || ctx.Bool("hex") {
|
||||
b, err = hex.DecodeString(s)
|
||||
}
|
||||
if err != nil {
|
||||
return cli.NewExitError("unknown encoding: base64 or hex are supported", 1)
|
||||
return cli.Exit("unknown encoding: base64 or hex are supported", 1)
|
||||
}
|
||||
v := vm.New()
|
||||
v.LoadScript(b)
|
||||
|
|
|
@ -8,30 +8,30 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/cli/paramcontext"
|
||||
"github.com/nspcc-dev/neo-go/cli/query"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func txDump(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
args := ctx.Args().Slice()
|
||||
if len(args) == 0 {
|
||||
return cli.NewExitError("missing input file", 1)
|
||||
return cli.Exit("missing input file", 1)
|
||||
} else if len(args) > 1 {
|
||||
return cli.NewExitError("only one input file is accepted", 1)
|
||||
return cli.Exit("only one input file is accepted", 1)
|
||||
}
|
||||
|
||||
c, err := paramcontext.Read(args[0])
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
tx, ok := c.Verifiable.(*transaction.Transaction)
|
||||
if !ok {
|
||||
return cli.NewExitError("verifiable item is not a transaction", 1)
|
||||
return cli.Exit("verifiable item is not a transaction", 1)
|
||||
}
|
||||
|
||||
err = query.DumpApplicationLog(ctx, nil, tx, nil, true)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
if ctx.String(options.RPCEndpointFlag) != "" {
|
||||
|
@ -41,15 +41,15 @@ func txDump(ctx *cli.Context) error {
|
|||
var err error
|
||||
cl, err := options.GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
res, err := cl.InvokeScript(tx.Script, tx.Signers)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
resS, err := json.MarshalIndent(res, "", " ")
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
fmt.Fprintln(ctx.App.Writer, string(resS))
|
||||
}
|
||||
|
|
|
@ -8,25 +8,25 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/cli/txctx"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/waiter"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func sendTx(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
args := ctx.Args().Slice()
|
||||
if len(args) == 0 {
|
||||
return cli.NewExitError("missing input file", 1)
|
||||
return cli.Exit("missing input file", 1)
|
||||
} else if len(args) > 1 {
|
||||
return cli.NewExitError("only one input file is accepted", 1)
|
||||
return cli.Exit("only one input file is accepted", 1)
|
||||
}
|
||||
|
||||
pc, err := paramcontext.Read(args[0])
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
tx, err := pc.GetCompleteTransaction()
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to complete transaction: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to complete transaction: %w", err), 1)
|
||||
}
|
||||
|
||||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
|
@ -34,18 +34,18 @@ func sendTx(ctx *cli.Context) error {
|
|||
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to create RPC client: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to create RPC client: %w", err), 1)
|
||||
}
|
||||
res, err := c.SendRawTransaction(tx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to submit transaction to RPC node: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to submit transaction to RPC node: %w", err), 1)
|
||||
}
|
||||
var aer *state.AppExecResult
|
||||
if ctx.Bool("await") {
|
||||
version, err := c.GetVersion()
|
||||
aer, err = waiter.New(c, version).Wait(res, tx.ValidUntilBlock, err)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to await transaction %s: %w", res.StringLE(), err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to await transaction %s: %w", res.StringLE(), err), 1)
|
||||
}
|
||||
}
|
||||
txctx.DumpTransactionInfo(ctx.App.Writer, res, aer)
|
||||
|
|
|
@ -44,7 +44,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/util/slice"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
@ -70,22 +70,22 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
historicFlag = cli.IntFlag{
|
||||
historicFlag = &cli.IntFlag{
|
||||
Name: historicFlagFullName,
|
||||
Usage: "Height for historic script invocation (for MPT-enabled blockchain configuration with KeepOnlyLatestState setting disabled). " +
|
||||
"Assuming that block N-th is specified as an argument, the historic invocation is based on the storage state of height N and fake currently-accepting block with index N+1.",
|
||||
}
|
||||
gasFlag = cli.Int64Flag{
|
||||
gasFlag = &cli.Int64Flag{
|
||||
Name: gasFlagFullName,
|
||||
Usage: "GAS limit for this execution (integer number, satoshi).",
|
||||
}
|
||||
hashFlag = cli.StringFlag{
|
||||
hashFlag = &cli.StringFlag{
|
||||
Name: hashFlagFullName,
|
||||
Usage: "Smart-contract hash in LE form or address",
|
||||
}
|
||||
)
|
||||
|
||||
var commands = []cli.Command{
|
||||
var commands = []*cli.Command{
|
||||
{
|
||||
Name: "exit",
|
||||
Usage: "Exit the VM prompt",
|
||||
|
@ -339,8 +339,9 @@ Example:
|
|||
Usage: "Dump state of the chain that is used for VM CLI invocations (use -v for verbose node configuration)",
|
||||
UsageText: `env [-v]`,
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: verboseFlagFullName + ",v",
|
||||
&cli.BoolFlag{
|
||||
Name: verboseFlagFullName,
|
||||
Aliases: []string{"v"},
|
||||
Usage: "Print the whole blockchain node configuration.",
|
||||
},
|
||||
},
|
||||
|
@ -353,14 +354,16 @@ Example:
|
|||
{
|
||||
Name: "storage",
|
||||
Usage: "Dump storage of the contract with the specified hash, address or ID as is at the current stage of script invocation",
|
||||
UsageText: `storage <hash-or-address-or-id> [<prefix>] [--backwards] [--diff]`,
|
||||
UsageText: `storage [--backwards] [--diff] <hash-or-address-or-id> [<prefix>]`,
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: backwardsFlagFullName + ",b",
|
||||
&cli.BoolFlag{
|
||||
Name: backwardsFlagFullName,
|
||||
Aliases: []string{"b"},
|
||||
Usage: "Backwards traversal direction",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: diffFlagFullName + ",d",
|
||||
&cli.BoolFlag{
|
||||
Name: diffFlagFullName,
|
||||
Aliases: []string{"d"},
|
||||
Usage: "Dump only those storage items that were added or changed during the current script invocation. Note that this call won't show removed storage items, use 'changes' command for that.",
|
||||
},
|
||||
},
|
||||
|
@ -400,7 +403,7 @@ func init() {
|
|||
if !c.Hidden {
|
||||
var flagsItems []readline.PrefixCompleterInterface
|
||||
for _, f := range c.Flags {
|
||||
names := strings.SplitN(f.GetName(), ", ", 2) // only long name will be offered
|
||||
names := strings.SplitN(f.Names()[0], ", ", 2) // only long name will be offered
|
||||
flagsItems = append(flagsItems, readline.PcItem("--"+names[0]))
|
||||
}
|
||||
pcItems = append(pcItems, readline.PcItem(c.Name, flagsItems...))
|
||||
|
@ -459,7 +462,7 @@ func NewWithConfig(printLogotype bool, onExit func(int), c *readline.Config, cfg
|
|||
|
||||
log, _, logCloser, err := options.HandleLoggingParams(false, cfg.ApplicationConfiguration)
|
||||
if err != nil {
|
||||
return nil, cli.NewExitError(fmt.Errorf("failed to init logger: %w", err), 1)
|
||||
return nil, cli.Exit(fmt.Errorf("failed to init logger: %w", err), 1)
|
||||
}
|
||||
filter := zap.WrapCore(func(z zapcore.Core) zapcore.Core {
|
||||
return options.NewFilteringCore(z, func(entry zapcore.Entry) bool {
|
||||
|
@ -479,12 +482,12 @@ func NewWithConfig(printLogotype bool, onExit func(int), c *readline.Config, cfg
|
|||
|
||||
chain, err := core.NewBlockchain(store, cfg.Blockchain(), fLog)
|
||||
if err != nil {
|
||||
return nil, cli.NewExitError(fmt.Errorf("could not initialize blockchain: %w", err), 1)
|
||||
return nil, cli.Exit(fmt.Errorf("could not initialize blockchain: %w", err), 1)
|
||||
}
|
||||
// Do not run chain, we need only state-related functionality from it.
|
||||
ic, err := chain.GetTestVM(trigger.Application, nil, nil)
|
||||
if err != nil {
|
||||
return nil, cli.NewExitError(fmt.Errorf("failed to create test VM: %w", err), 1)
|
||||
return nil, cli.Exit(fmt.Errorf("failed to create test VM: %w", err), 1)
|
||||
}
|
||||
|
||||
vmcli := CLI{
|
||||
|
@ -610,7 +613,7 @@ func handleJump(c *cli.Context) error {
|
|||
}
|
||||
|
||||
func getInstructionParameter(c *cli.Context) (int, error) {
|
||||
args := c.Args()
|
||||
args := c.Args().Slice()
|
||||
if len(args) != 1 {
|
||||
return 0, fmt.Errorf("%w: <ip>", ErrMissingParameter)
|
||||
}
|
||||
|
@ -690,7 +693,7 @@ func getHashFlag(c *cli.Context) (util.Uint160, error) {
|
|||
}
|
||||
|
||||
func handleLoadNEF(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
args := c.Args().Slice()
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("%w: <nef> is required", ErrMissingParameter)
|
||||
}
|
||||
|
@ -734,7 +737,7 @@ func handleLoadNEF(c *cli.Context) error {
|
|||
}
|
||||
var signers []transaction.Signer
|
||||
if signersStartOffset != 0 && len(args) > signersStartOffset {
|
||||
signers, err = cmdargs.ParseSigners(c.Args()[signersStartOffset:])
|
||||
signers, err = cmdargs.ParseSigners(args[signersStartOffset:])
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: failed to parse signers: %w", ErrInvalidParameter, err)
|
||||
}
|
||||
|
@ -761,7 +764,7 @@ func handleLoadNEF(c *cli.Context) error {
|
|||
}
|
||||
|
||||
func handleLoadBase64(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
args := c.Args().Slice()
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("%w: <string>", ErrMissingParameter)
|
||||
}
|
||||
|
@ -801,7 +804,7 @@ func createFakeTransaction(script []byte, signers []transaction.Signer) *transac
|
|||
}
|
||||
|
||||
func handleLoadHex(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
args := c.Args().Slice()
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("%w: <string>", ErrMissingParameter)
|
||||
}
|
||||
|
@ -833,7 +836,7 @@ func handleLoadHex(c *cli.Context) error {
|
|||
}
|
||||
|
||||
func handleLoadGo(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
args := c.Args().Slice()
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("%w: <file>", ErrMissingParameter)
|
||||
}
|
||||
|
@ -885,7 +888,7 @@ func handleLoadGo(c *cli.Context) error {
|
|||
}
|
||||
|
||||
func handleLoadTx(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
args := c.Args().Slice()
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("%w: <file-or-hash>", ErrMissingParameter)
|
||||
}
|
||||
|
@ -933,7 +936,7 @@ func handleLoadDeployed(c *cli.Context) error {
|
|||
if !c.Args().Present() {
|
||||
return errors.New("contract hash, address or ID is mandatory argument")
|
||||
}
|
||||
args := c.Args()
|
||||
args := c.Args().Slice()
|
||||
hashOrID := args[0]
|
||||
ic := getInteropContextFromContext(c.App)
|
||||
h, err := flags.ParseAddress(hashOrID)
|
||||
|
@ -1062,7 +1065,7 @@ func getManifestFromFile(name string) (*manifest.Manifest, error) {
|
|||
func handleRun(c *cli.Context) error {
|
||||
v := getVMFromContext(c.App)
|
||||
cs := getContractStateFromContext(c.App)
|
||||
args := c.Args()
|
||||
args := c.Args().Slice()
|
||||
if len(args) != 0 {
|
||||
var (
|
||||
params []stackitem.Item
|
||||
|
@ -1181,7 +1184,7 @@ func handleStep(c *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
v := getVMFromContext(c.App)
|
||||
args := c.Args()
|
||||
args := c.Args().Slice()
|
||||
if len(args) > 0 {
|
||||
n, err = strconv.Atoi(args[0])
|
||||
if err != nil {
|
||||
|
@ -1422,7 +1425,7 @@ func (c *CLI) Run() error {
|
|||
}
|
||||
|
||||
func handleParse(c *cli.Context) error {
|
||||
res, err := Parse(c.Args())
|
||||
res, err := Parse(c.Args().Slice())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1188,7 +1188,7 @@ func TestDumpStorage(t *testing.T) {
|
|||
"storage "+address.Uint160ToString(h),
|
||||
"storage 1",
|
||||
"storage 1 "+hex.EncodeToString(expected[0].Key),
|
||||
"storage 1 --backwards",
|
||||
"storage --backwards 1",
|
||||
"exit",
|
||||
)
|
||||
e.checkStorage(t, expected...)
|
||||
|
@ -1214,11 +1214,11 @@ func TestDumpStorageDiff(t *testing.T) {
|
|||
diff := storage.KeyValue{Key: []byte{3}, Value: []byte{3}}
|
||||
e.runProg(t,
|
||||
"storage 1",
|
||||
"storage 1 --diff",
|
||||
"storage --diff 1",
|
||||
"loadhex "+hex.EncodeToString(script.Bytes()),
|
||||
"run",
|
||||
"storage 1",
|
||||
"storage 1 --diff",
|
||||
"storage --diff 1",
|
||||
"exit",
|
||||
)
|
||||
|
||||
|
|
10
cli/vm/vm.go
10
cli/vm/vm.go
|
@ -8,14 +8,14 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/cli/cmdargs"
|
||||
"github.com/nspcc-dev/neo-go/cli/options"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/storage/dbconfig"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// NewCommands returns 'vm' command.
|
||||
func NewCommands() []cli.Command {
|
||||
func NewCommands() []*cli.Command {
|
||||
cfgFlags := []cli.Flag{options.Config, options.ConfigFile, options.RelativePath}
|
||||
cfgFlags = append(cfgFlags, options.Network...)
|
||||
return []cli.Command{{
|
||||
return []*cli.Command{{
|
||||
Name: "vm",
|
||||
Usage: "Start the virtual machine",
|
||||
Action: startVMPrompt,
|
||||
|
@ -30,7 +30,7 @@ func startVMPrompt(ctx *cli.Context) error {
|
|||
|
||||
cfg, err := options.GetConfigFromContext(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
if ctx.NumFlags() == 0 {
|
||||
cfg.ApplicationConfiguration.DBConfiguration.Type = dbconfig.InMemoryDB
|
||||
|
@ -42,7 +42,7 @@ func startVMPrompt(ctx *cli.Context) error {
|
|||
|
||||
p, err := NewWithConfig(true, os.Exit, &readline.Config{}, cfg)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to create VM CLI: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to create VM CLI: %w", err), 1)
|
||||
}
|
||||
return p.Run()
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/waiter"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func signStoredTransaction(ctx *cli.Context) error {
|
||||
|
@ -28,52 +28,52 @@ func signStoredTransaction(ctx *cli.Context) error {
|
|||
|
||||
pc, err := paramcontext.Read(ctx.String("in"))
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
if !addrFlag.IsSet {
|
||||
return cli.NewExitError("address was not provided", 1)
|
||||
return cli.Exit("address was not provided", 1)
|
||||
}
|
||||
acc, _, err := options.GetAccFromContext(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
tx, ok := pc.Verifiable.(*transaction.Transaction)
|
||||
if !ok {
|
||||
return cli.NewExitError("verifiable item is not a transaction", 1)
|
||||
return cli.Exit("verifiable item is not a transaction", 1)
|
||||
}
|
||||
|
||||
if !tx.HasSigner(acc.ScriptHash()) {
|
||||
return cli.NewExitError("tx signers don't contain provided account", 1)
|
||||
return cli.Exit("tx signers don't contain provided account", 1)
|
||||
}
|
||||
|
||||
if acc.CanSign() {
|
||||
sign := acc.SignHashable(pc.Network, pc.Verifiable)
|
||||
if err := pc.AddSignature(acc.ScriptHash(), acc.Contract, acc.PublicKey(), sign); err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't add signature: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't add signature: %w", err), 1)
|
||||
}
|
||||
} else if rpcNode == "" {
|
||||
return cli.NewExitError(fmt.Errorf("can't sign transactions with the given account and no RPC endpoing given to send anything signed"), 1)
|
||||
return cli.Exit(fmt.Errorf("can't sign transactions with the given account and no RPC endpoing given to send anything signed"), 1)
|
||||
}
|
||||
// Not saving and not sending, print.
|
||||
if out == "" && rpcNode == "" {
|
||||
txt, err := json.MarshalIndent(pc, " ", " ")
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't display resulting context: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't display resulting context: %w", err), 1)
|
||||
}
|
||||
fmt.Fprintln(ctx.App.Writer, string(txt))
|
||||
return nil
|
||||
}
|
||||
if out != "" {
|
||||
if err := paramcontext.Save(pc, out); err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't save resulting context: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't save resulting context: %w", err), 1)
|
||||
}
|
||||
}
|
||||
if rpcNode != "" {
|
||||
tx, err = pc.GetCompleteTransaction()
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to complete transaction: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to complete transaction: %w", err), 1)
|
||||
}
|
||||
|
||||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
|
@ -82,17 +82,17 @@ func signStoredTransaction(ctx *cli.Context) error {
|
|||
var err error // `GetRPCClient` returns specialized type.
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to create RPC client: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to create RPC client: %w", err), 1)
|
||||
}
|
||||
res, err := c.SendRawTransaction(tx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to submit transaction to RPC node: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to submit transaction to RPC node: %w", err), 1)
|
||||
}
|
||||
if ctx.Bool("await") {
|
||||
version, err := c.GetVersion()
|
||||
aer, err = waiter.New(c, version).Wait(res, tx.ValidUntilBlock, err)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to await transaction %s: %w", res.StringLE(), err), 1)
|
||||
return cli.Exit(fmt.Errorf("failed to await transaction %s: %w", res.StringLE(), err), 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,20 +19,20 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func newNEP11Commands() []cli.Command {
|
||||
func newNEP11Commands() []*cli.Command {
|
||||
maxIters := strconv.Itoa(config.DefaultMaxIteratorResultItems)
|
||||
tokenAddressFlag := flags.AddressFlag{
|
||||
tokenAddressFlag := &flags.AddressFlag{
|
||||
Name: "token",
|
||||
Usage: "Token contract address or hash in LE",
|
||||
}
|
||||
ownerAddressFlag := flags.AddressFlag{
|
||||
ownerAddressFlag := &flags.AddressFlag{
|
||||
Name: "address",
|
||||
Usage: "NFT owner address or hash in LE",
|
||||
}
|
||||
tokenID := cli.StringFlag{
|
||||
tokenID := &cli.StringFlag{
|
||||
Name: "id",
|
||||
Usage: "Hex-encoded token ID",
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ func newNEP11Commands() []cli.Command {
|
|||
copy(transferFlags, baseTransferFlags)
|
||||
transferFlags = append(transferFlags, tokenID)
|
||||
transferFlags = append(transferFlags, options.RPC...)
|
||||
return []cli.Command{
|
||||
return []*cli.Command{
|
||||
{
|
||||
Name: "balance",
|
||||
Usage: "Get address balance",
|
||||
|
@ -247,16 +247,16 @@ func printNEP11Owner(ctx *cli.Context, divisible bool) error {
|
|||
}
|
||||
tokenHash := ctx.Generic("token").(*flags.Address)
|
||||
if !tokenHash.IsSet {
|
||||
return cli.NewExitError("token contract hash was not set", 1)
|
||||
return cli.Exit("token contract hash was not set", 1)
|
||||
}
|
||||
|
||||
tokenID := ctx.String("id")
|
||||
if tokenID == "" {
|
||||
return cli.NewExitError(errors.New("token ID should be specified"), 1)
|
||||
return cli.Exit(errors.New("token ID should be specified"), 1)
|
||||
}
|
||||
tokenIDBytes, err := hex.DecodeString(tokenID)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid tokenID bytes: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("invalid tokenID bytes: %w", err), 1)
|
||||
}
|
||||
|
||||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
|
@ -271,7 +271,7 @@ func printNEP11Owner(ctx *cli.Context, divisible bool) error {
|
|||
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)
|
||||
return cli.Exit(fmt.Sprintf("failed to call NEP-11 divisible `ownerOf` method: %s", err.Error()), 1)
|
||||
}
|
||||
for _, h := range result {
|
||||
fmt.Fprintln(ctx.App.Writer, address.Uint160ToString(h))
|
||||
|
@ -280,7 +280,7 @@ func printNEP11Owner(ctx *cli.Context, divisible bool) error {
|
|||
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)
|
||||
return cli.Exit(fmt.Sprintf("failed to call NEP-11 non-divisible `ownerOf` method: %s", err.Error()), 1)
|
||||
}
|
||||
fmt.Fprintln(ctx.App.Writer, address.Uint160ToString(result))
|
||||
}
|
||||
|
@ -292,12 +292,12 @@ func printNEP11TokensOf(ctx *cli.Context) error {
|
|||
var err error
|
||||
tokenHash := ctx.Generic("token").(*flags.Address)
|
||||
if !tokenHash.IsSet {
|
||||
return cli.NewExitError("token contract hash was not set", 1)
|
||||
return cli.Exit("token contract hash was not set", 1)
|
||||
}
|
||||
|
||||
acc := ctx.Generic("address").(*flags.Address)
|
||||
if !acc.IsSet {
|
||||
return cli.NewExitError("owner address flag was not set", 1)
|
||||
return cli.Exit("owner address flag was not set", 1)
|
||||
}
|
||||
|
||||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
|
@ -311,7 +311,7 @@ func printNEP11TokensOf(ctx *cli.Context) error {
|
|||
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)
|
||||
return cli.Exit(fmt.Sprintf("failed to call NEP-11 `tokensOf` method: %s", err.Error()), 1)
|
||||
}
|
||||
|
||||
for i := range result {
|
||||
|
@ -327,7 +327,7 @@ func printNEP11Tokens(ctx *cli.Context) error {
|
|||
}
|
||||
tokenHash := ctx.Generic("token").(*flags.Address)
|
||||
if !tokenHash.IsSet {
|
||||
return cli.NewExitError("token contract hash was not set", 1)
|
||||
return cli.Exit("token contract hash was not set", 1)
|
||||
}
|
||||
|
||||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
|
@ -341,7 +341,7 @@ func printNEP11Tokens(ctx *cli.Context) error {
|
|||
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)
|
||||
return cli.Exit(fmt.Sprintf("failed to call optional NEP-11 `tokens` method: %s", err.Error()), 1)
|
||||
}
|
||||
|
||||
for i := range result {
|
||||
|
@ -357,16 +357,16 @@ func printNEP11Properties(ctx *cli.Context) error {
|
|||
}
|
||||
tokenHash := ctx.Generic("token").(*flags.Address)
|
||||
if !tokenHash.IsSet {
|
||||
return cli.NewExitError("token contract hash was not set", 1)
|
||||
return cli.Exit("token contract hash was not set", 1)
|
||||
}
|
||||
|
||||
tokenID := ctx.String("id")
|
||||
if tokenID == "" {
|
||||
return cli.NewExitError(errors.New("token ID should be specified"), 1)
|
||||
return cli.Exit(errors.New("token ID should be specified"), 1)
|
||||
}
|
||||
tokenIDBytes, err := hex.DecodeString(tokenID)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid tokenID bytes: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("invalid tokenID bytes: %w", err), 1)
|
||||
}
|
||||
|
||||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
|
@ -380,12 +380,12 @@ func printNEP11Properties(ctx *cli.Context) error {
|
|||
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)
|
||||
return cli.Exit(fmt.Sprintf("failed to call NEP-11 `properties` method: %s", err.Error()), 1)
|
||||
}
|
||||
|
||||
bytes, err := stackitem.ToJSON(result)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Sprintf("failed to convert result to JSON: %s", err), 1)
|
||||
return cli.Exit(fmt.Sprintf("failed to convert result to JSON: %s", err), 1)
|
||||
}
|
||||
fmt.Fprintln(ctx.App.Writer, string(bytes))
|
||||
return nil
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// transferTarget represents target address, token amount and data for transfer.
|
||||
|
@ -39,7 +39,7 @@ type transferTarget struct {
|
|||
}
|
||||
|
||||
var (
|
||||
tokenFlag = cli.StringFlag{
|
||||
tokenFlag = &cli.StringFlag{
|
||||
Name: "token",
|
||||
Usage: "Token to use (hash or name (for NEO/GAS or imported tokens))",
|
||||
}
|
||||
|
@ -47,15 +47,16 @@ var (
|
|||
walletPathFlag,
|
||||
walletConfigFlag,
|
||||
tokenFlag,
|
||||
flags.AddressFlag{
|
||||
Name: "address, a",
|
||||
&flags.AddressFlag{
|
||||
Name: "address",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Address to use",
|
||||
},
|
||||
}
|
||||
importFlags = append([]cli.Flag{
|
||||
walletPathFlag,
|
||||
walletConfigFlag,
|
||||
flags.AddressFlag{
|
||||
&flags.AddressFlag{
|
||||
Name: "token",
|
||||
Usage: "Token contract address or hash in LE",
|
||||
},
|
||||
|
@ -71,7 +72,7 @@ var (
|
|||
txctx.SysGasFlag,
|
||||
txctx.ForceFlag,
|
||||
txctx.AwaitFlag,
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "amount",
|
||||
Usage: "Amount of asset to send",
|
||||
},
|
||||
|
@ -88,14 +89,14 @@ var (
|
|||
}, options.RPC...)
|
||||
)
|
||||
|
||||
func newNEP17Commands() []cli.Command {
|
||||
func newNEP17Commands() []*cli.Command {
|
||||
balanceFlags := make([]cli.Flag, len(baseBalanceFlags))
|
||||
copy(balanceFlags, baseBalanceFlags)
|
||||
balanceFlags = append(balanceFlags, options.RPC...)
|
||||
transferFlags := make([]cli.Flag, len(baseTransferFlags))
|
||||
copy(transferFlags, baseTransferFlags)
|
||||
transferFlags = append(transferFlags, options.RPC...)
|
||||
return []cli.Command{
|
||||
return []*cli.Command{
|
||||
{
|
||||
Name: "balance",
|
||||
Usage: "Get address balance",
|
||||
|
@ -222,7 +223,7 @@ func getNEPBalance(ctx *cli.Context, standard string, accHandler func(*cli.Conte
|
|||
}
|
||||
wall, _, err := readWallet(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("bad wallet: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("bad wallet: %w", err), 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
|
||||
|
@ -231,12 +232,12 @@ func getNEPBalance(ctx *cli.Context, standard string, accHandler func(*cli.Conte
|
|||
addrHash := addrFlag.Uint160()
|
||||
acc := wall.GetAccount(addrHash)
|
||||
if acc == nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't find account for the address: %s", address.Uint160ToString(addrHash)), 1)
|
||||
return cli.Exit(fmt.Errorf("can't find account for the address: %s", address.Uint160ToString(addrHash)), 1)
|
||||
}
|
||||
accounts = append(accounts, acc)
|
||||
} else {
|
||||
if len(wall.Accounts) == 0 {
|
||||
return cli.NewExitError(errors.New("no accounts in the wallet"), 1)
|
||||
return cli.Exit(errors.New("no accounts in the wallet"), 1)
|
||||
}
|
||||
accounts = wall.Accounts
|
||||
}
|
||||
|
@ -246,7 +247,7 @@ func getNEPBalance(ctx *cli.Context, standard string, accHandler func(*cli.Conte
|
|||
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
name := ctx.String("token")
|
||||
|
@ -274,7 +275,7 @@ func getNEPBalance(ctx *cli.Context, standard string, accHandler func(*cli.Conte
|
|||
// But if we have an exact hash, it must be correct.
|
||||
token, err = getTokenWithStandard(c, h, standard)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("%q is not a valid %s token: %w", name, standard, err), 1)
|
||||
return cli.Exit(fmt.Errorf("%q is not a valid %s token: %w", name, standard, err), 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -284,7 +285,7 @@ func getNEPBalance(ctx *cli.Context, standard string, accHandler func(*cli.Conte
|
|||
if len(tokenID) > 0 {
|
||||
_, err = hex.DecodeString(tokenID)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid token ID: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("invalid token ID: %w", err), 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -296,7 +297,7 @@ func getNEPBalance(ctx *cli.Context, standard string, accHandler func(*cli.Conte
|
|||
|
||||
err = accHandler(ctx, c, acc.ScriptHash(), name, token, tokenID)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -388,20 +389,20 @@ func importNEPToken(ctx *cli.Context, standard string) error {
|
|||
}
|
||||
wall, _, err := openWallet(ctx, true)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
|
||||
tokenHashFlag := ctx.Generic("token").(*flags.Address)
|
||||
if !tokenHashFlag.IsSet {
|
||||
return cli.NewExitError("token contract hash was not set", 1)
|
||||
return cli.Exit("token contract hash was not set", 1)
|
||||
}
|
||||
tokenHash := tokenHashFlag.Uint160()
|
||||
|
||||
for _, t := range wall.Extra.Tokens {
|
||||
if t.Hash.Equals(tokenHash) && t.Standard == standard {
|
||||
printTokenInfo(ctx, t)
|
||||
return cli.NewExitError(fmt.Errorf("%s token already exists", standard), 1)
|
||||
return cli.Exit(fmt.Errorf("%s token already exists", standard), 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -410,17 +411,17 @@ func importNEPToken(ctx *cli.Context, standard string) error {
|
|||
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
tok, err := getTokenWithStandard(c, tokenHash, standard)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't receive token info: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't receive token info: %w", err), 1)
|
||||
}
|
||||
|
||||
wall.AddToken(tok)
|
||||
if err := wall.Save(); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
printTokenInfo(ctx, tok)
|
||||
return nil
|
||||
|
@ -457,14 +458,14 @@ func printNEPInfo(ctx *cli.Context, standard string) error {
|
|||
}
|
||||
wall, _, err := readWallet(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
|
||||
if name := ctx.String("token"); name != "" {
|
||||
token, err := getMatchingToken(ctx, wall, name, standard)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
printTokenInfo(ctx, token)
|
||||
return nil
|
||||
|
@ -493,13 +494,13 @@ func removeNEPToken(ctx *cli.Context, standard string) error {
|
|||
}
|
||||
wall, _, err := openWallet(ctx, true)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
|
||||
token, err := getMatchingToken(ctx, wall, ctx.String("token"), standard)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
if !ctx.Bool("force") {
|
||||
if ok := askForConsent(ctx.App.Writer); !ok {
|
||||
|
@ -507,9 +508,9 @@ func removeNEPToken(ctx *cli.Context, standard string) error {
|
|||
}
|
||||
}
|
||||
if err := wall.RemoveToken(token.Hash); err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't remove token: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't remove token: %w", err), 1)
|
||||
} else if err := wall.Save(); err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("error while saving wallet: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("error while saving wallet: %w", err), 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -517,25 +518,25 @@ func removeNEPToken(ctx *cli.Context, standard string) error {
|
|||
func multiTransferNEP17(ctx *cli.Context) error {
|
||||
wall, pass, err := readWallet(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
|
||||
fromFlag := ctx.Generic("from").(*flags.Address)
|
||||
from, err := getDefaultAddress(fromFlag, wall)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
acc, err := options.GetUnlockedAccount(wall, from, pass)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
defer cancel()
|
||||
|
||||
if ctx.NArg() == 0 {
|
||||
return cli.NewExitError("empty recipients list", 1)
|
||||
return cli.Exit("empty recipients list", 1)
|
||||
}
|
||||
var (
|
||||
recipients []transferTarget
|
||||
|
@ -554,7 +555,7 @@ func multiTransferNEP17(ctx *cli.Context) error {
|
|||
}
|
||||
signersAccounts, err := cmdargs.GetSignersAccounts(acc, wall, cosigners, transaction.CalledByEntry)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid signers: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("invalid signers: %w", err), 1)
|
||||
}
|
||||
c, act, exitErr := options.GetRPCWithActor(gctx, ctx, signersAccounts)
|
||||
if exitErr != nil {
|
||||
|
@ -566,7 +567,7 @@ func multiTransferNEP17(ctx *cli.Context) error {
|
|||
arg := ctx.Args().Get(i)
|
||||
ss := strings.SplitN(arg, ":", 3)
|
||||
if len(ss) != 3 {
|
||||
return cli.NewExitError("send format must be '<token>:<addr>:<amount>", 1)
|
||||
return cli.Exit("send format must be '<token>:<addr>:<amount>", 1)
|
||||
}
|
||||
token, ok := cache[ss[0]]
|
||||
if !ok {
|
||||
|
@ -574,18 +575,18 @@ func multiTransferNEP17(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
token, err = getMatchingTokenRPC(ctx, c, from, ss[0], manifest.NEP17StandardName)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't fetch matching token from RPC-node: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't fetch matching token from RPC-node: %w", err), 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
cache[ss[0]] = token
|
||||
addr, err := address.StringToUint160(ss[1])
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid address: '%s'", ss[1]), 1)
|
||||
return cli.Exit(fmt.Errorf("invalid address: '%s'", ss[1]), 1)
|
||||
}
|
||||
amount, err := fixedn.FromString(ss[2], int(token.Decimals))
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid amount: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("invalid amount: %w", err), 1)
|
||||
}
|
||||
recipients = append(recipients, transferTarget{
|
||||
Token: token.Hash,
|
||||
|
@ -597,7 +598,7 @@ func multiTransferNEP17(ctx *cli.Context) error {
|
|||
|
||||
tx, err := makeMultiTransferNEP17(act, recipients)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't make transaction: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't make transaction: %w", err), 1)
|
||||
}
|
||||
return txctx.SignAndSend(ctx, act, acc, tx)
|
||||
}
|
||||
|
@ -611,18 +612,18 @@ func transferNEP(ctx *cli.Context, standard string) error {
|
|||
|
||||
wall, pass, err := readWallet(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
|
||||
fromFlag := ctx.Generic("from").(*flags.Address)
|
||||
from, err := getDefaultAddress(fromFlag, wall)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
acc, err := options.GetUnlockedAccount(wall, from, pass)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
|
@ -638,7 +639,7 @@ func transferNEP(ctx *cli.Context, standard string) error {
|
|||
}
|
||||
signersAccounts, err := cmdargs.GetSignersAccounts(acc, wall, cosigners, transaction.CalledByEntry)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid signers: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("invalid signers: %w", err), 1)
|
||||
}
|
||||
|
||||
c, act, exitErr := options.GetRPCWithActor(gctx, ctx, signersAccounts)
|
||||
|
@ -648,14 +649,14 @@ func transferNEP(ctx *cli.Context, standard string) error {
|
|||
|
||||
toFlag := ctx.Generic("to").(*flags.Address)
|
||||
if !toFlag.IsSet {
|
||||
return cli.NewExitError(errors.New("missing receiver address (--to)"), 1)
|
||||
return cli.Exit(errors.New("missing receiver address (--to)"), 1)
|
||||
}
|
||||
to := toFlag.Uint160()
|
||||
token, err := getMatchingToken(ctx, wall, ctx.String("token"), standard)
|
||||
if err != nil {
|
||||
token, err = getMatchingTokenRPC(ctx, c, from, ctx.String("token"), standard)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't fetch matching token from RPC-node: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't fetch matching token from RPC-node: %w", err), 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -663,7 +664,7 @@ func transferNEP(ctx *cli.Context, standard string) error {
|
|||
amount, err := fixedn.FromString(amountArg, int(token.Decimals))
|
||||
// It's OK for NEP-11 transfer to not have amount set.
|
||||
if err != nil && (standard == manifest.NEP17StandardName || amountArg != "") {
|
||||
return cli.NewExitError(fmt.Errorf("invalid amount: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("invalid amount: %w", err), 1)
|
||||
}
|
||||
switch standard {
|
||||
case manifest.NEP17StandardName:
|
||||
|
@ -672,11 +673,11 @@ func transferNEP(ctx *cli.Context, standard string) error {
|
|||
case manifest.NEP11StandardName:
|
||||
tokenID := ctx.String("id")
|
||||
if tokenID == "" {
|
||||
return cli.NewExitError(errors.New("token ID should be specified"), 1)
|
||||
return cli.Exit(errors.New("token ID should be specified"), 1)
|
||||
}
|
||||
tokenIDBytes, terr := hex.DecodeString(tokenID)
|
||||
if terr != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid token ID: %w", terr), 1)
|
||||
return cli.Exit(fmt.Errorf("invalid token ID: %w", terr), 1)
|
||||
}
|
||||
if amountArg == "" {
|
||||
n11 := nep11.NewNonDivisible(act, token.Hash)
|
||||
|
@ -686,10 +687,10 @@ func transferNEP(ctx *cli.Context, standard string) error {
|
|||
tx, err = n11.TransferDUnsigned(act.Sender(), to, amount, tokenIDBytes, data)
|
||||
}
|
||||
default:
|
||||
return cli.NewExitError(fmt.Errorf("unsupported token standard %s", standard), 1)
|
||||
return cli.Exit(fmt.Errorf("unsupported token standard %s", standard), 1)
|
||||
}
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't make transaction: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't make transaction: %w", err), 1)
|
||||
}
|
||||
|
||||
return txctx.SignAndSend(ctx, act, acc, tx)
|
||||
|
|
|
@ -12,11 +12,11 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/neo"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func newValidatorCommands() []cli.Command {
|
||||
return []cli.Command{
|
||||
func newValidatorCommands() []*cli.Command {
|
||||
return []*cli.Command{
|
||||
{
|
||||
Name: "register",
|
||||
Usage: "Register as a new candidate",
|
||||
|
@ -30,8 +30,9 @@ func newValidatorCommands() []cli.Command {
|
|||
txctx.OutFlag,
|
||||
txctx.ForceFlag,
|
||||
txctx.AwaitFlag,
|
||||
flags.AddressFlag{
|
||||
Name: "address, a",
|
||||
&flags.AddressFlag{
|
||||
Name: "address",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Address to register",
|
||||
},
|
||||
}, options.RPC...),
|
||||
|
@ -49,8 +50,9 @@ func newValidatorCommands() []cli.Command {
|
|||
txctx.OutFlag,
|
||||
txctx.ForceFlag,
|
||||
txctx.AwaitFlag,
|
||||
flags.AddressFlag{
|
||||
Name: "address, a",
|
||||
&flags.AddressFlag{
|
||||
Name: "address",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Address to unregister",
|
||||
},
|
||||
}, options.RPC...),
|
||||
|
@ -72,12 +74,14 @@ func newValidatorCommands() []cli.Command {
|
|||
txctx.OutFlag,
|
||||
txctx.ForceFlag,
|
||||
txctx.AwaitFlag,
|
||||
flags.AddressFlag{
|
||||
Name: "address, a",
|
||||
&flags.AddressFlag{
|
||||
Name: "address",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Address to vote from",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "candidate, c",
|
||||
&cli.StringFlag{
|
||||
Name: "candidate",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "Public key of candidate to vote for",
|
||||
},
|
||||
}, options.RPC...),
|
||||
|
@ -103,18 +107,18 @@ func handleNeoAction(ctx *cli.Context, mkTx func(*neo.Contract, util.Uint160, *w
|
|||
}
|
||||
wall, pass, err := readWallet(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
|
||||
addrFlag := ctx.Generic("address").(*flags.Address)
|
||||
if !addrFlag.IsSet {
|
||||
return cli.NewExitError("address was not provided", 1)
|
||||
return cli.Exit("address was not provided", 1)
|
||||
}
|
||||
addr := addrFlag.Uint160()
|
||||
acc, err := options.GetUnlockedAccount(wall, addr, pass)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
|
@ -122,7 +126,7 @@ func handleNeoAction(ctx *cli.Context, mkTx func(*neo.Contract, util.Uint160, *w
|
|||
|
||||
signers, err := cmdargs.GetSignersAccounts(acc, wall, nil, transaction.CalledByEntry)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid signers: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("invalid signers: %w", err), 1)
|
||||
}
|
||||
_, act, exitErr := options.GetRPCWithActor(gctx, ctx, signers)
|
||||
if exitErr != nil {
|
||||
|
@ -132,7 +136,7 @@ func handleNeoAction(ctx *cli.Context, mkTx func(*neo.Contract, util.Uint160, *w
|
|||
contract := neo.New(act)
|
||||
tx, err := mkTx(contract, addr, acc)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
return txctx.SignAndSend(ctx, act, acc, tx)
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -47,38 +47,40 @@ var (
|
|||
)
|
||||
|
||||
var (
|
||||
walletPathFlag = cli.StringFlag{
|
||||
Name: "wallet, w",
|
||||
walletPathFlag = &cli.StringFlag{
|
||||
Name: "wallet",
|
||||
Aliases: []string{"w"},
|
||||
Usage: "Path to the wallet file ('-' to read from stdin); conflicts with --wallet-config flag.",
|
||||
}
|
||||
walletConfigFlag = cli.StringFlag{
|
||||
walletConfigFlag = &cli.StringFlag{
|
||||
Name: "wallet-config",
|
||||
Usage: "Path to the wallet config file; conflicts with --wallet flag.",
|
||||
}
|
||||
wifFlag = cli.StringFlag{
|
||||
wifFlag = &cli.StringFlag{
|
||||
Name: "wif",
|
||||
Usage: "WIF to import",
|
||||
}
|
||||
decryptFlag = cli.BoolFlag{
|
||||
Name: "decrypt, d",
|
||||
decryptFlag = &cli.BoolFlag{
|
||||
Name: "decrypt",
|
||||
Aliases: []string{"d"},
|
||||
Usage: "Decrypt encrypted keys.",
|
||||
}
|
||||
inFlag = cli.StringFlag{
|
||||
inFlag = &cli.StringFlag{
|
||||
Name: "in",
|
||||
Usage: "File with JSON transaction",
|
||||
}
|
||||
fromAddrFlag = flags.AddressFlag{
|
||||
fromAddrFlag = &flags.AddressFlag{
|
||||
Name: "from",
|
||||
Usage: "Address to send an asset from",
|
||||
}
|
||||
toAddrFlag = flags.AddressFlag{
|
||||
toAddrFlag = &flags.AddressFlag{
|
||||
Name: "to",
|
||||
Usage: "Address to send an asset to",
|
||||
}
|
||||
)
|
||||
|
||||
// NewCommands returns 'wallet' command.
|
||||
func NewCommands() []cli.Command {
|
||||
func NewCommands() []*cli.Command {
|
||||
claimFlags := []cli.Flag{
|
||||
walletPathFlag,
|
||||
walletConfigFlag,
|
||||
|
@ -87,8 +89,9 @@ func NewCommands() []cli.Command {
|
|||
txctx.OutFlag,
|
||||
txctx.ForceFlag,
|
||||
txctx.AwaitFlag,
|
||||
flags.AddressFlag{
|
||||
Name: "address, a",
|
||||
&flags.AddressFlag{
|
||||
Name: "address",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Address to claim GAS for",
|
||||
},
|
||||
}
|
||||
|
@ -99,16 +102,17 @@ func NewCommands() []cli.Command {
|
|||
txctx.OutFlag,
|
||||
txctx.AwaitFlag,
|
||||
inFlag,
|
||||
flags.AddressFlag{
|
||||
Name: "address, a",
|
||||
&flags.AddressFlag{
|
||||
Name: "address",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Address to use",
|
||||
},
|
||||
}
|
||||
signFlags = append(signFlags, options.RPC...)
|
||||
return []cli.Command{{
|
||||
return []*cli.Command{{
|
||||
Name: "wallet",
|
||||
Usage: "Create, open and manage a Neo wallet",
|
||||
Subcommands: []cli.Command{
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "claim",
|
||||
Usage: "Claim GAS",
|
||||
|
@ -124,8 +128,9 @@ func NewCommands() []cli.Command {
|
|||
Flags: []cli.Flag{
|
||||
walletPathFlag,
|
||||
walletConfigFlag,
|
||||
cli.BoolFlag{
|
||||
Name: "account, a",
|
||||
&cli.BoolFlag{
|
||||
Name: "account",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Create a new account",
|
||||
},
|
||||
},
|
||||
|
@ -137,8 +142,9 @@ func NewCommands() []cli.Command {
|
|||
Action: changePassword,
|
||||
Flags: []cli.Flag{
|
||||
walletPathFlag,
|
||||
flags.AddressFlag{
|
||||
Name: "address, a",
|
||||
&flags.AddressFlag{
|
||||
Name: "address",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Address to change password for",
|
||||
},
|
||||
},
|
||||
|
@ -151,8 +157,9 @@ func NewCommands() []cli.Command {
|
|||
Flags: []cli.Flag{
|
||||
walletPathFlag,
|
||||
walletConfigFlag,
|
||||
cli.StringFlag{
|
||||
Name: "out, o",
|
||||
&cli.StringFlag{
|
||||
Name: "out",
|
||||
Aliases: []string{"o"},
|
||||
Usage: "Where to write converted wallet",
|
||||
},
|
||||
},
|
||||
|
@ -191,8 +198,9 @@ func NewCommands() []cli.Command {
|
|||
Flags: []cli.Flag{
|
||||
walletPathFlag,
|
||||
walletConfigFlag,
|
||||
flags.AddressFlag{
|
||||
Name: "address, a",
|
||||
&flags.AddressFlag{
|
||||
Name: "address",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Address to print public keys for",
|
||||
},
|
||||
},
|
||||
|
@ -223,11 +231,12 @@ func NewCommands() []cli.Command {
|
|||
walletPathFlag,
|
||||
walletConfigFlag,
|
||||
wifFlag,
|
||||
cli.StringFlag{
|
||||
Name: "name, n",
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Aliases: []string{"n"},
|
||||
Usage: "Optional account name",
|
||||
},
|
||||
cli.StringFlag{
|
||||
&cli.StringFlag{
|
||||
Name: "contract",
|
||||
Usage: "Verification script for custom contracts",
|
||||
},
|
||||
|
@ -250,12 +259,14 @@ func NewCommands() []cli.Command {
|
|||
walletPathFlag,
|
||||
walletConfigFlag,
|
||||
wifFlag,
|
||||
cli.StringFlag{
|
||||
Name: "name, n",
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Aliases: []string{"n"},
|
||||
Usage: "Optional account name",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "min, m",
|
||||
&cli.IntFlag{
|
||||
Name: "min",
|
||||
Aliases: []string{"m"},
|
||||
Usage: "Minimal number of signatures",
|
||||
},
|
||||
},
|
||||
|
@ -269,12 +280,14 @@ func NewCommands() []cli.Command {
|
|||
walletPathFlag,
|
||||
walletConfigFlag,
|
||||
wifFlag,
|
||||
cli.StringFlag{
|
||||
Name: "name, n",
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Aliases: []string{"n"},
|
||||
Usage: "Optional account name",
|
||||
},
|
||||
flags.AddressFlag{
|
||||
Name: "contract, c",
|
||||
&flags.AddressFlag{
|
||||
Name: "contract",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "Contract hash or address",
|
||||
},
|
||||
}, options.RPC...),
|
||||
|
@ -288,8 +301,9 @@ func NewCommands() []cli.Command {
|
|||
walletPathFlag,
|
||||
walletConfigFlag,
|
||||
txctx.ForceFlag,
|
||||
flags.AddressFlag{
|
||||
Name: "address, a",
|
||||
&flags.AddressFlag{
|
||||
Name: "address",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Account address or hash in LE form to be removed",
|
||||
},
|
||||
},
|
||||
|
@ -358,24 +372,24 @@ func changePassword(ctx *cli.Context) error {
|
|||
}
|
||||
wall, _, err := openWallet(ctx, false)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
if len(wall.Accounts) == 0 {
|
||||
return cli.NewExitError("wallet has no accounts", 1)
|
||||
return cli.Exit("wallet has no accounts", 1)
|
||||
}
|
||||
addrFlag := ctx.Generic("address").(*flags.Address)
|
||||
if addrFlag.IsSet {
|
||||
// Check for account presence first before asking for password.
|
||||
acc := wall.GetAccount(addrFlag.Uint160())
|
||||
if acc == nil {
|
||||
return cli.NewExitError("account is missing", 1)
|
||||
return cli.Exit("account is missing", 1)
|
||||
}
|
||||
}
|
||||
|
||||
oldPass, err := input.ReadPassword(EnterOldPasswordPrompt)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("Error reading old password: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("Error reading old password: %w", err), 1)
|
||||
}
|
||||
|
||||
for i := range wall.Accounts {
|
||||
|
@ -384,13 +398,13 @@ func changePassword(ctx *cli.Context) error {
|
|||
}
|
||||
err := wall.Accounts[i].Decrypt(oldPass, wall.Scrypt)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("unable to decrypt account %s: %w", wall.Accounts[i].Address, err), 1)
|
||||
return cli.Exit(fmt.Errorf("unable to decrypt account %s: %w", wall.Accounts[i].Address, err), 1)
|
||||
}
|
||||
}
|
||||
|
||||
pass, err := readNewPassword()
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("Error reading new password: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("Error reading new password: %w", err), 1)
|
||||
}
|
||||
for i := range wall.Accounts {
|
||||
if addrFlag.IsSet && wall.Accounts[i].Address != addrFlag.String() {
|
||||
|
@ -398,12 +412,12 @@ func changePassword(ctx *cli.Context) error {
|
|||
}
|
||||
err := wall.Accounts[i].Encrypt(pass, wall.Scrypt)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
}
|
||||
err = wall.Save()
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("Error saving the wallet: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("Error saving the wallet: %w", err), 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -414,16 +428,16 @@ func convertWallet(ctx *cli.Context) error {
|
|||
}
|
||||
wall, pass, err := newWalletV2FromFile(ctx.String("wallet"), ctx.String("wallet-config"))
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
out := ctx.String("out")
|
||||
if len(out) == 0 {
|
||||
return cli.NewExitError("missing out path", 1)
|
||||
return cli.Exit("missing out path", 1)
|
||||
}
|
||||
newWallet, err := wallet.NewWallet(out)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
newWallet.Scrypt = wall.Scrypt
|
||||
|
||||
|
@ -431,19 +445,19 @@ func convertWallet(ctx *cli.Context) error {
|
|||
if len(wall.Accounts) != 1 || pass == nil {
|
||||
password, err := input.ReadPassword(fmt.Sprintf("Enter password for account %s (label '%s') > ", acc.Address, acc.Label))
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("Error reading password: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("Error reading password: %w", err), 1)
|
||||
}
|
||||
pass = &password
|
||||
}
|
||||
|
||||
newAcc, err := acc.convert(*pass, wall.Scrypt)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
newWallet.AddAccount(newAcc)
|
||||
}
|
||||
if err := newWallet.Save(); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -454,12 +468,12 @@ func addAccount(ctx *cli.Context) error {
|
|||
}
|
||||
wall, pass, err := openWallet(ctx, true)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
|
||||
if err := createAccount(wall, pass); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -468,7 +482,7 @@ func addAccount(ctx *cli.Context) error {
|
|||
func exportKeys(ctx *cli.Context) error {
|
||||
wall, pass, err := readWallet(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
|
||||
|
@ -476,13 +490,13 @@ func exportKeys(ctx *cli.Context) error {
|
|||
|
||||
decrypt := ctx.Bool("decrypt")
|
||||
if ctx.NArg() == 0 && decrypt {
|
||||
return cli.NewExitError(errors.New("address must be provided if '--decrypt' flag is used"), 1)
|
||||
return cli.Exit(errors.New("address must be provided if '--decrypt' flag is used"), 1)
|
||||
} else if ctx.NArg() > 0 {
|
||||
// check address format just to catch possible typos
|
||||
addr = ctx.Args().First()
|
||||
_, err := address.StringToUint160(addr)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't parse address: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't parse address: %w", err), 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -508,14 +522,14 @@ loop:
|
|||
if pass == nil {
|
||||
password, err := input.ReadPassword(EnterPasswordPrompt)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("Error reading password: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("Error reading password: %w", err), 1)
|
||||
}
|
||||
pass = &password
|
||||
}
|
||||
|
||||
pk, err := keys.NEP2Decrypt(wif, *pass, wall.Scrypt)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
wif = pk.WIF()
|
||||
|
@ -536,22 +550,22 @@ func importMultisig(ctx *cli.Context) error {
|
|||
|
||||
wall, pass, err := openWallet(ctx, true)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
|
||||
m := ctx.Int("min")
|
||||
if ctx.NArg() < m {
|
||||
return cli.NewExitError(errors.New("insufficient number of public keys"), 1)
|
||||
return cli.Exit(errors.New("insufficient number of public keys"), 1)
|
||||
}
|
||||
|
||||
args := []string(ctx.Args())
|
||||
args := ctx.Args().Slice()
|
||||
pubs := make([]*keys.PublicKey, len(args))
|
||||
|
||||
for i := range args {
|
||||
pubs[i], err = keys.NewPublicKeyFromString(args[i])
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't decode public key %d: %w", i, err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't decode public key %d: %w", i, err), 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -579,31 +593,31 @@ loop:
|
|||
if acc != nil {
|
||||
err = acc.ConvertMultisigEncrypted(accPub, m, pubs)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
if label != nil {
|
||||
acc.Label = *label
|
||||
}
|
||||
if err := addAccountAndSave(wall, acc); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if !ctx.IsSet("wif") {
|
||||
return cli.NewExitError(errors.New("none of the provided public keys correspond to an existing key in the wallet or multiple matching accounts found in the wallet, and no WIF is provided"), 1)
|
||||
return cli.Exit(errors.New("none of the provided public keys correspond to an existing key in the wallet or multiple matching accounts found in the wallet, and no WIF is provided"), 1)
|
||||
}
|
||||
acc, err = newAccountFromWIF(ctx.App.Writer, ctx.String("wif"), wall.Scrypt, label, pass)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
if err := acc.ConvertMultisig(m, pubs); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
if err := addAccountAndSave(wall, acc); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -615,13 +629,13 @@ func importDeployed(ctx *cli.Context) error {
|
|||
}
|
||||
wall, pass, err := openWallet(ctx, true)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
|
||||
rawHash := ctx.Generic("contract").(*flags.Address)
|
||||
if !rawHash.IsSet {
|
||||
return cli.NewExitError("contract hash was not provided", 1)
|
||||
return cli.Exit("contract hash was not provided", 1)
|
||||
}
|
||||
|
||||
var label *string
|
||||
|
@ -631,7 +645,7 @@ func importDeployed(ctx *cli.Context) error {
|
|||
}
|
||||
acc, err := newAccountFromWIF(ctx.App.Writer, ctx.String("wif"), wall.Scrypt, label, pass)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
|
@ -639,16 +653,16 @@ func importDeployed(ctx *cli.Context) error {
|
|||
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
cs, err := c.GetContractStateByHash(rawHash.Uint160())
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't fetch contract info: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("can't fetch contract info: %w", err), 1)
|
||||
}
|
||||
md := cs.Manifest.ABI.GetMethod(manifest.MethodVerify, -1)
|
||||
if md == nil || md.ReturnType != smartcontract.BoolType {
|
||||
return cli.NewExitError("contract has no `verify` method with boolean return", 1)
|
||||
return cli.Exit("contract has no `verify` method with boolean return", 1)
|
||||
}
|
||||
acc.Address = address.Uint160ToString(cs.Hash)
|
||||
// Explicitly overwrite single signature script of the provided WIF since the contract is known to be deployed.
|
||||
|
@ -663,7 +677,7 @@ func importDeployed(ctx *cli.Context) error {
|
|||
acc.Contract.Deployed = true
|
||||
|
||||
if err := addAccountAndSave(wall, acc); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -675,7 +689,7 @@ func importWallet(ctx *cli.Context) error {
|
|||
}
|
||||
wall, pass, err := openWallet(ctx, true)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
|
||||
|
@ -687,19 +701,19 @@ func importWallet(ctx *cli.Context) error {
|
|||
|
||||
acc, err := newAccountFromWIF(ctx.App.Writer, ctx.String("wif"), wall.Scrypt, label, pass)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
if ctrFlag := ctx.String("contract"); ctrFlag != "" {
|
||||
ctr, err := hex.DecodeString(ctrFlag)
|
||||
if err != nil {
|
||||
return cli.NewExitError("invalid contract", 1)
|
||||
return cli.Exit("invalid contract", 1)
|
||||
}
|
||||
acc.Contract.Script = ctr
|
||||
}
|
||||
|
||||
if err := addAccountAndSave(wall, acc); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -711,17 +725,17 @@ func removeAccount(ctx *cli.Context) error {
|
|||
}
|
||||
wall, _, err := openWallet(ctx, true)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
|
||||
addr := ctx.Generic("address").(*flags.Address)
|
||||
if !addr.IsSet {
|
||||
return cli.NewExitError("valid account address must be provided", 1)
|
||||
return cli.Exit("valid account address must be provided", 1)
|
||||
}
|
||||
acc := wall.GetAccount(addr.Uint160())
|
||||
if acc == nil {
|
||||
return cli.NewExitError("account wasn't found", 1)
|
||||
return cli.Exit("account wasn't found", 1)
|
||||
}
|
||||
|
||||
if !ctx.Bool("force") {
|
||||
|
@ -732,10 +746,10 @@ func removeAccount(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
if err := wall.RemoveAccount(acc.Address); err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("error on remove: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("error on remove: %w", err), 1)
|
||||
}
|
||||
if err := wall.Save(); err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("error while saving wallet: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("error while saving wallet: %w", err), 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -758,14 +772,14 @@ func dumpWallet(ctx *cli.Context) error {
|
|||
}
|
||||
wall, pass, err := readWallet(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
if ctx.Bool("decrypt") {
|
||||
if pass == nil {
|
||||
password, err := input.ReadPassword(EnterPasswordPrompt)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("Error reading password: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("Error reading password: %w", err), 1)
|
||||
}
|
||||
pass = &password
|
||||
}
|
||||
|
@ -773,7 +787,7 @@ func dumpWallet(ctx *cli.Context) error {
|
|||
// Just testing the decryption here.
|
||||
err := wall.Accounts[i].Decrypt(*pass, wall.Scrypt)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -787,7 +801,7 @@ func dumpKeys(ctx *cli.Context) error {
|
|||
}
|
||||
wall, _, err := readWallet(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
accounts := wall.Accounts
|
||||
|
@ -796,7 +810,7 @@ func dumpKeys(ctx *cli.Context) error {
|
|||
if addrFlag.IsSet {
|
||||
acc := wall.GetAccount(addrFlag.Uint160())
|
||||
if acc == nil {
|
||||
return cli.NewExitError("account is missing", 1)
|
||||
return cli.Exit("account is missing", 1)
|
||||
}
|
||||
accounts = []*wallet.Account{acc}
|
||||
}
|
||||
|
@ -826,7 +840,7 @@ func dumpKeys(ctx *cli.Context) error {
|
|||
continue
|
||||
}
|
||||
if addrFlag.IsSet {
|
||||
return cli.NewExitError(fmt.Errorf("unknown script type for address %s", address.Uint160ToString(addrFlag.Uint160())), 1)
|
||||
return cli.Exit(fmt.Errorf("unknown script type for address %s", address.Uint160ToString(addrFlag.Uint160())), 1)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -838,7 +852,7 @@ func stripKeys(ctx *cli.Context) error {
|
|||
}
|
||||
wall, _, err := readWallet(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
if !ctx.Bool("force") {
|
||||
|
@ -851,7 +865,7 @@ func stripKeys(ctx *cli.Context) error {
|
|||
a.EncryptedWIF = ""
|
||||
}
|
||||
if err := wall.Save(); err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("error while saving wallet: %w", err), 1)
|
||||
return cli.Exit(fmt.Errorf("error while saving wallet: %w", err), 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -867,28 +881,28 @@ func createWallet(ctx *cli.Context) error {
|
|||
return errConflictingWalletFlags
|
||||
}
|
||||
if len(path) == 0 && len(configPath) == 0 {
|
||||
return cli.NewExitError(errNoPath, 1)
|
||||
return cli.Exit(errNoPath, 1)
|
||||
}
|
||||
var pass *string
|
||||
if len(configPath) != 0 {
|
||||
cfg, err := options.ReadWalletConfig(configPath)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
path = cfg.Path
|
||||
pass = &cfg.Password
|
||||
}
|
||||
wall, err := wallet.NewWallet(path)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
if err := wall.Save(); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
if ctx.Bool("account") {
|
||||
if err := createAccount(wall, pass); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
}
|
||||
|
@ -949,14 +963,14 @@ func createAccount(wall *wallet.Wallet, pass *string) error {
|
|||
func openWallet(ctx *cli.Context, canUseWalletConfig bool) (*wallet.Wallet, *string, error) {
|
||||
path, pass, err := getWalletPathAndPass(ctx, canUseWalletConfig)
|
||||
if err != nil {
|
||||
return nil, nil, cli.NewExitError(fmt.Errorf("failed to get wallet path or password: %w", err), 1)
|
||||
return nil, nil, cli.Exit(fmt.Errorf("failed to get wallet path or password: %w", err), 1)
|
||||
}
|
||||
if path == "-" {
|
||||
return nil, nil, errNoStdin
|
||||
}
|
||||
w, err := wallet.NewWalletFromFile(path)
|
||||
if err != nil {
|
||||
return nil, nil, cli.NewExitError(fmt.Errorf("failed to read wallet: %w", err), 1)
|
||||
return nil, nil, cli.Exit(fmt.Errorf("failed to read wallet: %w", err), 1)
|
||||
}
|
||||
return w, pass, nil
|
||||
}
|
||||
|
|
|
@ -992,7 +992,7 @@ func TestOfflineSigning(t *testing.T) {
|
|||
|
||||
e.Run(t, "neo-go", "util", "sendtx",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
|
||||
txPath, "--await")
|
||||
"--await", txPath)
|
||||
e.CheckAwaitableTxPersisted(t)
|
||||
})
|
||||
}
|
||||
|
|
5
go.mod
5
go.mod
|
@ -25,7 +25,7 @@ require (
|
|||
github.com/stretchr/testify v1.9.0
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954
|
||||
github.com/twmb/murmur3 v1.1.8
|
||||
github.com/urfave/cli v1.22.5
|
||||
github.com/urfave/cli/v2 v2.27.2
|
||||
go.etcd.io/bbolt v1.3.9
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/crypto v0.21.0
|
||||
|
@ -42,7 +42,7 @@ require (
|
|||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/consensys/bavard v0.1.13 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||
github.com/frankban/quicktest v1.14.5 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.5.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
|
@ -60,6 +60,7 @@ require (
|
|||
github.com/rs/zerolog v1.30.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
|
||||
golang.org/x/mod v0.16.0 // indirect
|
||||
|
|
15
go.sum
15
go.sum
|
@ -1,4 +1,3 @@
|
|||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12 h1:npHgfD4Tl2WJS3AJaMUi5ynGDPUBfkg3U3fCzDyXZ+4=
|
||||
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
|
@ -22,9 +21,8 @@ github.com/consensys/gnark v0.9.1/go.mod h1:udWvWGXnfBE7mn7BsNoGAvZDnUhcONBEtNij
|
|||
github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb h1:f0BMgIjhZy4lSRHCXFbQst85f5agZAjtDMixQqBWNpc=
|
||||
github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
@ -131,20 +129,20 @@ github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDN
|
|||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c=
|
||||
github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 h1:xQdMZ1WLrgkkvOZ/LDQxjVxMLdby7osSh4ZEVa5sIjs=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM=
|
||||
github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg=
|
||||
github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
|
||||
github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU=
|
||||
github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
|
||||
github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw=
|
||||
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk=
|
||||
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
|
||||
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
|
@ -216,7 +214,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
|
|||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
|
|
|
@ -34,7 +34,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zaptest"
|
||||
"golang.org/x/term"
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var ledgerContractID = -4
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var errStateMatches = errors.New("state matches")
|
||||
|
@ -167,8 +167,9 @@ func main() {
|
|||
ctl.Usage = "compare-states RPC_A RPC_B"
|
||||
ctl.Action = cliMain
|
||||
ctl.Flags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "ignore-height, g",
|
||||
&cli.BoolFlag{
|
||||
Name: "ignore-height",
|
||||
Aliases: []string{"h"},
|
||||
Usage: "Ignore height difference",
|
||||
},
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue