rpc: accept NEP11 token IDs as []byte for client methods

Accepting IDs as string is encoding-ambiguous, so make it []byte instead.
This commit is contained in:
Anna Shaleva 2022-02-09 11:55:07 +03:00
parent 91350c3a48
commit 47652643df
4 changed files with 28 additions and 22 deletions

View file

@ -110,6 +110,12 @@ func topIterableFromStack(st []stackitem.Item, resultItemType interface{}) ([]in
result := make([]interface{}, len(iter.Values)) result := make([]interface{}, len(iter.Values))
for i := range iter.Values { for i := range iter.Values {
switch resultItemType.(type) { switch resultItemType.(type) {
case []byte:
bytes, err := iter.Values[i].TryBytes()
if err != nil {
return nil, fmt.Errorf("failed to deserialize []byte from stackitem #%d: %w", i, err)
}
result[i] = bytes
case string: case string:
bytes, err := iter.Values[i].TryBytes() bytes, err := iter.Values[i].TryBytes()
if err != nil { if err != nil {

View file

@ -51,15 +51,15 @@ func (c *Client) nepTotalSupply(tokenHash util.Uint160) (int64, error) {
} }
// nepBalanceOf invokes `balanceOf` NEP* method on a specified contract. // nepBalanceOf invokes `balanceOf` NEP* method on a specified contract.
func (c *Client) nepBalanceOf(tokenHash, acc util.Uint160, tokenID *string) (int64, error) { func (c *Client) nepBalanceOf(tokenHash, acc util.Uint160, tokenID []byte) (int64, error) {
params := []smartcontract.Parameter{{ params := []smartcontract.Parameter{{
Type: smartcontract.Hash160Type, Type: smartcontract.Hash160Type,
Value: acc, Value: acc,
}} }}
if tokenID != nil { if tokenID != nil {
params = append(params, smartcontract.Parameter{ params = append(params, smartcontract.Parameter{
Type: smartcontract.StringType, Type: smartcontract.ByteArrayType,
Value: *tokenID, Value: tokenID,
}) })
} }
result, err := c.InvokeFunction(tokenHash, "balanceOf", params, nil) result, err := c.InvokeFunction(tokenHash, "balanceOf", params, nil)

View file

@ -86,7 +86,7 @@ func (c *Client) CreateNEP11TransferTx(acc *wallet.Account, tokenHash util.Uint1
} }
// NEP11TokensOf returns an array of token IDs for the specified owner of the specified NFT token. // NEP11TokensOf returns an array of token IDs for the specified owner of the specified NFT token.
func (c *Client) NEP11TokensOf(tokenHash util.Uint160, owner util.Uint160) ([]string, error) { func (c *Client) NEP11TokensOf(tokenHash util.Uint160, owner util.Uint160) ([][]byte, error) {
result, err := c.InvokeFunction(tokenHash, "tokensOf", []smartcontract.Parameter{ result, err := c.InvokeFunction(tokenHash, "tokensOf", []smartcontract.Parameter{
{ {
Type: smartcontract.Hash160Type, Type: smartcontract.Hash160Type,
@ -101,13 +101,13 @@ func (c *Client) NEP11TokensOf(tokenHash util.Uint160, owner util.Uint160) ([]st
return nil, err return nil, err
} }
arr, err := topIterableFromStack(result.Stack, string("")) arr, err := topIterableFromStack(result.Stack, []byte{})
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get token IDs from stack: %w", err) return nil, fmt.Errorf("failed to get token IDs from stack: %w", err)
} }
ids := make([]string, len(arr)) ids := make([][]byte, len(arr))
for i := range ids { for i := range ids {
ids[i] = arr[i].(string) ids[i] = arr[i].([]byte)
} }
return ids, nil return ids, nil
} }
@ -116,10 +116,10 @@ func (c *Client) NEP11TokensOf(tokenHash util.Uint160, owner util.Uint160) ([]st
// NEP11NDOwnerOf invokes `ownerOf` non-devisible NEP-11 method with the // NEP11NDOwnerOf invokes `ownerOf` non-devisible NEP-11 method with the
// specified token ID on a specified contract. // specified token ID on a specified contract.
func (c *Client) NEP11NDOwnerOf(tokenHash util.Uint160, tokenID string) (util.Uint160, error) { func (c *Client) NEP11NDOwnerOf(tokenHash util.Uint160, tokenID []byte) (util.Uint160, error) {
result, err := c.InvokeFunction(tokenHash, "ownerOf", []smartcontract.Parameter{ result, err := c.InvokeFunction(tokenHash, "ownerOf", []smartcontract.Parameter{
{ {
Type: smartcontract.StringType, Type: smartcontract.ByteArrayType,
Value: tokenID, Value: tokenID,
}, },
}, nil) }, nil)
@ -143,7 +143,7 @@ func (c *Client) NEP11NDOwnerOf(tokenHash util.Uint160, tokenID string) (util.Ui
// (in FixedN format using contract's number of decimals) to given account and // (in FixedN format using contract's number of decimals) to given account and
// sends it to the network returning just a hash of it. // sends it to the network returning just a hash of it.
func (c *Client) TransferNEP11D(acc *wallet.Account, to util.Uint160, func (c *Client) TransferNEP11D(acc *wallet.Account, to util.Uint160,
tokenHash util.Uint160, amount int64, tokenID string, data interface{}, gas int64, cosigners []SignerAccount) (util.Uint256, error) { tokenHash util.Uint160, amount int64, tokenID []byte, data interface{}, gas int64, cosigners []SignerAccount) (util.Uint256, error) {
if !c.initDone { if !c.initDone {
return util.Uint256{}, errNetworkNotInitialized return util.Uint256{}, errNetworkNotInitialized
} }
@ -161,15 +161,15 @@ func (c *Client) TransferNEP11D(acc *wallet.Account, to util.Uint160,
// NEP11DBalanceOf invokes `balanceOf` divisible NEP-11 method on a // NEP11DBalanceOf invokes `balanceOf` divisible NEP-11 method on a
// specified contract. // specified contract.
func (c *Client) NEP11DBalanceOf(tokenHash, owner util.Uint160, tokenID string) (int64, error) { func (c *Client) NEP11DBalanceOf(tokenHash, owner util.Uint160, tokenID []byte) (int64, error) {
return c.nepBalanceOf(tokenHash, owner, &tokenID) return c.nepBalanceOf(tokenHash, owner, tokenID)
} }
// NEP11DOwnerOf returns list of the specified NEP-11 divisible token owners. // NEP11DOwnerOf returns list of the specified NEP-11 divisible token owners.
func (c *Client) NEP11DOwnerOf(tokenHash util.Uint160, tokenID string) ([]util.Uint160, error) { func (c *Client) NEP11DOwnerOf(tokenHash util.Uint160, tokenID []byte) ([]util.Uint160, error) {
result, err := c.InvokeFunction(tokenHash, "ownerOf", []smartcontract.Parameter{ result, err := c.InvokeFunction(tokenHash, "ownerOf", []smartcontract.Parameter{
{ {
Type: smartcontract.StringType, Type: smartcontract.ByteArrayType,
Value: tokenID, Value: tokenID,
}, },
}, nil) }, nil)
@ -198,9 +198,9 @@ func (c *Client) NEP11DOwnerOf(tokenHash util.Uint160, tokenID string) ([]util.U
// NEP11Properties invokes `properties` optional NEP-11 method on a // NEP11Properties invokes `properties` optional NEP-11 method on a
// specified contract. // specified contract.
func (c *Client) NEP11Properties(tokenHash util.Uint160, tokenID string) (*stackitem.Map, error) { func (c *Client) NEP11Properties(tokenHash util.Uint160, tokenID []byte) (*stackitem.Map, error) {
result, err := c.InvokeFunction(tokenHash, "properties", []smartcontract.Parameter{{ result, err := c.InvokeFunction(tokenHash, "properties", []smartcontract.Parameter{{
Type: smartcontract.StringType, Type: smartcontract.ByteArrayType,
Value: tokenID, Value: tokenID,
}}, nil) }}, nil)
if err != nil { if err != nil {
@ -215,7 +215,7 @@ func (c *Client) NEP11Properties(tokenHash util.Uint160, tokenID string) (*stack
} }
// NEP11Tokens returns list of the tokens minted by the contract. // NEP11Tokens returns list of the tokens minted by the contract.
func (c *Client) NEP11Tokens(tokenHash util.Uint160) ([]string, error) { func (c *Client) NEP11Tokens(tokenHash util.Uint160) ([][]byte, error) {
result, err := c.InvokeFunction(tokenHash, "tokens", []smartcontract.Parameter{}, nil) result, err := c.InvokeFunction(tokenHash, "tokens", []smartcontract.Parameter{}, nil)
if err != nil { if err != nil {
return nil, err return nil, err
@ -225,13 +225,13 @@ func (c *Client) NEP11Tokens(tokenHash util.Uint160) ([]string, error) {
return nil, err return nil, err
} }
arr, err := topIterableFromStack(result.Stack, string("")) arr, err := topIterableFromStack(result.Stack, []byte{})
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get token IDs from stack: %w", err) return nil, fmt.Errorf("failed to get token IDs from stack: %w", err)
} }
tokens := make([]string, len(arr)) tokens := make([][]byte, len(arr))
for i := range tokens { for i := range tokens {
tokens[i] = arr[i].(string) tokens[i] = arr[i].([]byte)
} }
return tokens, nil return tokens, nil
} }

View file

@ -846,12 +846,12 @@ func TestClient_NEP11(t *testing.T) {
require.EqualValues(t, 1, b) require.EqualValues(t, 1, b)
}) })
t.Run("OwnerOf", func(t *testing.T) { t.Run("OwnerOf", func(t *testing.T) {
b, err := c.NEP11NDOwnerOf(h, "neo.com") b, err := c.NEP11NDOwnerOf(h, []byte("neo.com"))
require.NoError(t, err) require.NoError(t, err)
require.EqualValues(t, acc, b) require.EqualValues(t, acc, b)
}) })
t.Run("Properties", func(t *testing.T) { t.Run("Properties", func(t *testing.T) {
p, err := c.NEP11Properties(h, "neo.com") p, err := c.NEP11Properties(h, []byte("neo.com"))
require.NoError(t, err) require.NoError(t, err)
blockRegisterDomain, err := chain.GetBlock(chain.GetHeaderHash(14)) // `neo.com` domain was registered in 14th block blockRegisterDomain, err := chain.GetBlock(chain.GetHeaderHash(14)) // `neo.com` domain was registered in 14th block
require.NoError(t, err) require.NoError(t, err)