forked from TrueCloudLab/neoneo-go
rpcclient: add enough of NNS into nns to deprecate NNS methods
This commit is contained in:
parent
bf06b32278
commit
0d9158bd79
6 changed files with 428 additions and 27 deletions
|
@ -31,6 +31,8 @@ func (c *Client) GetOraclePrice() (int64, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNNSPrice invokes `getPrice` method on a NeoNameService contract with the specified hash.
|
// GetNNSPrice invokes `getPrice` method on a NeoNameService contract with the specified hash.
|
||||||
|
//
|
||||||
|
// Deprecated: please use nns subpackage. This method will be removed in future versions.
|
||||||
func (c *Client) GetNNSPrice(nnsHash util.Uint160) (int64, error) {
|
func (c *Client) GetNNSPrice(nnsHash util.Uint160) (int64, error) {
|
||||||
return c.invokeNativeGetMethod(nnsHash, "getPrice")
|
return c.invokeNativeGetMethod(nnsHash, "getPrice")
|
||||||
}
|
}
|
||||||
|
@ -84,6 +86,8 @@ func (c *Client) GetDesignatedByRole(role noderoles.Role, index uint32) (keys.Pu
|
||||||
}
|
}
|
||||||
|
|
||||||
// NNSResolve invokes `resolve` method on a NameService contract with the specified hash.
|
// NNSResolve invokes `resolve` method on a NameService contract with the specified hash.
|
||||||
|
//
|
||||||
|
// Deprecated: please use nns subpackage. This method will be removed in future versions.
|
||||||
func (c *Client) NNSResolve(nnsHash util.Uint160, name string, typ nns.RecordType) (string, error) {
|
func (c *Client) NNSResolve(nnsHash util.Uint160, name string, typ nns.RecordType) (string, error) {
|
||||||
if typ == nns.CNAME {
|
if typ == nns.CNAME {
|
||||||
return "", errors.New("can't resolve CNAME record type")
|
return "", errors.New("can't resolve CNAME record type")
|
||||||
|
@ -92,6 +96,8 @@ func (c *Client) NNSResolve(nnsHash util.Uint160, name string, typ nns.RecordTyp
|
||||||
}
|
}
|
||||||
|
|
||||||
// NNSIsAvailable invokes `isAvailable` method on a NeoNameService contract with the specified hash.
|
// NNSIsAvailable invokes `isAvailable` method on a NeoNameService contract with the specified hash.
|
||||||
|
//
|
||||||
|
// Deprecated: please use nns subpackage. This method will be removed in future versions.
|
||||||
func (c *Client) NNSIsAvailable(nnsHash util.Uint160, name string) (bool, error) {
|
func (c *Client) NNSIsAvailable(nnsHash util.Uint160, name string) (bool, error) {
|
||||||
return unwrap.Bool(c.reader.Call(nnsHash, "isAvailable", name))
|
return unwrap.Bool(c.reader.Call(nnsHash, "isAvailable", name))
|
||||||
}
|
}
|
||||||
|
@ -101,6 +107,8 @@ func (c *Client) NNSIsAvailable(nnsHash util.Uint160, name string) (bool, error)
|
||||||
// third one is an error. Use TraverseIterator method to traverse iterator values or
|
// third one is an error. Use TraverseIterator method to traverse iterator values or
|
||||||
// TerminateSession to terminate opened iterator session. See TraverseIterator and
|
// TerminateSession to terminate opened iterator session. See TraverseIterator and
|
||||||
// TerminateSession documentation for more details.
|
// TerminateSession documentation for more details.
|
||||||
|
//
|
||||||
|
// Deprecated: please use nns subpackage. This method will be removed in future versions.
|
||||||
func (c *Client) NNSGetAllRecords(nnsHash util.Uint160, name string) (uuid.UUID, result.Iterator, error) {
|
func (c *Client) NNSGetAllRecords(nnsHash util.Uint160, name string) (uuid.UUID, result.Iterator, error) {
|
||||||
return unwrap.SessionIterator(c.reader.Call(nnsHash, "getAllRecords", name))
|
return unwrap.SessionIterator(c.reader.Call(nnsHash, "getAllRecords", name))
|
||||||
}
|
}
|
||||||
|
@ -109,6 +117,8 @@ func (c *Client) NNSGetAllRecords(nnsHash util.Uint160, name string) (uuid.UUID,
|
||||||
// (config.DefaultMaxIteratorResultItems at max). It differs from NNSGetAllRecords in
|
// (config.DefaultMaxIteratorResultItems at max). It differs from NNSGetAllRecords in
|
||||||
// that no iterator session is used to retrieve values from iterator. Instead, unpacking
|
// that no iterator session is used to retrieve values from iterator. Instead, unpacking
|
||||||
// VM script is created and invoked via `invokescript` JSON-RPC call.
|
// VM script is created and invoked via `invokescript` JSON-RPC call.
|
||||||
|
//
|
||||||
|
// Deprecated: please use nns subpackage. This method will be removed in future versions.
|
||||||
func (c *Client) NNSUnpackedGetAllRecords(nnsHash util.Uint160, name string) ([]nns.RecordState, error) {
|
func (c *Client) NNSUnpackedGetAllRecords(nnsHash util.Uint160, name string) ([]nns.RecordState, error) {
|
||||||
arr, err := unwrap.Array(c.reader.CallAndExpandIterator(nnsHash, "getAllRecords", config.DefaultMaxIteratorResultItems, name))
|
arr, err := unwrap.Array(c.reader.CallAndExpandIterator(nnsHash, "getAllRecords", config.DefaultMaxIteratorResultItems, name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
122
pkg/rpcclient/nns/contract.go
Normal file
122
pkg/rpcclient/nns/contract.go
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
Package nns provide some RPC wrappers for the non-native NNS contract.
|
||||||
|
|
||||||
|
It's not yet a complete interface because there are different NNS versions
|
||||||
|
available, yet it provides the most widely used ones that were available from
|
||||||
|
the old RPC client API.
|
||||||
|
*/
|
||||||
|
package nns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"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"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Invoker is used by ContractReader to call various methods.
|
||||||
|
type Invoker interface {
|
||||||
|
Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error)
|
||||||
|
CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...interface{}) (*result.Invoke, error)
|
||||||
|
TerminateSession(sessionID uuid.UUID) error
|
||||||
|
TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContractReader provides an interface to call read-only NNS contract methods.
|
||||||
|
type ContractReader struct {
|
||||||
|
invoker Invoker
|
||||||
|
hash util.Uint160
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordIterator is used for iterating over GetAllRecords results.
|
||||||
|
type RecordIterator struct {
|
||||||
|
client Invoker
|
||||||
|
session uuid.UUID
|
||||||
|
iterator result.Iterator
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewReader creates an instance of ContractReader that can be used to read
|
||||||
|
// data from the contract.
|
||||||
|
func NewReader(invoker Invoker, hash util.Uint160) *ContractReader {
|
||||||
|
return &ContractReader{invoker, hash}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPrice returns current domain registration price in GAS.
|
||||||
|
func (c *ContractReader) GetPrice() (int64, error) {
|
||||||
|
return unwrap.Int64(c.invoker.Call(c.hash, "getPrice"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAvailable checks whether the domain given is available for registration.
|
||||||
|
func (c *ContractReader) IsAvailable(name string) (bool, error) {
|
||||||
|
return unwrap.Bool(c.invoker.Call(c.hash, "isAvailable", name))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve resolves the given record type for the given domain (with no more
|
||||||
|
// than three redirects).
|
||||||
|
func (c *ContractReader) Resolve(name string, typ RecordType) (string, error) {
|
||||||
|
return unwrap.UTF8String(c.invoker.Call(c.hash, "resolve", name, int64(typ)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAllRecords returns an iterator that allows to retrieve all RecordState
|
||||||
|
// items for the given domain name. It depends on the server to provide proper
|
||||||
|
// session-based iterator, but can also work with expanded one.
|
||||||
|
func (c *ContractReader) GetAllRecords(name string) (*RecordIterator, error) {
|
||||||
|
sess, iter, err := unwrap.SessionIterator(c.invoker.Call(c.hash, "getAllRecords", name))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &RecordIterator{
|
||||||
|
client: c.invoker,
|
||||||
|
iterator: iter,
|
||||||
|
session: sess,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next returns the next set of elements from the iterator (up to num of them).
|
||||||
|
// It can return less than num elements in case iterator doesn't have that many
|
||||||
|
// or zero elements if the iterator has no more elements or the session is
|
||||||
|
// expired.
|
||||||
|
func (r *RecordIterator) Next(num int) ([]RecordState, error) {
|
||||||
|
items, err := r.client.TraverseIterator(r.session, &r.iterator, num)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return itemsToRecords(items)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Terminate closes the iterator session used by RecordIterator (if it's
|
||||||
|
// session-based).
|
||||||
|
func (r *RecordIterator) Terminate() error {
|
||||||
|
if r.iterator.ID == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return r.client.TerminateSession(r.session)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAllRecordsExpanded is similar to GetAllRecords (uses the same NNS
|
||||||
|
// method), but can be useful if the server used doesn't support sessions and
|
||||||
|
// doesn't expand iterators. It creates a script that will get num of result
|
||||||
|
// items from the iterator right in the VM and return them to you. It's only
|
||||||
|
// limited by VM stack and GAS available for RPC invocations.
|
||||||
|
func (c *ContractReader) GetAllRecordsExpanded(name string, num int) ([]RecordState, error) {
|
||||||
|
arr, err := unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "getAllRecords", num, name))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return itemsToRecords(arr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func itemsToRecords(arr []stackitem.Item) ([]RecordState, error) {
|
||||||
|
res := make([]RecordState, len(arr))
|
||||||
|
for i := range arr {
|
||||||
|
err := res[i].FromStackItem(arr[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("item #%d: %w", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
197
pkg/rpcclient/nns/contract_test.go
Normal file
197
pkg/rpcclient/nns/contract_test.go
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
package nns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
type testAct struct {
|
||||||
|
err error
|
||||||
|
res *result.Invoke
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *testAct) Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) {
|
||||||
|
return t.res, t.err
|
||||||
|
}
|
||||||
|
func (t *testAct) CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...interface{}) (*result.Invoke, error) {
|
||||||
|
return t.res, t.err
|
||||||
|
}
|
||||||
|
func (t *testAct) TerminateSession(sessionID uuid.UUID) error {
|
||||||
|
return t.err
|
||||||
|
}
|
||||||
|
func (t *testAct) TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error) {
|
||||||
|
return t.res.Stack, t.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSimpleGetters(t *testing.T) {
|
||||||
|
ta := &testAct{}
|
||||||
|
nns := NewReader(ta, util.Uint160{1, 2, 3})
|
||||||
|
|
||||||
|
ta.err = errors.New("")
|
||||||
|
_, err := nns.GetPrice()
|
||||||
|
require.Error(t, err)
|
||||||
|
_, err = nns.IsAvailable("nspcc.neo")
|
||||||
|
require.Error(t, err)
|
||||||
|
_, err = nns.Resolve("nspcc.neo", A)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
ta.err = nil
|
||||||
|
ta.res = &result.Invoke{
|
||||||
|
State: "HALT",
|
||||||
|
Stack: []stackitem.Item{
|
||||||
|
stackitem.Make(100500),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
price, err := nns.GetPrice()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, int64(100500), price)
|
||||||
|
|
||||||
|
ta.res = &result.Invoke{
|
||||||
|
State: "HALT",
|
||||||
|
Stack: []stackitem.Item{
|
||||||
|
stackitem.Make(true),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ava, err := nns.IsAvailable("nspcc.neo")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, true, ava)
|
||||||
|
|
||||||
|
ta.res = &result.Invoke{
|
||||||
|
State: "HALT",
|
||||||
|
Stack: []stackitem.Item{
|
||||||
|
stackitem.Make("some text"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
txt, err := nns.Resolve("nspcc.neo", TXT)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "some text", txt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetAllRecords(t *testing.T) {
|
||||||
|
ta := &testAct{}
|
||||||
|
nns := NewReader(ta, util.Uint160{1, 2, 3})
|
||||||
|
|
||||||
|
ta.err = errors.New("")
|
||||||
|
_, err := nns.GetAllRecords("nspcc.neo")
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
ta.err = nil
|
||||||
|
iid := uuid.New()
|
||||||
|
ta.res = &result.Invoke{
|
||||||
|
State: "HALT",
|
||||||
|
Stack: []stackitem.Item{
|
||||||
|
stackitem.NewInterop(result.Iterator{
|
||||||
|
ID: &iid,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err = nns.GetAllRecords("nspcc.neo")
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// Session-based iterator.
|
||||||
|
sid := uuid.New()
|
||||||
|
ta.res = &result.Invoke{
|
||||||
|
Session: sid,
|
||||||
|
State: "HALT",
|
||||||
|
Stack: []stackitem.Item{
|
||||||
|
stackitem.NewInterop(result.Iterator{
|
||||||
|
ID: &iid,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
iter, err := nns.GetAllRecords("nspcc.neo")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
ta.res = &result.Invoke{
|
||||||
|
Stack: []stackitem.Item{
|
||||||
|
stackitem.Make([]stackitem.Item{
|
||||||
|
stackitem.Make("n3"),
|
||||||
|
stackitem.Make(16),
|
||||||
|
stackitem.Make("cool"),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
vals, err := iter.Next(10)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(vals))
|
||||||
|
require.Equal(t, RecordState{
|
||||||
|
Name: "n3",
|
||||||
|
Type: TXT,
|
||||||
|
Data: "cool",
|
||||||
|
}, vals[0])
|
||||||
|
|
||||||
|
ta.err = errors.New("")
|
||||||
|
_, err = iter.Next(1)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
err = iter.Terminate()
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// Value-based iterator.
|
||||||
|
ta.err = nil
|
||||||
|
ta.res = &result.Invoke{
|
||||||
|
State: "HALT",
|
||||||
|
Stack: []stackitem.Item{
|
||||||
|
stackitem.NewInterop(result.Iterator{
|
||||||
|
Values: []stackitem.Item{
|
||||||
|
stackitem.Make("n3"),
|
||||||
|
stackitem.Make(16),
|
||||||
|
stackitem.Make("cool"),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
iter, err = nns.GetAllRecords("nspcc.neo")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
ta.err = errors.New("")
|
||||||
|
err = iter.Terminate()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetAllRecordsExpanded(t *testing.T) {
|
||||||
|
ta := &testAct{}
|
||||||
|
nns := NewReader(ta, util.Uint160{1, 2, 3})
|
||||||
|
|
||||||
|
ta.err = errors.New("")
|
||||||
|
_, err := nns.GetAllRecordsExpanded("nspcc.neo", 8)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
ta.err = nil
|
||||||
|
ta.res = &result.Invoke{
|
||||||
|
State: "HALT",
|
||||||
|
Stack: []stackitem.Item{
|
||||||
|
stackitem.Make(42),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err = nns.GetAllRecordsExpanded("nspcc.neo", 8)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
ta.res = &result.Invoke{
|
||||||
|
State: "HALT",
|
||||||
|
Stack: []stackitem.Item{
|
||||||
|
stackitem.Make([]stackitem.Item{
|
||||||
|
stackitem.Make([]stackitem.Item{
|
||||||
|
stackitem.Make("n3"),
|
||||||
|
stackitem.Make(16),
|
||||||
|
stackitem.Make("cool"),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
vals, err := nns.GetAllRecordsExpanded("nspcc.neo", 8)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(vals))
|
||||||
|
require.Equal(t, RecordState{
|
||||||
|
Name: "n3",
|
||||||
|
Type: TXT,
|
||||||
|
Data: "cool",
|
||||||
|
}, vals[0])
|
||||||
|
}
|
|
@ -1,5 +1,12 @@
|
||||||
package nns
|
package nns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
)
|
||||||
|
|
||||||
// RecordState is a type that registered entities are saved as.
|
// RecordState is a type that registered entities are saved as.
|
||||||
type RecordState struct {
|
type RecordState struct {
|
||||||
Name string
|
Name string
|
||||||
|
@ -25,3 +32,35 @@ const (
|
||||||
// AAAA represents IPv6 address record type.
|
// AAAA represents IPv6 address record type.
|
||||||
AAAA RecordType = 28
|
AAAA RecordType = 28
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FromStackItem fills RecordState with data from the given stack item if it can
|
||||||
|
// be correctly converted to RecordState.
|
||||||
|
func (r *RecordState) FromStackItem(itm stackitem.Item) error {
|
||||||
|
rs, ok := itm.Value().([]stackitem.Item)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("not a struct")
|
||||||
|
}
|
||||||
|
if len(rs) != 3 {
|
||||||
|
return errors.New("wrong number of elements")
|
||||||
|
}
|
||||||
|
name, err := rs[0].TryBytes()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("bad name: %w", err)
|
||||||
|
}
|
||||||
|
typ, err := rs[1].TryInteger()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("bad type: %w", err)
|
||||||
|
}
|
||||||
|
data, err := rs[2].TryBytes()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("bad data: %w", err)
|
||||||
|
}
|
||||||
|
u64Typ := typ.Uint64()
|
||||||
|
if !typ.IsUint64() || u64Typ > 255 {
|
||||||
|
return errors.New("bad type")
|
||||||
|
}
|
||||||
|
r.Name = string(name)
|
||||||
|
r.Type = RecordType(u64Typ)
|
||||||
|
r.Data = string(data)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
39
pkg/rpcclient/nns/record_test.go
Normal file
39
pkg/rpcclient/nns/record_test.go
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
package nns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRecordStateFromStackItem(t *testing.T) {
|
||||||
|
r := &RecordState{}
|
||||||
|
require.Error(t, r.FromStackItem(stackitem.Make(42)))
|
||||||
|
require.Error(t, r.FromStackItem(stackitem.Make([]stackitem.Item{})))
|
||||||
|
require.Error(t, r.FromStackItem(stackitem.Make([]stackitem.Item{
|
||||||
|
stackitem.Make([]stackitem.Item{}),
|
||||||
|
stackitem.Make(16),
|
||||||
|
stackitem.Make("cool"),
|
||||||
|
})))
|
||||||
|
require.Error(t, r.FromStackItem(stackitem.Make([]stackitem.Item{
|
||||||
|
stackitem.Make("n3"),
|
||||||
|
stackitem.Make([]stackitem.Item{}),
|
||||||
|
stackitem.Make("cool"),
|
||||||
|
})))
|
||||||
|
require.Error(t, r.FromStackItem(stackitem.Make([]stackitem.Item{
|
||||||
|
stackitem.Make("n3"),
|
||||||
|
stackitem.Make(16),
|
||||||
|
stackitem.Make([]stackitem.Item{}),
|
||||||
|
})))
|
||||||
|
require.Error(t, r.FromStackItem(stackitem.Make([]stackitem.Item{
|
||||||
|
stackitem.Make("n3"),
|
||||||
|
stackitem.Make(100500),
|
||||||
|
stackitem.Make("cool"),
|
||||||
|
})))
|
||||||
|
require.NoError(t, r.FromStackItem(stackitem.Make([]stackitem.Item{
|
||||||
|
stackitem.Make("n3"),
|
||||||
|
stackitem.Make(16),
|
||||||
|
stackitem.Make("cool"),
|
||||||
|
})))
|
||||||
|
}
|
|
@ -1402,51 +1402,45 @@ func TestClient_NNS(t *testing.T) {
|
||||||
c, err := rpcclient.New(context.Background(), httpSrv.URL, rpcclient.Options{})
|
c, err := rpcclient.New(context.Background(), httpSrv.URL, rpcclient.Options{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, c.Init())
|
require.NoError(t, c.Init())
|
||||||
|
nnc := nns.NewReader(invoker.New(c, nil), nnsHash)
|
||||||
|
|
||||||
t.Run("NNSIsAvailable, false", func(t *testing.T) {
|
t.Run("IsAvailable, false", func(t *testing.T) {
|
||||||
b, err := c.NNSIsAvailable(nnsHash, "neo.com")
|
b, err := nnc.IsAvailable("neo.com")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, false, b)
|
require.Equal(t, false, b)
|
||||||
})
|
})
|
||||||
t.Run("NNSIsAvailable, true", func(t *testing.T) {
|
t.Run("IsAvailable, true", func(t *testing.T) {
|
||||||
b, err := c.NNSIsAvailable(nnsHash, "neogo.com")
|
b, err := nnc.IsAvailable("neogo.com")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, true, b)
|
require.Equal(t, true, b)
|
||||||
})
|
})
|
||||||
t.Run("NNSResolve, good", func(t *testing.T) {
|
t.Run("Resolve, good", func(t *testing.T) {
|
||||||
b, err := c.NNSResolve(nnsHash, "neo.com", nns.A)
|
b, err := nnc.Resolve("neo.com", nns.A)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, "1.2.3.4", b)
|
require.Equal(t, "1.2.3.4", b)
|
||||||
})
|
})
|
||||||
t.Run("NNSResolve, bad", func(t *testing.T) {
|
t.Run("Resolve, bad", func(t *testing.T) {
|
||||||
_, err := c.NNSResolve(nnsHash, "neogo.com", nns.A)
|
_, err := nnc.Resolve("neogo.com", nns.A)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
})
|
})
|
||||||
t.Run("NNSResolve, forbidden", func(t *testing.T) {
|
t.Run("Resolve, CNAME", func(t *testing.T) {
|
||||||
_, err := c.NNSResolve(nnsHash, "neogo.com", nns.CNAME)
|
_, err := nnc.Resolve("neogo.com", nns.CNAME)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
})
|
})
|
||||||
t.Run("NNSGetAllRecords, good", func(t *testing.T) {
|
t.Run("GetAllRecords, good", func(t *testing.T) {
|
||||||
sess, iter, err := c.NNSGetAllRecords(nnsHash, "neo.com")
|
iter, err := nnc.GetAllRecords("neo.com")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
arr, err := c.TraverseIterator(sess, *iter.ID, config.DefaultMaxIteratorResultItems)
|
arr, err := iter.Next(config.DefaultMaxIteratorResultItems)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 1, len(arr))
|
require.Equal(t, 1, len(arr))
|
||||||
rs := arr[0].Value().([]stackitem.Item)
|
|
||||||
require.Equal(t, 3, len(rs))
|
|
||||||
actual := nns.RecordState{
|
|
||||||
Name: string(rs[0].Value().([]byte)),
|
|
||||||
Type: nns.RecordType(rs[1].Value().(*big.Int).Int64()),
|
|
||||||
Data: string(rs[2].Value().([]byte)),
|
|
||||||
}
|
|
||||||
require.Equal(t, nns.RecordState{
|
require.Equal(t, nns.RecordState{
|
||||||
Name: "neo.com",
|
Name: "neo.com",
|
||||||
Type: nns.A,
|
Type: nns.A,
|
||||||
Data: "1.2.3.4",
|
Data: "1.2.3.4",
|
||||||
}, actual)
|
}, arr[0])
|
||||||
})
|
})
|
||||||
t.Run("NNSUnpackedGetAllRecords, good", func(t *testing.T) {
|
t.Run("GetAllRecordsExpanded, good", func(t *testing.T) {
|
||||||
rss, err := c.NNSUnpackedGetAllRecords(nnsHash, "neo.com")
|
rss, err := nnc.GetAllRecordsExpanded("neo.com", 42)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, []nns.RecordState{
|
require.Equal(t, []nns.RecordState{
|
||||||
{
|
{
|
||||||
|
@ -1456,12 +1450,12 @@ func TestClient_NNS(t *testing.T) {
|
||||||
},
|
},
|
||||||
}, rss)
|
}, rss)
|
||||||
})
|
})
|
||||||
t.Run("NNSGetAllRecords, bad", func(t *testing.T) {
|
t.Run("GetAllRecords, bad", func(t *testing.T) {
|
||||||
_, _, err := c.NNSGetAllRecords(nnsHash, "neopython.com")
|
_, err := nnc.GetAllRecords("neopython.com")
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
})
|
})
|
||||||
t.Run("NNSUnpackedGetAllRecords, bad", func(t *testing.T) {
|
t.Run("GetAllRecordsExpanded, bad", func(t *testing.T) {
|
||||||
_, err := c.NNSUnpackedGetAllRecords(nnsHash, "neopython.com")
|
_, err := nnc.GetAllRecordsExpanded("neopython.com", 7)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue