forked from TrueCloudLab/frostfs-contract
[#48] Add commonclient package
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
parent
5cc810096f
commit
b76f592095
3 changed files with 118 additions and 0 deletions
20
commonclient/invoker.go
Normal file
20
commonclient/invoker.go
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
package commonclient
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Invoker is a subset of methods provided by struct invoker.Invoker. The subset contains only those
|
||||||
|
// methods that are used by ActorWrapper and clients of the contracts.
|
||||||
|
type Invoker interface {
|
||||||
|
Call(contract util.Uint160, method string, params ...any) (*result.Invoke, error)
|
||||||
|
TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error)
|
||||||
|
TerminateSession(sessionID uuid.UUID) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the interface is compatible with the invoker.Invoker struct.
|
||||||
|
var _ Invoker = (*invoker.Invoker)(nil)
|
35
commonclient/iterator.go
Normal file
35
commonclient/iterator.go
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
package commonclient
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReadIteratorItems calls method that returns iterator and traverses the iterator until all items are read into array.
|
||||||
|
func ReadIteratorItems(inv Invoker, batchSize int, contract util.Uint160, method string, params ...any) ([]stackitem.Item, error) {
|
||||||
|
if batchSize <= 0 {
|
||||||
|
panic("batch size must be positive")
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionID, iter, err := unwrap.SessionIterator(inv.Call(contract, method, params...))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unwrap session iterator: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var shouldStop bool
|
||||||
|
res := make([]stackitem.Item, 0, len(iter.Values))
|
||||||
|
for !shouldStop {
|
||||||
|
items, err := inv.TraverseIterator(sessionID, &iter, batchSize)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res = append(res, items...)
|
||||||
|
shouldStop = len(items) < batchSize
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
63
commonclient/transaction.go
Normal file
63
commonclient/transaction.go
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
package commonclient
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Transaction allows to invoke several contract method at once.
|
||||||
|
type Transaction struct {
|
||||||
|
writer *io.BufBinWriter
|
||||||
|
buffer *io.BufBinWriter
|
||||||
|
contract util.Uint160
|
||||||
|
}
|
||||||
|
|
||||||
|
var ErrTransactionTooLarge = errors.New("transaction/script size limit exceeded")
|
||||||
|
|
||||||
|
// NewTransaction creates new transaction to accumulate contract invocations.
|
||||||
|
func NewTransaction(contractHash util.Uint160) *Transaction {
|
||||||
|
return &Transaction{
|
||||||
|
writer: io.NewBufBinWriter(),
|
||||||
|
buffer: io.NewBufBinWriter(),
|
||||||
|
contract: contractHash,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapCall accept methods and arguments to invoke.
|
||||||
|
// Should be used with method on clients like Client.MethodNameCall.
|
||||||
|
func (t Transaction) WrapCall(method string, args []any) error {
|
||||||
|
t.buffer.Reset()
|
||||||
|
emit.AppCall(t.buffer.BinWriter, t.contract, method, callflag.All, args...)
|
||||||
|
|
||||||
|
if t.writer.Len()+t.buffer.Len() > transaction.MaxScriptLength {
|
||||||
|
return ErrTransactionTooLarge
|
||||||
|
}
|
||||||
|
|
||||||
|
t.writer.WriteBytes(t.buffer.Bytes())
|
||||||
|
|
||||||
|
return t.writer.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapCallErr accept methods, arguments and error to handle and invoke.
|
||||||
|
// Should be used with method on clients like *CallErr.
|
||||||
|
func (t Transaction) WrapCallErr(method string, args []any, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return t.WrapCall(method, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes returns the resulting buffer and makes future writes return an error.
|
||||||
|
func (t Transaction) Bytes() ([]byte, error) {
|
||||||
|
if t.writer.Len() > transaction.MaxScriptLength {
|
||||||
|
return nil, ErrTransactionTooLarge
|
||||||
|
}
|
||||||
|
|
||||||
|
return t.writer.Bytes(), nil
|
||||||
|
}
|
Loading…
Reference in a new issue