From 49c35dec2059ecfb0ad2d3fa64c25f1a5b86577c Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 21 Apr 2021 12:43:30 +0300 Subject: [PATCH] rpc: allow to provide cosigners for NEP17-transfer-related commands --- cli/wallet/nep17.go | 2 +- cli/wallet/wallet.go | 2 +- pkg/rpc/client/nep17.go | 44 +++++++++++++++++------------------ pkg/rpc/server/client_test.go | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/cli/wallet/nep17.go b/cli/wallet/nep17.go index 1836ce168..f23b89f5a 100644 --- a/cli/wallet/nep17.go +++ b/cli/wallet/nep17.go @@ -477,7 +477,7 @@ func transferNEP17(ctx *cli.Context) error { func signAndSendTransfer(ctx *cli.Context, c *client.Client, acc *wallet.Account, recipients []client.TransferTarget) error { gas := flags.Fixed8FromContext(ctx, "gas") - tx, err := c.CreateNEP17MultiTransferTx(acc, int64(gas), recipients) + tx, err := c.CreateNEP17MultiTransferTx(acc, int64(gas), recipients, nil) if err != nil { return cli.NewExitError(err, 1) } diff --git a/cli/wallet/wallet.go b/cli/wallet/wallet.go index 0913d5a1c..9b2f3eee7 100644 --- a/cli/wallet/wallet.go +++ b/cli/wallet/wallet.go @@ -272,7 +272,7 @@ func claimGas(ctx *cli.Context) error { if err != nil { return cli.NewExitError(err, 1) } - hash, err := c.TransferNEP17(acc, scriptHash, neoContractHash, 0, 0, nil) + hash, err := c.TransferNEP17(acc, scriptHash, neoContractHash, 0, 0, nil, nil) if err != nil { return cli.NewExitError(err, 1) } diff --git a/pkg/rpc/client/nep17.go b/pkg/rpc/client/nep17.go index 3b27ebf54..470de9380 100644 --- a/pkg/rpc/client/nep17.go +++ b/pkg/rpc/client/nep17.go @@ -69,19 +69,23 @@ func (c *Client) NEP17TokenInfo(tokenHash util.Uint160) (*wallet.Token, error) { // method of a given contract (token) to move specified amount of NEP17 assets // (in FixedN format using contract's number of decimals) to given account and // returns it. The returned transaction is not signed. -func (c *Client) CreateNEP17TransferTx(acc *wallet.Account, to util.Uint160, token util.Uint160, amount int64, gas int64, data interface{}) (*transaction.Transaction, error) { +func (c *Client) CreateNEP17TransferTx(acc *wallet.Account, to util.Uint160, + token util.Uint160, amount int64, gas int64, data interface{}, cosigners []SignerAccount) (*transaction.Transaction, error) { return c.CreateNEP17MultiTransferTx(acc, gas, []TransferTarget{ {Token: token, Address: to, Amount: amount, Data: data, }, - }) + }, cosigners) } -// CreateNEP17MultiTransferTx creates an invocation transaction for performing NEP17 transfers -// from a single sender to multiple recipients with the given data. -func (c *Client) CreateNEP17MultiTransferTx(acc *wallet.Account, gas int64, recipients []TransferTarget) (*transaction.Transaction, error) { +// CreateNEP17MultiTransferTx creates an invocation transaction for performing +// NEP17 transfers from a single sender to multiple recipients with the given +// data and cosigners. Transaction's sender is included with the CalledByEntry +// scope by default. +func (c *Client) CreateNEP17MultiTransferTx(acc *wallet.Account, gas int64, + recipients []TransferTarget, cosigners []SignerAccount) (*transaction.Transaction, error) { from, err := address.StringToUint160(acc.Address) if err != nil { return nil, fmt.Errorf("bad account address: %w", err) @@ -95,13 +99,13 @@ func (c *Client) CreateNEP17MultiTransferTx(acc *wallet.Account, gas int64, reci if w.Err != nil { return nil, fmt.Errorf("failed to create transfer script: %w", w.Err) } - return c.CreateTxFromScript(w.Bytes(), acc, -1, gas, []SignerAccount{{ + return c.CreateTxFromScript(w.Bytes(), acc, -1, gas, append([]SignerAccount{{ Signer: transaction.Signer{ Account: from, Scopes: transaction.CalledByEntry, }, Account: acc, - }}) + }}, cosigners...)) } // CreateTxFromScript creates transaction and properly sets cosigners and NetworkFee. @@ -143,38 +147,34 @@ func (c *Client) CreateTxFromScript(script []byte, acc *wallet.Account, sysFee, // TransferNEP17 creates an invocation transaction that invokes 'transfer' method // on a given token to move specified amount of NEP17 assets (in FixedN format // using contract's number of decimals) to given account with data specified and -// sends it to the network returning just a hash of it. -func (c *Client) TransferNEP17(acc *wallet.Account, to util.Uint160, token util.Uint160, amount int64, gas int64, data interface{}) (util.Uint256, error) { +// sends it to the network returning just a hash of it. Cosigners argument +// specifies a set of the transaction cosigners (may be nil or may include sender) +// with proper scope and accounts to cosign the transaction. If cosigning is +// impossible (e.g. due to locked cosigner's account) an error is returned. +func (c *Client) TransferNEP17(acc *wallet.Account, to util.Uint160, token util.Uint160, + amount int64, gas int64, data interface{}, cosigners []SignerAccount) (util.Uint256, error) { if !c.initDone { return util.Uint256{}, errNetworkNotInitialized } - tx, err := c.CreateNEP17TransferTx(acc, to, token, amount, gas, data) + tx, err := c.CreateNEP17TransferTx(acc, to, token, amount, gas, data, cosigners) if err != nil { return util.Uint256{}, err } - if err := acc.SignTx(c.GetNetwork(), tx); err != nil { - return util.Uint256{}, fmt.Errorf("can't sign tx: %w", err) - } - - return c.SendRawTransaction(tx) + return c.SignAndPushTx(tx, acc, cosigners) } // MultiTransferNEP17 is similar to TransferNEP17, buf allows to have multiple recipients. -func (c *Client) MultiTransferNEP17(acc *wallet.Account, gas int64, recipients []TransferTarget) (util.Uint256, error) { +func (c *Client) MultiTransferNEP17(acc *wallet.Account, gas int64, recipients []TransferTarget, cosigners []SignerAccount) (util.Uint256, error) { if !c.initDone { return util.Uint256{}, errNetworkNotInitialized } - tx, err := c.CreateNEP17MultiTransferTx(acc, gas, recipients) + tx, err := c.CreateNEP17MultiTransferTx(acc, gas, recipients, cosigners) if err != nil { return util.Uint256{}, err } - if err := acc.SignTx(c.GetNetwork(), tx); err != nil { - return util.Uint256{}, fmt.Errorf("can't sign tx: %w", err) - } - - return c.SendRawTransaction(tx) + return c.SignAndPushTx(tx, acc, cosigners) } diff --git a/pkg/rpc/server/client_test.go b/pkg/rpc/server/client_test.go index e6014afd4..b71e32ab2 100644 --- a/pkg/rpc/server/client_test.go +++ b/pkg/rpc/server/client_test.go @@ -707,7 +707,7 @@ func TestCreateNEP17TransferTx(t *testing.T) { gasContractHash, err := c.GetNativeContractHash(nativenames.Gas) require.NoError(t, err) - tx, err := c.CreateNEP17TransferTx(acc, util.Uint160{}, gasContractHash, 1000, 0, nil) + tx, err := c.CreateNEP17TransferTx(acc, util.Uint160{}, gasContractHash, 1000, 0, nil, nil) require.NoError(t, err) require.NoError(t, acc.SignTx(testchain.Network(), tx)) require.NoError(t, chain.VerifyTx(tx))