forked from TrueCloudLab/neoneo-go
cli: implement NEP5 balance querying
This commit is contained in:
parent
519b27fe0e
commit
bcc03e2068
1 changed files with 114 additions and 0 deletions
|
@ -1,8 +1,10 @@
|
||||||
package wallet
|
package wallet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
|
@ -11,6 +13,25 @@ import (
|
||||||
|
|
||||||
func newNEP5Commands() []cli.Command {
|
func newNEP5Commands() []cli.Command {
|
||||||
return []cli.Command{
|
return []cli.Command{
|
||||||
|
{
|
||||||
|
Name: "balance",
|
||||||
|
Usage: "get address balance",
|
||||||
|
UsageText: "balance --path <path> --rpc <node> --addr <addr> [--token <hash-or-name>]",
|
||||||
|
Action: getNEP5Balance,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
walletPathFlag,
|
||||||
|
rpcFlag,
|
||||||
|
timeoutFlag,
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "addr",
|
||||||
|
Usage: "Address to use",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "token",
|
||||||
|
Usage: "Token to use",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "import",
|
Name: "import",
|
||||||
Usage: "import NEP5 token to a wallet",
|
Usage: "import NEP5 token to a wallet",
|
||||||
|
@ -28,6 +49,99 @@ func newNEP5Commands() []cli.Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getNEP5Balance(ctx *cli.Context) error {
|
||||||
|
wall, err := openWallet(ctx.String("path"))
|
||||||
|
if err != nil {
|
||||||
|
return cli.NewExitError(err, 1)
|
||||||
|
}
|
||||||
|
defer wall.Close()
|
||||||
|
|
||||||
|
addr := ctx.String("addr")
|
||||||
|
addrHash, err := address.StringToUint160(addr)
|
||||||
|
if err != nil {
|
||||||
|
return cli.NewExitError(fmt.Errorf("invalid address: %v", err), 1)
|
||||||
|
}
|
||||||
|
acc := wall.GetAccount(addrHash)
|
||||||
|
if acc == nil {
|
||||||
|
return cli.NewExitError(fmt.Errorf("can't find account for the address: %s", addr), 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
gctx, cancel := getGoContext(ctx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
c, err := client.New(gctx, ctx.String("rpc"), client.Options{})
|
||||||
|
if err != nil {
|
||||||
|
return cli.NewExitError(err, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
var token *wallet.Token
|
||||||
|
name := ctx.String("token")
|
||||||
|
if name != "" {
|
||||||
|
token, err = getMatchingToken(wall, name)
|
||||||
|
if err != nil {
|
||||||
|
token, err = getMatchingTokenRPC(c, addrHash, name)
|
||||||
|
if err != nil {
|
||||||
|
return cli.NewExitError(err, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
balances, err := c.GetNEP5Balances(addrHash)
|
||||||
|
if err != nil {
|
||||||
|
return cli.NewExitError(err, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range balances.Balances {
|
||||||
|
asset := balances.Balances[i].Asset
|
||||||
|
if name != "" && !token.Hash.Equals(asset) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Printf("TokenHash: %s\n", asset)
|
||||||
|
fmt.Printf("\tAmount : %s\n", balances.Balances[i].Amount)
|
||||||
|
fmt.Printf("\tUpdated: %d\n", balances.Balances[i].LastUpdated)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMatchingToken(w *wallet.Wallet, name string) (*wallet.Token, error) {
|
||||||
|
return getMatchingTokenAux(func(i int) *wallet.Token {
|
||||||
|
return w.Extra.Tokens[i]
|
||||||
|
}, len(w.Extra.Tokens), name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMatchingTokenRPC(c *client.Client, addr util.Uint160, name string) (*wallet.Token, error) {
|
||||||
|
bs, err := c.GetNEP5Balances(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
get := func(i int) *wallet.Token {
|
||||||
|
t, _ := c.NEP5TokenInfo(bs.Balances[i].Asset)
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
return getMatchingTokenAux(get, len(bs.Balances), name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMatchingTokenAux(get func(i int) *wallet.Token, n int, name string) (*wallet.Token, error) {
|
||||||
|
var token *wallet.Token
|
||||||
|
var count int
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
t := get(i)
|
||||||
|
if t != nil && (t.Name == name || t.Symbol == name || t.Address == name || t.Hash.StringLE() == name) {
|
||||||
|
if count == 1 {
|
||||||
|
printTokenInfo(token)
|
||||||
|
printTokenInfo(t)
|
||||||
|
return nil, errors.New("multiple matching tokens found")
|
||||||
|
}
|
||||||
|
count++
|
||||||
|
token = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if count == 0 {
|
||||||
|
return nil, errors.New("token was not found")
|
||||||
|
}
|
||||||
|
return token, nil
|
||||||
|
}
|
||||||
|
|
||||||
func importNEP5Token(ctx *cli.Context) error {
|
func importNEP5Token(ctx *cli.Context) error {
|
||||||
wall, err := openWallet(ctx.String("path"))
|
wall, err := openWallet(ctx.String("path"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue