mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-23 13:41:37 +00:00
Merge pull request #2315 from nspcc-dev/cli/zero-balance-warning
cli: print zero balance of known token if `token` flag specified
This commit is contained in:
commit
fcbb0aacc2
2 changed files with 78 additions and 8 deletions
|
@ -49,6 +49,16 @@ func TestNEP17Balance(t *testing.T) {
|
|||
b := e.Chain.GetUtilityTokenBalance(validatorHash)
|
||||
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(b.Int64()).String()+"$")
|
||||
})
|
||||
t.Run("zero balance of known token", func(t *testing.T) {
|
||||
e.Run(t, append(cmdbase, []string{"--token", "NEO"}...)...)
|
||||
addr1, err := address.StringToUint160("Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn")
|
||||
require.NoError(t, err)
|
||||
e.checkNextLine(t, "^Account "+address.Uint160ToString(addr1))
|
||||
e.checkNextLine(t, "^\\s*NEO:\\s+NeoToken \\("+e.Chain.GoverningTokenHash().StringLE()+"\\)")
|
||||
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(0).String()+"$")
|
||||
e.checkNextLine(t, "^\\s*Updated:")
|
||||
e.checkNextLine(t, "^\\s*$")
|
||||
})
|
||||
t.Run("all accounts", func(t *testing.T) {
|
||||
e.Run(t, cmdbase...)
|
||||
addr1, err := address.StringToUint160("Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn")
|
||||
|
|
|
@ -11,9 +11,11 @@ import (
|
|||
"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/core/native/nativenames"
|
||||
"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/rpc/client"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
||||
"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"
|
||||
|
@ -188,6 +190,7 @@ func getNEP17Balance(ctx *cli.Context) error {
|
|||
}
|
||||
fmt.Fprintf(ctx.App.Writer, "Account %s\n", acc.Address)
|
||||
|
||||
var tokenFound bool
|
||||
for i := range balances.Balances {
|
||||
var tokenName, tokenSymbol string
|
||||
tokenDecimals := 0
|
||||
|
@ -203,27 +206,84 @@ func getNEP17Balance(ctx *cli.Context) error {
|
|||
tokenName = token.Name
|
||||
tokenSymbol = token.Symbol
|
||||
tokenDecimals = int(token.Decimals)
|
||||
tokenFound = true
|
||||
} else {
|
||||
if name != "" {
|
||||
continue
|
||||
}
|
||||
tokenSymbol = "UNKNOWN"
|
||||
}
|
||||
fmt.Fprintf(ctx.App.Writer, "%s: %s (%s)\n", tokenSymbol, tokenName, asset.StringLE())
|
||||
amount := balances.Balances[i].Amount
|
||||
if tokenDecimals != 0 {
|
||||
b, ok := new(big.Int).SetString(amount, 10)
|
||||
if ok {
|
||||
amount = fixedn.ToString(b, tokenDecimals)
|
||||
printAssetBalance(ctx, asset, tokenName, tokenSymbol, tokenDecimals, balances.Balances[i])
|
||||
}
|
||||
if name == "" || tokenFound {
|
||||
continue
|
||||
}
|
||||
// Token was explicitly specified, but was not found among balances, thus either balance is 0
|
||||
// or the token doesn't exist. Try to find token by its address/hash/name/symbol and print zero
|
||||
// balance if found. Search into wallet first.
|
||||
token, err := getMatchingToken(ctx, wall, name, manifest.NEP17StandardName)
|
||||
if err != nil {
|
||||
// The wallet doesn't contain specified token, so try to ask chain.
|
||||
h, err := flags.ParseAddress(name)
|
||||
if err != nil {
|
||||
h, err = c.GetNativeContractHash(name)
|
||||
if err != nil {
|
||||
// Try to get native NEP17 with matching symbol.
|
||||
var gasSymbol, neoSymbol string
|
||||
gasSymbol, h, err = getNativeNEP17Symbol(c, nativenames.Gas)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if gasSymbol != name {
|
||||
neoSymbol, h, err = getNativeNEP17Symbol(c, nativenames.Neo)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if neoSymbol != name {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(ctx.App.Writer, "\tAmount : %s\n", amount)
|
||||
fmt.Fprintf(ctx.App.Writer, "\tUpdated: %d\n", balances.Balances[i].LastUpdated)
|
||||
token, err = c.NEP17TokenInfo(h)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
printAssetBalance(ctx, token.Hash, token.Name, token.Symbol, int(token.Decimals), result.NEP17Balance{
|
||||
Asset: token.Hash,
|
||||
Amount: "0",
|
||||
LastUpdated: 0,
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func printAssetBalance(ctx *cli.Context, asset util.Uint160, tokenName, tokenSymbol string, tokenDecimals int, balance result.NEP17Balance) {
|
||||
fmt.Fprintf(ctx.App.Writer, "%s: %s (%s)\n", tokenSymbol, tokenName, asset.StringLE())
|
||||
amount := balance.Amount
|
||||
if tokenDecimals != 0 {
|
||||
b, ok := new(big.Int).SetString(amount, 10)
|
||||
if ok {
|
||||
amount = fixedn.ToString(b, tokenDecimals)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(ctx.App.Writer, "\tAmount : %s\n", amount)
|
||||
fmt.Fprintf(ctx.App.Writer, "\tUpdated: %d\n", balance.LastUpdated)
|
||||
}
|
||||
|
||||
func getNativeNEP17Symbol(c *client.Client, name string) (string, util.Uint160, error) {
|
||||
h, err := c.GetNativeContractHash(name)
|
||||
if err != nil {
|
||||
return "", util.Uint160{}, fmt.Errorf("failed to get native %s hash: %w", name, err)
|
||||
}
|
||||
symbol, err := c.NEP17Symbol(h)
|
||||
if err != nil {
|
||||
return "", util.Uint160{}, fmt.Errorf("failed to get native %s symbol: %w", name, err)
|
||||
}
|
||||
return symbol, h, nil
|
||||
}
|
||||
|
||||
func getMatchingToken(ctx *cli.Context, w *wallet.Wallet, name string, standard string) (*wallet.Token, error) {
|
||||
return getMatchingTokenAux(ctx, func(i int) *wallet.Token {
|
||||
return w.Extra.Tokens[i]
|
||||
|
|
Loading…
Reference in a new issue