Merge pull request #1104 from nspcc-dev/fix/client

Fix `wallet nep5 transfer` command
This commit is contained in:
Roman Khimov 2020-06-25 17:34:39 +03:00 committed by GitHub
commit c08e0f4418
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 57 additions and 23 deletions

View file

@ -27,7 +27,7 @@ func newMultisigCommands() []cli.Command {
{ {
Name: "sign", Name: "sign",
Usage: "sign a transaction", Usage: "sign a transaction",
UsageText: "multisig sign --path <path> --addr <addr> --in <file.in> --out <file.out>", UsageText: "multisig sign --wallet <path> --addr <addr> --in <file.in> --out <file.out>",
Action: signMultisig, Action: signMultisig,
Flags: signFlags, Flags: signFlags,
}, },

View file

@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"strings"
"github.com/nspcc-dev/neo-go/cli/flags" "github.com/nspcc-dev/neo-go/cli/flags"
"github.com/nspcc-dev/neo-go/cli/options" "github.com/nspcc-dev/neo-go/cli/options"
@ -16,6 +17,11 @@ import (
"github.com/urfave/cli" "github.com/urfave/cli"
) )
var (
neoToken = wallet.NewToken(client.NeoContractHash, "NEO", "neo", 0)
gasToken = wallet.NewToken(client.GasContractHash, "GAS", "gas", 8)
)
func newNEP5Commands() []cli.Command { func newNEP5Commands() []cli.Command {
balanceFlags := []cli.Flag{ balanceFlags := []cli.Flag{
walletPathFlag, walletPathFlag,
@ -60,21 +66,21 @@ func newNEP5Commands() []cli.Command {
{ {
Name: "balance", Name: "balance",
Usage: "get address balance", Usage: "get address balance",
UsageText: "balance --path <path> --rpc-endpoint <node> --timeout <time> --addr <addr> [--token <hash-or-name>]", UsageText: "balance --wallet <path> --rpc-endpoint <node> --timeout <time> --addr <addr> [--token <hash-or-name>]",
Action: getNEP5Balance, Action: getNEP5Balance,
Flags: balanceFlags, Flags: balanceFlags,
}, },
{ {
Name: "import", Name: "import",
Usage: "import NEP5 token to a wallet", Usage: "import NEP5 token to a wallet",
UsageText: "import --path <path> --rpc-endpoint <node> --timeout <time> --token <hash>", UsageText: "import --wallet <path> --rpc-endpoint <node> --timeout <time> --token <hash>",
Action: importNEP5Token, Action: importNEP5Token,
Flags: importFlags, Flags: importFlags,
}, },
{ {
Name: "info", Name: "info",
Usage: "print imported NEP5 token info", Usage: "print imported NEP5 token info",
UsageText: "print --path <path> [--token <hash-or-name>]", UsageText: "print --wallet <path> [--token <hash-or-name>]",
Action: printNEP5Info, Action: printNEP5Info,
Flags: []cli.Flag{ Flags: []cli.Flag{
walletPathFlag, walletPathFlag,
@ -87,7 +93,7 @@ func newNEP5Commands() []cli.Command {
{ {
Name: "remove", Name: "remove",
Usage: "remove NEP5 token from the wallet", Usage: "remove NEP5 token from the wallet",
UsageText: "remove --path <path> <hash-or-name>", UsageText: "remove --wallet <path> <hash-or-name>",
Action: removeNEP5Token, Action: removeNEP5Token,
Flags: []cli.Flag{ Flags: []cli.Flag{
walletPathFlag, walletPathFlag,
@ -101,7 +107,7 @@ func newNEP5Commands() []cli.Command {
{ {
Name: "transfer", Name: "transfer",
Usage: "transfer NEP5 tokens", Usage: "transfer NEP5 tokens",
UsageText: "transfer --path <path> --rpc-endpoint <node> --timeout <time> --from <addr> --to <addr> --token <hash> --amount string", UsageText: "transfer --wallet <path> --rpc-endpoint <node> --timeout <time> --from <addr> --to <addr> --token <hash> --amount string",
Action: transferNEP5, Action: transferNEP5,
Flags: transferFlags, Flags: transferFlags,
}, },
@ -155,7 +161,7 @@ func getNEP5Balance(ctx *cli.Context) error {
if name != "" && !token.Hash.Equals(asset) { if name != "" && !token.Hash.Equals(asset) {
continue continue
} }
fmt.Printf("TokenHash: %s\n", asset) fmt.Printf("TokenHash: %s\n", asset.StringLE())
fmt.Printf("\tAmount : %s\n", balances.Balances[i].Amount) fmt.Printf("\tAmount : %s\n", balances.Balances[i].Amount)
fmt.Printf("\tUpdated: %d\n", balances.Balances[i].LastUpdated) fmt.Printf("\tUpdated: %d\n", balances.Balances[i].LastUpdated)
} }
@ -163,6 +169,12 @@ func getNEP5Balance(ctx *cli.Context) error {
} }
func getMatchingToken(w *wallet.Wallet, name string) (*wallet.Token, error) { func getMatchingToken(w *wallet.Wallet, name string) (*wallet.Token, error) {
switch strings.ToLower(name) {
case "neo":
return neoToken, nil
case "gas":
return gasToken, nil
}
return getMatchingTokenAux(func(i int) *wallet.Token { return getMatchingTokenAux(func(i int) *wallet.Token {
return w.Extra.Tokens[i] return w.Extra.Tokens[i]
}, len(w.Extra.Tokens), name) }, len(w.Extra.Tokens), name)

View file

@ -20,13 +20,13 @@ import (
) )
var ( var (
errNoPath = errors.New("target path where the wallet should be stored is mandatory and should be passed using (--path, -p) flags") errNoPath = errors.New("target path where the wallet should be stored is mandatory and should be passed using (--wallet, -w) flags")
errPhraseMismatch = errors.New("the entered pass-phrases do not match. Maybe you have misspelled them") errPhraseMismatch = errors.New("the entered pass-phrases do not match. Maybe you have misspelled them")
) )
var ( var (
walletPathFlag = cli.StringFlag{ walletPathFlag = cli.StringFlag{
Name: "path, p", Name: "wallet, w",
Usage: "Target location of the wallet file.", Usage: "Target location of the wallet file.",
} }
wifFlag = cli.StringFlag{ wifFlag = cli.StringFlag{
@ -123,7 +123,7 @@ func NewCommands() []cli.Command {
{ {
Name: "export", Name: "export",
Usage: "export keys for address", Usage: "export keys for address",
UsageText: "export --path <path> [--decrypt] [<address>]", UsageText: "export --wallet <path> [--decrypt] [<address>]",
Action: exportKeys, Action: exportKeys,
Flags: []cli.Flag{ Flags: []cli.Flag{
walletPathFlag, walletPathFlag,
@ -150,7 +150,7 @@ func NewCommands() []cli.Command {
{ {
Name: "import-multisig", Name: "import-multisig",
Usage: "import multisig contract", Usage: "import multisig contract",
UsageText: "import-multisig --path <path> --wif <wif> --min <n>" + UsageText: "import-multisig --wallet <path> --wif <wif> --min <n>" +
" [<pubkey1> [<pubkey2> [...]]]", " [<pubkey1> [<pubkey2> [...]]]",
Action: importMultisig, Action: importMultisig,
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -169,7 +169,7 @@ func NewCommands() []cli.Command {
{ {
Name: "remove", Name: "remove",
Usage: "remove an account from the wallet", Usage: "remove an account from the wallet",
UsageText: "remove --path <path> [--force] <addr>", UsageText: "remove --wallet <path> [--force] <addr>",
Action: removeAccount, Action: removeAccount,
Flags: []cli.Flag{ Flags: []cli.Flag{
walletPathFlag, walletPathFlag,

View file

@ -178,6 +178,6 @@ There is a small subset of commands:
## Wallet operations ## Wallet operations
- `./bin/neo-go wallet init -p newWallet` to create new wallet in the path `newWallet` - `./bin/neo-go wallet init -w newWallet` to create new wallet in the path `newWallet`
- `./bin/neo-go wallet dump -p newWallet` to open created wallet in the path `newWallet` - `./bin/neo-go wallet dump -w newWallet` to open created wallet in the path `newWallet`
- `./bin/neo-go wallet init -p newWallet -a` to create new account - `./bin/neo-go wallet init -w newWallet -a` to create new account

View file

@ -13,6 +13,7 @@ import (
coreb "github.com/nspcc-dev/neo-go/pkg/core/block" coreb "github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/blockchainer" "github.com/nspcc-dev/neo-go/pkg/core/blockchainer"
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract"
@ -478,6 +479,15 @@ func (s *service) newBlockFromContext(ctx *dbft.Context) block.Block {
primaryIndex := uint32(ctx.PrimaryIndex) primaryIndex := uint32(ctx.PrimaryIndex)
block.Block.ConsensusData.PrimaryIndex = primaryIndex block.Block.ConsensusData.PrimaryIndex = primaryIndex
block.Block.RebuildMerkleRoot() hashes := make([]util.Uint256, len(ctx.TransactionHashes)+1)
hashes[0] = block.Block.ConsensusData.Hash()
copy(hashes[1:], ctx.TransactionHashes)
mt, err := hash.NewMerkleTree(hashes)
if err != nil {
s.log.Fatal("can't calculate merkle root for the new block")
return nil
}
block.Block.MerkleRoot = mt.Root()
return block return block
} }

View file

@ -16,6 +16,13 @@ import (
"github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/nspcc-dev/neo-go/pkg/wallet"
) )
var (
// NeoContractHash is a hash of the NEO native contract.
NeoContractHash, _ = util.Uint160DecodeStringBE("3b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c")
// GasContractHash is a hash of the GAS native contract.
GasContractHash, _ = util.Uint160DecodeStringBE("897720d8cd76f4f00abfa37c0edd889c208fde9b")
)
// NEP5Decimals invokes `decimals` NEP5 method on a specified contract. // NEP5Decimals invokes `decimals` NEP5 method on a specified contract.
func (c *Client) NEP5Decimals(tokenHash util.Uint160) (int64, error) { func (c *Client) NEP5Decimals(tokenHash util.Uint160) (int64, error) {
result, err := c.InvokeFunction(tokenHash.StringLE(), "decimals", []smartcontract.Parameter{}, nil) result, err := c.InvokeFunction(tokenHash.StringLE(), "decimals", []smartcontract.Parameter{}, nil)

View file

@ -8,6 +8,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/state" "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/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/rpc/request" "github.com/nspcc-dev/neo-go/pkg/rpc/request"
@ -517,14 +518,18 @@ func (c *Client) AddNetworkFee(tx *transaction.Transaction, acc *wallet.Account)
size += sizeDelta size += sizeDelta
} }
for _, cosigner := range tx.Cosigners { for _, cosigner := range tx.Cosigners {
contract, err := c.GetContractState(cosigner.Account) script := acc.Contract.Script
if err != nil { if !cosigner.Account.Equals(hash.Hash160(acc.Contract.Script)) {
return err contract, err := c.GetContractState(cosigner.Account)
if err != nil {
return err
}
if contract == nil {
continue
}
script = contract.Script
} }
if contract == nil { netFee, sizeDelta := core.CalculateNetworkFee(script)
continue
}
netFee, sizeDelta := core.CalculateNetworkFee(contract.Script)
tx.NetworkFee += netFee tx.NetworkFee += netFee
size += sizeDelta size += sizeDelta
} }