cli: allow to provide cosigners for 'wallet nep17 transfer'

This commit is contained in:
Anna Shaleva 2021-04-21 12:50:04 +03:00
parent 127d0ad2ba
commit f848783d5d
3 changed files with 81 additions and 41 deletions

View file

@ -226,6 +226,33 @@ func TestContractDeployWithData(t *testing.T) {
require.Equal(t, []byte("take_me_to_church"), res.Stack[0].Value())
}
func deployVerifyContract(t *testing.T, e *executor) util.Uint160 {
tmpDir := path.Join(os.TempDir(), "neogo.test.deployverifycontract")
require.NoError(t, os.Mkdir(tmpDir, os.ModePerm))
t.Cleanup(func() {
os.RemoveAll(tmpDir)
})
// deploy verification contract
nefName := path.Join(tmpDir, "verify.nef")
manifestName := path.Join(tmpDir, "verify.manifest.json")
e.Run(t, "neo-go", "contract", "compile",
"--in", "testdata/verify.go",
"--config", "testdata/verify.yml",
"--out", nefName, "--manifest", manifestName)
e.In.WriteString("one\r")
e.Run(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--address", validatorAddr,
"--in", nefName, "--manifest", manifestName)
line, err := e.Out.ReadString('\n')
require.NoError(t, err)
line = strings.TrimSpace(strings.TrimPrefix(line, "Contract: "))
hVerify, err := util.Uint160DecodeStringLE(line)
require.NoError(t, err)
e.checkTxPersisted(t)
return hVerify
}
func TestComlileAndInvokeFunction(t *testing.T) {
e := newExecutor(t, true)
@ -315,23 +342,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
require.Equal(t, []byte("on create|sub create"), res.Stack[0].Value())
// deploy verification contract
nefName = path.Join(tmpDir, "verify.nef")
manifestName = path.Join(tmpDir, "verify.manifest.json")
e.Run(t, "neo-go", "contract", "compile",
"--in", "testdata/verify.go",
"--config", "testdata/verify.yml",
"--out", nefName, "--manifest", manifestName)
e.In.WriteString("one\r")
e.Run(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--address", validatorAddr,
"--in", nefName, "--manifest", manifestName)
line, err = e.Out.ReadString('\n')
require.NoError(t, err)
line = strings.TrimSpace(strings.TrimPrefix(line, "Contract: "))
hVerify, err := util.Uint160DecodeStringLE(line)
require.NoError(t, err)
e.checkTxPersisted(t)
hVerify := deployVerifyContract(t, e)
t.Run("real invoke", func(t *testing.T) {
cmd := []string{"neo-go", "contract", "invokefunction",

View file

@ -132,6 +132,8 @@ func TestNEP17Transfer(t *testing.T) {
b, _ := e.Chain.GetGoverningTokenBalance(sh)
require.Equal(t, big.NewInt(1), b)
hVerify := deployVerifyContract(t, e)
t.Run("default address", func(t *testing.T) {
const validatorDefault = "NTh9TnZTstvAePEYWDGLLxidBikJE24uTo"
e.In.WriteString("one\r")
@ -159,21 +161,39 @@ func TestNEP17Transfer(t *testing.T) {
require.Equal(t, big.NewInt(41), b)
})
validTil := e.Chain.BlockHeight() + 100
cmd := []string{
"neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", validatorWallet,
"--to", address.Uint160ToString(e.Chain.GetNotaryContractScriptHash()),
"--token", "GAS",
"--amount", "1",
"--from", validatorAddr,
"[", validatorAddr, strconv.Itoa(int(validTil)), "]"}
t.Run("with data", func(t *testing.T) {
e.In.WriteString("one\r")
validTil := e.Chain.BlockHeight() + 100
e.Run(t, []string{
"neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", validatorWallet,
"--to", address.Uint160ToString(e.Chain.GetNotaryContractScriptHash()),
"--token", "GAS",
"--amount", "1",
"--from", validatorAddr,
"[", validatorAddr, strconv.Itoa(int(validTil)), "]",
}...)
e.Run(t, cmd...)
e.checkTxPersisted(t)
})
t.Run("with data and signers", func(t *testing.T) {
t.Run("invalid sender's scope", func(t *testing.T) {
e.In.WriteString("one\r")
e.RunWithError(t, append(cmd, "--", validatorAddr+":None")...)
})
t.Run("good", func(t *testing.T) {
e.In.WriteString("one\r")
e.Run(t, append(cmd, "--", validatorAddr+":Global")...) // CalledByEntry is enough, but it's the default value, so check something else
e.checkTxPersisted(t)
})
t.Run("several signers", func(t *testing.T) {
e.In.WriteString("one\r")
e.Run(t, append(cmd, "--", validatorAddr, hVerify.StringLE())...)
e.checkTxPersisted(t)
})
})
}
func TestNEP17MultiTransfer(t *testing.T) {

View file

@ -112,12 +112,15 @@ func newNEP17Commands() []cli.Command {
{
Name: "transfer",
Usage: "transfer NEP17 tokens",
UsageText: "transfer --wallet <path> --rpc-endpoint <node> --timeout <time> --from <addr> --to <addr> --token <hash> --amount string [data]",
UsageText: "transfer --wallet <path> --rpc-endpoint <node> --timeout <time> --from <addr> --to <addr> --token <hash> --amount string [data] [-- <cosigner1:Scope> [<cosigner2> [...]]]",
Action: transferNEP17,
Flags: transferFlags,
Description: `Transfers specified NEP17 token amount with optional 'data' parameter attached to the transfer.
See 'contract testinvokefunction' documentation for the details about 'data'
parameter. If no 'data' is given then default nil value will be used`,
Description: `Transfers specified NEP17 token amount with optional 'data' parameter and cosigners
list attached to the transfer. See 'contract testinvokefunction' documentation
for the details about 'data' parameter and cosigners syntax. If no 'data' is
given then default nil value will be used. If no cosigners are given then the
sender with CalledByEntry scope will be used as the only signer.
`,
},
{
Name: "multitransfer",
@ -417,7 +420,7 @@ func multiTransferNEP17(ctx *cli.Context) error {
})
}
return signAndSendTransfer(ctx, c, acc, recipients)
return signAndSendTransfer(ctx, c, acc, recipients, nil)
}
func transferNEP17(ctx *cli.Context) error {
@ -461,23 +464,32 @@ func transferNEP17(ctx *cli.Context) error {
return cli.NewExitError(fmt.Errorf("invalid amount: %w", err), 1)
}
_, data, extErr := cmdargs.GetDataFromContext(ctx)
cosignersOffset, data, extErr := cmdargs.GetDataFromContext(ctx)
if extErr != nil {
return extErr
}
cosigners, extErr := cmdargs.GetSignersFromContext(ctx, cosignersOffset)
if extErr != nil {
return extErr
}
cosignersAccounts, err := cmdargs.GetSignersAccounts(wall, cosigners)
if err != nil {
return cli.NewExitError(fmt.Errorf("failed to create NEP17 transfer transaction: %w", err), 1)
}
return signAndSendTransfer(ctx, c, acc, []client.TransferTarget{{
Token: token.Hash,
Address: to,
Amount: amount.Int64(),
Data: data,
}})
}}, cosignersAccounts)
}
func signAndSendTransfer(ctx *cli.Context, c *client.Client, acc *wallet.Account, recipients []client.TransferTarget) error {
func signAndSendTransfer(ctx *cli.Context, c *client.Client, acc *wallet.Account, recipients []client.TransferTarget, cosigners []client.SignerAccount) error {
gas := flags.Fixed8FromContext(ctx, "gas")
tx, err := c.CreateNEP17MultiTransferTx(acc, int64(gas), recipients, nil)
tx, err := c.CreateNEP17MultiTransferTx(acc, int64(gas), recipients, cosigners)
if err != nil {
return cli.NewExitError(err, 1)
}
@ -487,13 +499,10 @@ func signAndSendTransfer(ctx *cli.Context, c *client.Client, acc *wallet.Account
return cli.NewExitError(err, 1)
}
} else {
_ = acc.SignTx(c.GetNetwork(), tx)
res, err := c.SendRawTransaction(tx)
_, err := c.SignAndPushTx(tx, acc, cosigners)
if err != nil {
return cli.NewExitError(err, 1)
}
fmt.Fprintln(ctx.App.Writer, res.StringLE())
return nil
}
fmt.Fprintln(ctx.App.Writer, tx.Hash().StringLE())