diff --git a/cli/wallet/nep11.go b/cli/wallet/nep11.go index d69c27ecd..044619b51 100644 --- a/cli/wallet/nep11.go +++ b/cli/wallet/nep11.go @@ -9,18 +9,13 @@ import ( "github.com/nspcc-dev/neo-go/cli/cmdargs" "github.com/nspcc-dev/neo-go/cli/flags" - "github.com/nspcc-dev/neo-go/cli/input" "github.com/nspcc-dev/neo-go/cli/options" - "github.com/nspcc-dev/neo-go/cli/paramcontext" "github.com/nspcc-dev/neo-go/pkg/config" - "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep11" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" - "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" @@ -262,48 +257,6 @@ func transferNEP11(ctx *cli.Context) error { return transferNEP(ctx, manifest.NEP11StandardName) } -func signAndSendNEP11Transfer(ctx *cli.Context, act *actor.Actor, acc *wallet.Account, token, to util.Uint160, tokenID []byte, amount *big.Int, data interface{}) error { - var ( - err error - gas = flags.Fixed8FromContext(ctx, "gas") - sysgas = flags.Fixed8FromContext(ctx, "sysgas") - tx *transaction.Transaction - ) - if amount != nil { - n11 := nep11.NewDivisible(act, token) - tx, err = n11.TransferDUnsigned(act.Sender(), to, amount, tokenID, data) - } else { - n11 := nep11.NewNonDivisible(act, token) - tx, err = n11.TransferUnsigned(to, tokenID, data) - } - if err != nil { - return cli.NewExitError(err, 1) - } - tx.SystemFee += int64(sysgas) - tx.NetworkFee += int64(gas) - - if outFile := ctx.String("out"); outFile != "" { - ver := act.GetVersion() - // Make a long-lived transaction, it's to be signed manually. - tx.ValidUntilBlock += (ver.Protocol.MaxValidUntilBlockIncrement - uint32(ver.Protocol.ValidatorsCount)) - 2 - err = paramcontext.InitAndSave(ver.Protocol.Network, tx, acc, outFile) - } else { - if !ctx.Bool("force") { - err := input.ConfirmTx(ctx.App.Writer, tx) - if err != nil { - return cli.NewExitError(err, 1) - } - } - _, _, err = act.SignAndSend(tx) - } - if err != nil { - return cli.NewExitError(err, 1) - } - - fmt.Fprintln(ctx.App.Writer, tx.Hash().StringLE()) - return nil -} - func printNEP11NDOwner(ctx *cli.Context) error { return printNEP11Owner(ctx, false) } diff --git a/cli/wallet/nep17.go b/cli/wallet/nep17.go index b14d593a6..97a99bddc 100644 --- a/cli/wallet/nep17.go +++ b/cli/wallet/nep17.go @@ -21,6 +21,8 @@ import ( "github.com/nspcc-dev/neo-go/pkg/rpcclient/gas" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/neo" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep11" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/util" @@ -558,7 +560,11 @@ func multiTransferNEP17(ctx *cli.Context) error { return cli.NewExitError(fmt.Errorf("failed to create RPC actor: %w", err), 1) } - return signAndSendNEP17Transfer(ctx, act, acc, recipients) + tx, err := makeMultiTransferNEP17(act, recipients) + if err != nil { + return cli.NewExitError(fmt.Errorf("can't make transaction: %w", err), 1) + } + return signAndSendSomeTransaction(ctx, act, acc, tx) } func transferNEP17(ctx *cli.Context) error { @@ -566,6 +572,8 @@ func transferNEP17(ctx *cli.Context) error { } func transferNEP(ctx *cli.Context, standard string) error { + var tx *transaction.Transaction + wall, pass, err := readWallet(ctx) if err != nil { return cli.NewExitError(err, 1) @@ -621,44 +629,42 @@ func transferNEP(ctx *cli.Context, standard string) error { } amountArg := ctx.String("amount") + 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) + } switch standard { case manifest.NEP17StandardName: - amount, err := fixedn.FromString(amountArg, int(token.Decimals)) - if err != nil { - return cli.NewExitError(fmt.Errorf("invalid amount: %w", err), 1) - } - return signAndSendNEP17Transfer(ctx, act, acc, []rpcclient.TransferTarget{{ - Token: token.Hash, - Address: to, - Amount: amount.Int64(), - Data: data, - }}) + n17 := nep17.New(act, token.Hash) + tx, err = n17.TransferUnsigned(act.Sender(), to, amount, data) case manifest.NEP11StandardName: tokenID := ctx.String("id") if tokenID == "" { return cli.NewExitError(errors.New("token ID should be specified"), 1) } - tokenIDBytes, err := hex.DecodeString(tokenID) - if err != nil { - return cli.NewExitError(fmt.Errorf("invalid token ID: %w", err), 1) + tokenIDBytes, terr := hex.DecodeString(tokenID) + if terr != nil { + return cli.NewExitError(fmt.Errorf("invalid token ID: %w", terr), 1) } if amountArg == "" { - return signAndSendNEP11Transfer(ctx, act, acc, token.Hash, to, tokenIDBytes, nil, data) + n11 := nep11.NewNonDivisible(act, token.Hash) + tx, err = n11.TransferUnsigned(to, tokenIDBytes, data) + } else { + n11 := nep11.NewDivisible(act, token.Hash) + tx, err = n11.TransferDUnsigned(act.Sender(), to, amount, tokenIDBytes, data) } - amount, err := fixedn.FromString(amountArg, int(token.Decimals)) - if err != nil { - return cli.NewExitError(fmt.Errorf("invalid amount: %w", err), 1) - } - return signAndSendNEP11Transfer(ctx, act, acc, token.Hash, to, tokenIDBytes, amount, data) default: return cli.NewExitError(fmt.Errorf("unsupported token standard %s", standard), 1) } + if err != nil { + return cli.NewExitError(fmt.Errorf("can't make transaction: %w", err), 1) + } + + return signAndSendSomeTransaction(ctx, act, acc, tx) } -func signAndSendNEP17Transfer(ctx *cli.Context, act *actor.Actor, acc *wallet.Account, recipients []rpcclient.TransferTarget) error { - gas := flags.Fixed8FromContext(ctx, "gas") - sysgas := flags.Fixed8FromContext(ctx, "sysgas") - +func makeMultiTransferNEP17(act *actor.Actor, recipients []rpcclient.TransferTarget) (*transaction.Transaction, error) { scr := smartcontract.NewBuilder() for i := range recipients { scr.InvokeWithAssert(recipients[i].Token, "transfer", act.Sender(), @@ -666,12 +672,18 @@ func signAndSendNEP17Transfer(ctx *cli.Context, act *actor.Actor, acc *wallet.Ac } script, err := scr.Script() if err != nil { - return err - } - tx, err := act.MakeUnsignedRun(script, nil) - if err != nil { - return cli.NewExitError(err, 1) + return nil, err } + return act.MakeUnsignedRun(script, nil) +} + +func signAndSendSomeTransaction(ctx *cli.Context, act *actor.Actor, acc *wallet.Account, tx *transaction.Transaction) error { + var ( + err error + gas = flags.Fixed8FromContext(ctx, "gas") + sysgas = flags.Fixed8FromContext(ctx, "sysgas") + ) + tx.SystemFee += int64(sysgas) tx.NetworkFee += int64(gas)