mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-29 13:41:47 +00:00
neptoken: add Info to replace old NEPXXTokenInfo methods
I'm still not sure it's good to have this exposed from neptoken at all, but let's try it this way.
This commit is contained in:
parent
a3f32bf306
commit
ed6ed61712
7 changed files with 222 additions and 17 deletions
|
@ -206,7 +206,7 @@ func getNEP11Balance(ctx *cli.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cli.NewExitError(fmt.Errorf("can't fetch matching token from RPC-node: %w", err), 1)
|
return cli.NewExitError(fmt.Errorf("can't fetch matching token from RPC-node: %w", err), 1)
|
||||||
}
|
}
|
||||||
token, err = c.NEP11TokenInfo(tokenHash)
|
token, err = getTokenWithStandard(c, tokenHash, manifest.NEP11StandardName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cli.NewExitError(err.Error(), 1)
|
return cli.NewExitError(err.Error(), 1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/neo"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/neo"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep11"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep11"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/neptoken"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
@ -214,7 +215,7 @@ func getNEP17Balance(ctx *cli.Context) error {
|
||||||
asset := balances.Balances[i].Asset
|
asset := balances.Balances[i].Asset
|
||||||
token, err := getMatchingToken(ctx, wall, asset.StringLE(), manifest.NEP17StandardName)
|
token, err := getMatchingToken(ctx, wall, asset.StringLE(), manifest.NEP17StandardName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
token, err = c.NEP17TokenInfo(asset)
|
token, err = getTokenWithStandard(c, asset, manifest.NEP17StandardName)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if name != "" && !(token.Name == name || token.Symbol == name || token.Address() == name || token.Hash.StringLE() == name) {
|
if name != "" && !(token.Name == name || token.Symbol == name || token.Address() == name || token.Hash.StringLE() == name) {
|
||||||
|
@ -268,7 +269,7 @@ func getNEP17Balance(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
token, err = c.NEP17TokenInfo(h)
|
token, err = getTokenWithStandard(c, h, manifest.NEP17StandardName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -309,7 +310,7 @@ func getMatchingTokenRPC(ctx *cli.Context, c *rpcclient.Client, addr util.Uint16
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
get := func(i int) *wallet.Token {
|
get := func(i int) *wallet.Token {
|
||||||
t, _ := c.NEP17TokenInfo(bs.Balances[i].Asset)
|
t, _ := getTokenWithStandard(c, bs.Balances[i].Asset, standard)
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
return getMatchingTokenAux(ctx, get, len(bs.Balances), name, standard)
|
return getMatchingTokenAux(ctx, get, len(bs.Balances), name, standard)
|
||||||
|
@ -319,7 +320,7 @@ func getMatchingTokenRPC(ctx *cli.Context, c *rpcclient.Client, addr util.Uint16
|
||||||
return nil, fmt.Errorf("valid token adress or hash in LE should be specified for %s RPC-node request: %s", standard, err.Error())
|
return nil, fmt.Errorf("valid token adress or hash in LE should be specified for %s RPC-node request: %s", standard, err.Error())
|
||||||
}
|
}
|
||||||
get := func(i int) *wallet.Token {
|
get := func(i int) *wallet.Token {
|
||||||
t, _ := c.NEP11TokenInfo(tokenHash)
|
t, _ := getTokenWithStandard(c, tokenHash, standard)
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
return getMatchingTokenAux(ctx, get, 1, name, standard)
|
return getMatchingTokenAux(ctx, get, 1, name, standard)
|
||||||
|
@ -383,15 +384,7 @@ func importNEPToken(ctx *cli.Context, standard string) error {
|
||||||
return cli.NewExitError(err, 1)
|
return cli.NewExitError(err, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
var tok *wallet.Token
|
tok, err := getTokenWithStandard(c, tokenHash, standard)
|
||||||
switch standard {
|
|
||||||
case manifest.NEP17StandardName:
|
|
||||||
tok, err = c.NEP17TokenInfo(tokenHash)
|
|
||||||
case manifest.NEP11StandardName:
|
|
||||||
tok, err = c.NEP11TokenInfo(tokenHash)
|
|
||||||
default:
|
|
||||||
return cli.NewExitError(fmt.Sprintf("unsupported token standard: %s", standard), 1)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cli.NewExitError(fmt.Errorf("can't receive token info: %w", err), 1)
|
return cli.NewExitError(fmt.Errorf("can't receive token info: %w", err), 1)
|
||||||
}
|
}
|
||||||
|
@ -404,6 +397,17 @@ func importNEPToken(ctx *cli.Context, standard string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getTokenWithStandard(c *rpcclient.Client, hash util.Uint160, std string) (*wallet.Token, error) {
|
||||||
|
token, err := neptoken.Info(c, hash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if token.Standard != std {
|
||||||
|
return nil, fmt.Errorf("%s is not a %s token", hash.StringLE(), std)
|
||||||
|
}
|
||||||
|
return token, err
|
||||||
|
}
|
||||||
|
|
||||||
func printTokenInfo(ctx *cli.Context, tok *wallet.Token) {
|
func printTokenInfo(ctx *cli.Context, tok *wallet.Token) {
|
||||||
w := ctx.App.Writer
|
w := ctx.App.Writer
|
||||||
fmt.Fprintf(w, "Name:\t%s\n", tok.Name)
|
fmt.Fprintf(w, "Name:\t%s\n", tok.Name)
|
||||||
|
|
|
@ -49,6 +49,9 @@ func (c *Client) NEP11BalanceOf(tokenHash, owner util.Uint160) (int64, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NEP11TokenInfo returns full NEP-11 token info.
|
// NEP11TokenInfo returns full NEP-11 token info.
|
||||||
|
//
|
||||||
|
// Deprecated: please use Info method from the neptoken subpackage. This method
|
||||||
|
// will be removed in future versions.
|
||||||
func (c *Client) NEP11TokenInfo(tokenHash util.Uint160) (*wallet.Token, error) {
|
func (c *Client) NEP11TokenInfo(tokenHash util.Uint160) (*wallet.Token, error) {
|
||||||
return c.nepTokenInfo(tokenHash, manifest.NEP11StandardName)
|
return c.nepTokenInfo(tokenHash, manifest.NEP11StandardName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,9 @@ func (c *Client) NEP17BalanceOf(tokenHash, acc util.Uint160) (int64, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NEP17TokenInfo returns full NEP-17 token info.
|
// NEP17TokenInfo returns full NEP-17 token info.
|
||||||
|
//
|
||||||
|
// Deprecated: please use Info method from the neptoken subpackage. This method
|
||||||
|
// will be removed in future versions.
|
||||||
func (c *Client) NEP17TokenInfo(tokenHash util.Uint160) (*wallet.Token, error) {
|
func (c *Client) NEP17TokenInfo(tokenHash util.Uint160) (*wallet.Token, error) {
|
||||||
return c.nepTokenInfo(tokenHash, manifest.NEP17StandardName)
|
return c.nepTokenInfo(tokenHash, manifest.NEP17StandardName)
|
||||||
}
|
}
|
||||||
|
|
47
pkg/rpcclient/neptoken/info.go
Normal file
47
pkg/rpcclient/neptoken/info.go
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
package neptoken
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// InfoClient is a set of RPC methods required to get all of the NEP-11/NEP-17
|
||||||
|
// token data.
|
||||||
|
type InfoClient interface {
|
||||||
|
invoker.RPCInvoke
|
||||||
|
|
||||||
|
GetContractStateByHash(hash util.Uint160) (*state.Contract, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info allows to get basic token info using RPC client.
|
||||||
|
func Info(c InfoClient, hash util.Uint160) (*wallet.Token, error) {
|
||||||
|
cs, err := c.GetContractStateByHash(hash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var standard string
|
||||||
|
for _, st := range cs.Manifest.SupportedStandards {
|
||||||
|
if st == manifest.NEP17StandardName || st == manifest.NEP11StandardName {
|
||||||
|
standard = st
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if standard == "" {
|
||||||
|
return nil, fmt.Errorf("contract %s is not NEP-11/NEP17", hash.StringLE())
|
||||||
|
}
|
||||||
|
b := New(invoker.New(c, nil), hash)
|
||||||
|
symbol, err := b.Symbol()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
decimals, err := b.Decimals()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return wallet.NewToken(hash, cs.Manifest.Name, symbol, int64(decimals), standard), nil
|
||||||
|
}
|
147
pkg/rpcclient/neptoken/info_test.go
Normal file
147
pkg/rpcclient/neptoken/info_test.go
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
package neptoken
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"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/neorpc/result"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
type rpcClient struct {
|
||||||
|
cnt int
|
||||||
|
cserr error
|
||||||
|
cs *state.Contract
|
||||||
|
inverrs []error
|
||||||
|
invs []*result.Invoke
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rpcClient) InvokeContractVerify(contract util.Uint160, params []smartcontract.Parameter, signers []transaction.Signer, witnesses ...transaction.Witness) (*result.Invoke, error) {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
func (r *rpcClient) InvokeFunction(contract util.Uint160, operation string, params []smartcontract.Parameter, signers []transaction.Signer) (*result.Invoke, error) {
|
||||||
|
e, i := r.inverrs[r.cnt], r.invs[r.cnt]
|
||||||
|
r.cnt = (r.cnt + 1) % len(r.invs)
|
||||||
|
return i, e
|
||||||
|
}
|
||||||
|
func (r *rpcClient) InvokeScript(script []byte, signers []transaction.Signer) (*result.Invoke, error) {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
func (r *rpcClient) TerminateSession(sessionID uuid.UUID) (bool, error) {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
func (r *rpcClient) TraverseIterator(sessionID, iteratorID uuid.UUID, maxItemsCount int) ([]stackitem.Item, error) {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
func (r *rpcClient) GetContractStateByHash(hash util.Uint160) (*state.Contract, error) {
|
||||||
|
return r.cs, r.cserr
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInfo(t *testing.T) {
|
||||||
|
c := &rpcClient{}
|
||||||
|
hash := util.Uint160{1, 2, 3}
|
||||||
|
|
||||||
|
// Error on contract state.
|
||||||
|
c.cserr = errors.New("")
|
||||||
|
_, err := Info(c, hash)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// Error on missing standard.
|
||||||
|
c.cserr = nil
|
||||||
|
c.cs = &state.Contract{
|
||||||
|
ContractBase: state.ContractBase{
|
||||||
|
Manifest: manifest.Manifest{
|
||||||
|
Name: "Vasiliy",
|
||||||
|
SupportedStandards: []string{"RFC 1149"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err = Info(c, hash)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// Error on Symbol()
|
||||||
|
c.cs = &state.Contract{
|
||||||
|
ContractBase: state.ContractBase{
|
||||||
|
Manifest: manifest.Manifest{
|
||||||
|
Name: "Übertoken",
|
||||||
|
SupportedStandards: []string{"NEP-17"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
c.inverrs = []error{errors.New(""), nil}
|
||||||
|
c.invs = []*result.Invoke{nil, nil}
|
||||||
|
_, err = Info(c, hash)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// Error on Decimals()
|
||||||
|
c.cnt = 0
|
||||||
|
c.inverrs[0], c.inverrs[1] = c.inverrs[1], c.inverrs[0]
|
||||||
|
c.invs[0] = &result.Invoke{
|
||||||
|
State: "HALT",
|
||||||
|
Stack: []stackitem.Item{
|
||||||
|
stackitem.Make("UBT"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err = Info(c, hash)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// OK
|
||||||
|
c.cnt = 0
|
||||||
|
c.inverrs[1] = nil
|
||||||
|
c.invs[1] = &result.Invoke{
|
||||||
|
State: "HALT",
|
||||||
|
Stack: []stackitem.Item{
|
||||||
|
stackitem.Make(8),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ti, err := Info(c, hash)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, &wallet.Token{
|
||||||
|
Name: "Übertoken",
|
||||||
|
Hash: hash,
|
||||||
|
Decimals: 8,
|
||||||
|
Symbol: "UBT",
|
||||||
|
Standard: "NEP-17",
|
||||||
|
}, ti)
|
||||||
|
|
||||||
|
// NEP-11
|
||||||
|
c.cs = &state.Contract{
|
||||||
|
ContractBase: state.ContractBase{
|
||||||
|
Manifest: manifest.Manifest{
|
||||||
|
Name: "NFTizer",
|
||||||
|
SupportedStandards: []string{"NEP-11"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
c.cnt = 0
|
||||||
|
c.inverrs[1] = nil
|
||||||
|
c.invs[0] = &result.Invoke{
|
||||||
|
State: "HALT",
|
||||||
|
Stack: []stackitem.Item{
|
||||||
|
stackitem.Make("NZ"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
c.invs[1] = &result.Invoke{
|
||||||
|
State: "HALT",
|
||||||
|
Stack: []stackitem.Item{
|
||||||
|
stackitem.Make(0),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ti, err = Info(c, hash)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, &wallet.Token{
|
||||||
|
Name: "NFTizer",
|
||||||
|
Hash: hash,
|
||||||
|
Decimals: 0,
|
||||||
|
Symbol: "NZ",
|
||||||
|
Standard: "NEP-11",
|
||||||
|
}, ti)
|
||||||
|
}
|
|
@ -36,6 +36,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/neo"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/neo"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep11"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep11"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/neptoken"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/nns"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/nns"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/oracle"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/oracle"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/policy"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/policy"
|
||||||
|
@ -82,7 +83,7 @@ func TestClient_NEP17(t *testing.T) {
|
||||||
require.Equal(t, "RUB", sym)
|
require.Equal(t, "RUB", sym)
|
||||||
})
|
})
|
||||||
t.Run("TokenInfo", func(t *testing.T) {
|
t.Run("TokenInfo", func(t *testing.T) {
|
||||||
tok, err := c.NEP17TokenInfo(h)
|
tok, err := neptoken.Info(c, h)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, h, tok.Hash)
|
require.Equal(t, h, tok.Hash)
|
||||||
require.Equal(t, "Rubl", tok.Name)
|
require.Equal(t, "Rubl", tok.Name)
|
||||||
|
@ -1259,7 +1260,7 @@ func TestClient_NEP11_ND(t *testing.T) {
|
||||||
require.Equal(t, "NNS", sym)
|
require.Equal(t, "NNS", sym)
|
||||||
})
|
})
|
||||||
t.Run("TokenInfo", func(t *testing.T) {
|
t.Run("TokenInfo", func(t *testing.T) {
|
||||||
tok, err := c.NEP11TokenInfo(h)
|
tok, err := neptoken.Info(c, h)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, &wallet.Token{
|
require.Equal(t, &wallet.Token{
|
||||||
Name: "NameService",
|
Name: "NameService",
|
||||||
|
@ -1345,7 +1346,7 @@ func TestClient_NEP11_D(t *testing.T) {
|
||||||
require.Equal(t, "NFSO", sym)
|
require.Equal(t, "NFSO", sym)
|
||||||
})
|
})
|
||||||
t.Run("TokenInfo", func(t *testing.T) {
|
t.Run("TokenInfo", func(t *testing.T) {
|
||||||
tok, err := c.NEP11TokenInfo(nfsoHash)
|
tok, err := neptoken.Info(c, nfsoHash)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, &wallet.Token{
|
require.Equal(t, &wallet.Token{
|
||||||
Name: "NeoFS Object NFT",
|
Name: "NeoFS Object NFT",
|
||||||
|
|
Loading…
Reference in a new issue