Merge pull request #2792 from nspcc-dev/rpcwrapper-arrays
RPC wrapper for simple arrays
This commit is contained in:
commit
c67ee54566
8 changed files with 419 additions and 1 deletions
|
@ -365,6 +365,44 @@ func TestGenerateRPCBindings(t *testing.T) {
|
||||||
filepath.Join("testdata", "nonepiter", "iter.go"))
|
filepath.Join("testdata", "nonepiter", "iter.go"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAssistedRPCBindings(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
app := cli.NewApp()
|
||||||
|
app.Commands = NewCommands()
|
||||||
|
|
||||||
|
var checkBinding = func(source string) {
|
||||||
|
t.Run(source, func(t *testing.T) {
|
||||||
|
manifestF := filepath.Join(tmpDir, "manifest.json")
|
||||||
|
bindingF := filepath.Join(tmpDir, "binding.yml")
|
||||||
|
nefF := filepath.Join(tmpDir, "out.nef")
|
||||||
|
require.NoError(t, app.Run([]string{"", "contract", "compile",
|
||||||
|
"--in", source,
|
||||||
|
"--config", filepath.Join(source, "config.yml"),
|
||||||
|
"--manifest", manifestF,
|
||||||
|
"--bindings", bindingF,
|
||||||
|
"--out", nefF,
|
||||||
|
}))
|
||||||
|
outFile := filepath.Join(tmpDir, "out.go")
|
||||||
|
require.NoError(t, app.Run([]string{"", "contract", "generate-rpcwrapper",
|
||||||
|
"--config", bindingF,
|
||||||
|
"--manifest", manifestF,
|
||||||
|
"--out", outFile,
|
||||||
|
"--hash", "0x00112233445566778899aabbccddeeff00112233",
|
||||||
|
}))
|
||||||
|
|
||||||
|
data, err := os.ReadFile(outFile)
|
||||||
|
require.NoError(t, err)
|
||||||
|
data = bytes.ReplaceAll(data, []byte("\r"), []byte{}) // Windows.
|
||||||
|
expected, err := os.ReadFile(filepath.Join(source, "rpcbindings.out"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
expected = bytes.ReplaceAll(expected, []byte("\r"), []byte{}) // Windows.
|
||||||
|
require.Equal(t, string(expected), string(data))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
checkBinding(filepath.Join("testdata", "types"))
|
||||||
|
}
|
||||||
|
|
||||||
func TestGenerate_Errors(t *testing.T) {
|
func TestGenerate_Errors(t *testing.T) {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Commands = []cli.Command{generateWrapperCmd}
|
app.Commands = []cli.Command{generateWrapperCmd}
|
||||||
|
|
3
cli/smartcontract/testdata/types/config.yml
vendored
Normal file
3
cli/smartcontract/testdata/types/config.yml
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
name: "Types"
|
||||||
|
sourceurl: https://github.com/nspcc-dev/neo-go/
|
||||||
|
safemethods: ["bool", "int", "bytes", "string", "hash160", "hash256", "publicKey", "signature", "bools", "ints", "bytess", "strings", "hash160s", "hash256s", "publicKeys", "signatures"]
|
109
cli/smartcontract/testdata/types/rpcbindings.out
vendored
Normal file
109
cli/smartcontract/testdata/types/rpcbindings.out
vendored
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// Package types contains RPC wrappers for Types contract.
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Hash contains contract hash.
|
||||||
|
var Hash = util.Uint160{0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x0}
|
||||||
|
|
||||||
|
// Invoker is used by ContractReader to call various safe methods.
|
||||||
|
type Invoker interface {
|
||||||
|
Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContractReader implements safe contract methods.
|
||||||
|
type ContractReader struct {
|
||||||
|
invoker Invoker
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewReader creates an instance of ContractReader using Hash and the given Invoker.
|
||||||
|
func NewReader(invoker Invoker) *ContractReader {
|
||||||
|
return &ContractReader{invoker}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Bool invokes `bool` method of contract.
|
||||||
|
func (c *ContractReader) Bool(b bool) (bool, error) {
|
||||||
|
return unwrap.Bool(c.invoker.Call(Hash, "bool", b))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bools invokes `bools` method of contract.
|
||||||
|
func (c *ContractReader) Bools(b []bool) ([]bool, error) {
|
||||||
|
return unwrap.ArrayOfBools(c.invoker.Call(Hash, "bools", b))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes invokes `bytes` method of contract.
|
||||||
|
func (c *ContractReader) Bytes(b []byte) ([]byte, error) {
|
||||||
|
return unwrap.Bytes(c.invoker.Call(Hash, "bytes", b))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytess invokes `bytess` method of contract.
|
||||||
|
func (c *ContractReader) Bytess(b [][]byte) ([][]byte, error) {
|
||||||
|
return unwrap.ArrayOfBytes(c.invoker.Call(Hash, "bytess", b))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash160 invokes `hash160` method of contract.
|
||||||
|
func (c *ContractReader) Hash160(h util.Uint160) (util.Uint160, error) {
|
||||||
|
return unwrap.Uint160(c.invoker.Call(Hash, "hash160", h))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash160s invokes `hash160s` method of contract.
|
||||||
|
func (c *ContractReader) Hash160s(h []util.Uint160) ([]util.Uint160, error) {
|
||||||
|
return unwrap.ArrayOfUint160(c.invoker.Call(Hash, "hash160s", h))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash256 invokes `hash256` method of contract.
|
||||||
|
func (c *ContractReader) Hash256(h util.Uint256) (util.Uint256, error) {
|
||||||
|
return unwrap.Uint256(c.invoker.Call(Hash, "hash256", h))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash256s invokes `hash256s` method of contract.
|
||||||
|
func (c *ContractReader) Hash256s(h []util.Uint256) ([]util.Uint256, error) {
|
||||||
|
return unwrap.ArrayOfUint256(c.invoker.Call(Hash, "hash256s", h))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int invokes `int` method of contract.
|
||||||
|
func (c *ContractReader) Int(i *big.Int) (*big.Int, error) {
|
||||||
|
return unwrap.BigInt(c.invoker.Call(Hash, "int", i))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ints invokes `ints` method of contract.
|
||||||
|
func (c *ContractReader) Ints(i []*big.Int) ([]*big.Int, error) {
|
||||||
|
return unwrap.ArrayOfBigInts(c.invoker.Call(Hash, "ints", i))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PublicKey invokes `publicKey` method of contract.
|
||||||
|
func (c *ContractReader) PublicKey(k *keys.PublicKey) (*keys.PublicKey, error) {
|
||||||
|
return unwrap.PublicKey(c.invoker.Call(Hash, "publicKey", k))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PublicKeys invokes `publicKeys` method of contract.
|
||||||
|
func (c *ContractReader) PublicKeys(k keys.PublicKeys) (keys.PublicKeys, error) {
|
||||||
|
return unwrap.ArrayOfPublicKeys(c.invoker.Call(Hash, "publicKeys", k))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signature invokes `signature` method of contract.
|
||||||
|
func (c *ContractReader) Signature(s []byte) ([]byte, error) {
|
||||||
|
return unwrap.Bytes(c.invoker.Call(Hash, "signature", s))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signatures invokes `signatures` method of contract.
|
||||||
|
func (c *ContractReader) Signatures(s [][]byte) ([][]byte, error) {
|
||||||
|
return unwrap.ArrayOfBytes(c.invoker.Call(Hash, "signatures", s))
|
||||||
|
}
|
||||||
|
|
||||||
|
// String invokes `string` method of contract.
|
||||||
|
func (c *ContractReader) String(s string) (string, error) {
|
||||||
|
return unwrap.UTF8String(c.invoker.Call(Hash, "string", s))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strings invokes `strings` method of contract.
|
||||||
|
func (c *ContractReader) Strings(s []string) ([]string, error) {
|
||||||
|
return unwrap.ArrayOfUTF8Strings(c.invoker.Call(Hash, "strings", s))
|
||||||
|
}
|
69
cli/smartcontract/testdata/types/types.go
vendored
Normal file
69
cli/smartcontract/testdata/types/types.go
vendored
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/interop"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Bool(b bool) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func Int(i int) int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func Bytes(b []byte) []byte {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func String(s string) string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func Hash160(h interop.Hash160) interop.Hash160 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Hash256(h interop.Hash256) interop.Hash256 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func PublicKey(k interop.PublicKey) interop.PublicKey {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Signature(s interop.Signature) interop.Signature {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Bools(b []bool) []bool {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Ints(i []int) []int {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Bytess(b [][]byte) [][]byte {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Strings(s []string) []string {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Hash160s(h []interop.Hash160) []interop.Hash160 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Hash256s(h []interop.Hash256) []interop.Hash256 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func PublicKeys(k []interop.PublicKey) []interop.PublicKey {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Signatures(s []interop.Signature) []interop.Signature {
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -446,6 +446,10 @@ does not do anything else unless the method's returned value is of a boolean
|
||||||
type, in this case an ASSERT is added to script making it fail when the method
|
type, in this case an ASSERT is added to script making it fail when the method
|
||||||
returns false.
|
returns false.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./bin/neo-go contract generate-rpcwrapper --manifest manifest.json --out rpcwrapper.go --hash 0x1b4357bff5a01bdf2a6581247cf9ed1e24629176
|
||||||
|
```
|
||||||
|
|
||||||
If your contract is NEP-11 or NEP-17 that's autodetected and an appropriate
|
If your contract is NEP-11 or NEP-17 that's autodetected and an appropriate
|
||||||
package is included as well. Notice that the type data available in the
|
package is included as well. Notice that the type data available in the
|
||||||
manifest is limited, so in some cases the interface generated may use generic
|
manifest is limited, so in some cases the interface generated may use generic
|
||||||
|
@ -454,8 +458,13 @@ iterator and an appropriate unwrapper is used with UUID and iterator structure
|
||||||
result. This pair can then be used in Invoker `TraverseIterator` method to
|
result. This pair can then be used in Invoker `TraverseIterator` method to
|
||||||
retrieve actual resulting items.
|
retrieve actual resulting items.
|
||||||
|
|
||||||
|
Go contracts can also make use of additional type data from bindings
|
||||||
|
configuration file generated during compilation. At the moment it allows to
|
||||||
|
generate proper wrappers for simple array types, but doesn't cover structures:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ ./bin/neo-go contract generate-rpcwrapper --manifest manifest.json --out rpcwrapper.go --hash 0x1b4357bff5a01bdf2a6581247cf9ed1e24629176
|
$ ./bin/neo-go contract compile -i contract.go --config contract.yml -o contract.nef --manifest manifest.json --bindings contract.bindings.yml
|
||||||
|
$ ./bin/neo-go contract generate-rpcwrapper --manifest manifest.json --config contract.bindings.yml --out rpcwrapper.go --hash 0x1b4357bff5a01bdf2a6581247cf9ed1e24629176
|
||||||
```
|
```
|
||||||
|
|
||||||
## Smart contract examples
|
## Smart contract examples
|
||||||
|
|
|
@ -196,6 +196,42 @@ func Array(r *result.Invoke, err error) ([]stackitem.Item, error) {
|
||||||
return arr, nil
|
return arr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArrayOfBools checks the result for correct state (HALT) and then extracts a
|
||||||
|
// slice of boolean values from the returned stack item.
|
||||||
|
func ArrayOfBools(r *result.Invoke, err error) ([]bool, error) {
|
||||||
|
a, err := Array(r, err)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := make([]bool, len(a))
|
||||||
|
for i := range a {
|
||||||
|
b, err := a[i].TryBool()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("element %d is not a boolean: %w", i, err)
|
||||||
|
}
|
||||||
|
res[i] = b
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArrayOfBigInts checks the result for correct state (HALT) and then extracts a
|
||||||
|
// slice of (big) integer values from the returned stack item.
|
||||||
|
func ArrayOfBigInts(r *result.Invoke, err error) ([]*big.Int, error) {
|
||||||
|
a, err := Array(r, err)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := make([]*big.Int, len(a))
|
||||||
|
for i := range a {
|
||||||
|
v, err := a[i].TryInteger()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("element %d is not an integer: %w", i, err)
|
||||||
|
}
|
||||||
|
res[i] = v
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ArrayOfBytes checks the result for correct state (HALT) and then extracts a
|
// ArrayOfBytes checks the result for correct state (HALT) and then extracts a
|
||||||
// slice of byte slices from the returned stack item.
|
// slice of byte slices from the returned stack item.
|
||||||
func ArrayOfBytes(r *result.Invoke, err error) ([][]byte, error) {
|
func ArrayOfBytes(r *result.Invoke, err error) ([][]byte, error) {
|
||||||
|
@ -214,6 +250,27 @@ func ArrayOfBytes(r *result.Invoke, err error) ([][]byte, error) {
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArrayOfUTB8Strings checks the result for correct state (HALT) and then extracts a
|
||||||
|
// slice of UTF-8 strings from the returned stack item.
|
||||||
|
func ArrayOfUTF8Strings(r *result.Invoke, err error) ([]string, error) {
|
||||||
|
a, err := Array(r, err)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := make([]string, len(a))
|
||||||
|
for i := range a {
|
||||||
|
b, err := a[i].TryBytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("element %d is not a byte string: %w", i, err)
|
||||||
|
}
|
||||||
|
if !utf8.Valid(b) {
|
||||||
|
return nil, fmt.Errorf("element %d is not a UTF-8 string", i)
|
||||||
|
}
|
||||||
|
res[i] = string(b)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ArrayOfUint160 checks the result for correct state (HALT) and then extracts a
|
// ArrayOfUint160 checks the result for correct state (HALT) and then extracts a
|
||||||
// slice of util.Uint160 from the returned stack item.
|
// slice of util.Uint160 from the returned stack item.
|
||||||
func ArrayOfUint160(r *result.Invoke, err error) ([]util.Uint160, error) {
|
func ArrayOfUint160(r *result.Invoke, err error) ([]util.Uint160, error) {
|
||||||
|
@ -236,6 +293,28 @@ func ArrayOfUint160(r *result.Invoke, err error) ([]util.Uint160, error) {
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArrayOfUint256 checks the result for correct state (HALT) and then extracts a
|
||||||
|
// slice of util.Uint256 from the returned stack item.
|
||||||
|
func ArrayOfUint256(r *result.Invoke, err error) ([]util.Uint256, error) {
|
||||||
|
a, err := Array(r, err)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := make([]util.Uint256, len(a))
|
||||||
|
for i := range a {
|
||||||
|
b, err := a[i].TryBytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("element %d is not a byte string: %w", i, err)
|
||||||
|
}
|
||||||
|
u, err := util.Uint256DecodeBytesBE(b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("element %d is not a uint256: %w", i, err)
|
||||||
|
}
|
||||||
|
res[i] = u
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ArrayOfPublicKeys checks the result for correct state (HALT) and then
|
// ArrayOfPublicKeys checks the result for correct state (HALT) and then
|
||||||
// extracts a slice of public keys from the returned stack item.
|
// extracts a slice of public keys from the returned stack item.
|
||||||
func ArrayOfPublicKeys(r *result.Invoke, err error) (keys.PublicKeys, error) {
|
func ArrayOfPublicKeys(r *result.Invoke, err error) (keys.PublicKeys, error) {
|
||||||
|
|
|
@ -53,9 +53,24 @@ func TestStdErrors(t *testing.T) {
|
||||||
func(r *result.Invoke, err error) (interface{}, error) {
|
func(r *result.Invoke, err error) (interface{}, error) {
|
||||||
return Array(r, err)
|
return Array(r, err)
|
||||||
},
|
},
|
||||||
|
func(r *result.Invoke, err error) (interface{}, error) {
|
||||||
|
return ArrayOfBools(r, err)
|
||||||
|
},
|
||||||
|
func(r *result.Invoke, err error) (interface{}, error) {
|
||||||
|
return ArrayOfBigInts(r, err)
|
||||||
|
},
|
||||||
func(r *result.Invoke, err error) (interface{}, error) {
|
func(r *result.Invoke, err error) (interface{}, error) {
|
||||||
return ArrayOfBytes(r, err)
|
return ArrayOfBytes(r, err)
|
||||||
},
|
},
|
||||||
|
func(r *result.Invoke, err error) (interface{}, error) {
|
||||||
|
return ArrayOfUTF8Strings(r, err)
|
||||||
|
},
|
||||||
|
func(r *result.Invoke, err error) (interface{}, error) {
|
||||||
|
return ArrayOfUint160(r, err)
|
||||||
|
},
|
||||||
|
func(r *result.Invoke, err error) (interface{}, error) {
|
||||||
|
return ArrayOfUint256(r, err)
|
||||||
|
},
|
||||||
func(r *result.Invoke, err error) (interface{}, error) {
|
func(r *result.Invoke, err error) (interface{}, error) {
|
||||||
return ArrayOfPublicKeys(r, err)
|
return ArrayOfPublicKeys(r, err)
|
||||||
},
|
},
|
||||||
|
@ -233,6 +248,32 @@ func TestArray(t *testing.T) {
|
||||||
require.Equal(t, stackitem.Make(42), a[0])
|
require.Equal(t, stackitem.Make(42), a[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestArrayOfBools(t *testing.T) {
|
||||||
|
_, err := ArrayOfBools(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
_, err = ArrayOfBools(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make("reallybigstringthatcantbeanumberandthuscantbeconvertedtobool")})}}, nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
a, err := ArrayOfBools(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make(true)})}}, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(a))
|
||||||
|
require.Equal(t, true, a[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestArrayOfBigInts(t *testing.T) {
|
||||||
|
_, err := ArrayOfBigInts(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
_, err = ArrayOfBigInts(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]stackitem.Item{})})}}, nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
a, err := ArrayOfBigInts(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make(42)})}}, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(a))
|
||||||
|
require.Equal(t, big.NewInt(42), a[0])
|
||||||
|
}
|
||||||
|
|
||||||
func TestArrayOfBytes(t *testing.T) {
|
func TestArrayOfBytes(t *testing.T) {
|
||||||
_, err := ArrayOfBytes(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
|
_, err := ArrayOfBytes(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
@ -246,6 +287,22 @@ func TestArrayOfBytes(t *testing.T) {
|
||||||
require.Equal(t, []byte("some"), a[0])
|
require.Equal(t, []byte("some"), a[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestArrayOfUTF8Strings(t *testing.T) {
|
||||||
|
_, err := ArrayOfUTF8Strings(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
_, err = ArrayOfUTF8Strings(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]stackitem.Item{})})}}, nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
_, err = ArrayOfUTF8Strings(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]byte{0, 0xff})})}}, nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
a, err := ArrayOfUTF8Strings(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make("some")})}}, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(a))
|
||||||
|
require.Equal(t, "some", a[0])
|
||||||
|
}
|
||||||
|
|
||||||
func TestArrayOfUint160(t *testing.T) {
|
func TestArrayOfUint160(t *testing.T) {
|
||||||
_, err := ArrayOfUint160(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
|
_, err := ArrayOfUint160(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
@ -263,6 +320,23 @@ func TestArrayOfUint160(t *testing.T) {
|
||||||
require.Equal(t, u160, uints[0])
|
require.Equal(t, u160, uints[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestArrayOfUint256(t *testing.T) {
|
||||||
|
_, err := ArrayOfUint256(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
_, err = ArrayOfUint256(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]stackitem.Item{})})}}, nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
_, err = ArrayOfUint256(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]byte("some"))})}}, nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
u256 := util.Uint256{1, 2, 3}
|
||||||
|
uints, err := ArrayOfUint256(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make(u256.BytesBE())})}}, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(uints))
|
||||||
|
require.Equal(t, u256, uints[0])
|
||||||
|
}
|
||||||
|
|
||||||
func TestArrayOfPublicKeys(t *testing.T) {
|
func TestArrayOfPublicKeys(t *testing.T) {
|
||||||
_, err := ArrayOfPublicKeys(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
|
_, err := ArrayOfPublicKeys(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
|
@ -296,6 +296,29 @@ func dropStdMethods(meths []manifest.Method, std *standard.Standard) []manifest.
|
||||||
}
|
}
|
||||||
|
|
||||||
func scTypeToGo(name string, typ smartcontract.ParamType, overrides map[string]binding.Override) (string, string) {
|
func scTypeToGo(name string, typ smartcontract.ParamType, overrides map[string]binding.Override) (string, string) {
|
||||||
|
over, ok := overrides[name]
|
||||||
|
if ok {
|
||||||
|
switch over.TypeName {
|
||||||
|
case "[]bool":
|
||||||
|
return "[]bool", ""
|
||||||
|
case "[]int", "[]uint", "[]int8", "[]uint8", "[]int16",
|
||||||
|
"[]uint16", "[]int32", "[]uint32", "[]int64", "[]uint64":
|
||||||
|
return "[]*big.Int", "math/big"
|
||||||
|
case "[][]byte":
|
||||||
|
return "[][]byte", ""
|
||||||
|
case "[]string":
|
||||||
|
return "[]string", ""
|
||||||
|
case "[]interop.Hash160":
|
||||||
|
return "[]util.Uint160", "github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
case "[]interop.Hash256":
|
||||||
|
return "[]util.Uint256", "github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
case "[]interop.PublicKey":
|
||||||
|
return "keys.PublicKeys", "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
case "[]interop.Signature":
|
||||||
|
return "[][]byte", ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch typ {
|
switch typ {
|
||||||
case smartcontract.AnyType:
|
case smartcontract.AnyType:
|
||||||
return "interface{}", ""
|
return "interface{}", ""
|
||||||
|
@ -383,6 +406,20 @@ func scTemplateToRPC(cfg binding.Config, ctr ContractTmpl, imports map[string]st
|
||||||
ctr.SafeMethods[i].CallFlag = "Array"
|
ctr.SafeMethods[i].CallFlag = "Array"
|
||||||
case "*stackitem.Map":
|
case "*stackitem.Map":
|
||||||
ctr.SafeMethods[i].CallFlag = "Map"
|
ctr.SafeMethods[i].CallFlag = "Map"
|
||||||
|
case "[]bool":
|
||||||
|
ctr.SafeMethods[i].CallFlag = "ArrayOfBools"
|
||||||
|
case "[]*big.Int":
|
||||||
|
ctr.SafeMethods[i].CallFlag = "ArrayOfBigInts"
|
||||||
|
case "[][]byte":
|
||||||
|
ctr.SafeMethods[i].CallFlag = "ArrayOfBytes"
|
||||||
|
case "[]string":
|
||||||
|
ctr.SafeMethods[i].CallFlag = "ArrayOfUTF8Strings"
|
||||||
|
case "[]util.Uint160":
|
||||||
|
ctr.SafeMethods[i].CallFlag = "ArrayOfUint160"
|
||||||
|
case "[]util.Uint256":
|
||||||
|
ctr.SafeMethods[i].CallFlag = "ArrayOfUint256"
|
||||||
|
case "keys.PublicKeys":
|
||||||
|
ctr.SafeMethods[i].CallFlag = "ArrayOfPublicKeys"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue