diff --git a/.github/workflows/config/.golangci.yml b/.github/workflows/config/.golangci.yml new file mode 100644 index 00000000..1fda7f2a --- /dev/null +++ b/.github/workflows/config/.golangci.yml @@ -0,0 +1,5 @@ +issues: + exclude-rules: + - path: ./rpc + linters: + - unused # RPC bindings are allowed to contain some unused convertors. diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index e590eecc..1eccd1b3 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -18,6 +18,7 @@ jobs: uses: golangci/golangci-lint-action@v3 with: version: latest + args: --config=.github/workflows/config/.golangci.yml tests: name: Tests @@ -38,7 +39,7 @@ jobs: run: go test -v ./... build: - name: Build + name: Build contracts and RPC bindings runs-on: ubuntu-latest strategy: matrix: @@ -52,5 +53,17 @@ jobs: with: go-version: '${{ matrix.go_versions }}' - - name: Compile contracts + - name: Clear built RPC bindings + run: make mr_proper + + - name: Compile contracts and build RPC bindings run: make build + + - name: Check that fresh version of RPC bindings is committed (for minimum supported Go version only) + if: ${{ matrix.go_versions == '1.18' }} + run: | + if [[ $(git diff --name-only | grep '^rpc/*' -c) != 0 ]]; then + echo "Fresh version of RPC bindings should be committed for the following contracts:"; + git diff --name-only; + exit 1; + fi diff --git a/.gitignore b/.gitignore index b5ef81d9..bf0ca221 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ *.avm *.nef -*.manifest.json +bindings_config.yml config.json /vendor/ .idea diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e896bec..667b0851 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,15 +4,16 @@ Changelog for NeoFS Contract ## [Unreleased] ### Added -- bump minimum required go version up to 1.18 +- bump minimum required go version up to 1.18 (#346) +- RPC bindings generation (#345) ### Updated ### Removed -- old unused (notary-disabled) events +- old unused (notary-disabled) events (#341) ### Fixed -- migration of non-notary network to notarized one with stale votes +- migration of non-notary network to notarized one with stale votes (#333) ### Updating from v0.17.0 diff --git a/Makefile b/Makefile index f0ec107c..e52be04d 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ export GOBIN ?= $(shell pwd)/bin export CGO_ENABLED=0 NEOGO ?= $(GOBIN)/cli VERSION ?= $(shell git describe --tags --dirty --match "v*" --always --abbrev=8 2>/dev/null || cat VERSION 2>/dev/null || echo "develop") -NEOGOORIGMOD = github.com/nspcc-dev/neo-go +NEOGOORIGMOD = github.com/nspcc-dev/neo-go@v0.101.5-0.20230802075307-afa4530c7d73 NEOGOMOD = $(shell go list -f '{{.Path}}' -m $(NEOGOORIGMOD)) NEOGOVER = $(shell go list -f '{{.Version}}' -m $(NEOGOORIGMOD) | tr -d v) @@ -31,7 +31,9 @@ nns_sc = nns define sc_template $(2)$(1)/$(1)_contract.nef: $(2)$(1)/$(1)_contract.go - $(NEOGO) contract compile -i $(2)$(1) -c $(if $(2),$(2),$(1)/)config.yml -m $(2)$(1)/config.json -o $(2)$(1)/$(1)_contract.nef + $(NEOGO) contract compile -i $(2)$(1) -c $(if $(2),$(2),$(1)/)config.yml -m $(2)$(1)/config.json -o $(2)$(1)/$(1)_contract.nef --bindings $(2)$(1)/bindings_config.yml + mkdir -p rpc/$(1) + $(NEOGO) contract generate-rpcwrapper -o rpc/$(1)/rpcbinding.go -m $(2)$(1)/config.json --config $(2)$(1)/bindings_config.yml $(if $(2),$(2)$(1)/$(1)_contract.go: alphabet/alphabet.go alphabet/alphabet.tpl go run alphabet/alphabet.go @@ -57,6 +59,8 @@ test: clean: find . -name '*.nef' -exec rm -rf {} \; find . -name 'config.json' -exec rm -rf {} \; + find . -name 'bindings_config.yml' -exec rm -rf {} \; + find . -name 'rpc' -type d -prune -exec rm -rf {} \; rm -rf ./bin/ mr_proper: clean diff --git a/README.md b/README.md index d7175fd4..0c44fc89 100644 --- a/README.md +++ b/README.md @@ -37,28 +37,21 @@ Sidechain contracts: To compile smart contracts you need: -- [neo-go](https://github.com/nspcc-dev/neo-go) >= 0.99.2 +- [neo-go](https://github.com/nspcc-dev/neo-go) >= 0.102.0 ## Compilation To build and compile smart contract, run `make all` command. Compiled contracts `*_contract.nef` and manifest `config.json` files are placed in the -corresponding directories. +corresponding directories. Generated RPC binding files `rpcbinding.go` are +placed in the corresponding `rpc` directories. ``` $ make all -/home/user/go/bin/cli contract compile -i alphabet -c alphabet/config.yml -m alphabet/config.json -o alphabet/alphabet_contract.nef -/home/user/go/bin/cli contract compile -i audit -c audit/config.yml -m audit/config.json -o audit/audit_contract.nef -/home/user/go/bin/cli contract compile -i balance -c balance/config.yml -m balance/config.json -o balance/balance_contract.nef -/home/user/go/bin/cli contract compile -i container -c container/config.yml -m container/config.json -o container/container_contract.nef -/home/user/go/bin/cli contract compile -i neofsid -c neofsid/config.yml -m neofsid/config.json -o neofsid/neofsid_contract.nef -/home/user/go/bin/cli contract compile -i netmap -c netmap/config.yml -m netmap/config.json -o netmap/netmap_contract.nef -/home/user/go/bin/cli contract compile -i proxy -c proxy/config.yml -m proxy/config.json -o proxy/proxy_contract.nef -/home/user/go/bin/cli contract compile -i reputation -c reputation/config.yml -m reputation/config.json -o reputation/reputation_contract.nef -/home/user/go/bin/cli contract compile -i subnet -c subnet/config.yml -m subnet/config.json -o subnet/subnet_contract.nef -/home/user/go/bin/cli contract compile -i nns -c nns/config.yml -m nns/config.json -o nns/nns_contract.nef -/home/user/go/bin/cli contract compile -i neofs -c neofs/config.yml -m neofs/config.json -o neofs/neofs_contract.nef -/home/user/go/bin/cli contract compile -i processing -c processing/config.yml -m processing/config.json -o processing/processing_contract.nef +/home/user/go/bin/cli contract compile -i alphabet -c alphabet/config.yml -m alphabet/config.json -o alphabet/alphabet_contract.nef --bindings alphabet/bindings_config.yml +mkdir -p rpc/alphabet +/home/user/go/bin/cli contract generate-rpcwrapper -o rpc/alphabet/rpcbinding.go -m alphabet/config.json --config alphabet/bindings_config.yml +... ``` You can specify path to the `neo-go` binary with `NEOGO` environment variable: diff --git a/neofs/config.yml b/neofs/config.yml index cfeb49e4..58f35684 100644 --- a/neofs/config.yml +++ b/neofs/config.yml @@ -37,18 +37,30 @@ events: type: ByteArray - name: keys type: Array + extendedtype: + base: Array + value: + base: PublicKey - name: Unbind parameters: - name: user type: ByteArray - name: keys type: Array + extendedtype: + base: Array + value: + base: PublicKey - name: AlphabetUpdate parameters: - name: id type: ByteArray - name: alphabet type: Array + extendedtype: + base: Array + value: + base: PublicKey - name: SetConfig parameters: - name: id diff --git a/rpc/alphabet/rpcbinding.go b/rpc/alphabet/rpcbinding.go new file mode 100644 index 00000000..8768701e --- /dev/null +++ b/rpc/alphabet/rpcbinding.go @@ -0,0 +1,1540 @@ +// Package alphabet contains RPC wrappers for NeoFS Alphabet contract. +package alphabet + +import ( + "crypto/elliptic" + "errors" + "fmt" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "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" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" + "unicode/utf8" +) + +// CommonBallot is a contract-specific common.Ballot type used by its methods. +type CommonBallot struct { + ID []byte + Voters keys.PublicKeys + Height *big.Int +} + +// LedgerBlock is a contract-specific ledger.Block type used by its methods. +type LedgerBlock struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int +} + +// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. +type LedgerBlockSR struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int + PrevStateRoot util.Uint256 +} + +// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. +type LedgerTransaction struct { + Hash util.Uint256 + Version *big.Int + Nonce *big.Int + Sender util.Uint160 + SysFee *big.Int + NetFee *big.Int + ValidUntilBlock *big.Int + Script []byte +} + +// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. +type LedgerTransactionSigner struct { + Account util.Uint160 + Scopes *big.Int + AllowedContracts []util.Uint160 + AllowedGroups keys.PublicKeys + Rules []*LedgerWitnessRule +} + +// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. +type LedgerWitnessCondition struct { + Type *big.Int + Value any +} + +// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. +type LedgerWitnessRule struct { + Action *big.Int + Condition *LedgerWitnessCondition +} + +// ManagementABI is a contract-specific management.ABI type used by its methods. +type ManagementABI struct { + Methods []*ManagementMethod + Events []*ManagementEvent +} + +// ManagementContract is a contract-specific management.Contract type used by its methods. +type ManagementContract struct { + ID *big.Int + UpdateCounter *big.Int + Hash util.Uint160 + NEF []byte + Manifest *ManagementManifest +} + +// ManagementEvent is a contract-specific management.Event type used by its methods. +type ManagementEvent struct { + Name string + Params []*ManagementParameter +} + +// ManagementGroup is a contract-specific management.Group type used by its methods. +type ManagementGroup struct { + PublicKey *keys.PublicKey + Signature []byte +} + +// ManagementManifest is a contract-specific management.Manifest type used by its methods. +type ManagementManifest struct { + Name string + Groups []*ManagementGroup + Features map[string]string + SupportedStandards []string + ABI *ManagementABI + Permissions []*ManagementPermission + Trusts []util.Uint160 + Extra any +} + +// ManagementMethod is a contract-specific management.Method type used by its methods. +type ManagementMethod struct { + Name string + Params []*ManagementParameter + ReturnType *big.Int + Offset *big.Int + Safe bool +} + +// ManagementParameter is a contract-specific management.Parameter type used by its methods. +type ManagementParameter struct { + Name string + Type *big.Int +} + +// ManagementPermission is a contract-specific management.Permission type used by its methods. +type ManagementPermission struct { + Contract util.Uint160 + Methods []string +} + +// Invoker is used by ContractReader to call various safe methods. +type Invoker interface { + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) +} + +// Actor is used by Contract to call state-changing methods. +type Actor interface { + Invoker + + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeRun(script []byte) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) + SendRun(script []byte) (util.Uint256, uint32, error) +} + +// ContractReader implements safe contract methods. +type ContractReader struct { + invoker Invoker + hash util.Uint160 +} + +// Contract implements all contract methods. +type Contract struct { + ContractReader + actor Actor + hash util.Uint160 +} + +// NewReader creates an instance of ContractReader using provided contract hash and the given Invoker. +func NewReader(invoker Invoker, hash util.Uint160) *ContractReader { + return &ContractReader{invoker, hash} +} + +// New creates an instance of Contract using provided contract hash and the given Actor. +func New(actor Actor, hash util.Uint160) *Contract { + return &Contract{ContractReader{actor, hash}, actor, hash} +} + +// Gas invokes `gas` method of contract. +func (c *ContractReader) Gas() (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "gas")) +} + +// Name invokes `name` method of contract. +func (c *ContractReader) Name() (string, error) { + return unwrap.UTF8String(c.invoker.Call(c.hash, "name")) +} + +// Neo invokes `neo` method of contract. +func (c *ContractReader) Neo() (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "neo")) +} + +// Version invokes `version` method of contract. +func (c *ContractReader) Version() (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "version")) +} + +// Emit creates a transaction invoking `emit` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Emit() (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "emit") +} + +// EmitTransaction creates a transaction invoking `emit` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) EmitTransaction() (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "emit") +} + +// EmitUnsigned creates a transaction invoking `emit` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) EmitUnsigned() (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "emit", nil) +} + +// Update creates a transaction invoking `update` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Update(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "update", script, manifest, data) +} + +// UpdateTransaction creates a transaction invoking `update` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UpdateTransaction(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "update", script, manifest, data) +} + +// UpdateUnsigned creates a transaction invoking `update` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data) +} + +// Vote creates a transaction invoking `vote` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Vote(epoch *big.Int, candidates keys.PublicKeys) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "vote", epoch, candidates) +} + +// VoteTransaction creates a transaction invoking `vote` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) VoteTransaction(epoch *big.Int, candidates keys.PublicKeys) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "vote", epoch, candidates) +} + +// VoteUnsigned creates a transaction invoking `vote` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) VoteUnsigned(epoch *big.Int, candidates keys.PublicKeys) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "vote", nil, epoch, candidates) +} + +// itemToCommonBallot converts stack item into *CommonBallot. +func itemToCommonBallot(item stackitem.Item, err error) (*CommonBallot, error) { + if err != nil { + return nil, err + } + var res = new(CommonBallot) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of CommonBallot from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *CommonBallot) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.Voters, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Voters: %w", err) + } + + index++ + res.Height, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Height: %w", err) + } + + return nil +} + +// itemToLedgerBlock converts stack item into *LedgerBlock. +func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 9 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + return nil +} + +// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. +func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 10 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + index++ + res.PrevStateRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevStateRoot: %w", err) + } + + return nil +} + +// itemToLedgerTransaction converts stack item into *LedgerTransaction. +func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Sender, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + + index++ + res.SysFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + + index++ + res.NetFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + + index++ + res.ValidUntilBlock, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + + index++ + res.Script, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + + return nil +} + +// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. +func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Account, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Account: %w", err) + } + + index++ + res.Scopes, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Scopes: %w", err) + } + + index++ + res.AllowedContracts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedContracts: %w", err) + } + + index++ + res.AllowedGroups, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedGroups: %w", err) + } + + index++ + res.Rules, err = func (item stackitem.Item) ([]*LedgerWitnessRule, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*LedgerWitnessRule, len(arr)) + for i := range res { + res[i], err = itemToLedgerWitnessRule(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Rules: %w", err) + } + + return nil +} + +// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. +func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + index++ + res.Value, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} + +// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. +func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Action, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Action: %w", err) + } + + index++ + res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) + if err != nil { + return fmt.Errorf("field Condition: %w", err) + } + + return nil +} + +// itemToManagementABI converts stack item into *ManagementABI. +func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { + if err != nil { + return nil, err + } + var res = new(ManagementABI) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementABI from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementABI) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Methods, err = func (item stackitem.Item) ([]*ManagementMethod, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementMethod, len(arr)) + for i := range res { + res[i], err = itemToManagementMethod(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + index++ + res.Events, err = func (item stackitem.Item) ([]*ManagementEvent, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementEvent, len(arr)) + for i := range res { + res[i], err = itemToManagementEvent(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Events: %w", err) + } + + return nil +} + +// itemToManagementContract converts stack item into *ManagementContract. +func itemToManagementContract(item stackitem.Item, err error) (*ManagementContract, error) { + if err != nil { + return nil, err + } + var res = new(ManagementContract) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementContract from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementContract) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.UpdateCounter, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field UpdateCounter: %w", err) + } + + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.NEF, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field NEF: %w", err) + } + + index++ + res.Manifest, err = itemToManagementManifest(arr[index], nil) + if err != nil { + return fmt.Errorf("field Manifest: %w", err) + } + + return nil +} + +// itemToManagementEvent converts stack item into *ManagementEvent. +func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, error) { + if err != nil { + return nil, err + } + var res = new(ManagementEvent) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementEvent from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + return nil +} + +// itemToManagementGroup converts stack item into *ManagementGroup. +func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, error) { + if err != nil { + return nil, err + } + var res = new(ManagementGroup) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementGroup from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + index++ + res.Signature, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Signature: %w", err) + } + + return nil +} + +// itemToManagementManifest converts stack item into *ManagementManifest. +func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManifest, error) { + if err != nil { + return nil, err + } + var res = new(ManagementManifest) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementManifest from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Groups, err = func (item stackitem.Item) ([]*ManagementGroup, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementGroup, len(arr)) + for i := range res { + res[i], err = itemToManagementGroup(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Groups: %w", err) + } + + index++ + res.Features, err = func (item stackitem.Item) (map[string]string, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string]string) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Features: %w", err) + } + + index++ + res.SupportedStandards, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field SupportedStandards: %w", err) + } + + index++ + res.ABI, err = itemToManagementABI(arr[index], nil) + if err != nil { + return fmt.Errorf("field ABI: %w", err) + } + + index++ + res.Permissions, err = func (item stackitem.Item) ([]*ManagementPermission, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementPermission, len(arr)) + for i := range res { + res[i], err = itemToManagementPermission(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Permissions: %w", err) + } + + index++ + res.Trusts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Trusts: %w", err) + } + + index++ + res.Extra, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Extra: %w", err) + } + + return nil +} + +// itemToManagementMethod converts stack item into *ManagementMethod. +func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, error) { + if err != nil { + return nil, err + } + var res = new(ManagementMethod) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementMethod from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + index++ + res.ReturnType, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ReturnType: %w", err) + } + + index++ + res.Offset, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Offset: %w", err) + } + + index++ + res.Safe, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field Safe: %w", err) + } + + return nil +} + +// itemToManagementParameter converts stack item into *ManagementParameter. +func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParameter, error) { + if err != nil { + return nil, err + } + var res = new(ManagementParameter) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementParameter from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + return nil +} + +// itemToManagementPermission converts stack item into *ManagementPermission. +func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPermission, error) { + if err != nil { + return nil, err + } + var res = new(ManagementPermission) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementPermission from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Contract, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Contract: %w", err) + } + + index++ + res.Methods, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + return nil +} diff --git a/rpc/audit/rpcbinding.go b/rpc/audit/rpcbinding.go new file mode 100644 index 00000000..767cadce --- /dev/null +++ b/rpc/audit/rpcbinding.go @@ -0,0 +1,1591 @@ +// Package audit contains RPC wrappers for NeoFS Audit contract. +package audit + +import ( + "crypto/elliptic" + "errors" + "fmt" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "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" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" + "unicode/utf8" +) + +// AuditauditHeader is a contract-specific audit.auditHeader type used by its methods. +type AuditauditHeader struct { + epoch *big.Int + cid []byte + from *keys.PublicKey +} + +// CommonBallot is a contract-specific common.Ballot type used by its methods. +type CommonBallot struct { + ID []byte + Voters keys.PublicKeys + Height *big.Int +} + +// LedgerBlock is a contract-specific ledger.Block type used by its methods. +type LedgerBlock struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int +} + +// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. +type LedgerBlockSR struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int + PrevStateRoot util.Uint256 +} + +// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. +type LedgerTransaction struct { + Hash util.Uint256 + Version *big.Int + Nonce *big.Int + Sender util.Uint160 + SysFee *big.Int + NetFee *big.Int + ValidUntilBlock *big.Int + Script []byte +} + +// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. +type LedgerTransactionSigner struct { + Account util.Uint160 + Scopes *big.Int + AllowedContracts []util.Uint160 + AllowedGroups keys.PublicKeys + Rules []*LedgerWitnessRule +} + +// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. +type LedgerWitnessCondition struct { + Type *big.Int + Value any +} + +// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. +type LedgerWitnessRule struct { + Action *big.Int + Condition *LedgerWitnessCondition +} + +// ManagementABI is a contract-specific management.ABI type used by its methods. +type ManagementABI struct { + Methods []*ManagementMethod + Events []*ManagementEvent +} + +// ManagementContract is a contract-specific management.Contract type used by its methods. +type ManagementContract struct { + ID *big.Int + UpdateCounter *big.Int + Hash util.Uint160 + NEF []byte + Manifest *ManagementManifest +} + +// ManagementEvent is a contract-specific management.Event type used by its methods. +type ManagementEvent struct { + Name string + Params []*ManagementParameter +} + +// ManagementGroup is a contract-specific management.Group type used by its methods. +type ManagementGroup struct { + PublicKey *keys.PublicKey + Signature []byte +} + +// ManagementManifest is a contract-specific management.Manifest type used by its methods. +type ManagementManifest struct { + Name string + Groups []*ManagementGroup + Features map[string]string + SupportedStandards []string + ABI *ManagementABI + Permissions []*ManagementPermission + Trusts []util.Uint160 + Extra any +} + +// ManagementMethod is a contract-specific management.Method type used by its methods. +type ManagementMethod struct { + Name string + Params []*ManagementParameter + ReturnType *big.Int + Offset *big.Int + Safe bool +} + +// ManagementParameter is a contract-specific management.Parameter type used by its methods. +type ManagementParameter struct { + Name string + Type *big.Int +} + +// ManagementPermission is a contract-specific management.Permission type used by its methods. +type ManagementPermission struct { + Contract util.Uint160 + Methods []string +} + +// Invoker is used by ContractReader to call various safe methods. +type Invoker interface { + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) +} + +// Actor is used by Contract to call state-changing methods. +type Actor interface { + Invoker + + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeRun(script []byte) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) + SendRun(script []byte) (util.Uint256, uint32, error) +} + +// ContractReader implements safe contract methods. +type ContractReader struct { + invoker Invoker + hash util.Uint160 +} + +// Contract implements all contract methods. +type Contract struct { + ContractReader + actor Actor + hash util.Uint160 +} + +// NewReader creates an instance of ContractReader using provided contract hash and the given Invoker. +func NewReader(invoker Invoker, hash util.Uint160) *ContractReader { + return &ContractReader{invoker, hash} +} + +// New creates an instance of Contract using provided contract hash and the given Actor. +func New(actor Actor, hash util.Uint160) *Contract { + return &Contract{ContractReader{actor, hash}, actor, hash} +} + +// Get invokes `get` method of contract. +func (c *ContractReader) Get(id []byte) ([]byte, error) { + return unwrap.Bytes(c.invoker.Call(c.hash, "get", id)) +} + +// List invokes `list` method of contract. +func (c *ContractReader) List() ([][]byte, error) { + return unwrap.ArrayOfBytes(c.invoker.Call(c.hash, "list")) +} + +// ListByCID invokes `listByCID` method of contract. +func (c *ContractReader) ListByCID(epoch *big.Int, cid []byte) ([][]byte, error) { + return unwrap.ArrayOfBytes(c.invoker.Call(c.hash, "listByCID", epoch, cid)) +} + +// ListByEpoch invokes `listByEpoch` method of contract. +func (c *ContractReader) ListByEpoch(epoch *big.Int) ([][]byte, error) { + return unwrap.ArrayOfBytes(c.invoker.Call(c.hash, "listByEpoch", epoch)) +} + +// ListByNode invokes `listByNode` method of contract. +func (c *ContractReader) ListByNode(epoch *big.Int, cid []byte, key *keys.PublicKey) ([][]byte, error) { + return unwrap.ArrayOfBytes(c.invoker.Call(c.hash, "listByNode", epoch, cid, key)) +} + +// Version invokes `version` method of contract. +func (c *ContractReader) Version() (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "version")) +} + +// Put creates a transaction invoking `put` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Put(rawAuditResult []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "put", rawAuditResult) +} + +// PutTransaction creates a transaction invoking `put` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) PutTransaction(rawAuditResult []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "put", rawAuditResult) +} + +// PutUnsigned creates a transaction invoking `put` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) PutUnsigned(rawAuditResult []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "put", nil, rawAuditResult) +} + +// Update creates a transaction invoking `update` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Update(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "update", script, manifest, data) +} + +// UpdateTransaction creates a transaction invoking `update` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UpdateTransaction(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "update", script, manifest, data) +} + +// UpdateUnsigned creates a transaction invoking `update` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data) +} + +// itemToAuditauditHeader converts stack item into *AuditauditHeader. +func itemToAuditauditHeader(item stackitem.Item, err error) (*AuditauditHeader, error) { + if err != nil { + return nil, err + } + var res = new(AuditauditHeader) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of AuditauditHeader from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *AuditauditHeader) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.epoch, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field epoch: %w", err) + } + + index++ + res.cid, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field cid: %w", err) + } + + index++ + res.from, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field from: %w", err) + } + + return nil +} + +// itemToCommonBallot converts stack item into *CommonBallot. +func itemToCommonBallot(item stackitem.Item, err error) (*CommonBallot, error) { + if err != nil { + return nil, err + } + var res = new(CommonBallot) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of CommonBallot from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *CommonBallot) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.Voters, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Voters: %w", err) + } + + index++ + res.Height, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Height: %w", err) + } + + return nil +} + +// itemToLedgerBlock converts stack item into *LedgerBlock. +func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 9 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + return nil +} + +// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. +func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 10 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + index++ + res.PrevStateRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevStateRoot: %w", err) + } + + return nil +} + +// itemToLedgerTransaction converts stack item into *LedgerTransaction. +func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Sender, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + + index++ + res.SysFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + + index++ + res.NetFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + + index++ + res.ValidUntilBlock, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + + index++ + res.Script, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + + return nil +} + +// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. +func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Account, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Account: %w", err) + } + + index++ + res.Scopes, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Scopes: %w", err) + } + + index++ + res.AllowedContracts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedContracts: %w", err) + } + + index++ + res.AllowedGroups, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedGroups: %w", err) + } + + index++ + res.Rules, err = func (item stackitem.Item) ([]*LedgerWitnessRule, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*LedgerWitnessRule, len(arr)) + for i := range res { + res[i], err = itemToLedgerWitnessRule(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Rules: %w", err) + } + + return nil +} + +// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. +func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + index++ + res.Value, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} + +// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. +func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Action, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Action: %w", err) + } + + index++ + res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) + if err != nil { + return fmt.Errorf("field Condition: %w", err) + } + + return nil +} + +// itemToManagementABI converts stack item into *ManagementABI. +func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { + if err != nil { + return nil, err + } + var res = new(ManagementABI) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementABI from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementABI) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Methods, err = func (item stackitem.Item) ([]*ManagementMethod, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementMethod, len(arr)) + for i := range res { + res[i], err = itemToManagementMethod(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + index++ + res.Events, err = func (item stackitem.Item) ([]*ManagementEvent, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementEvent, len(arr)) + for i := range res { + res[i], err = itemToManagementEvent(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Events: %w", err) + } + + return nil +} + +// itemToManagementContract converts stack item into *ManagementContract. +func itemToManagementContract(item stackitem.Item, err error) (*ManagementContract, error) { + if err != nil { + return nil, err + } + var res = new(ManagementContract) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementContract from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementContract) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.UpdateCounter, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field UpdateCounter: %w", err) + } + + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.NEF, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field NEF: %w", err) + } + + index++ + res.Manifest, err = itemToManagementManifest(arr[index], nil) + if err != nil { + return fmt.Errorf("field Manifest: %w", err) + } + + return nil +} + +// itemToManagementEvent converts stack item into *ManagementEvent. +func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, error) { + if err != nil { + return nil, err + } + var res = new(ManagementEvent) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementEvent from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + return nil +} + +// itemToManagementGroup converts stack item into *ManagementGroup. +func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, error) { + if err != nil { + return nil, err + } + var res = new(ManagementGroup) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementGroup from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + index++ + res.Signature, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Signature: %w", err) + } + + return nil +} + +// itemToManagementManifest converts stack item into *ManagementManifest. +func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManifest, error) { + if err != nil { + return nil, err + } + var res = new(ManagementManifest) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementManifest from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Groups, err = func (item stackitem.Item) ([]*ManagementGroup, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementGroup, len(arr)) + for i := range res { + res[i], err = itemToManagementGroup(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Groups: %w", err) + } + + index++ + res.Features, err = func (item stackitem.Item) (map[string]string, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string]string) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Features: %w", err) + } + + index++ + res.SupportedStandards, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field SupportedStandards: %w", err) + } + + index++ + res.ABI, err = itemToManagementABI(arr[index], nil) + if err != nil { + return fmt.Errorf("field ABI: %w", err) + } + + index++ + res.Permissions, err = func (item stackitem.Item) ([]*ManagementPermission, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementPermission, len(arr)) + for i := range res { + res[i], err = itemToManagementPermission(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Permissions: %w", err) + } + + index++ + res.Trusts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Trusts: %w", err) + } + + index++ + res.Extra, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Extra: %w", err) + } + + return nil +} + +// itemToManagementMethod converts stack item into *ManagementMethod. +func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, error) { + if err != nil { + return nil, err + } + var res = new(ManagementMethod) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementMethod from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + index++ + res.ReturnType, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ReturnType: %w", err) + } + + index++ + res.Offset, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Offset: %w", err) + } + + index++ + res.Safe, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field Safe: %w", err) + } + + return nil +} + +// itemToManagementParameter converts stack item into *ManagementParameter. +func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParameter, error) { + if err != nil { + return nil, err + } + var res = new(ManagementParameter) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementParameter from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + return nil +} + +// itemToManagementPermission converts stack item into *ManagementPermission. +func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPermission, error) { + if err != nil { + return nil, err + } + var res = new(ManagementPermission) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementPermission from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Contract, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Contract: %w", err) + } + + index++ + res.Methods, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + return nil +} diff --git a/rpc/balance/rpcbinding.go b/rpc/balance/rpcbinding.go new file mode 100644 index 00000000..87366ec2 --- /dev/null +++ b/rpc/balance/rpcbinding.go @@ -0,0 +1,2072 @@ +// Package balance contains RPC wrappers for NeoFS Balance contract. +package balance + +import ( + "crypto/elliptic" + "errors" + "fmt" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "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/nep17" + "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" + "math/big" + "unicode/utf8" +) + +// BalanceAccount is a contract-specific balance.Account type used by its methods. +type BalanceAccount struct { + Balance *big.Int + Until *big.Int + Parent []byte +} + +// BalanceToken is a contract-specific balance.Token type used by its methods. +type BalanceToken struct { + Symbol string + Decimals *big.Int + CirculationKey string +} + +// CommonBallot is a contract-specific common.Ballot type used by its methods. +type CommonBallot struct { + ID []byte + Voters keys.PublicKeys + Height *big.Int +} + +// LedgerBlock is a contract-specific ledger.Block type used by its methods. +type LedgerBlock struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int +} + +// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. +type LedgerBlockSR struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int + PrevStateRoot util.Uint256 +} + +// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. +type LedgerTransaction struct { + Hash util.Uint256 + Version *big.Int + Nonce *big.Int + Sender util.Uint160 + SysFee *big.Int + NetFee *big.Int + ValidUntilBlock *big.Int + Script []byte +} + +// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. +type LedgerTransactionSigner struct { + Account util.Uint160 + Scopes *big.Int + AllowedContracts []util.Uint160 + AllowedGroups keys.PublicKeys + Rules []*LedgerWitnessRule +} + +// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. +type LedgerWitnessCondition struct { + Type *big.Int + Value any +} + +// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. +type LedgerWitnessRule struct { + Action *big.Int + Condition *LedgerWitnessCondition +} + +// ManagementABI is a contract-specific management.ABI type used by its methods. +type ManagementABI struct { + Methods []*ManagementMethod + Events []*ManagementEvent +} + +// ManagementContract is a contract-specific management.Contract type used by its methods. +type ManagementContract struct { + ID *big.Int + UpdateCounter *big.Int + Hash util.Uint160 + NEF []byte + Manifest *ManagementManifest +} + +// ManagementEvent is a contract-specific management.Event type used by its methods. +type ManagementEvent struct { + Name string + Params []*ManagementParameter +} + +// ManagementGroup is a contract-specific management.Group type used by its methods. +type ManagementGroup struct { + PublicKey *keys.PublicKey + Signature []byte +} + +// ManagementManifest is a contract-specific management.Manifest type used by its methods. +type ManagementManifest struct { + Name string + Groups []*ManagementGroup + Features map[string]string + SupportedStandards []string + ABI *ManagementABI + Permissions []*ManagementPermission + Trusts []util.Uint160 + Extra any +} + +// ManagementMethod is a contract-specific management.Method type used by its methods. +type ManagementMethod struct { + Name string + Params []*ManagementParameter + ReturnType *big.Int + Offset *big.Int + Safe bool +} + +// ManagementParameter is a contract-specific management.Parameter type used by its methods. +type ManagementParameter struct { + Name string + Type *big.Int +} + +// ManagementPermission is a contract-specific management.Permission type used by its methods. +type ManagementPermission struct { + Contract util.Uint160 + Methods []string +} + +// LockEvent represents "Lock" event emitted by the contract. +type LockEvent struct { + TxID []byte + From util.Uint160 + To util.Uint160 + Amount *big.Int + Until *big.Int +} + +// TransferXEvent represents "TransferX" event emitted by the contract. +type TransferXEvent struct { + From util.Uint160 + To util.Uint160 + Amount *big.Int + Details []byte +} + +// MintEvent represents "Mint" event emitted by the contract. +type MintEvent struct { + To util.Uint160 + Amount *big.Int +} + +// BurnEvent represents "Burn" event emitted by the contract. +type BurnEvent struct { + From util.Uint160 + Amount *big.Int +} + +// Invoker is used by ContractReader to call various safe methods. +type Invoker interface { + nep17.Invoker +} + +// Actor is used by Contract to call state-changing methods. +type Actor interface { + Invoker + + nep17.Actor + + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeRun(script []byte) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) + SendRun(script []byte) (util.Uint256, uint32, error) +} + +// ContractReader implements safe contract methods. +type ContractReader struct { + nep17.TokenReader + invoker Invoker + hash util.Uint160 +} + +// Contract implements all contract methods. +type Contract struct { + ContractReader + nep17.TokenWriter + actor Actor + hash util.Uint160 +} + +// NewReader creates an instance of ContractReader using provided contract hash and the given Invoker. +func NewReader(invoker Invoker, hash util.Uint160) *ContractReader { + return &ContractReader{*nep17.NewReader(invoker, hash), invoker, hash} +} + +// New creates an instance of Contract using provided contract hash and the given Actor. +func New(actor Actor, hash util.Uint160) *Contract { + var nep17t = nep17.New(actor, hash) + return &Contract{ContractReader{nep17t.TokenReader, actor, hash}, nep17t.TokenWriter, actor, hash} +} + +// Version invokes `version` method of contract. +func (c *ContractReader) Version() (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "version")) +} + +// Burn creates a transaction invoking `burn` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Burn(from util.Uint160, amount *big.Int, txDetails []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "burn", from, amount, txDetails) +} + +// BurnTransaction creates a transaction invoking `burn` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) BurnTransaction(from util.Uint160, amount *big.Int, txDetails []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "burn", from, amount, txDetails) +} + +// BurnUnsigned creates a transaction invoking `burn` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) BurnUnsigned(from util.Uint160, amount *big.Int, txDetails []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "burn", nil, from, amount, txDetails) +} + +// Lock creates a transaction invoking `lock` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Lock(txDetails []byte, from util.Uint160, to util.Uint160, amount *big.Int, until *big.Int) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "lock", txDetails, from, to, amount, until) +} + +// LockTransaction creates a transaction invoking `lock` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) LockTransaction(txDetails []byte, from util.Uint160, to util.Uint160, amount *big.Int, until *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "lock", txDetails, from, to, amount, until) +} + +// LockUnsigned creates a transaction invoking `lock` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) LockUnsigned(txDetails []byte, from util.Uint160, to util.Uint160, amount *big.Int, until *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "lock", nil, txDetails, from, to, amount, until) +} + +// Mint creates a transaction invoking `mint` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Mint(to util.Uint160, amount *big.Int, txDetails []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "mint", to, amount, txDetails) +} + +// MintTransaction creates a transaction invoking `mint` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) MintTransaction(to util.Uint160, amount *big.Int, txDetails []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "mint", to, amount, txDetails) +} + +// MintUnsigned creates a transaction invoking `mint` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) MintUnsigned(to util.Uint160, amount *big.Int, txDetails []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "mint", nil, to, amount, txDetails) +} + +// NewEpoch creates a transaction invoking `newEpoch` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) NewEpoch(epochNum *big.Int) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "newEpoch", epochNum) +} + +// NewEpochTransaction creates a transaction invoking `newEpoch` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) NewEpochTransaction(epochNum *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "newEpoch", epochNum) +} + +// NewEpochUnsigned creates a transaction invoking `newEpoch` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) NewEpochUnsigned(epochNum *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "newEpoch", nil, epochNum) +} + +// TransferX creates a transaction invoking `transferX` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) TransferX(from util.Uint160, to util.Uint160, amount *big.Int, details []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "transferX", from, to, amount, details) +} + +// TransferXTransaction creates a transaction invoking `transferX` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) TransferXTransaction(from util.Uint160, to util.Uint160, amount *big.Int, details []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "transferX", from, to, amount, details) +} + +// TransferXUnsigned creates a transaction invoking `transferX` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) TransferXUnsigned(from util.Uint160, to util.Uint160, amount *big.Int, details []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "transferX", nil, from, to, amount, details) +} + +// Update creates a transaction invoking `update` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Update(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "update", script, manifest, data) +} + +// UpdateTransaction creates a transaction invoking `update` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UpdateTransaction(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "update", script, manifest, data) +} + +// UpdateUnsigned creates a transaction invoking `update` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data) +} + +// itemToBalanceAccount converts stack item into *BalanceAccount. +func itemToBalanceAccount(item stackitem.Item, err error) (*BalanceAccount, error) { + if err != nil { + return nil, err + } + var res = new(BalanceAccount) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of BalanceAccount from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *BalanceAccount) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Balance, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Balance: %w", err) + } + + index++ + res.Until, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Until: %w", err) + } + + index++ + res.Parent, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Parent: %w", err) + } + + return nil +} + +// itemToBalanceToken converts stack item into *BalanceToken. +func itemToBalanceToken(item stackitem.Item, err error) (*BalanceToken, error) { + if err != nil { + return nil, err + } + var res = new(BalanceToken) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of BalanceToken from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *BalanceToken) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Symbol, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Symbol: %w", err) + } + + index++ + res.Decimals, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Decimals: %w", err) + } + + index++ + res.CirculationKey, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field CirculationKey: %w", err) + } + + return nil +} + +// itemToCommonBallot converts stack item into *CommonBallot. +func itemToCommonBallot(item stackitem.Item, err error) (*CommonBallot, error) { + if err != nil { + return nil, err + } + var res = new(CommonBallot) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of CommonBallot from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *CommonBallot) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.Voters, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Voters: %w", err) + } + + index++ + res.Height, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Height: %w", err) + } + + return nil +} + +// itemToLedgerBlock converts stack item into *LedgerBlock. +func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 9 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + return nil +} + +// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. +func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 10 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + index++ + res.PrevStateRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevStateRoot: %w", err) + } + + return nil +} + +// itemToLedgerTransaction converts stack item into *LedgerTransaction. +func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Sender, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + + index++ + res.SysFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + + index++ + res.NetFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + + index++ + res.ValidUntilBlock, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + + index++ + res.Script, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + + return nil +} + +// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. +func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Account, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Account: %w", err) + } + + index++ + res.Scopes, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Scopes: %w", err) + } + + index++ + res.AllowedContracts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedContracts: %w", err) + } + + index++ + res.AllowedGroups, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedGroups: %w", err) + } + + index++ + res.Rules, err = func (item stackitem.Item) ([]*LedgerWitnessRule, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*LedgerWitnessRule, len(arr)) + for i := range res { + res[i], err = itemToLedgerWitnessRule(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Rules: %w", err) + } + + return nil +} + +// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. +func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + index++ + res.Value, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} + +// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. +func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Action, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Action: %w", err) + } + + index++ + res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) + if err != nil { + return fmt.Errorf("field Condition: %w", err) + } + + return nil +} + +// itemToManagementABI converts stack item into *ManagementABI. +func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { + if err != nil { + return nil, err + } + var res = new(ManagementABI) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementABI from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementABI) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Methods, err = func (item stackitem.Item) ([]*ManagementMethod, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementMethod, len(arr)) + for i := range res { + res[i], err = itemToManagementMethod(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + index++ + res.Events, err = func (item stackitem.Item) ([]*ManagementEvent, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementEvent, len(arr)) + for i := range res { + res[i], err = itemToManagementEvent(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Events: %w", err) + } + + return nil +} + +// itemToManagementContract converts stack item into *ManagementContract. +func itemToManagementContract(item stackitem.Item, err error) (*ManagementContract, error) { + if err != nil { + return nil, err + } + var res = new(ManagementContract) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementContract from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementContract) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.UpdateCounter, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field UpdateCounter: %w", err) + } + + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.NEF, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field NEF: %w", err) + } + + index++ + res.Manifest, err = itemToManagementManifest(arr[index], nil) + if err != nil { + return fmt.Errorf("field Manifest: %w", err) + } + + return nil +} + +// itemToManagementEvent converts stack item into *ManagementEvent. +func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, error) { + if err != nil { + return nil, err + } + var res = new(ManagementEvent) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementEvent from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + return nil +} + +// itemToManagementGroup converts stack item into *ManagementGroup. +func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, error) { + if err != nil { + return nil, err + } + var res = new(ManagementGroup) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementGroup from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + index++ + res.Signature, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Signature: %w", err) + } + + return nil +} + +// itemToManagementManifest converts stack item into *ManagementManifest. +func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManifest, error) { + if err != nil { + return nil, err + } + var res = new(ManagementManifest) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementManifest from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Groups, err = func (item stackitem.Item) ([]*ManagementGroup, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementGroup, len(arr)) + for i := range res { + res[i], err = itemToManagementGroup(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Groups: %w", err) + } + + index++ + res.Features, err = func (item stackitem.Item) (map[string]string, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string]string) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Features: %w", err) + } + + index++ + res.SupportedStandards, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field SupportedStandards: %w", err) + } + + index++ + res.ABI, err = itemToManagementABI(arr[index], nil) + if err != nil { + return fmt.Errorf("field ABI: %w", err) + } + + index++ + res.Permissions, err = func (item stackitem.Item) ([]*ManagementPermission, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementPermission, len(arr)) + for i := range res { + res[i], err = itemToManagementPermission(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Permissions: %w", err) + } + + index++ + res.Trusts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Trusts: %w", err) + } + + index++ + res.Extra, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Extra: %w", err) + } + + return nil +} + +// itemToManagementMethod converts stack item into *ManagementMethod. +func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, error) { + if err != nil { + return nil, err + } + var res = new(ManagementMethod) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementMethod from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + index++ + res.ReturnType, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ReturnType: %w", err) + } + + index++ + res.Offset, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Offset: %w", err) + } + + index++ + res.Safe, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field Safe: %w", err) + } + + return nil +} + +// itemToManagementParameter converts stack item into *ManagementParameter. +func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParameter, error) { + if err != nil { + return nil, err + } + var res = new(ManagementParameter) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementParameter from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + return nil +} + +// itemToManagementPermission converts stack item into *ManagementPermission. +func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPermission, error) { + if err != nil { + return nil, err + } + var res = new(ManagementPermission) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementPermission from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Contract, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Contract: %w", err) + } + + index++ + res.Methods, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + return nil +} + +// LockEventsFromApplicationLog retrieves a set of all emitted events +// with "Lock" name from the provided [result.ApplicationLog]. +func LockEventsFromApplicationLog(log *result.ApplicationLog) ([]*LockEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*LockEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Lock" { + continue + } + event := new(LockEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize LockEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to LockEvent or +// returns an error if it's not possible to do to so. +func (e *LockEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.TxID, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field TxID: %w", err) + } + + index++ + e.From, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field From: %w", err) + } + + index++ + e.To, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field To: %w", err) + } + + index++ + e.Amount, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Amount: %w", err) + } + + index++ + e.Until, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Until: %w", err) + } + + return nil +} + +// TransferXEventsFromApplicationLog retrieves a set of all emitted events +// with "TransferX" name from the provided [result.ApplicationLog]. +func TransferXEventsFromApplicationLog(log *result.ApplicationLog) ([]*TransferXEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*TransferXEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "TransferX" { + continue + } + event := new(TransferXEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize TransferXEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to TransferXEvent or +// returns an error if it's not possible to do to so. +func (e *TransferXEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 4 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.From, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field From: %w", err) + } + + index++ + e.To, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field To: %w", err) + } + + index++ + e.Amount, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Amount: %w", err) + } + + index++ + e.Details, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Details: %w", err) + } + + return nil +} + +// MintEventsFromApplicationLog retrieves a set of all emitted events +// with "Mint" name from the provided [result.ApplicationLog]. +func MintEventsFromApplicationLog(log *result.ApplicationLog) ([]*MintEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*MintEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Mint" { + continue + } + event := new(MintEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize MintEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to MintEvent or +// returns an error if it's not possible to do to so. +func (e *MintEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.To, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field To: %w", err) + } + + index++ + e.Amount, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Amount: %w", err) + } + + return nil +} + +// BurnEventsFromApplicationLog retrieves a set of all emitted events +// with "Burn" name from the provided [result.ApplicationLog]. +func BurnEventsFromApplicationLog(log *result.ApplicationLog) ([]*BurnEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*BurnEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Burn" { + continue + } + event := new(BurnEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize BurnEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to BurnEvent or +// returns an error if it's not possible to do to so. +func (e *BurnEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.From, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field From: %w", err) + } + + index++ + e.Amount, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Amount: %w", err) + } + + return nil +} diff --git a/rpc/container/rpcbinding.go b/rpc/container/rpcbinding.go new file mode 100644 index 00000000..4536d2d1 --- /dev/null +++ b/rpc/container/rpcbinding.go @@ -0,0 +1,2322 @@ +// Package container contains RPC wrappers for NeoFS Container contract. +package container + +import ( + "crypto/elliptic" + "errors" + "fmt" + "github.com/google/uuid" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "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" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" + "unicode/utf8" +) + +// CommonBallot is a contract-specific common.Ballot type used by its methods. +type CommonBallot struct { + ID []byte + Voters keys.PublicKeys + Height *big.Int +} + +// ContainerContainer is a contract-specific container.Container type used by its methods. +type ContainerContainer struct { + value []byte + sig []byte + pub *keys.PublicKey + token []byte +} + +// ContainerEstimation is a contract-specific container.Estimation type used by its methods. +type ContainerEstimation struct { + From *keys.PublicKey + Size *big.Int +} + +// ContainerExtendedACL is a contract-specific container.ExtendedACL type used by its methods. +type ContainerExtendedACL struct { + value []byte + sig []byte + pub *keys.PublicKey + token []byte +} + +// ContainercontainerSizes is a contract-specific container.containerSizes type used by its methods. +type ContainercontainerSizes struct { + cid []byte + estimations []*ContainerEstimation +} + +// LedgerBlock is a contract-specific ledger.Block type used by its methods. +type LedgerBlock struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int +} + +// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. +type LedgerBlockSR struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int + PrevStateRoot util.Uint256 +} + +// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. +type LedgerTransaction struct { + Hash util.Uint256 + Version *big.Int + Nonce *big.Int + Sender util.Uint160 + SysFee *big.Int + NetFee *big.Int + ValidUntilBlock *big.Int + Script []byte +} + +// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. +type LedgerTransactionSigner struct { + Account util.Uint160 + Scopes *big.Int + AllowedContracts []util.Uint160 + AllowedGroups keys.PublicKeys + Rules []*LedgerWitnessRule +} + +// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. +type LedgerWitnessCondition struct { + Type *big.Int + Value any +} + +// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. +type LedgerWitnessRule struct { + Action *big.Int + Condition *LedgerWitnessCondition +} + +// ManagementABI is a contract-specific management.ABI type used by its methods. +type ManagementABI struct { + Methods []*ManagementMethod + Events []*ManagementEvent +} + +// ManagementContract is a contract-specific management.Contract type used by its methods. +type ManagementContract struct { + ID *big.Int + UpdateCounter *big.Int + Hash util.Uint160 + NEF []byte + Manifest *ManagementManifest +} + +// ManagementEvent is a contract-specific management.Event type used by its methods. +type ManagementEvent struct { + Name string + Params []*ManagementParameter +} + +// ManagementGroup is a contract-specific management.Group type used by its methods. +type ManagementGroup struct { + PublicKey *keys.PublicKey + Signature []byte +} + +// ManagementManifest is a contract-specific management.Manifest type used by its methods. +type ManagementManifest struct { + Name string + Groups []*ManagementGroup + Features map[string]string + SupportedStandards []string + ABI *ManagementABI + Permissions []*ManagementPermission + Trusts []util.Uint160 + Extra any +} + +// ManagementMethod is a contract-specific management.Method type used by its methods. +type ManagementMethod struct { + Name string + Params []*ManagementParameter + ReturnType *big.Int + Offset *big.Int + Safe bool +} + +// ManagementParameter is a contract-specific management.Parameter type used by its methods. +type ManagementParameter struct { + Name string + Type *big.Int +} + +// ManagementPermission is a contract-specific management.Permission type used by its methods. +type ManagementPermission struct { + Contract util.Uint160 + Methods []string +} + +// PutSuccessEvent represents "PutSuccess" event emitted by the contract. +type PutSuccessEvent struct { + ContainerID util.Uint256 + PublicKey *keys.PublicKey +} + +// DeleteSuccessEvent represents "DeleteSuccess" event emitted by the contract. +type DeleteSuccessEvent struct { + ContainerID []byte +} + +// SetEACLSuccessEvent represents "SetEACLSuccess" event emitted by the contract. +type SetEACLSuccessEvent struct { + ContainerID []byte + PublicKey *keys.PublicKey +} + +// StartEstimationEvent represents "StartEstimation" event emitted by the contract. +type StartEstimationEvent struct { + Epoch *big.Int +} + +// StopEstimationEvent represents "StopEstimation" event emitted by the contract. +type StopEstimationEvent struct { + Epoch *big.Int +} + +// Invoker is used by ContractReader to call various safe methods. +type Invoker interface { + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) + CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...any) (*result.Invoke, error) + TerminateSession(sessionID uuid.UUID) error + TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error) +} + +// Actor is used by Contract to call state-changing methods. +type Actor interface { + Invoker + + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeRun(script []byte) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) + SendRun(script []byte) (util.Uint256, uint32, error) +} + +// ContractReader implements safe contract methods. +type ContractReader struct { + invoker Invoker + hash util.Uint160 +} + +// Contract implements all contract methods. +type Contract struct { + ContractReader + actor Actor + hash util.Uint160 +} + +// NewReader creates an instance of ContractReader using provided contract hash and the given Invoker. +func NewReader(invoker Invoker, hash util.Uint160) *ContractReader { + return &ContractReader{invoker, hash} +} + +// New creates an instance of Contract using provided contract hash and the given Actor. +func New(actor Actor, hash util.Uint160) *Contract { + return &Contract{ContractReader{actor, hash}, actor, hash} +} + +// ContainersOf invokes `containersOf` method of contract. +func (c *ContractReader) ContainersOf(owner []byte) (uuid.UUID, result.Iterator, error) { + return unwrap.SessionIterator(c.invoker.Call(c.hash, "containersOf", owner)) +} + +// ContainersOfExpanded is similar to ContainersOf (uses the same contract +// 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 the specified +// number 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) ContainersOfExpanded(owner []byte, _numOfIteratorItems int) ([]stackitem.Item, error) { + return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "containersOf", _numOfIteratorItems, owner)) +} + +// Count invokes `count` method of contract. +func (c *ContractReader) Count() (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "count")) +} + +// EACL invokes `eACL` method of contract. +func (c *ContractReader) EACL(containerID []byte) (*ContainerExtendedACL, error) { + return itemToContainerExtendedACL(unwrap.Item(c.invoker.Call(c.hash, "eACL", containerID))) +} + +// Get invokes `get` method of contract. +func (c *ContractReader) Get(containerID []byte) (*ContainerContainer, error) { + return itemToContainerContainer(unwrap.Item(c.invoker.Call(c.hash, "get", containerID))) +} + +// GetContainerSize invokes `getContainerSize` method of contract. +func (c *ContractReader) GetContainerSize(id []byte) (*ContainercontainerSizes, error) { + return itemToContainercontainerSizes(unwrap.Item(c.invoker.Call(c.hash, "getContainerSize", id))) +} + +// IterateAllContainerSizes invokes `iterateAllContainerSizes` method of contract. +func (c *ContractReader) IterateAllContainerSizes(epoch *big.Int) (uuid.UUID, result.Iterator, error) { + return unwrap.SessionIterator(c.invoker.Call(c.hash, "iterateAllContainerSizes", epoch)) +} + +// IterateAllContainerSizesExpanded is similar to IterateAllContainerSizes (uses the same contract +// 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 the specified +// number 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) IterateAllContainerSizesExpanded(epoch *big.Int, _numOfIteratorItems int) ([]stackitem.Item, error) { + return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "iterateAllContainerSizes", _numOfIteratorItems, epoch)) +} + +// IterateContainerSizes invokes `iterateContainerSizes` method of contract. +func (c *ContractReader) IterateContainerSizes(epoch *big.Int, cid util.Uint256) (uuid.UUID, result.Iterator, error) { + return unwrap.SessionIterator(c.invoker.Call(c.hash, "iterateContainerSizes", epoch, cid)) +} + +// IterateContainerSizesExpanded is similar to IterateContainerSizes (uses the same contract +// 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 the specified +// number 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) IterateContainerSizesExpanded(epoch *big.Int, cid util.Uint256, _numOfIteratorItems int) ([]stackitem.Item, error) { + return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "iterateContainerSizes", _numOfIteratorItems, epoch, cid)) +} + +// List invokes `list` method of contract. +func (c *ContractReader) List(owner []byte) ([][]byte, error) { + return unwrap.ArrayOfBytes(c.invoker.Call(c.hash, "list", owner)) +} + +// ListContainerSizes invokes `listContainerSizes` method of contract. +func (c *ContractReader) ListContainerSizes(epoch *big.Int) ([][]byte, error) { + return unwrap.ArrayOfBytes(c.invoker.Call(c.hash, "listContainerSizes", epoch)) +} + +// Owner invokes `owner` method of contract. +func (c *ContractReader) Owner(containerID []byte) ([]byte, error) { + return unwrap.Bytes(c.invoker.Call(c.hash, "owner", containerID)) +} + +// Version invokes `version` method of contract. +func (c *ContractReader) Version() (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "version")) +} + +// Delete creates a transaction invoking `delete` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Delete(containerID []byte, signature []byte, token []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "delete", containerID, signature, token) +} + +// DeleteTransaction creates a transaction invoking `delete` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) DeleteTransaction(containerID []byte, signature []byte, token []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "delete", containerID, signature, token) +} + +// DeleteUnsigned creates a transaction invoking `delete` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) DeleteUnsigned(containerID []byte, signature []byte, token []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "delete", nil, containerID, signature, token) +} + +// NewEpoch creates a transaction invoking `newEpoch` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) NewEpoch(epochNum *big.Int) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "newEpoch", epochNum) +} + +// NewEpochTransaction creates a transaction invoking `newEpoch` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) NewEpochTransaction(epochNum *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "newEpoch", epochNum) +} + +// NewEpochUnsigned creates a transaction invoking `newEpoch` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) NewEpochUnsigned(epochNum *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "newEpoch", nil, epochNum) +} + +// Put creates a transaction invoking `put` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Put(container []byte, signature []byte, publicKey *keys.PublicKey, token []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "put", container, signature, publicKey, token) +} + +// PutTransaction creates a transaction invoking `put` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) PutTransaction(container []byte, signature []byte, publicKey *keys.PublicKey, token []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "put", container, signature, publicKey, token) +} + +// PutUnsigned creates a transaction invoking `put` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) PutUnsigned(container []byte, signature []byte, publicKey *keys.PublicKey, token []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "put", nil, container, signature, publicKey, token) +} + +// PutContainerSize creates a transaction invoking `putContainerSize` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) PutContainerSize(epoch *big.Int, cid []byte, usedSize *big.Int, pubKey *keys.PublicKey) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "putContainerSize", epoch, cid, usedSize, pubKey) +} + +// PutContainerSizeTransaction creates a transaction invoking `putContainerSize` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) PutContainerSizeTransaction(epoch *big.Int, cid []byte, usedSize *big.Int, pubKey *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "putContainerSize", epoch, cid, usedSize, pubKey) +} + +// PutContainerSizeUnsigned creates a transaction invoking `putContainerSize` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) PutContainerSizeUnsigned(epoch *big.Int, cid []byte, usedSize *big.Int, pubKey *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "putContainerSize", nil, epoch, cid, usedSize, pubKey) +} + +// PutNamed creates a transaction invoking `putNamed` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) PutNamed(container []byte, signature []byte, publicKey *keys.PublicKey, token []byte, name string, zone string) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "putNamed", container, signature, publicKey, token, name, zone) +} + +// PutNamedTransaction creates a transaction invoking `putNamed` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) PutNamedTransaction(container []byte, signature []byte, publicKey *keys.PublicKey, token []byte, name string, zone string) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "putNamed", container, signature, publicKey, token, name, zone) +} + +// PutNamedUnsigned creates a transaction invoking `putNamed` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) PutNamedUnsigned(container []byte, signature []byte, publicKey *keys.PublicKey, token []byte, name string, zone string) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "putNamed", nil, container, signature, publicKey, token, name, zone) +} + +// SetEACL creates a transaction invoking `setEACL` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) SetEACL(eACL []byte, signature []byte, publicKey *keys.PublicKey, token []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "setEACL", eACL, signature, publicKey, token) +} + +// SetEACLTransaction creates a transaction invoking `setEACL` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) SetEACLTransaction(eACL []byte, signature []byte, publicKey *keys.PublicKey, token []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "setEACL", eACL, signature, publicKey, token) +} + +// SetEACLUnsigned creates a transaction invoking `setEACL` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) SetEACLUnsigned(eACL []byte, signature []byte, publicKey *keys.PublicKey, token []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "setEACL", nil, eACL, signature, publicKey, token) +} + +// StartContainerEstimation creates a transaction invoking `startContainerEstimation` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) StartContainerEstimation(epoch *big.Int) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "startContainerEstimation", epoch) +} + +// StartContainerEstimationTransaction creates a transaction invoking `startContainerEstimation` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) StartContainerEstimationTransaction(epoch *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "startContainerEstimation", epoch) +} + +// StartContainerEstimationUnsigned creates a transaction invoking `startContainerEstimation` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) StartContainerEstimationUnsigned(epoch *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "startContainerEstimation", nil, epoch) +} + +// StopContainerEstimation creates a transaction invoking `stopContainerEstimation` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) StopContainerEstimation(epoch *big.Int) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "stopContainerEstimation", epoch) +} + +// StopContainerEstimationTransaction creates a transaction invoking `stopContainerEstimation` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) StopContainerEstimationTransaction(epoch *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "stopContainerEstimation", epoch) +} + +// StopContainerEstimationUnsigned creates a transaction invoking `stopContainerEstimation` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) StopContainerEstimationUnsigned(epoch *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "stopContainerEstimation", nil, epoch) +} + +// Update creates a transaction invoking `update` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Update(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "update", script, manifest, data) +} + +// UpdateTransaction creates a transaction invoking `update` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UpdateTransaction(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "update", script, manifest, data) +} + +// UpdateUnsigned creates a transaction invoking `update` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data) +} + +// itemToCommonBallot converts stack item into *CommonBallot. +func itemToCommonBallot(item stackitem.Item, err error) (*CommonBallot, error) { + if err != nil { + return nil, err + } + var res = new(CommonBallot) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of CommonBallot from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *CommonBallot) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.Voters, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Voters: %w", err) + } + + index++ + res.Height, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Height: %w", err) + } + + return nil +} + +// itemToContainerContainer converts stack item into *ContainerContainer. +func itemToContainerContainer(item stackitem.Item, err error) (*ContainerContainer, error) { + if err != nil { + return nil, err + } + var res = new(ContainerContainer) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ContainerContainer from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ContainerContainer) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 4 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.value, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field value: %w", err) + } + + index++ + res.sig, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field sig: %w", err) + } + + index++ + res.pub, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field pub: %w", err) + } + + index++ + res.token, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field token: %w", err) + } + + return nil +} + +// itemToContainerEstimation converts stack item into *ContainerEstimation. +func itemToContainerEstimation(item stackitem.Item, err error) (*ContainerEstimation, error) { + if err != nil { + return nil, err + } + var res = new(ContainerEstimation) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ContainerEstimation from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ContainerEstimation) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.From, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field From: %w", err) + } + + index++ + res.Size, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Size: %w", err) + } + + return nil +} + +// itemToContainerExtendedACL converts stack item into *ContainerExtendedACL. +func itemToContainerExtendedACL(item stackitem.Item, err error) (*ContainerExtendedACL, error) { + if err != nil { + return nil, err + } + var res = new(ContainerExtendedACL) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ContainerExtendedACL from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ContainerExtendedACL) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 4 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.value, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field value: %w", err) + } + + index++ + res.sig, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field sig: %w", err) + } + + index++ + res.pub, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field pub: %w", err) + } + + index++ + res.token, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field token: %w", err) + } + + return nil +} + +// itemToContainercontainerSizes converts stack item into *ContainercontainerSizes. +func itemToContainercontainerSizes(item stackitem.Item, err error) (*ContainercontainerSizes, error) { + if err != nil { + return nil, err + } + var res = new(ContainercontainerSizes) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ContainercontainerSizes from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ContainercontainerSizes) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.cid, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field cid: %w", err) + } + + index++ + res.estimations, err = func (item stackitem.Item) ([]*ContainerEstimation, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ContainerEstimation, len(arr)) + for i := range res { + res[i], err = itemToContainerEstimation(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field estimations: %w", err) + } + + return nil +} + +// itemToLedgerBlock converts stack item into *LedgerBlock. +func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 9 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + return nil +} + +// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. +func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 10 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + index++ + res.PrevStateRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevStateRoot: %w", err) + } + + return nil +} + +// itemToLedgerTransaction converts stack item into *LedgerTransaction. +func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Sender, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + + index++ + res.SysFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + + index++ + res.NetFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + + index++ + res.ValidUntilBlock, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + + index++ + res.Script, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + + return nil +} + +// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. +func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Account, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Account: %w", err) + } + + index++ + res.Scopes, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Scopes: %w", err) + } + + index++ + res.AllowedContracts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedContracts: %w", err) + } + + index++ + res.AllowedGroups, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedGroups: %w", err) + } + + index++ + res.Rules, err = func (item stackitem.Item) ([]*LedgerWitnessRule, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*LedgerWitnessRule, len(arr)) + for i := range res { + res[i], err = itemToLedgerWitnessRule(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Rules: %w", err) + } + + return nil +} + +// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. +func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + index++ + res.Value, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} + +// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. +func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Action, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Action: %w", err) + } + + index++ + res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) + if err != nil { + return fmt.Errorf("field Condition: %w", err) + } + + return nil +} + +// itemToManagementABI converts stack item into *ManagementABI. +func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { + if err != nil { + return nil, err + } + var res = new(ManagementABI) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementABI from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementABI) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Methods, err = func (item stackitem.Item) ([]*ManagementMethod, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementMethod, len(arr)) + for i := range res { + res[i], err = itemToManagementMethod(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + index++ + res.Events, err = func (item stackitem.Item) ([]*ManagementEvent, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementEvent, len(arr)) + for i := range res { + res[i], err = itemToManagementEvent(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Events: %w", err) + } + + return nil +} + +// itemToManagementContract converts stack item into *ManagementContract. +func itemToManagementContract(item stackitem.Item, err error) (*ManagementContract, error) { + if err != nil { + return nil, err + } + var res = new(ManagementContract) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementContract from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementContract) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.UpdateCounter, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field UpdateCounter: %w", err) + } + + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.NEF, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field NEF: %w", err) + } + + index++ + res.Manifest, err = itemToManagementManifest(arr[index], nil) + if err != nil { + return fmt.Errorf("field Manifest: %w", err) + } + + return nil +} + +// itemToManagementEvent converts stack item into *ManagementEvent. +func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, error) { + if err != nil { + return nil, err + } + var res = new(ManagementEvent) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementEvent from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + return nil +} + +// itemToManagementGroup converts stack item into *ManagementGroup. +func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, error) { + if err != nil { + return nil, err + } + var res = new(ManagementGroup) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementGroup from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + index++ + res.Signature, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Signature: %w", err) + } + + return nil +} + +// itemToManagementManifest converts stack item into *ManagementManifest. +func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManifest, error) { + if err != nil { + return nil, err + } + var res = new(ManagementManifest) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementManifest from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Groups, err = func (item stackitem.Item) ([]*ManagementGroup, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementGroup, len(arr)) + for i := range res { + res[i], err = itemToManagementGroup(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Groups: %w", err) + } + + index++ + res.Features, err = func (item stackitem.Item) (map[string]string, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string]string) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Features: %w", err) + } + + index++ + res.SupportedStandards, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field SupportedStandards: %w", err) + } + + index++ + res.ABI, err = itemToManagementABI(arr[index], nil) + if err != nil { + return fmt.Errorf("field ABI: %w", err) + } + + index++ + res.Permissions, err = func (item stackitem.Item) ([]*ManagementPermission, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementPermission, len(arr)) + for i := range res { + res[i], err = itemToManagementPermission(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Permissions: %w", err) + } + + index++ + res.Trusts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Trusts: %w", err) + } + + index++ + res.Extra, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Extra: %w", err) + } + + return nil +} + +// itemToManagementMethod converts stack item into *ManagementMethod. +func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, error) { + if err != nil { + return nil, err + } + var res = new(ManagementMethod) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementMethod from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + index++ + res.ReturnType, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ReturnType: %w", err) + } + + index++ + res.Offset, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Offset: %w", err) + } + + index++ + res.Safe, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field Safe: %w", err) + } + + return nil +} + +// itemToManagementParameter converts stack item into *ManagementParameter. +func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParameter, error) { + if err != nil { + return nil, err + } + var res = new(ManagementParameter) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementParameter from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + return nil +} + +// itemToManagementPermission converts stack item into *ManagementPermission. +func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPermission, error) { + if err != nil { + return nil, err + } + var res = new(ManagementPermission) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementPermission from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Contract, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Contract: %w", err) + } + + index++ + res.Methods, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + return nil +} + +// PutSuccessEventsFromApplicationLog retrieves a set of all emitted events +// with "PutSuccess" name from the provided [result.ApplicationLog]. +func PutSuccessEventsFromApplicationLog(log *result.ApplicationLog) ([]*PutSuccessEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*PutSuccessEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "PutSuccess" { + continue + } + event := new(PutSuccessEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize PutSuccessEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to PutSuccessEvent or +// returns an error if it's not possible to do to so. +func (e *PutSuccessEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.ContainerID, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field ContainerID: %w", err) + } + + index++ + e.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + return nil +} + +// DeleteSuccessEventsFromApplicationLog retrieves a set of all emitted events +// with "DeleteSuccess" name from the provided [result.ApplicationLog]. +func DeleteSuccessEventsFromApplicationLog(log *result.ApplicationLog) ([]*DeleteSuccessEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*DeleteSuccessEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "DeleteSuccess" { + continue + } + event := new(DeleteSuccessEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize DeleteSuccessEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to DeleteSuccessEvent or +// returns an error if it's not possible to do to so. +func (e *DeleteSuccessEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.ContainerID, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field ContainerID: %w", err) + } + + return nil +} + +// SetEACLSuccessEventsFromApplicationLog retrieves a set of all emitted events +// with "SetEACLSuccess" name from the provided [result.ApplicationLog]. +func SetEACLSuccessEventsFromApplicationLog(log *result.ApplicationLog) ([]*SetEACLSuccessEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*SetEACLSuccessEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "SetEACLSuccess" { + continue + } + event := new(SetEACLSuccessEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize SetEACLSuccessEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to SetEACLSuccessEvent or +// returns an error if it's not possible to do to so. +func (e *SetEACLSuccessEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.ContainerID, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field ContainerID: %w", err) + } + + index++ + e.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + return nil +} + +// StartEstimationEventsFromApplicationLog retrieves a set of all emitted events +// with "StartEstimation" name from the provided [result.ApplicationLog]. +func StartEstimationEventsFromApplicationLog(log *result.ApplicationLog) ([]*StartEstimationEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*StartEstimationEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "StartEstimation" { + continue + } + event := new(StartEstimationEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize StartEstimationEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to StartEstimationEvent or +// returns an error if it's not possible to do to so. +func (e *StartEstimationEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.Epoch, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Epoch: %w", err) + } + + return nil +} + +// StopEstimationEventsFromApplicationLog retrieves a set of all emitted events +// with "StopEstimation" name from the provided [result.ApplicationLog]. +func StopEstimationEventsFromApplicationLog(log *result.ApplicationLog) ([]*StopEstimationEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*StopEstimationEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "StopEstimation" { + continue + } + event := new(StopEstimationEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize StopEstimationEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to StopEstimationEvent or +// returns an error if it's not possible to do to so. +func (e *StopEstimationEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.Epoch, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Epoch: %w", err) + } + + return nil +} diff --git a/rpc/neofs/rpcbinding.go b/rpc/neofs/rpcbinding.go new file mode 100644 index 00000000..4c27a882 --- /dev/null +++ b/rpc/neofs/rpcbinding.go @@ -0,0 +1,2455 @@ +// Package neofs contains RPC wrappers for NeoFS contract. +package neofs + +import ( + "crypto/elliptic" + "errors" + "fmt" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "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" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" + "unicode/utf8" +) + +// CommonBallot is a contract-specific common.Ballot type used by its methods. +type CommonBallot struct { + ID []byte + Voters keys.PublicKeys + Height *big.Int +} + +// CommonIRNode is a contract-specific common.IRNode type used by its methods. +type CommonIRNode struct { + PublicKey *keys.PublicKey +} + +// LedgerBlock is a contract-specific ledger.Block type used by its methods. +type LedgerBlock struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int +} + +// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. +type LedgerBlockSR struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int + PrevStateRoot util.Uint256 +} + +// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. +type LedgerTransaction struct { + Hash util.Uint256 + Version *big.Int + Nonce *big.Int + Sender util.Uint160 + SysFee *big.Int + NetFee *big.Int + ValidUntilBlock *big.Int + Script []byte +} + +// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. +type LedgerTransactionSigner struct { + Account util.Uint160 + Scopes *big.Int + AllowedContracts []util.Uint160 + AllowedGroups keys.PublicKeys + Rules []*LedgerWitnessRule +} + +// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. +type LedgerWitnessCondition struct { + Type *big.Int + Value any +} + +// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. +type LedgerWitnessRule struct { + Action *big.Int + Condition *LedgerWitnessCondition +} + +// ManagementABI is a contract-specific management.ABI type used by its methods. +type ManagementABI struct { + Methods []*ManagementMethod + Events []*ManagementEvent +} + +// ManagementContract is a contract-specific management.Contract type used by its methods. +type ManagementContract struct { + ID *big.Int + UpdateCounter *big.Int + Hash util.Uint160 + NEF []byte + Manifest *ManagementManifest +} + +// ManagementEvent is a contract-specific management.Event type used by its methods. +type ManagementEvent struct { + Name string + Params []*ManagementParameter +} + +// ManagementGroup is a contract-specific management.Group type used by its methods. +type ManagementGroup struct { + PublicKey *keys.PublicKey + Signature []byte +} + +// ManagementManifest is a contract-specific management.Manifest type used by its methods. +type ManagementManifest struct { + Name string + Groups []*ManagementGroup + Features map[string]string + SupportedStandards []string + ABI *ManagementABI + Permissions []*ManagementPermission + Trusts []util.Uint160 + Extra any +} + +// ManagementMethod is a contract-specific management.Method type used by its methods. +type ManagementMethod struct { + Name string + Params []*ManagementParameter + ReturnType *big.Int + Offset *big.Int + Safe bool +} + +// ManagementParameter is a contract-specific management.Parameter type used by its methods. +type ManagementParameter struct { + Name string + Type *big.Int +} + +// ManagementPermission is a contract-specific management.Permission type used by its methods. +type ManagementPermission struct { + Contract util.Uint160 + Methods []string +} + +// Neofsrecord is a contract-specific neofs.record type used by its methods. +type Neofsrecord struct { + key []byte + val []byte +} + +// DepositEvent represents "Deposit" event emitted by the contract. +type DepositEvent struct { + From util.Uint160 + Amount *big.Int + Receiver util.Uint160 + TxHash util.Uint256 +} + +// WithdrawEvent represents "Withdraw" event emitted by the contract. +type WithdrawEvent struct { + User util.Uint160 + Amount *big.Int + TxHash util.Uint256 +} + +// ChequeEvent represents "Cheque" event emitted by the contract. +type ChequeEvent struct { + Id []byte + User util.Uint160 + Amount *big.Int + LockAccount []byte +} + +// BindEvent represents "Bind" event emitted by the contract. +type BindEvent struct { + User []byte + Keys keys.PublicKeys +} + +// UnbindEvent represents "Unbind" event emitted by the contract. +type UnbindEvent struct { + User []byte + Keys keys.PublicKeys +} + +// AlphabetUpdateEvent represents "AlphabetUpdate" event emitted by the contract. +type AlphabetUpdateEvent struct { + Id []byte + Alphabet keys.PublicKeys +} + +// SetConfigEvent represents "SetConfig" event emitted by the contract. +type SetConfigEvent struct { + Id []byte + Key []byte + Value []byte +} + +// Invoker is used by ContractReader to call various safe methods. +type Invoker interface { + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) +} + +// Actor is used by Contract to call state-changing methods. +type Actor interface { + Invoker + + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeRun(script []byte) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) + SendRun(script []byte) (util.Uint256, uint32, error) +} + +// ContractReader implements safe contract methods. +type ContractReader struct { + invoker Invoker + hash util.Uint160 +} + +// Contract implements all contract methods. +type Contract struct { + ContractReader + actor Actor + hash util.Uint160 +} + +// NewReader creates an instance of ContractReader using provided contract hash and the given Invoker. +func NewReader(invoker Invoker, hash util.Uint160) *ContractReader { + return &ContractReader{invoker, hash} +} + +// New creates an instance of Contract using provided contract hash and the given Actor. +func New(actor Actor, hash util.Uint160) *Contract { + return &Contract{ContractReader{actor, hash}, actor, hash} +} + +// AlphabetAddress invokes `alphabetAddress` method of contract. +func (c *ContractReader) AlphabetAddress() (util.Uint160, error) { + return unwrap.Uint160(c.invoker.Call(c.hash, "alphabetAddress")) +} + +// AlphabetList invokes `alphabetList` method of contract. +func (c *ContractReader) AlphabetList() ([]*CommonIRNode, error) { + return func (item stackitem.Item, err error) ([]*CommonIRNode, error) { + if err != nil { + return nil, err + } + return func (item stackitem.Item) ([]*CommonIRNode, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*CommonIRNode, len(arr)) + for i := range res { + res[i], err = itemToCommonIRNode(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (item) + } (unwrap.Item(c.invoker.Call(c.hash, "alphabetList"))) +} + +// Config invokes `config` method of contract. +func (c *ContractReader) Config(key []byte) (any, error) { + return func (item stackitem.Item, err error) (any, error) { + if err != nil { + return nil, err + } + return item.Value(), error(nil) + } (unwrap.Item(c.invoker.Call(c.hash, "config", key))) +} + +// InnerRingCandidates invokes `innerRingCandidates` method of contract. +func (c *ContractReader) InnerRingCandidates() ([]*CommonIRNode, error) { + return func (item stackitem.Item, err error) ([]*CommonIRNode, error) { + if err != nil { + return nil, err + } + return func (item stackitem.Item) ([]*CommonIRNode, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*CommonIRNode, len(arr)) + for i := range res { + res[i], err = itemToCommonIRNode(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (item) + } (unwrap.Item(c.invoker.Call(c.hash, "innerRingCandidates"))) +} + +// ListConfig invokes `listConfig` method of contract. +func (c *ContractReader) ListConfig() ([]*Neofsrecord, error) { + return func (item stackitem.Item, err error) ([]*Neofsrecord, error) { + if err != nil { + return nil, err + } + return func (item stackitem.Item) ([]*Neofsrecord, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*Neofsrecord, len(arr)) + for i := range res { + res[i], err = itemToNeofsrecord(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (item) + } (unwrap.Item(c.invoker.Call(c.hash, "listConfig"))) +} + +// Version invokes `version` method of contract. +func (c *ContractReader) Version() (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "version")) +} + +// AlphabetUpdate creates a transaction invoking `alphabetUpdate` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) AlphabetUpdate(id []byte, args keys.PublicKeys) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "alphabetUpdate", id, args) +} + +// AlphabetUpdateTransaction creates a transaction invoking `alphabetUpdate` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) AlphabetUpdateTransaction(id []byte, args keys.PublicKeys) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "alphabetUpdate", id, args) +} + +// AlphabetUpdateUnsigned creates a transaction invoking `alphabetUpdate` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) AlphabetUpdateUnsigned(id []byte, args keys.PublicKeys) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "alphabetUpdate", nil, id, args) +} + +// Bind creates a transaction invoking `bind` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Bind(user []byte, keys keys.PublicKeys) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "bind", user, keys) +} + +// BindTransaction creates a transaction invoking `bind` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) BindTransaction(user []byte, keys keys.PublicKeys) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "bind", user, keys) +} + +// BindUnsigned creates a transaction invoking `bind` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) BindUnsigned(user []byte, keys keys.PublicKeys) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "bind", nil, user, keys) +} + +// Cheque creates a transaction invoking `cheque` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Cheque(id []byte, user util.Uint160, amount *big.Int, lockAcc []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "cheque", id, user, amount, lockAcc) +} + +// ChequeTransaction creates a transaction invoking `cheque` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) ChequeTransaction(id []byte, user util.Uint160, amount *big.Int, lockAcc []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "cheque", id, user, amount, lockAcc) +} + +// ChequeUnsigned creates a transaction invoking `cheque` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) ChequeUnsigned(id []byte, user util.Uint160, amount *big.Int, lockAcc []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "cheque", nil, id, user, amount, lockAcc) +} + +// InnerRingCandidateAdd creates a transaction invoking `innerRingCandidateAdd` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) InnerRingCandidateAdd(key *keys.PublicKey) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "innerRingCandidateAdd", key) +} + +// InnerRingCandidateAddTransaction creates a transaction invoking `innerRingCandidateAdd` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) InnerRingCandidateAddTransaction(key *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "innerRingCandidateAdd", key) +} + +// InnerRingCandidateAddUnsigned creates a transaction invoking `innerRingCandidateAdd` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) InnerRingCandidateAddUnsigned(key *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "innerRingCandidateAdd", nil, key) +} + +// InnerRingCandidateRemove creates a transaction invoking `innerRingCandidateRemove` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) InnerRingCandidateRemove(key *keys.PublicKey) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "innerRingCandidateRemove", key) +} + +// InnerRingCandidateRemoveTransaction creates a transaction invoking `innerRingCandidateRemove` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) InnerRingCandidateRemoveTransaction(key *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "innerRingCandidateRemove", key) +} + +// InnerRingCandidateRemoveUnsigned creates a transaction invoking `innerRingCandidateRemove` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) InnerRingCandidateRemoveUnsigned(key *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "innerRingCandidateRemove", nil, key) +} + +// SetConfig creates a transaction invoking `setConfig` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) SetConfig(id []byte, key []byte, val []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "setConfig", id, key, val) +} + +// SetConfigTransaction creates a transaction invoking `setConfig` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) SetConfigTransaction(id []byte, key []byte, val []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "setConfig", id, key, val) +} + +// SetConfigUnsigned creates a transaction invoking `setConfig` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) SetConfigUnsigned(id []byte, key []byte, val []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "setConfig", nil, id, key, val) +} + +// Unbind creates a transaction invoking `unbind` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Unbind(user []byte, keys keys.PublicKeys) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "unbind", user, keys) +} + +// UnbindTransaction creates a transaction invoking `unbind` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UnbindTransaction(user []byte, keys keys.PublicKeys) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "unbind", user, keys) +} + +// UnbindUnsigned creates a transaction invoking `unbind` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UnbindUnsigned(user []byte, keys keys.PublicKeys) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "unbind", nil, user, keys) +} + +// Update creates a transaction invoking `update` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Update(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "update", script, manifest, data) +} + +// UpdateTransaction creates a transaction invoking `update` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UpdateTransaction(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "update", script, manifest, data) +} + +// UpdateUnsigned creates a transaction invoking `update` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data) +} + +// Withdraw creates a transaction invoking `withdraw` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Withdraw(user util.Uint160, amount *big.Int) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "withdraw", user, amount) +} + +// WithdrawTransaction creates a transaction invoking `withdraw` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) WithdrawTransaction(user util.Uint160, amount *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "withdraw", user, amount) +} + +// WithdrawUnsigned creates a transaction invoking `withdraw` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) WithdrawUnsigned(user util.Uint160, amount *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "withdraw", nil, user, amount) +} + +// itemToCommonBallot converts stack item into *CommonBallot. +func itemToCommonBallot(item stackitem.Item, err error) (*CommonBallot, error) { + if err != nil { + return nil, err + } + var res = new(CommonBallot) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of CommonBallot from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *CommonBallot) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.Voters, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Voters: %w", err) + } + + index++ + res.Height, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Height: %w", err) + } + + return nil +} + +// itemToCommonIRNode converts stack item into *CommonIRNode. +func itemToCommonIRNode(item stackitem.Item, err error) (*CommonIRNode, error) { + if err != nil { + return nil, err + } + var res = new(CommonIRNode) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of CommonIRNode from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *CommonIRNode) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + return nil +} + +// itemToLedgerBlock converts stack item into *LedgerBlock. +func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 9 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + return nil +} + +// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. +func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 10 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + index++ + res.PrevStateRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevStateRoot: %w", err) + } + + return nil +} + +// itemToLedgerTransaction converts stack item into *LedgerTransaction. +func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Sender, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + + index++ + res.SysFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + + index++ + res.NetFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + + index++ + res.ValidUntilBlock, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + + index++ + res.Script, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + + return nil +} + +// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. +func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Account, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Account: %w", err) + } + + index++ + res.Scopes, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Scopes: %w", err) + } + + index++ + res.AllowedContracts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedContracts: %w", err) + } + + index++ + res.AllowedGroups, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedGroups: %w", err) + } + + index++ + res.Rules, err = func (item stackitem.Item) ([]*LedgerWitnessRule, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*LedgerWitnessRule, len(arr)) + for i := range res { + res[i], err = itemToLedgerWitnessRule(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Rules: %w", err) + } + + return nil +} + +// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. +func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + index++ + res.Value, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} + +// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. +func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Action, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Action: %w", err) + } + + index++ + res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) + if err != nil { + return fmt.Errorf("field Condition: %w", err) + } + + return nil +} + +// itemToManagementABI converts stack item into *ManagementABI. +func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { + if err != nil { + return nil, err + } + var res = new(ManagementABI) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementABI from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementABI) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Methods, err = func (item stackitem.Item) ([]*ManagementMethod, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementMethod, len(arr)) + for i := range res { + res[i], err = itemToManagementMethod(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + index++ + res.Events, err = func (item stackitem.Item) ([]*ManagementEvent, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementEvent, len(arr)) + for i := range res { + res[i], err = itemToManagementEvent(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Events: %w", err) + } + + return nil +} + +// itemToManagementContract converts stack item into *ManagementContract. +func itemToManagementContract(item stackitem.Item, err error) (*ManagementContract, error) { + if err != nil { + return nil, err + } + var res = new(ManagementContract) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementContract from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementContract) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.UpdateCounter, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field UpdateCounter: %w", err) + } + + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.NEF, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field NEF: %w", err) + } + + index++ + res.Manifest, err = itemToManagementManifest(arr[index], nil) + if err != nil { + return fmt.Errorf("field Manifest: %w", err) + } + + return nil +} + +// itemToManagementEvent converts stack item into *ManagementEvent. +func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, error) { + if err != nil { + return nil, err + } + var res = new(ManagementEvent) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementEvent from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + return nil +} + +// itemToManagementGroup converts stack item into *ManagementGroup. +func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, error) { + if err != nil { + return nil, err + } + var res = new(ManagementGroup) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementGroup from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + index++ + res.Signature, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Signature: %w", err) + } + + return nil +} + +// itemToManagementManifest converts stack item into *ManagementManifest. +func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManifest, error) { + if err != nil { + return nil, err + } + var res = new(ManagementManifest) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementManifest from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Groups, err = func (item stackitem.Item) ([]*ManagementGroup, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementGroup, len(arr)) + for i := range res { + res[i], err = itemToManagementGroup(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Groups: %w", err) + } + + index++ + res.Features, err = func (item stackitem.Item) (map[string]string, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string]string) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Features: %w", err) + } + + index++ + res.SupportedStandards, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field SupportedStandards: %w", err) + } + + index++ + res.ABI, err = itemToManagementABI(arr[index], nil) + if err != nil { + return fmt.Errorf("field ABI: %w", err) + } + + index++ + res.Permissions, err = func (item stackitem.Item) ([]*ManagementPermission, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementPermission, len(arr)) + for i := range res { + res[i], err = itemToManagementPermission(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Permissions: %w", err) + } + + index++ + res.Trusts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Trusts: %w", err) + } + + index++ + res.Extra, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Extra: %w", err) + } + + return nil +} + +// itemToManagementMethod converts stack item into *ManagementMethod. +func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, error) { + if err != nil { + return nil, err + } + var res = new(ManagementMethod) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementMethod from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + index++ + res.ReturnType, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ReturnType: %w", err) + } + + index++ + res.Offset, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Offset: %w", err) + } + + index++ + res.Safe, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field Safe: %w", err) + } + + return nil +} + +// itemToManagementParameter converts stack item into *ManagementParameter. +func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParameter, error) { + if err != nil { + return nil, err + } + var res = new(ManagementParameter) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementParameter from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + return nil +} + +// itemToManagementPermission converts stack item into *ManagementPermission. +func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPermission, error) { + if err != nil { + return nil, err + } + var res = new(ManagementPermission) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementPermission from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Contract, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Contract: %w", err) + } + + index++ + res.Methods, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + return nil +} + +// itemToNeofsrecord converts stack item into *Neofsrecord. +func itemToNeofsrecord(item stackitem.Item, err error) (*Neofsrecord, error) { + if err != nil { + return nil, err + } + var res = new(Neofsrecord) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of Neofsrecord from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *Neofsrecord) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.key, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field key: %w", err) + } + + index++ + res.val, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field val: %w", err) + } + + return nil +} + +// DepositEventsFromApplicationLog retrieves a set of all emitted events +// with "Deposit" name from the provided [result.ApplicationLog]. +func DepositEventsFromApplicationLog(log *result.ApplicationLog) ([]*DepositEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*DepositEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Deposit" { + continue + } + event := new(DepositEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize DepositEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to DepositEvent or +// returns an error if it's not possible to do to so. +func (e *DepositEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 4 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.From, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field From: %w", err) + } + + index++ + e.Amount, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Amount: %w", err) + } + + index++ + e.Receiver, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Receiver: %w", err) + } + + index++ + e.TxHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field TxHash: %w", err) + } + + return nil +} + +// WithdrawEventsFromApplicationLog retrieves a set of all emitted events +// with "Withdraw" name from the provided [result.ApplicationLog]. +func WithdrawEventsFromApplicationLog(log *result.ApplicationLog) ([]*WithdrawEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*WithdrawEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Withdraw" { + continue + } + event := new(WithdrawEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize WithdrawEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to WithdrawEvent or +// returns an error if it's not possible to do to so. +func (e *WithdrawEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.User, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field User: %w", err) + } + + index++ + e.Amount, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Amount: %w", err) + } + + index++ + e.TxHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field TxHash: %w", err) + } + + return nil +} + +// ChequeEventsFromApplicationLog retrieves a set of all emitted events +// with "Cheque" name from the provided [result.ApplicationLog]. +func ChequeEventsFromApplicationLog(log *result.ApplicationLog) ([]*ChequeEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*ChequeEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Cheque" { + continue + } + event := new(ChequeEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize ChequeEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to ChequeEvent or +// returns an error if it's not possible to do to so. +func (e *ChequeEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 4 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.Id, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Id: %w", err) + } + + index++ + e.User, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field User: %w", err) + } + + index++ + e.Amount, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Amount: %w", err) + } + + index++ + e.LockAccount, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field LockAccount: %w", err) + } + + return nil +} + +// BindEventsFromApplicationLog retrieves a set of all emitted events +// with "Bind" name from the provided [result.ApplicationLog]. +func BindEventsFromApplicationLog(log *result.ApplicationLog) ([]*BindEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*BindEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Bind" { + continue + } + event := new(BindEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize BindEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to BindEvent or +// returns an error if it's not possible to do to so. +func (e *BindEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.User, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field User: %w", err) + } + + index++ + e.Keys, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Keys: %w", err) + } + + return nil +} + +// UnbindEventsFromApplicationLog retrieves a set of all emitted events +// with "Unbind" name from the provided [result.ApplicationLog]. +func UnbindEventsFromApplicationLog(log *result.ApplicationLog) ([]*UnbindEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*UnbindEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Unbind" { + continue + } + event := new(UnbindEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize UnbindEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to UnbindEvent or +// returns an error if it's not possible to do to so. +func (e *UnbindEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.User, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field User: %w", err) + } + + index++ + e.Keys, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Keys: %w", err) + } + + return nil +} + +// AlphabetUpdateEventsFromApplicationLog retrieves a set of all emitted events +// with "AlphabetUpdate" name from the provided [result.ApplicationLog]. +func AlphabetUpdateEventsFromApplicationLog(log *result.ApplicationLog) ([]*AlphabetUpdateEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*AlphabetUpdateEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "AlphabetUpdate" { + continue + } + event := new(AlphabetUpdateEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize AlphabetUpdateEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to AlphabetUpdateEvent or +// returns an error if it's not possible to do to so. +func (e *AlphabetUpdateEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.Id, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Id: %w", err) + } + + index++ + e.Alphabet, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Alphabet: %w", err) + } + + return nil +} + +// SetConfigEventsFromApplicationLog retrieves a set of all emitted events +// with "SetConfig" name from the provided [result.ApplicationLog]. +func SetConfigEventsFromApplicationLog(log *result.ApplicationLog) ([]*SetConfigEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*SetConfigEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "SetConfig" { + continue + } + event := new(SetConfigEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize SetConfigEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to SetConfigEvent or +// returns an error if it's not possible to do to so. +func (e *SetConfigEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.Id, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Id: %w", err) + } + + index++ + e.Key, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Key: %w", err) + } + + index++ + e.Value, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} diff --git a/rpc/neofsid/rpcbinding.go b/rpc/neofsid/rpcbinding.go new file mode 100644 index 00000000..edd846d9 --- /dev/null +++ b/rpc/neofsid/rpcbinding.go @@ -0,0 +1,1582 @@ +// Package neofsid contains RPC wrappers for NeoFS ID contract. +package neofsid + +import ( + "crypto/elliptic" + "errors" + "fmt" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "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" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" + "unicode/utf8" +) + +// CommonBallot is a contract-specific common.Ballot type used by its methods. +type CommonBallot struct { + ID []byte + Voters keys.PublicKeys + Height *big.Int +} + +// LedgerBlock is a contract-specific ledger.Block type used by its methods. +type LedgerBlock struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int +} + +// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. +type LedgerBlockSR struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int + PrevStateRoot util.Uint256 +} + +// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. +type LedgerTransaction struct { + Hash util.Uint256 + Version *big.Int + Nonce *big.Int + Sender util.Uint160 + SysFee *big.Int + NetFee *big.Int + ValidUntilBlock *big.Int + Script []byte +} + +// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. +type LedgerTransactionSigner struct { + Account util.Uint160 + Scopes *big.Int + AllowedContracts []util.Uint160 + AllowedGroups keys.PublicKeys + Rules []*LedgerWitnessRule +} + +// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. +type LedgerWitnessCondition struct { + Type *big.Int + Value any +} + +// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. +type LedgerWitnessRule struct { + Action *big.Int + Condition *LedgerWitnessCondition +} + +// ManagementABI is a contract-specific management.ABI type used by its methods. +type ManagementABI struct { + Methods []*ManagementMethod + Events []*ManagementEvent +} + +// ManagementContract is a contract-specific management.Contract type used by its methods. +type ManagementContract struct { + ID *big.Int + UpdateCounter *big.Int + Hash util.Uint160 + NEF []byte + Manifest *ManagementManifest +} + +// ManagementEvent is a contract-specific management.Event type used by its methods. +type ManagementEvent struct { + Name string + Params []*ManagementParameter +} + +// ManagementGroup is a contract-specific management.Group type used by its methods. +type ManagementGroup struct { + PublicKey *keys.PublicKey + Signature []byte +} + +// ManagementManifest is a contract-specific management.Manifest type used by its methods. +type ManagementManifest struct { + Name string + Groups []*ManagementGroup + Features map[string]string + SupportedStandards []string + ABI *ManagementABI + Permissions []*ManagementPermission + Trusts []util.Uint160 + Extra any +} + +// ManagementMethod is a contract-specific management.Method type used by its methods. +type ManagementMethod struct { + Name string + Params []*ManagementParameter + ReturnType *big.Int + Offset *big.Int + Safe bool +} + +// ManagementParameter is a contract-specific management.Parameter type used by its methods. +type ManagementParameter struct { + Name string + Type *big.Int +} + +// ManagementPermission is a contract-specific management.Permission type used by its methods. +type ManagementPermission struct { + Contract util.Uint160 + Methods []string +} + +// NeofsidUserInfo is a contract-specific neofsid.UserInfo type used by its methods. +type NeofsidUserInfo struct { + Keys [][]byte +} + +// Invoker is used by ContractReader to call various safe methods. +type Invoker interface { + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) +} + +// Actor is used by Contract to call state-changing methods. +type Actor interface { + Invoker + + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeRun(script []byte) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) + SendRun(script []byte) (util.Uint256, uint32, error) +} + +// ContractReader implements safe contract methods. +type ContractReader struct { + invoker Invoker + hash util.Uint160 +} + +// Contract implements all contract methods. +type Contract struct { + ContractReader + actor Actor + hash util.Uint160 +} + +// NewReader creates an instance of ContractReader using provided contract hash and the given Invoker. +func NewReader(invoker Invoker, hash util.Uint160) *ContractReader { + return &ContractReader{invoker, hash} +} + +// New creates an instance of Contract using provided contract hash and the given Actor. +func New(actor Actor, hash util.Uint160) *Contract { + return &Contract{ContractReader{actor, hash}, actor, hash} +} + +// Key invokes `key` method of contract. +func (c *ContractReader) Key(owner []byte) ([][]byte, error) { + return unwrap.ArrayOfBytes(c.invoker.Call(c.hash, "key", owner)) +} + +// Version invokes `version` method of contract. +func (c *ContractReader) Version() (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "version")) +} + +// AddKey creates a transaction invoking `addKey` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) AddKey(owner []byte, keys keys.PublicKeys) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "addKey", owner, keys) +} + +// AddKeyTransaction creates a transaction invoking `addKey` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) AddKeyTransaction(owner []byte, keys keys.PublicKeys) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "addKey", owner, keys) +} + +// AddKeyUnsigned creates a transaction invoking `addKey` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) AddKeyUnsigned(owner []byte, keys keys.PublicKeys) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "addKey", nil, owner, keys) +} + +// RemoveKey creates a transaction invoking `removeKey` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) RemoveKey(owner []byte, keys keys.PublicKeys) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "removeKey", owner, keys) +} + +// RemoveKeyTransaction creates a transaction invoking `removeKey` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) RemoveKeyTransaction(owner []byte, keys keys.PublicKeys) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "removeKey", owner, keys) +} + +// RemoveKeyUnsigned creates a transaction invoking `removeKey` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) RemoveKeyUnsigned(owner []byte, keys keys.PublicKeys) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "removeKey", nil, owner, keys) +} + +// Update creates a transaction invoking `update` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Update(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "update", script, manifest, data) +} + +// UpdateTransaction creates a transaction invoking `update` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UpdateTransaction(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "update", script, manifest, data) +} + +// UpdateUnsigned creates a transaction invoking `update` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data) +} + +// itemToCommonBallot converts stack item into *CommonBallot. +func itemToCommonBallot(item stackitem.Item, err error) (*CommonBallot, error) { + if err != nil { + return nil, err + } + var res = new(CommonBallot) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of CommonBallot from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *CommonBallot) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.Voters, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Voters: %w", err) + } + + index++ + res.Height, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Height: %w", err) + } + + return nil +} + +// itemToLedgerBlock converts stack item into *LedgerBlock. +func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 9 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + return nil +} + +// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. +func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 10 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + index++ + res.PrevStateRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevStateRoot: %w", err) + } + + return nil +} + +// itemToLedgerTransaction converts stack item into *LedgerTransaction. +func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Sender, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + + index++ + res.SysFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + + index++ + res.NetFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + + index++ + res.ValidUntilBlock, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + + index++ + res.Script, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + + return nil +} + +// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. +func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Account, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Account: %w", err) + } + + index++ + res.Scopes, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Scopes: %w", err) + } + + index++ + res.AllowedContracts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedContracts: %w", err) + } + + index++ + res.AllowedGroups, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedGroups: %w", err) + } + + index++ + res.Rules, err = func (item stackitem.Item) ([]*LedgerWitnessRule, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*LedgerWitnessRule, len(arr)) + for i := range res { + res[i], err = itemToLedgerWitnessRule(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Rules: %w", err) + } + + return nil +} + +// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. +func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + index++ + res.Value, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} + +// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. +func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Action, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Action: %w", err) + } + + index++ + res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) + if err != nil { + return fmt.Errorf("field Condition: %w", err) + } + + return nil +} + +// itemToManagementABI converts stack item into *ManagementABI. +func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { + if err != nil { + return nil, err + } + var res = new(ManagementABI) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementABI from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementABI) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Methods, err = func (item stackitem.Item) ([]*ManagementMethod, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementMethod, len(arr)) + for i := range res { + res[i], err = itemToManagementMethod(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + index++ + res.Events, err = func (item stackitem.Item) ([]*ManagementEvent, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementEvent, len(arr)) + for i := range res { + res[i], err = itemToManagementEvent(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Events: %w", err) + } + + return nil +} + +// itemToManagementContract converts stack item into *ManagementContract. +func itemToManagementContract(item stackitem.Item, err error) (*ManagementContract, error) { + if err != nil { + return nil, err + } + var res = new(ManagementContract) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementContract from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementContract) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.UpdateCounter, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field UpdateCounter: %w", err) + } + + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.NEF, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field NEF: %w", err) + } + + index++ + res.Manifest, err = itemToManagementManifest(arr[index], nil) + if err != nil { + return fmt.Errorf("field Manifest: %w", err) + } + + return nil +} + +// itemToManagementEvent converts stack item into *ManagementEvent. +func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, error) { + if err != nil { + return nil, err + } + var res = new(ManagementEvent) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementEvent from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + return nil +} + +// itemToManagementGroup converts stack item into *ManagementGroup. +func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, error) { + if err != nil { + return nil, err + } + var res = new(ManagementGroup) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementGroup from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + index++ + res.Signature, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Signature: %w", err) + } + + return nil +} + +// itemToManagementManifest converts stack item into *ManagementManifest. +func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManifest, error) { + if err != nil { + return nil, err + } + var res = new(ManagementManifest) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementManifest from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Groups, err = func (item stackitem.Item) ([]*ManagementGroup, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementGroup, len(arr)) + for i := range res { + res[i], err = itemToManagementGroup(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Groups: %w", err) + } + + index++ + res.Features, err = func (item stackitem.Item) (map[string]string, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string]string) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Features: %w", err) + } + + index++ + res.SupportedStandards, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field SupportedStandards: %w", err) + } + + index++ + res.ABI, err = itemToManagementABI(arr[index], nil) + if err != nil { + return fmt.Errorf("field ABI: %w", err) + } + + index++ + res.Permissions, err = func (item stackitem.Item) ([]*ManagementPermission, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementPermission, len(arr)) + for i := range res { + res[i], err = itemToManagementPermission(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Permissions: %w", err) + } + + index++ + res.Trusts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Trusts: %w", err) + } + + index++ + res.Extra, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Extra: %w", err) + } + + return nil +} + +// itemToManagementMethod converts stack item into *ManagementMethod. +func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, error) { + if err != nil { + return nil, err + } + var res = new(ManagementMethod) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementMethod from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + index++ + res.ReturnType, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ReturnType: %w", err) + } + + index++ + res.Offset, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Offset: %w", err) + } + + index++ + res.Safe, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field Safe: %w", err) + } + + return nil +} + +// itemToManagementParameter converts stack item into *ManagementParameter. +func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParameter, error) { + if err != nil { + return nil, err + } + var res = new(ManagementParameter) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementParameter from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + return nil +} + +// itemToManagementPermission converts stack item into *ManagementPermission. +func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPermission, error) { + if err != nil { + return nil, err + } + var res = new(ManagementPermission) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementPermission from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Contract, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Contract: %w", err) + } + + index++ + res.Methods, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + return nil +} + +// itemToNeofsidUserInfo converts stack item into *NeofsidUserInfo. +func itemToNeofsidUserInfo(item stackitem.Item, err error) (*NeofsidUserInfo, error) { + if err != nil { + return nil, err + } + var res = new(NeofsidUserInfo) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of NeofsidUserInfo from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *NeofsidUserInfo) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Keys, err = func (item stackitem.Item) ([][]byte, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([][]byte, len(arr)) + for i := range res { + res[i], err = arr[i].TryBytes() + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Keys: %w", err) + } + + return nil +} diff --git a/rpc/netmap/rpcbinding.go b/rpc/netmap/rpcbinding.go new file mode 100644 index 00000000..b8c6564a --- /dev/null +++ b/rpc/netmap/rpcbinding.go @@ -0,0 +1,2149 @@ +// Package netmap contains RPC wrappers for NeoFS Netmap contract. +package netmap + +import ( + "crypto/elliptic" + "errors" + "fmt" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "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" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" + "unicode/utf8" +) + +// CommonBallot is a contract-specific common.Ballot type used by its methods. +type CommonBallot struct { + ID []byte + Voters keys.PublicKeys + Height *big.Int +} + +// CommonIRNode is a contract-specific common.IRNode type used by its methods. +type CommonIRNode struct { + PublicKey *keys.PublicKey +} + +// LedgerBlock is a contract-specific ledger.Block type used by its methods. +type LedgerBlock struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int +} + +// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. +type LedgerBlockSR struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int + PrevStateRoot util.Uint256 +} + +// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. +type LedgerTransaction struct { + Hash util.Uint256 + Version *big.Int + Nonce *big.Int + Sender util.Uint160 + SysFee *big.Int + NetFee *big.Int + ValidUntilBlock *big.Int + Script []byte +} + +// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. +type LedgerTransactionSigner struct { + Account util.Uint160 + Scopes *big.Int + AllowedContracts []util.Uint160 + AllowedGroups keys.PublicKeys + Rules []*LedgerWitnessRule +} + +// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. +type LedgerWitnessCondition struct { + Type *big.Int + Value any +} + +// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. +type LedgerWitnessRule struct { + Action *big.Int + Condition *LedgerWitnessCondition +} + +// ManagementABI is a contract-specific management.ABI type used by its methods. +type ManagementABI struct { + Methods []*ManagementMethod + Events []*ManagementEvent +} + +// ManagementContract is a contract-specific management.Contract type used by its methods. +type ManagementContract struct { + ID *big.Int + UpdateCounter *big.Int + Hash util.Uint160 + NEF []byte + Manifest *ManagementManifest +} + +// ManagementEvent is a contract-specific management.Event type used by its methods. +type ManagementEvent struct { + Name string + Params []*ManagementParameter +} + +// ManagementGroup is a contract-specific management.Group type used by its methods. +type ManagementGroup struct { + PublicKey *keys.PublicKey + Signature []byte +} + +// ManagementManifest is a contract-specific management.Manifest type used by its methods. +type ManagementManifest struct { + Name string + Groups []*ManagementGroup + Features map[string]string + SupportedStandards []string + ABI *ManagementABI + Permissions []*ManagementPermission + Trusts []util.Uint160 + Extra any +} + +// ManagementMethod is a contract-specific management.Method type used by its methods. +type ManagementMethod struct { + Name string + Params []*ManagementParameter + ReturnType *big.Int + Offset *big.Int + Safe bool +} + +// ManagementParameter is a contract-specific management.Parameter type used by its methods. +type ManagementParameter struct { + Name string + Type *big.Int +} + +// ManagementPermission is a contract-specific management.Permission type used by its methods. +type ManagementPermission struct { + Contract util.Uint160 + Methods []string +} + +// NetmapNode is a contract-specific netmap.Node type used by its methods. +type NetmapNode struct { + BLOB []byte + State *big.Int +} + +// Netmaprecord is a contract-specific netmap.record type used by its methods. +type Netmaprecord struct { + key []byte + val []byte +} + +// AddPeerSuccessEvent represents "AddPeerSuccess" event emitted by the contract. +type AddPeerSuccessEvent struct { + PublicKey *keys.PublicKey +} + +// UpdateStateSuccessEvent represents "UpdateStateSuccess" event emitted by the contract. +type UpdateStateSuccessEvent struct { + PublicKey *keys.PublicKey + State *big.Int +} + +// NewEpochEvent represents "NewEpoch" event emitted by the contract. +type NewEpochEvent struct { + Epoch *big.Int +} + +// Invoker is used by ContractReader to call various safe methods. +type Invoker interface { + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) +} + +// Actor is used by Contract to call state-changing methods. +type Actor interface { + Invoker + + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeRun(script []byte) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) + SendRun(script []byte) (util.Uint256, uint32, error) +} + +// ContractReader implements safe contract methods. +type ContractReader struct { + invoker Invoker + hash util.Uint160 +} + +// Contract implements all contract methods. +type Contract struct { + ContractReader + actor Actor + hash util.Uint160 +} + +// NewReader creates an instance of ContractReader using provided contract hash and the given Invoker. +func NewReader(invoker Invoker, hash util.Uint160) *ContractReader { + return &ContractReader{invoker, hash} +} + +// New creates an instance of Contract using provided contract hash and the given Actor. +func New(actor Actor, hash util.Uint160) *Contract { + return &Contract{ContractReader{actor, hash}, actor, hash} +} + +// Config invokes `config` method of contract. +func (c *ContractReader) Config(key []byte) (any, error) { + return func (item stackitem.Item, err error) (any, error) { + if err != nil { + return nil, err + } + return item.Value(), error(nil) + } (unwrap.Item(c.invoker.Call(c.hash, "config", key))) +} + +// Epoch invokes `epoch` method of contract. +func (c *ContractReader) Epoch() (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "epoch")) +} + +// InnerRingList invokes `innerRingList` method of contract. +func (c *ContractReader) InnerRingList() ([]*CommonIRNode, error) { + return func (item stackitem.Item, err error) ([]*CommonIRNode, error) { + if err != nil { + return nil, err + } + return func (item stackitem.Item) ([]*CommonIRNode, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*CommonIRNode, len(arr)) + for i := range res { + res[i], err = itemToCommonIRNode(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (item) + } (unwrap.Item(c.invoker.Call(c.hash, "innerRingList"))) +} + +// ListConfig invokes `listConfig` method of contract. +func (c *ContractReader) ListConfig() ([]*Netmaprecord, error) { + return func (item stackitem.Item, err error) ([]*Netmaprecord, error) { + if err != nil { + return nil, err + } + return func (item stackitem.Item) ([]*Netmaprecord, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*Netmaprecord, len(arr)) + for i := range res { + res[i], err = itemToNetmaprecord(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (item) + } (unwrap.Item(c.invoker.Call(c.hash, "listConfig"))) +} + +// Netmap invokes `netmap` method of contract. +func (c *ContractReader) Netmap() ([]*NetmapNode, error) { + return func (item stackitem.Item, err error) ([]*NetmapNode, error) { + if err != nil { + return nil, err + } + return func (item stackitem.Item) ([]*NetmapNode, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*NetmapNode, len(arr)) + for i := range res { + res[i], err = itemToNetmapNode(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (item) + } (unwrap.Item(c.invoker.Call(c.hash, "netmap"))) +} + +// NetmapCandidates invokes `netmapCandidates` method of contract. +func (c *ContractReader) NetmapCandidates() ([]*NetmapNode, error) { + return func (item stackitem.Item, err error) ([]*NetmapNode, error) { + if err != nil { + return nil, err + } + return func (item stackitem.Item) ([]*NetmapNode, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*NetmapNode, len(arr)) + for i := range res { + res[i], err = itemToNetmapNode(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (item) + } (unwrap.Item(c.invoker.Call(c.hash, "netmapCandidates"))) +} + +// Snapshot invokes `snapshot` method of contract. +func (c *ContractReader) Snapshot(diff *big.Int) ([]*NetmapNode, error) { + return func (item stackitem.Item, err error) ([]*NetmapNode, error) { + if err != nil { + return nil, err + } + return func (item stackitem.Item) ([]*NetmapNode, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*NetmapNode, len(arr)) + for i := range res { + res[i], err = itemToNetmapNode(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (item) + } (unwrap.Item(c.invoker.Call(c.hash, "snapshot", diff))) +} + +// SnapshotByEpoch invokes `snapshotByEpoch` method of contract. +func (c *ContractReader) SnapshotByEpoch(epoch *big.Int) ([]*NetmapNode, error) { + return func (item stackitem.Item, err error) ([]*NetmapNode, error) { + if err != nil { + return nil, err + } + return func (item stackitem.Item) ([]*NetmapNode, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*NetmapNode, len(arr)) + for i := range res { + res[i], err = itemToNetmapNode(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (item) + } (unwrap.Item(c.invoker.Call(c.hash, "snapshotByEpoch", epoch))) +} + +// Version invokes `version` method of contract. +func (c *ContractReader) Version() (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "version")) +} + +// AddPeer creates a transaction invoking `addPeer` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) AddPeer(nodeInfo []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "addPeer", nodeInfo) +} + +// AddPeerTransaction creates a transaction invoking `addPeer` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) AddPeerTransaction(nodeInfo []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "addPeer", nodeInfo) +} + +// AddPeerUnsigned creates a transaction invoking `addPeer` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) AddPeerUnsigned(nodeInfo []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "addPeer", nil, nodeInfo) +} + +// AddPeerIR creates a transaction invoking `addPeerIR` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) AddPeerIR(nodeInfo []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "addPeerIR", nodeInfo) +} + +// AddPeerIRTransaction creates a transaction invoking `addPeerIR` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) AddPeerIRTransaction(nodeInfo []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "addPeerIR", nodeInfo) +} + +// AddPeerIRUnsigned creates a transaction invoking `addPeerIR` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) AddPeerIRUnsigned(nodeInfo []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "addPeerIR", nil, nodeInfo) +} + +// LastEpochBlock creates a transaction invoking `lastEpochBlock` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) LastEpochBlock() (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "lastEpochBlock") +} + +// LastEpochBlockTransaction creates a transaction invoking `lastEpochBlock` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) LastEpochBlockTransaction() (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "lastEpochBlock") +} + +// LastEpochBlockUnsigned creates a transaction invoking `lastEpochBlock` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) LastEpochBlockUnsigned() (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "lastEpochBlock", nil) +} + +// NewEpoch creates a transaction invoking `newEpoch` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) NewEpoch(epochNum *big.Int) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "newEpoch", epochNum) +} + +// NewEpochTransaction creates a transaction invoking `newEpoch` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) NewEpochTransaction(epochNum *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "newEpoch", epochNum) +} + +// NewEpochUnsigned creates a transaction invoking `newEpoch` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) NewEpochUnsigned(epochNum *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "newEpoch", nil, epochNum) +} + +// SetConfig creates a transaction invoking `setConfig` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) SetConfig(id []byte, key []byte, val []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "setConfig", id, key, val) +} + +// SetConfigTransaction creates a transaction invoking `setConfig` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) SetConfigTransaction(id []byte, key []byte, val []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "setConfig", id, key, val) +} + +// SetConfigUnsigned creates a transaction invoking `setConfig` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) SetConfigUnsigned(id []byte, key []byte, val []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "setConfig", nil, id, key, val) +} + +// Update creates a transaction invoking `update` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Update(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "update", script, manifest, data) +} + +// UpdateTransaction creates a transaction invoking `update` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UpdateTransaction(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "update", script, manifest, data) +} + +// UpdateUnsigned creates a transaction invoking `update` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data) +} + +// UpdateSnapshotCount creates a transaction invoking `updateSnapshotCount` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) UpdateSnapshotCount(count *big.Int) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "updateSnapshotCount", count) +} + +// UpdateSnapshotCountTransaction creates a transaction invoking `updateSnapshotCount` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UpdateSnapshotCountTransaction(count *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "updateSnapshotCount", count) +} + +// UpdateSnapshotCountUnsigned creates a transaction invoking `updateSnapshotCount` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UpdateSnapshotCountUnsigned(count *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "updateSnapshotCount", nil, count) +} + +// UpdateState creates a transaction invoking `updateState` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) UpdateState(state *big.Int, publicKey *keys.PublicKey) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "updateState", state, publicKey) +} + +// UpdateStateTransaction creates a transaction invoking `updateState` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UpdateStateTransaction(state *big.Int, publicKey *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "updateState", state, publicKey) +} + +// UpdateStateUnsigned creates a transaction invoking `updateState` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UpdateStateUnsigned(state *big.Int, publicKey *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "updateState", nil, state, publicKey) +} + +// UpdateStateIR creates a transaction invoking `updateStateIR` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) UpdateStateIR(state *big.Int, publicKey *keys.PublicKey) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "updateStateIR", state, publicKey) +} + +// UpdateStateIRTransaction creates a transaction invoking `updateStateIR` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UpdateStateIRTransaction(state *big.Int, publicKey *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "updateStateIR", state, publicKey) +} + +// UpdateStateIRUnsigned creates a transaction invoking `updateStateIR` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UpdateStateIRUnsigned(state *big.Int, publicKey *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "updateStateIR", nil, state, publicKey) +} + +// itemToCommonBallot converts stack item into *CommonBallot. +func itemToCommonBallot(item stackitem.Item, err error) (*CommonBallot, error) { + if err != nil { + return nil, err + } + var res = new(CommonBallot) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of CommonBallot from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *CommonBallot) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.Voters, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Voters: %w", err) + } + + index++ + res.Height, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Height: %w", err) + } + + return nil +} + +// itemToCommonIRNode converts stack item into *CommonIRNode. +func itemToCommonIRNode(item stackitem.Item, err error) (*CommonIRNode, error) { + if err != nil { + return nil, err + } + var res = new(CommonIRNode) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of CommonIRNode from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *CommonIRNode) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + return nil +} + +// itemToLedgerBlock converts stack item into *LedgerBlock. +func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 9 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + return nil +} + +// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. +func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 10 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + index++ + res.PrevStateRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevStateRoot: %w", err) + } + + return nil +} + +// itemToLedgerTransaction converts stack item into *LedgerTransaction. +func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Sender, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + + index++ + res.SysFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + + index++ + res.NetFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + + index++ + res.ValidUntilBlock, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + + index++ + res.Script, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + + return nil +} + +// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. +func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Account, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Account: %w", err) + } + + index++ + res.Scopes, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Scopes: %w", err) + } + + index++ + res.AllowedContracts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedContracts: %w", err) + } + + index++ + res.AllowedGroups, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedGroups: %w", err) + } + + index++ + res.Rules, err = func (item stackitem.Item) ([]*LedgerWitnessRule, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*LedgerWitnessRule, len(arr)) + for i := range res { + res[i], err = itemToLedgerWitnessRule(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Rules: %w", err) + } + + return nil +} + +// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. +func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + index++ + res.Value, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} + +// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. +func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Action, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Action: %w", err) + } + + index++ + res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) + if err != nil { + return fmt.Errorf("field Condition: %w", err) + } + + return nil +} + +// itemToManagementABI converts stack item into *ManagementABI. +func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { + if err != nil { + return nil, err + } + var res = new(ManagementABI) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementABI from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementABI) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Methods, err = func (item stackitem.Item) ([]*ManagementMethod, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementMethod, len(arr)) + for i := range res { + res[i], err = itemToManagementMethod(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + index++ + res.Events, err = func (item stackitem.Item) ([]*ManagementEvent, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementEvent, len(arr)) + for i := range res { + res[i], err = itemToManagementEvent(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Events: %w", err) + } + + return nil +} + +// itemToManagementContract converts stack item into *ManagementContract. +func itemToManagementContract(item stackitem.Item, err error) (*ManagementContract, error) { + if err != nil { + return nil, err + } + var res = new(ManagementContract) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementContract from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementContract) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.UpdateCounter, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field UpdateCounter: %w", err) + } + + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.NEF, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field NEF: %w", err) + } + + index++ + res.Manifest, err = itemToManagementManifest(arr[index], nil) + if err != nil { + return fmt.Errorf("field Manifest: %w", err) + } + + return nil +} + +// itemToManagementEvent converts stack item into *ManagementEvent. +func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, error) { + if err != nil { + return nil, err + } + var res = new(ManagementEvent) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementEvent from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + return nil +} + +// itemToManagementGroup converts stack item into *ManagementGroup. +func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, error) { + if err != nil { + return nil, err + } + var res = new(ManagementGroup) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementGroup from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + index++ + res.Signature, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Signature: %w", err) + } + + return nil +} + +// itemToManagementManifest converts stack item into *ManagementManifest. +func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManifest, error) { + if err != nil { + return nil, err + } + var res = new(ManagementManifest) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementManifest from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Groups, err = func (item stackitem.Item) ([]*ManagementGroup, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementGroup, len(arr)) + for i := range res { + res[i], err = itemToManagementGroup(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Groups: %w", err) + } + + index++ + res.Features, err = func (item stackitem.Item) (map[string]string, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string]string) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Features: %w", err) + } + + index++ + res.SupportedStandards, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field SupportedStandards: %w", err) + } + + index++ + res.ABI, err = itemToManagementABI(arr[index], nil) + if err != nil { + return fmt.Errorf("field ABI: %w", err) + } + + index++ + res.Permissions, err = func (item stackitem.Item) ([]*ManagementPermission, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementPermission, len(arr)) + for i := range res { + res[i], err = itemToManagementPermission(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Permissions: %w", err) + } + + index++ + res.Trusts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Trusts: %w", err) + } + + index++ + res.Extra, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Extra: %w", err) + } + + return nil +} + +// itemToManagementMethod converts stack item into *ManagementMethod. +func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, error) { + if err != nil { + return nil, err + } + var res = new(ManagementMethod) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementMethod from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + index++ + res.ReturnType, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ReturnType: %w", err) + } + + index++ + res.Offset, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Offset: %w", err) + } + + index++ + res.Safe, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field Safe: %w", err) + } + + return nil +} + +// itemToManagementParameter converts stack item into *ManagementParameter. +func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParameter, error) { + if err != nil { + return nil, err + } + var res = new(ManagementParameter) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementParameter from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + return nil +} + +// itemToManagementPermission converts stack item into *ManagementPermission. +func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPermission, error) { + if err != nil { + return nil, err + } + var res = new(ManagementPermission) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementPermission from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Contract, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Contract: %w", err) + } + + index++ + res.Methods, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + return nil +} + +// itemToNetmapNode converts stack item into *NetmapNode. +func itemToNetmapNode(item stackitem.Item, err error) (*NetmapNode, error) { + if err != nil { + return nil, err + } + var res = new(NetmapNode) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of NetmapNode from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *NetmapNode) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.BLOB, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field BLOB: %w", err) + } + + index++ + res.State, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field State: %w", err) + } + + return nil +} + +// itemToNetmaprecord converts stack item into *Netmaprecord. +func itemToNetmaprecord(item stackitem.Item, err error) (*Netmaprecord, error) { + if err != nil { + return nil, err + } + var res = new(Netmaprecord) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of Netmaprecord from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *Netmaprecord) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.key, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field key: %w", err) + } + + index++ + res.val, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field val: %w", err) + } + + return nil +} + +// AddPeerSuccessEventsFromApplicationLog retrieves a set of all emitted events +// with "AddPeerSuccess" name from the provided [result.ApplicationLog]. +func AddPeerSuccessEventsFromApplicationLog(log *result.ApplicationLog) ([]*AddPeerSuccessEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*AddPeerSuccessEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "AddPeerSuccess" { + continue + } + event := new(AddPeerSuccessEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize AddPeerSuccessEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to AddPeerSuccessEvent or +// returns an error if it's not possible to do to so. +func (e *AddPeerSuccessEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + return nil +} + +// UpdateStateSuccessEventsFromApplicationLog retrieves a set of all emitted events +// with "UpdateStateSuccess" name from the provided [result.ApplicationLog]. +func UpdateStateSuccessEventsFromApplicationLog(log *result.ApplicationLog) ([]*UpdateStateSuccessEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*UpdateStateSuccessEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "UpdateStateSuccess" { + continue + } + event := new(UpdateStateSuccessEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize UpdateStateSuccessEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to UpdateStateSuccessEvent or +// returns an error if it's not possible to do to so. +func (e *UpdateStateSuccessEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + index++ + e.State, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field State: %w", err) + } + + return nil +} + +// NewEpochEventsFromApplicationLog retrieves a set of all emitted events +// with "NewEpoch" name from the provided [result.ApplicationLog]. +func NewEpochEventsFromApplicationLog(log *result.ApplicationLog) ([]*NewEpochEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*NewEpochEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "NewEpoch" { + continue + } + event := new(NewEpochEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize NewEpochEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to NewEpochEvent or +// returns an error if it's not possible to do to so. +func (e *NewEpochEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.Epoch, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Epoch: %w", err) + } + + return nil +} diff --git a/rpc/nns/rpcbinding.go b/rpc/nns/rpcbinding.go new file mode 100644 index 00000000..0e76d3bd --- /dev/null +++ b/rpc/nns/rpcbinding.go @@ -0,0 +1,1848 @@ +// Package nns contains RPC wrappers for NameService contract. +package nns + +import ( + "crypto/elliptic" + "errors" + "fmt" + "github.com/google/uuid" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "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/nep11" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" + "github.com/nspcc-dev/neo-go/pkg/smartcontract" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" + "unicode/utf8" +) + +// CommonBallot is a contract-specific common.Ballot type used by its methods. +type CommonBallot struct { + ID []byte + Voters keys.PublicKeys + Height *big.Int +} + +// LedgerBlock is a contract-specific ledger.Block type used by its methods. +type LedgerBlock struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int +} + +// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. +type LedgerBlockSR struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int + PrevStateRoot util.Uint256 +} + +// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. +type LedgerTransaction struct { + Hash util.Uint256 + Version *big.Int + Nonce *big.Int + Sender util.Uint160 + SysFee *big.Int + NetFee *big.Int + ValidUntilBlock *big.Int + Script []byte +} + +// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. +type LedgerTransactionSigner struct { + Account util.Uint160 + Scopes *big.Int + AllowedContracts []util.Uint160 + AllowedGroups keys.PublicKeys + Rules []*LedgerWitnessRule +} + +// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. +type LedgerWitnessCondition struct { + Type *big.Int + Value any +} + +// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. +type LedgerWitnessRule struct { + Action *big.Int + Condition *LedgerWitnessCondition +} + +// ManagementABI is a contract-specific management.ABI type used by its methods. +type ManagementABI struct { + Methods []*ManagementMethod + Events []*ManagementEvent +} + +// ManagementContract is a contract-specific management.Contract type used by its methods. +type ManagementContract struct { + ID *big.Int + UpdateCounter *big.Int + Hash util.Uint160 + NEF []byte + Manifest *ManagementManifest +} + +// ManagementEvent is a contract-specific management.Event type used by its methods. +type ManagementEvent struct { + Name string + Params []*ManagementParameter +} + +// ManagementGroup is a contract-specific management.Group type used by its methods. +type ManagementGroup struct { + PublicKey *keys.PublicKey + Signature []byte +} + +// ManagementManifest is a contract-specific management.Manifest type used by its methods. +type ManagementManifest struct { + Name string + Groups []*ManagementGroup + Features map[string]string + SupportedStandards []string + ABI *ManagementABI + Permissions []*ManagementPermission + Trusts []util.Uint160 + Extra any +} + +// ManagementMethod is a contract-specific management.Method type used by its methods. +type ManagementMethod struct { + Name string + Params []*ManagementParameter + ReturnType *big.Int + Offset *big.Int + Safe bool +} + +// ManagementParameter is a contract-specific management.Parameter type used by its methods. +type ManagementParameter struct { + Name string + Type *big.Int +} + +// ManagementPermission is a contract-specific management.Permission type used by its methods. +type ManagementPermission struct { + Contract util.Uint160 + Methods []string +} + +// NnsNameState is a contract-specific nns.NameState type used by its methods. +type NnsNameState struct { + Owner util.Uint160 + Name string + Expiration *big.Int + Admin util.Uint160 +} + +// Invoker is used by ContractReader to call various safe methods. +type Invoker interface { + nep11.Invoker +} + +// Actor is used by Contract to call state-changing methods. +type Actor interface { + Invoker + + nep11.Actor + + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeRun(script []byte) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) + SendRun(script []byte) (util.Uint256, uint32, error) +} + +// ContractReader implements safe contract methods. +type ContractReader struct { + nep11.NonDivisibleReader + invoker Invoker + hash util.Uint160 +} + +// Contract implements all contract methods. +type Contract struct { + ContractReader + nep11.BaseWriter + actor Actor + hash util.Uint160 +} + +// NewReader creates an instance of ContractReader using provided contract hash and the given Invoker. +func NewReader(invoker Invoker, hash util.Uint160) *ContractReader { + return &ContractReader{*nep11.NewNonDivisibleReader(invoker, hash), invoker, hash} +} + +// New creates an instance of Contract using provided contract hash and the given Actor. +func New(actor Actor, hash util.Uint160) *Contract { + var nep11ndt = nep11.NewNonDivisible(actor, hash) + return &Contract{ContractReader{nep11ndt.NonDivisibleReader, actor, hash}, nep11ndt.BaseWriter, actor, hash} +} + +// GetPrice invokes `getPrice` method of contract. +func (c *ContractReader) GetPrice() (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "getPrice")) +} + +// GetRecords invokes `getRecords` method of contract. +func (c *ContractReader) GetRecords(name string, typ *big.Int) ([]string, error) { + return unwrap.ArrayOfUTF8Strings(c.invoker.Call(c.hash, "getRecords", name, typ)) +} + +// IsAvailable invokes `isAvailable` method of contract. +func (c *ContractReader) IsAvailable(name string) (bool, error) { + return unwrap.Bool(c.invoker.Call(c.hash, "isAvailable", name)) +} + +// Resolve invokes `resolve` method of contract. +func (c *ContractReader) Resolve(name string, typ *big.Int) ([]string, error) { + return unwrap.ArrayOfUTF8Strings(c.invoker.Call(c.hash, "resolve", name, typ)) +} + +// Roots invokes `roots` method of contract. +func (c *ContractReader) Roots() (uuid.UUID, result.Iterator, error) { + return unwrap.SessionIterator(c.invoker.Call(c.hash, "roots")) +} + +// RootsExpanded is similar to Roots (uses the same contract +// 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 the specified +// number 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) RootsExpanded(_numOfIteratorItems int) ([]stackitem.Item, error) { + return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "roots", _numOfIteratorItems)) +} + +// Version invokes `version` method of contract. +func (c *ContractReader) Version() (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "version")) +} + +// AddRecord creates a transaction invoking `addRecord` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) AddRecord(name string, typ *big.Int, data string) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "addRecord", name, typ, data) +} + +// AddRecordTransaction creates a transaction invoking `addRecord` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) AddRecordTransaction(name string, typ *big.Int, data string) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "addRecord", name, typ, data) +} + +// AddRecordUnsigned creates a transaction invoking `addRecord` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) AddRecordUnsigned(name string, typ *big.Int, data string) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "addRecord", nil, name, typ, data) +} + +// DeleteRecords creates a transaction invoking `deleteRecords` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) DeleteRecords(name string, typ *big.Int) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "deleteRecords", name, typ) +} + +// DeleteRecordsTransaction creates a transaction invoking `deleteRecords` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) DeleteRecordsTransaction(name string, typ *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "deleteRecords", name, typ) +} + +// DeleteRecordsUnsigned creates a transaction invoking `deleteRecords` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) DeleteRecordsUnsigned(name string, typ *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "deleteRecords", nil, name, typ) +} + +// GetAllRecords creates a transaction invoking `getAllRecords` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) GetAllRecords(name string) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "getAllRecords", name) +} + +// GetAllRecordsTransaction creates a transaction invoking `getAllRecords` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) GetAllRecordsTransaction(name string) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "getAllRecords", name) +} + +// GetAllRecordsUnsigned creates a transaction invoking `getAllRecords` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) GetAllRecordsUnsigned(name string) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "getAllRecords", nil, name) +} + +func (c *Contract) scriptForRegister(name string, owner util.Uint160, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) ([]byte, error) { + return smartcontract.CreateCallWithAssertScript(c.hash, "register", name, owner, email, refresh, retry, expire, ttl) +} + +// Register creates a transaction invoking `register` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Register(name string, owner util.Uint160, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) (util.Uint256, uint32, error) { + script, err := c.scriptForRegister(name, owner, email, refresh, retry, expire, ttl) + if err != nil { + return util.Uint256{}, 0, err + } + return c.actor.SendRun(script) +} + +// RegisterTransaction creates a transaction invoking `register` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) RegisterTransaction(name string, owner util.Uint160, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) (*transaction.Transaction, error) { + script, err := c.scriptForRegister(name, owner, email, refresh, retry, expire, ttl) + if err != nil { + return nil, err + } + return c.actor.MakeRun(script) +} + +// RegisterUnsigned creates a transaction invoking `register` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) RegisterUnsigned(name string, owner util.Uint160, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) (*transaction.Transaction, error) { + script, err := c.scriptForRegister(name, owner, email, refresh, retry, expire, ttl) + if err != nil { + return nil, err + } + return c.actor.MakeUnsignedRun(script, nil) +} + +// RegisterTLD creates a transaction invoking `registerTLD` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) RegisterTLD(name string, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "registerTLD", name, email, refresh, retry, expire, ttl) +} + +// RegisterTLDTransaction creates a transaction invoking `registerTLD` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) RegisterTLDTransaction(name string, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "registerTLD", name, email, refresh, retry, expire, ttl) +} + +// RegisterTLDUnsigned creates a transaction invoking `registerTLD` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) RegisterTLDUnsigned(name string, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "registerTLD", nil, name, email, refresh, retry, expire, ttl) +} + +// Renew creates a transaction invoking `renew` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Renew(name string) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "renew", name) +} + +// RenewTransaction creates a transaction invoking `renew` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) RenewTransaction(name string) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "renew", name) +} + +// RenewUnsigned creates a transaction invoking `renew` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) RenewUnsigned(name string) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "renew", nil, name) +} + +// SetAdmin creates a transaction invoking `setAdmin` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) SetAdmin(name string, admin util.Uint160) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "setAdmin", name, admin) +} + +// SetAdminTransaction creates a transaction invoking `setAdmin` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) SetAdminTransaction(name string, admin util.Uint160) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "setAdmin", name, admin) +} + +// SetAdminUnsigned creates a transaction invoking `setAdmin` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) SetAdminUnsigned(name string, admin util.Uint160) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "setAdmin", nil, name, admin) +} + +// SetPrice creates a transaction invoking `setPrice` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) SetPrice(price *big.Int) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "setPrice", price) +} + +// SetPriceTransaction creates a transaction invoking `setPrice` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) SetPriceTransaction(price *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "setPrice", price) +} + +// SetPriceUnsigned creates a transaction invoking `setPrice` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) SetPriceUnsigned(price *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "setPrice", nil, price) +} + +// SetRecord creates a transaction invoking `setRecord` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) SetRecord(name string, typ *big.Int, id *big.Int, data string) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "setRecord", name, typ, id, data) +} + +// SetRecordTransaction creates a transaction invoking `setRecord` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) SetRecordTransaction(name string, typ *big.Int, id *big.Int, data string) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "setRecord", name, typ, id, data) +} + +// SetRecordUnsigned creates a transaction invoking `setRecord` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) SetRecordUnsigned(name string, typ *big.Int, id *big.Int, data string) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "setRecord", nil, name, typ, id, data) +} + +// Update creates a transaction invoking `update` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Update(nef []byte, manifest string, data any) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "update", nef, manifest, data) +} + +// UpdateTransaction creates a transaction invoking `update` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UpdateTransaction(nef []byte, manifest string, data any) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "update", nef, manifest, data) +} + +// UpdateUnsigned creates a transaction invoking `update` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UpdateUnsigned(nef []byte, manifest string, data any) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "update", nil, nef, manifest, data) +} + +// UpdateSOA creates a transaction invoking `updateSOA` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) UpdateSOA(name string, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "updateSOA", name, email, refresh, retry, expire, ttl) +} + +// UpdateSOATransaction creates a transaction invoking `updateSOA` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UpdateSOATransaction(name string, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "updateSOA", name, email, refresh, retry, expire, ttl) +} + +// UpdateSOAUnsigned creates a transaction invoking `updateSOA` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UpdateSOAUnsigned(name string, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "updateSOA", nil, name, email, refresh, retry, expire, ttl) +} + +// itemToCommonBallot converts stack item into *CommonBallot. +func itemToCommonBallot(item stackitem.Item, err error) (*CommonBallot, error) { + if err != nil { + return nil, err + } + var res = new(CommonBallot) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of CommonBallot from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *CommonBallot) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.Voters, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Voters: %w", err) + } + + index++ + res.Height, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Height: %w", err) + } + + return nil +} + +// itemToLedgerBlock converts stack item into *LedgerBlock. +func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 9 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + return nil +} + +// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. +func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 10 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + index++ + res.PrevStateRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevStateRoot: %w", err) + } + + return nil +} + +// itemToLedgerTransaction converts stack item into *LedgerTransaction. +func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Sender, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + + index++ + res.SysFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + + index++ + res.NetFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + + index++ + res.ValidUntilBlock, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + + index++ + res.Script, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + + return nil +} + +// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. +func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Account, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Account: %w", err) + } + + index++ + res.Scopes, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Scopes: %w", err) + } + + index++ + res.AllowedContracts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedContracts: %w", err) + } + + index++ + res.AllowedGroups, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedGroups: %w", err) + } + + index++ + res.Rules, err = func (item stackitem.Item) ([]*LedgerWitnessRule, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*LedgerWitnessRule, len(arr)) + for i := range res { + res[i], err = itemToLedgerWitnessRule(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Rules: %w", err) + } + + return nil +} + +// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. +func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + index++ + res.Value, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} + +// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. +func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Action, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Action: %w", err) + } + + index++ + res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) + if err != nil { + return fmt.Errorf("field Condition: %w", err) + } + + return nil +} + +// itemToManagementABI converts stack item into *ManagementABI. +func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { + if err != nil { + return nil, err + } + var res = new(ManagementABI) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementABI from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementABI) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Methods, err = func (item stackitem.Item) ([]*ManagementMethod, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementMethod, len(arr)) + for i := range res { + res[i], err = itemToManagementMethod(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + index++ + res.Events, err = func (item stackitem.Item) ([]*ManagementEvent, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementEvent, len(arr)) + for i := range res { + res[i], err = itemToManagementEvent(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Events: %w", err) + } + + return nil +} + +// itemToManagementContract converts stack item into *ManagementContract. +func itemToManagementContract(item stackitem.Item, err error) (*ManagementContract, error) { + if err != nil { + return nil, err + } + var res = new(ManagementContract) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementContract from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementContract) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.UpdateCounter, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field UpdateCounter: %w", err) + } + + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.NEF, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field NEF: %w", err) + } + + index++ + res.Manifest, err = itemToManagementManifest(arr[index], nil) + if err != nil { + return fmt.Errorf("field Manifest: %w", err) + } + + return nil +} + +// itemToManagementEvent converts stack item into *ManagementEvent. +func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, error) { + if err != nil { + return nil, err + } + var res = new(ManagementEvent) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementEvent from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + return nil +} + +// itemToManagementGroup converts stack item into *ManagementGroup. +func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, error) { + if err != nil { + return nil, err + } + var res = new(ManagementGroup) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementGroup from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + index++ + res.Signature, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Signature: %w", err) + } + + return nil +} + +// itemToManagementManifest converts stack item into *ManagementManifest. +func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManifest, error) { + if err != nil { + return nil, err + } + var res = new(ManagementManifest) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementManifest from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Groups, err = func (item stackitem.Item) ([]*ManagementGroup, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementGroup, len(arr)) + for i := range res { + res[i], err = itemToManagementGroup(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Groups: %w", err) + } + + index++ + res.Features, err = func (item stackitem.Item) (map[string]string, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string]string) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Features: %w", err) + } + + index++ + res.SupportedStandards, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field SupportedStandards: %w", err) + } + + index++ + res.ABI, err = itemToManagementABI(arr[index], nil) + if err != nil { + return fmt.Errorf("field ABI: %w", err) + } + + index++ + res.Permissions, err = func (item stackitem.Item) ([]*ManagementPermission, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementPermission, len(arr)) + for i := range res { + res[i], err = itemToManagementPermission(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Permissions: %w", err) + } + + index++ + res.Trusts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Trusts: %w", err) + } + + index++ + res.Extra, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Extra: %w", err) + } + + return nil +} + +// itemToManagementMethod converts stack item into *ManagementMethod. +func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, error) { + if err != nil { + return nil, err + } + var res = new(ManagementMethod) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementMethod from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + index++ + res.ReturnType, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ReturnType: %w", err) + } + + index++ + res.Offset, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Offset: %w", err) + } + + index++ + res.Safe, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field Safe: %w", err) + } + + return nil +} + +// itemToManagementParameter converts stack item into *ManagementParameter. +func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParameter, error) { + if err != nil { + return nil, err + } + var res = new(ManagementParameter) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementParameter from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + return nil +} + +// itemToManagementPermission converts stack item into *ManagementPermission. +func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPermission, error) { + if err != nil { + return nil, err + } + var res = new(ManagementPermission) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementPermission from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Contract, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Contract: %w", err) + } + + index++ + res.Methods, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + return nil +} + +// itemToNnsNameState converts stack item into *NnsNameState. +func itemToNnsNameState(item stackitem.Item, err error) (*NnsNameState, error) { + if err != nil { + return nil, err + } + var res = new(NnsNameState) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of NnsNameState from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *NnsNameState) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 4 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Owner, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Owner: %w", err) + } + + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Expiration, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Expiration: %w", err) + } + + index++ + res.Admin, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Admin: %w", err) + } + + return nil +} diff --git a/rpc/processing/rpcbinding.go b/rpc/processing/rpcbinding.go new file mode 100644 index 00000000..b8b06b91 --- /dev/null +++ b/rpc/processing/rpcbinding.go @@ -0,0 +1,1486 @@ +// Package processing contains RPC wrappers for NeoFS Multi Signature Processing contract. +package processing + +import ( + "crypto/elliptic" + "errors" + "fmt" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "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" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" + "unicode/utf8" +) + +// CommonBallot is a contract-specific common.Ballot type used by its methods. +type CommonBallot struct { + ID []byte + Voters keys.PublicKeys + Height *big.Int +} + +// LedgerBlock is a contract-specific ledger.Block type used by its methods. +type LedgerBlock struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int +} + +// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. +type LedgerBlockSR struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int + PrevStateRoot util.Uint256 +} + +// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. +type LedgerTransaction struct { + Hash util.Uint256 + Version *big.Int + Nonce *big.Int + Sender util.Uint160 + SysFee *big.Int + NetFee *big.Int + ValidUntilBlock *big.Int + Script []byte +} + +// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. +type LedgerTransactionSigner struct { + Account util.Uint160 + Scopes *big.Int + AllowedContracts []util.Uint160 + AllowedGroups keys.PublicKeys + Rules []*LedgerWitnessRule +} + +// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. +type LedgerWitnessCondition struct { + Type *big.Int + Value any +} + +// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. +type LedgerWitnessRule struct { + Action *big.Int + Condition *LedgerWitnessCondition +} + +// ManagementABI is a contract-specific management.ABI type used by its methods. +type ManagementABI struct { + Methods []*ManagementMethod + Events []*ManagementEvent +} + +// ManagementContract is a contract-specific management.Contract type used by its methods. +type ManagementContract struct { + ID *big.Int + UpdateCounter *big.Int + Hash util.Uint160 + NEF []byte + Manifest *ManagementManifest +} + +// ManagementEvent is a contract-specific management.Event type used by its methods. +type ManagementEvent struct { + Name string + Params []*ManagementParameter +} + +// ManagementGroup is a contract-specific management.Group type used by its methods. +type ManagementGroup struct { + PublicKey *keys.PublicKey + Signature []byte +} + +// ManagementManifest is a contract-specific management.Manifest type used by its methods. +type ManagementManifest struct { + Name string + Groups []*ManagementGroup + Features map[string]string + SupportedStandards []string + ABI *ManagementABI + Permissions []*ManagementPermission + Trusts []util.Uint160 + Extra any +} + +// ManagementMethod is a contract-specific management.Method type used by its methods. +type ManagementMethod struct { + Name string + Params []*ManagementParameter + ReturnType *big.Int + Offset *big.Int + Safe bool +} + +// ManagementParameter is a contract-specific management.Parameter type used by its methods. +type ManagementParameter struct { + Name string + Type *big.Int +} + +// ManagementPermission is a contract-specific management.Permission type used by its methods. +type ManagementPermission struct { + Contract util.Uint160 + Methods []string +} + +// Invoker is used by ContractReader to call various safe methods. +type Invoker interface { + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) +} + +// Actor is used by Contract to call state-changing methods. +type Actor interface { + Invoker + + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeRun(script []byte) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) + SendRun(script []byte) (util.Uint256, uint32, error) +} + +// ContractReader implements safe contract methods. +type ContractReader struct { + invoker Invoker + hash util.Uint160 +} + +// Contract implements all contract methods. +type Contract struct { + ContractReader + actor Actor + hash util.Uint160 +} + +// NewReader creates an instance of ContractReader using provided contract hash and the given Invoker. +func NewReader(invoker Invoker, hash util.Uint160) *ContractReader { + return &ContractReader{invoker, hash} +} + +// New creates an instance of Contract using provided contract hash and the given Actor. +func New(actor Actor, hash util.Uint160) *Contract { + return &Contract{ContractReader{actor, hash}, actor, hash} +} + +// Verify invokes `verify` method of contract. +func (c *ContractReader) Verify() (bool, error) { + return unwrap.Bool(c.invoker.Call(c.hash, "verify")) +} + +// Version invokes `version` method of contract. +func (c *ContractReader) Version() (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "version")) +} + +// Update creates a transaction invoking `update` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Update(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "update", script, manifest, data) +} + +// UpdateTransaction creates a transaction invoking `update` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UpdateTransaction(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "update", script, manifest, data) +} + +// UpdateUnsigned creates a transaction invoking `update` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data) +} + +// itemToCommonBallot converts stack item into *CommonBallot. +func itemToCommonBallot(item stackitem.Item, err error) (*CommonBallot, error) { + if err != nil { + return nil, err + } + var res = new(CommonBallot) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of CommonBallot from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *CommonBallot) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.Voters, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Voters: %w", err) + } + + index++ + res.Height, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Height: %w", err) + } + + return nil +} + +// itemToLedgerBlock converts stack item into *LedgerBlock. +func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 9 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + return nil +} + +// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. +func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 10 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + index++ + res.PrevStateRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevStateRoot: %w", err) + } + + return nil +} + +// itemToLedgerTransaction converts stack item into *LedgerTransaction. +func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Sender, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + + index++ + res.SysFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + + index++ + res.NetFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + + index++ + res.ValidUntilBlock, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + + index++ + res.Script, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + + return nil +} + +// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. +func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Account, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Account: %w", err) + } + + index++ + res.Scopes, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Scopes: %w", err) + } + + index++ + res.AllowedContracts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedContracts: %w", err) + } + + index++ + res.AllowedGroups, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedGroups: %w", err) + } + + index++ + res.Rules, err = func (item stackitem.Item) ([]*LedgerWitnessRule, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*LedgerWitnessRule, len(arr)) + for i := range res { + res[i], err = itemToLedgerWitnessRule(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Rules: %w", err) + } + + return nil +} + +// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. +func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + index++ + res.Value, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} + +// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. +func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Action, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Action: %w", err) + } + + index++ + res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) + if err != nil { + return fmt.Errorf("field Condition: %w", err) + } + + return nil +} + +// itemToManagementABI converts stack item into *ManagementABI. +func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { + if err != nil { + return nil, err + } + var res = new(ManagementABI) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementABI from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementABI) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Methods, err = func (item stackitem.Item) ([]*ManagementMethod, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementMethod, len(arr)) + for i := range res { + res[i], err = itemToManagementMethod(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + index++ + res.Events, err = func (item stackitem.Item) ([]*ManagementEvent, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementEvent, len(arr)) + for i := range res { + res[i], err = itemToManagementEvent(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Events: %w", err) + } + + return nil +} + +// itemToManagementContract converts stack item into *ManagementContract. +func itemToManagementContract(item stackitem.Item, err error) (*ManagementContract, error) { + if err != nil { + return nil, err + } + var res = new(ManagementContract) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementContract from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementContract) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.UpdateCounter, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field UpdateCounter: %w", err) + } + + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.NEF, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field NEF: %w", err) + } + + index++ + res.Manifest, err = itemToManagementManifest(arr[index], nil) + if err != nil { + return fmt.Errorf("field Manifest: %w", err) + } + + return nil +} + +// itemToManagementEvent converts stack item into *ManagementEvent. +func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, error) { + if err != nil { + return nil, err + } + var res = new(ManagementEvent) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementEvent from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + return nil +} + +// itemToManagementGroup converts stack item into *ManagementGroup. +func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, error) { + if err != nil { + return nil, err + } + var res = new(ManagementGroup) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementGroup from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + index++ + res.Signature, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Signature: %w", err) + } + + return nil +} + +// itemToManagementManifest converts stack item into *ManagementManifest. +func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManifest, error) { + if err != nil { + return nil, err + } + var res = new(ManagementManifest) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementManifest from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Groups, err = func (item stackitem.Item) ([]*ManagementGroup, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementGroup, len(arr)) + for i := range res { + res[i], err = itemToManagementGroup(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Groups: %w", err) + } + + index++ + res.Features, err = func (item stackitem.Item) (map[string]string, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string]string) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Features: %w", err) + } + + index++ + res.SupportedStandards, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field SupportedStandards: %w", err) + } + + index++ + res.ABI, err = itemToManagementABI(arr[index], nil) + if err != nil { + return fmt.Errorf("field ABI: %w", err) + } + + index++ + res.Permissions, err = func (item stackitem.Item) ([]*ManagementPermission, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementPermission, len(arr)) + for i := range res { + res[i], err = itemToManagementPermission(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Permissions: %w", err) + } + + index++ + res.Trusts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Trusts: %w", err) + } + + index++ + res.Extra, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Extra: %w", err) + } + + return nil +} + +// itemToManagementMethod converts stack item into *ManagementMethod. +func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, error) { + if err != nil { + return nil, err + } + var res = new(ManagementMethod) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementMethod from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + index++ + res.ReturnType, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ReturnType: %w", err) + } + + index++ + res.Offset, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Offset: %w", err) + } + + index++ + res.Safe, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field Safe: %w", err) + } + + return nil +} + +// itemToManagementParameter converts stack item into *ManagementParameter. +func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParameter, error) { + if err != nil { + return nil, err + } + var res = new(ManagementParameter) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementParameter from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + return nil +} + +// itemToManagementPermission converts stack item into *ManagementPermission. +func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPermission, error) { + if err != nil { + return nil, err + } + var res = new(ManagementPermission) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementPermission from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Contract, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Contract: %w", err) + } + + index++ + res.Methods, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + return nil +} diff --git a/rpc/proxy/rpcbinding.go b/rpc/proxy/rpcbinding.go new file mode 100644 index 00000000..0d5c6e3b --- /dev/null +++ b/rpc/proxy/rpcbinding.go @@ -0,0 +1,1486 @@ +// Package proxy contains RPC wrappers for NeoFS Notary Proxy contract. +package proxy + +import ( + "crypto/elliptic" + "errors" + "fmt" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "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" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" + "unicode/utf8" +) + +// CommonBallot is a contract-specific common.Ballot type used by its methods. +type CommonBallot struct { + ID []byte + Voters keys.PublicKeys + Height *big.Int +} + +// LedgerBlock is a contract-specific ledger.Block type used by its methods. +type LedgerBlock struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int +} + +// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. +type LedgerBlockSR struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int + PrevStateRoot util.Uint256 +} + +// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. +type LedgerTransaction struct { + Hash util.Uint256 + Version *big.Int + Nonce *big.Int + Sender util.Uint160 + SysFee *big.Int + NetFee *big.Int + ValidUntilBlock *big.Int + Script []byte +} + +// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. +type LedgerTransactionSigner struct { + Account util.Uint160 + Scopes *big.Int + AllowedContracts []util.Uint160 + AllowedGroups keys.PublicKeys + Rules []*LedgerWitnessRule +} + +// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. +type LedgerWitnessCondition struct { + Type *big.Int + Value any +} + +// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. +type LedgerWitnessRule struct { + Action *big.Int + Condition *LedgerWitnessCondition +} + +// ManagementABI is a contract-specific management.ABI type used by its methods. +type ManagementABI struct { + Methods []*ManagementMethod + Events []*ManagementEvent +} + +// ManagementContract is a contract-specific management.Contract type used by its methods. +type ManagementContract struct { + ID *big.Int + UpdateCounter *big.Int + Hash util.Uint160 + NEF []byte + Manifest *ManagementManifest +} + +// ManagementEvent is a contract-specific management.Event type used by its methods. +type ManagementEvent struct { + Name string + Params []*ManagementParameter +} + +// ManagementGroup is a contract-specific management.Group type used by its methods. +type ManagementGroup struct { + PublicKey *keys.PublicKey + Signature []byte +} + +// ManagementManifest is a contract-specific management.Manifest type used by its methods. +type ManagementManifest struct { + Name string + Groups []*ManagementGroup + Features map[string]string + SupportedStandards []string + ABI *ManagementABI + Permissions []*ManagementPermission + Trusts []util.Uint160 + Extra any +} + +// ManagementMethod is a contract-specific management.Method type used by its methods. +type ManagementMethod struct { + Name string + Params []*ManagementParameter + ReturnType *big.Int + Offset *big.Int + Safe bool +} + +// ManagementParameter is a contract-specific management.Parameter type used by its methods. +type ManagementParameter struct { + Name string + Type *big.Int +} + +// ManagementPermission is a contract-specific management.Permission type used by its methods. +type ManagementPermission struct { + Contract util.Uint160 + Methods []string +} + +// Invoker is used by ContractReader to call various safe methods. +type Invoker interface { + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) +} + +// Actor is used by Contract to call state-changing methods. +type Actor interface { + Invoker + + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeRun(script []byte) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) + SendRun(script []byte) (util.Uint256, uint32, error) +} + +// ContractReader implements safe contract methods. +type ContractReader struct { + invoker Invoker + hash util.Uint160 +} + +// Contract implements all contract methods. +type Contract struct { + ContractReader + actor Actor + hash util.Uint160 +} + +// NewReader creates an instance of ContractReader using provided contract hash and the given Invoker. +func NewReader(invoker Invoker, hash util.Uint160) *ContractReader { + return &ContractReader{invoker, hash} +} + +// New creates an instance of Contract using provided contract hash and the given Actor. +func New(actor Actor, hash util.Uint160) *Contract { + return &Contract{ContractReader{actor, hash}, actor, hash} +} + +// Verify invokes `verify` method of contract. +func (c *ContractReader) Verify() (bool, error) { + return unwrap.Bool(c.invoker.Call(c.hash, "verify")) +} + +// Version invokes `version` method of contract. +func (c *ContractReader) Version() (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "version")) +} + +// Update creates a transaction invoking `update` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Update(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "update", script, manifest, data) +} + +// UpdateTransaction creates a transaction invoking `update` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UpdateTransaction(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "update", script, manifest, data) +} + +// UpdateUnsigned creates a transaction invoking `update` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data) +} + +// itemToCommonBallot converts stack item into *CommonBallot. +func itemToCommonBallot(item stackitem.Item, err error) (*CommonBallot, error) { + if err != nil { + return nil, err + } + var res = new(CommonBallot) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of CommonBallot from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *CommonBallot) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.Voters, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Voters: %w", err) + } + + index++ + res.Height, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Height: %w", err) + } + + return nil +} + +// itemToLedgerBlock converts stack item into *LedgerBlock. +func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 9 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + return nil +} + +// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. +func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 10 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + index++ + res.PrevStateRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevStateRoot: %w", err) + } + + return nil +} + +// itemToLedgerTransaction converts stack item into *LedgerTransaction. +func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Sender, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + + index++ + res.SysFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + + index++ + res.NetFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + + index++ + res.ValidUntilBlock, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + + index++ + res.Script, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + + return nil +} + +// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. +func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Account, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Account: %w", err) + } + + index++ + res.Scopes, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Scopes: %w", err) + } + + index++ + res.AllowedContracts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedContracts: %w", err) + } + + index++ + res.AllowedGroups, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedGroups: %w", err) + } + + index++ + res.Rules, err = func (item stackitem.Item) ([]*LedgerWitnessRule, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*LedgerWitnessRule, len(arr)) + for i := range res { + res[i], err = itemToLedgerWitnessRule(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Rules: %w", err) + } + + return nil +} + +// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. +func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + index++ + res.Value, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} + +// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. +func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Action, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Action: %w", err) + } + + index++ + res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) + if err != nil { + return fmt.Errorf("field Condition: %w", err) + } + + return nil +} + +// itemToManagementABI converts stack item into *ManagementABI. +func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { + if err != nil { + return nil, err + } + var res = new(ManagementABI) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementABI from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementABI) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Methods, err = func (item stackitem.Item) ([]*ManagementMethod, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementMethod, len(arr)) + for i := range res { + res[i], err = itemToManagementMethod(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + index++ + res.Events, err = func (item stackitem.Item) ([]*ManagementEvent, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementEvent, len(arr)) + for i := range res { + res[i], err = itemToManagementEvent(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Events: %w", err) + } + + return nil +} + +// itemToManagementContract converts stack item into *ManagementContract. +func itemToManagementContract(item stackitem.Item, err error) (*ManagementContract, error) { + if err != nil { + return nil, err + } + var res = new(ManagementContract) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementContract from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementContract) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.UpdateCounter, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field UpdateCounter: %w", err) + } + + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.NEF, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field NEF: %w", err) + } + + index++ + res.Manifest, err = itemToManagementManifest(arr[index], nil) + if err != nil { + return fmt.Errorf("field Manifest: %w", err) + } + + return nil +} + +// itemToManagementEvent converts stack item into *ManagementEvent. +func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, error) { + if err != nil { + return nil, err + } + var res = new(ManagementEvent) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementEvent from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + return nil +} + +// itemToManagementGroup converts stack item into *ManagementGroup. +func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, error) { + if err != nil { + return nil, err + } + var res = new(ManagementGroup) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementGroup from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + index++ + res.Signature, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Signature: %w", err) + } + + return nil +} + +// itemToManagementManifest converts stack item into *ManagementManifest. +func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManifest, error) { + if err != nil { + return nil, err + } + var res = new(ManagementManifest) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementManifest from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Groups, err = func (item stackitem.Item) ([]*ManagementGroup, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementGroup, len(arr)) + for i := range res { + res[i], err = itemToManagementGroup(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Groups: %w", err) + } + + index++ + res.Features, err = func (item stackitem.Item) (map[string]string, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string]string) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Features: %w", err) + } + + index++ + res.SupportedStandards, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field SupportedStandards: %w", err) + } + + index++ + res.ABI, err = itemToManagementABI(arr[index], nil) + if err != nil { + return fmt.Errorf("field ABI: %w", err) + } + + index++ + res.Permissions, err = func (item stackitem.Item) ([]*ManagementPermission, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementPermission, len(arr)) + for i := range res { + res[i], err = itemToManagementPermission(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Permissions: %w", err) + } + + index++ + res.Trusts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Trusts: %w", err) + } + + index++ + res.Extra, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Extra: %w", err) + } + + return nil +} + +// itemToManagementMethod converts stack item into *ManagementMethod. +func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, error) { + if err != nil { + return nil, err + } + var res = new(ManagementMethod) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementMethod from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + index++ + res.ReturnType, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ReturnType: %w", err) + } + + index++ + res.Offset, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Offset: %w", err) + } + + index++ + res.Safe, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field Safe: %w", err) + } + + return nil +} + +// itemToManagementParameter converts stack item into *ManagementParameter. +func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParameter, error) { + if err != nil { + return nil, err + } + var res = new(ManagementParameter) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementParameter from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + return nil +} + +// itemToManagementPermission converts stack item into *ManagementPermission. +func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPermission, error) { + if err != nil { + return nil, err + } + var res = new(ManagementPermission) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementPermission from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Contract, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Contract: %w", err) + } + + index++ + res.Methods, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + return nil +} diff --git a/rpc/reputation/rpcbinding.go b/rpc/reputation/rpcbinding.go new file mode 100644 index 00000000..f445216c --- /dev/null +++ b/rpc/reputation/rpcbinding.go @@ -0,0 +1,1535 @@ +// Package reputation contains RPC wrappers for NeoFS Reputation contract. +package reputation + +import ( + "crypto/elliptic" + "errors" + "fmt" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "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" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" + "unicode/utf8" +) + +// CommonBallot is a contract-specific common.Ballot type used by its methods. +type CommonBallot struct { + ID []byte + Voters keys.PublicKeys + Height *big.Int +} + +// LedgerBlock is a contract-specific ledger.Block type used by its methods. +type LedgerBlock struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int +} + +// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. +type LedgerBlockSR struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int + PrevStateRoot util.Uint256 +} + +// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. +type LedgerTransaction struct { + Hash util.Uint256 + Version *big.Int + Nonce *big.Int + Sender util.Uint160 + SysFee *big.Int + NetFee *big.Int + ValidUntilBlock *big.Int + Script []byte +} + +// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. +type LedgerTransactionSigner struct { + Account util.Uint160 + Scopes *big.Int + AllowedContracts []util.Uint160 + AllowedGroups keys.PublicKeys + Rules []*LedgerWitnessRule +} + +// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. +type LedgerWitnessCondition struct { + Type *big.Int + Value any +} + +// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. +type LedgerWitnessRule struct { + Action *big.Int + Condition *LedgerWitnessCondition +} + +// ManagementABI is a contract-specific management.ABI type used by its methods. +type ManagementABI struct { + Methods []*ManagementMethod + Events []*ManagementEvent +} + +// ManagementContract is a contract-specific management.Contract type used by its methods. +type ManagementContract struct { + ID *big.Int + UpdateCounter *big.Int + Hash util.Uint160 + NEF []byte + Manifest *ManagementManifest +} + +// ManagementEvent is a contract-specific management.Event type used by its methods. +type ManagementEvent struct { + Name string + Params []*ManagementParameter +} + +// ManagementGroup is a contract-specific management.Group type used by its methods. +type ManagementGroup struct { + PublicKey *keys.PublicKey + Signature []byte +} + +// ManagementManifest is a contract-specific management.Manifest type used by its methods. +type ManagementManifest struct { + Name string + Groups []*ManagementGroup + Features map[string]string + SupportedStandards []string + ABI *ManagementABI + Permissions []*ManagementPermission + Trusts []util.Uint160 + Extra any +} + +// ManagementMethod is a contract-specific management.Method type used by its methods. +type ManagementMethod struct { + Name string + Params []*ManagementParameter + ReturnType *big.Int + Offset *big.Int + Safe bool +} + +// ManagementParameter is a contract-specific management.Parameter type used by its methods. +type ManagementParameter struct { + Name string + Type *big.Int +} + +// ManagementPermission is a contract-specific management.Permission type used by its methods. +type ManagementPermission struct { + Contract util.Uint160 + Methods []string +} + +// Invoker is used by ContractReader to call various safe methods. +type Invoker interface { + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) +} + +// Actor is used by Contract to call state-changing methods. +type Actor interface { + Invoker + + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeRun(script []byte) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) + SendRun(script []byte) (util.Uint256, uint32, error) +} + +// ContractReader implements safe contract methods. +type ContractReader struct { + invoker Invoker + hash util.Uint160 +} + +// Contract implements all contract methods. +type Contract struct { + ContractReader + actor Actor + hash util.Uint160 +} + +// NewReader creates an instance of ContractReader using provided contract hash and the given Invoker. +func NewReader(invoker Invoker, hash util.Uint160) *ContractReader { + return &ContractReader{invoker, hash} +} + +// New creates an instance of Contract using provided contract hash and the given Actor. +func New(actor Actor, hash util.Uint160) *Contract { + return &Contract{ContractReader{actor, hash}, actor, hash} +} + +// Get invokes `get` method of contract. +func (c *ContractReader) Get(epoch *big.Int, peerID []byte) ([][]byte, error) { + return unwrap.ArrayOfBytes(c.invoker.Call(c.hash, "get", epoch, peerID)) +} + +// GetByID invokes `getByID` method of contract. +func (c *ContractReader) GetByID(id []byte) ([][]byte, error) { + return unwrap.ArrayOfBytes(c.invoker.Call(c.hash, "getByID", id)) +} + +// ListByEpoch invokes `listByEpoch` method of contract. +func (c *ContractReader) ListByEpoch(epoch *big.Int) ([][]byte, error) { + return unwrap.ArrayOfBytes(c.invoker.Call(c.hash, "listByEpoch", epoch)) +} + +// Put creates a transaction invoking `put` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Put(epoch *big.Int, peerID []byte, value []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "put", epoch, peerID, value) +} + +// PutTransaction creates a transaction invoking `put` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) PutTransaction(epoch *big.Int, peerID []byte, value []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "put", epoch, peerID, value) +} + +// PutUnsigned creates a transaction invoking `put` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) PutUnsigned(epoch *big.Int, peerID []byte, value []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "put", nil, epoch, peerID, value) +} + +// Update creates a transaction invoking `update` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Update(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "update", script, manifest, data) +} + +// UpdateTransaction creates a transaction invoking `update` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UpdateTransaction(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "update", script, manifest, data) +} + +// UpdateUnsigned creates a transaction invoking `update` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data) +} + +// Version creates a transaction invoking `version` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Version() (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "version") +} + +// VersionTransaction creates a transaction invoking `version` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) VersionTransaction() (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "version") +} + +// VersionUnsigned creates a transaction invoking `version` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) VersionUnsigned() (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "version", nil) +} + +// itemToCommonBallot converts stack item into *CommonBallot. +func itemToCommonBallot(item stackitem.Item, err error) (*CommonBallot, error) { + if err != nil { + return nil, err + } + var res = new(CommonBallot) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of CommonBallot from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *CommonBallot) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.Voters, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Voters: %w", err) + } + + index++ + res.Height, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Height: %w", err) + } + + return nil +} + +// itemToLedgerBlock converts stack item into *LedgerBlock. +func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 9 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + return nil +} + +// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. +func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 10 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + index++ + res.PrevStateRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevStateRoot: %w", err) + } + + return nil +} + +// itemToLedgerTransaction converts stack item into *LedgerTransaction. +func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Sender, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + + index++ + res.SysFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + + index++ + res.NetFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + + index++ + res.ValidUntilBlock, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + + index++ + res.Script, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + + return nil +} + +// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. +func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Account, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Account: %w", err) + } + + index++ + res.Scopes, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Scopes: %w", err) + } + + index++ + res.AllowedContracts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedContracts: %w", err) + } + + index++ + res.AllowedGroups, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedGroups: %w", err) + } + + index++ + res.Rules, err = func (item stackitem.Item) ([]*LedgerWitnessRule, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*LedgerWitnessRule, len(arr)) + for i := range res { + res[i], err = itemToLedgerWitnessRule(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Rules: %w", err) + } + + return nil +} + +// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. +func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + index++ + res.Value, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} + +// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. +func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Action, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Action: %w", err) + } + + index++ + res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) + if err != nil { + return fmt.Errorf("field Condition: %w", err) + } + + return nil +} + +// itemToManagementABI converts stack item into *ManagementABI. +func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { + if err != nil { + return nil, err + } + var res = new(ManagementABI) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementABI from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementABI) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Methods, err = func (item stackitem.Item) ([]*ManagementMethod, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementMethod, len(arr)) + for i := range res { + res[i], err = itemToManagementMethod(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + index++ + res.Events, err = func (item stackitem.Item) ([]*ManagementEvent, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementEvent, len(arr)) + for i := range res { + res[i], err = itemToManagementEvent(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Events: %w", err) + } + + return nil +} + +// itemToManagementContract converts stack item into *ManagementContract. +func itemToManagementContract(item stackitem.Item, err error) (*ManagementContract, error) { + if err != nil { + return nil, err + } + var res = new(ManagementContract) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementContract from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementContract) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.UpdateCounter, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field UpdateCounter: %w", err) + } + + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.NEF, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field NEF: %w", err) + } + + index++ + res.Manifest, err = itemToManagementManifest(arr[index], nil) + if err != nil { + return fmt.Errorf("field Manifest: %w", err) + } + + return nil +} + +// itemToManagementEvent converts stack item into *ManagementEvent. +func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, error) { + if err != nil { + return nil, err + } + var res = new(ManagementEvent) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementEvent from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + return nil +} + +// itemToManagementGroup converts stack item into *ManagementGroup. +func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, error) { + if err != nil { + return nil, err + } + var res = new(ManagementGroup) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementGroup from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + index++ + res.Signature, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Signature: %w", err) + } + + return nil +} + +// itemToManagementManifest converts stack item into *ManagementManifest. +func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManifest, error) { + if err != nil { + return nil, err + } + var res = new(ManagementManifest) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementManifest from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Groups, err = func (item stackitem.Item) ([]*ManagementGroup, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementGroup, len(arr)) + for i := range res { + res[i], err = itemToManagementGroup(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Groups: %w", err) + } + + index++ + res.Features, err = func (item stackitem.Item) (map[string]string, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string]string) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Features: %w", err) + } + + index++ + res.SupportedStandards, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field SupportedStandards: %w", err) + } + + index++ + res.ABI, err = itemToManagementABI(arr[index], nil) + if err != nil { + return fmt.Errorf("field ABI: %w", err) + } + + index++ + res.Permissions, err = func (item stackitem.Item) ([]*ManagementPermission, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementPermission, len(arr)) + for i := range res { + res[i], err = itemToManagementPermission(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Permissions: %w", err) + } + + index++ + res.Trusts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Trusts: %w", err) + } + + index++ + res.Extra, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Extra: %w", err) + } + + return nil +} + +// itemToManagementMethod converts stack item into *ManagementMethod. +func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, error) { + if err != nil { + return nil, err + } + var res = new(ManagementMethod) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementMethod from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + index++ + res.ReturnType, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ReturnType: %w", err) + } + + index++ + res.Offset, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Offset: %w", err) + } + + index++ + res.Safe, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field Safe: %w", err) + } + + return nil +} + +// itemToManagementParameter converts stack item into *ManagementParameter. +func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParameter, error) { + if err != nil { + return nil, err + } + var res = new(ManagementParameter) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementParameter from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + return nil +} + +// itemToManagementPermission converts stack item into *ManagementPermission. +func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPermission, error) { + if err != nil { + return nil, err + } + var res = new(ManagementPermission) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementPermission from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Contract, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Contract: %w", err) + } + + index++ + res.Methods, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + return nil +} diff --git a/rpc/subnet/rpcbinding.go b/rpc/subnet/rpcbinding.go new file mode 100644 index 00000000..9832e7f7 --- /dev/null +++ b/rpc/subnet/rpcbinding.go @@ -0,0 +1,1931 @@ +// Package subnet contains RPC wrappers for NeoFS Subnet contract. +package subnet + +import ( + "crypto/elliptic" + "errors" + "fmt" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "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/smartcontract" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" + "unicode/utf8" +) + +// CommonBallot is a contract-specific common.Ballot type used by its methods. +type CommonBallot struct { + ID []byte + Voters keys.PublicKeys + Height *big.Int +} + +// LedgerBlock is a contract-specific ledger.Block type used by its methods. +type LedgerBlock struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int +} + +// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. +type LedgerBlockSR struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int + PrevStateRoot util.Uint256 +} + +// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. +type LedgerTransaction struct { + Hash util.Uint256 + Version *big.Int + Nonce *big.Int + Sender util.Uint160 + SysFee *big.Int + NetFee *big.Int + ValidUntilBlock *big.Int + Script []byte +} + +// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. +type LedgerTransactionSigner struct { + Account util.Uint160 + Scopes *big.Int + AllowedContracts []util.Uint160 + AllowedGroups keys.PublicKeys + Rules []*LedgerWitnessRule +} + +// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. +type LedgerWitnessCondition struct { + Type *big.Int + Value any +} + +// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. +type LedgerWitnessRule struct { + Action *big.Int + Condition *LedgerWitnessCondition +} + +// ManagementABI is a contract-specific management.ABI type used by its methods. +type ManagementABI struct { + Methods []*ManagementMethod + Events []*ManagementEvent +} + +// ManagementContract is a contract-specific management.Contract type used by its methods. +type ManagementContract struct { + ID *big.Int + UpdateCounter *big.Int + Hash util.Uint160 + NEF []byte + Manifest *ManagementManifest +} + +// ManagementEvent is a contract-specific management.Event type used by its methods. +type ManagementEvent struct { + Name string + Params []*ManagementParameter +} + +// ManagementGroup is a contract-specific management.Group type used by its methods. +type ManagementGroup struct { + PublicKey *keys.PublicKey + Signature []byte +} + +// ManagementManifest is a contract-specific management.Manifest type used by its methods. +type ManagementManifest struct { + Name string + Groups []*ManagementGroup + Features map[string]string + SupportedStandards []string + ABI *ManagementABI + Permissions []*ManagementPermission + Trusts []util.Uint160 + Extra any +} + +// ManagementMethod is a contract-specific management.Method type used by its methods. +type ManagementMethod struct { + Name string + Params []*ManagementParameter + ReturnType *big.Int + Offset *big.Int + Safe bool +} + +// ManagementParameter is a contract-specific management.Parameter type used by its methods. +type ManagementParameter struct { + Name string + Type *big.Int +} + +// ManagementPermission is a contract-specific management.Permission type used by its methods. +type ManagementPermission struct { + Contract util.Uint160 + Methods []string +} + +// DeleteEvent represents "Delete" event emitted by the contract. +type DeleteEvent struct { + Id []byte +} + +// RemoveNodeEvent represents "RemoveNode" event emitted by the contract. +type RemoveNodeEvent struct { + SubnetID []byte + Node *keys.PublicKey +} + +// Invoker is used by ContractReader to call various safe methods. +type Invoker interface { + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) +} + +// Actor is used by Contract to call state-changing methods. +type Actor interface { + Invoker + + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeRun(script []byte) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) + SendRun(script []byte) (util.Uint256, uint32, error) +} + +// ContractReader implements safe contract methods. +type ContractReader struct { + invoker Invoker + hash util.Uint160 +} + +// Contract implements all contract methods. +type Contract struct { + ContractReader + actor Actor + hash util.Uint160 +} + +// NewReader creates an instance of ContractReader using provided contract hash and the given Invoker. +func NewReader(invoker Invoker, hash util.Uint160) *ContractReader { + return &ContractReader{invoker, hash} +} + +// New creates an instance of Contract using provided contract hash and the given Actor. +func New(actor Actor, hash util.Uint160) *Contract { + return &Contract{ContractReader{actor, hash}, actor, hash} +} + +// Version invokes `version` method of contract. +func (c *ContractReader) Version() (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "version")) +} + +// AddClientAdmin creates a transaction invoking `addClientAdmin` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) AddClientAdmin(subnetID []byte, groupID []byte, adminPublicKey *keys.PublicKey) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "addClientAdmin", subnetID, groupID, adminPublicKey) +} + +// AddClientAdminTransaction creates a transaction invoking `addClientAdmin` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) AddClientAdminTransaction(subnetID []byte, groupID []byte, adminPublicKey *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "addClientAdmin", subnetID, groupID, adminPublicKey) +} + +// AddClientAdminUnsigned creates a transaction invoking `addClientAdmin` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) AddClientAdminUnsigned(subnetID []byte, groupID []byte, adminPublicKey *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "addClientAdmin", nil, subnetID, groupID, adminPublicKey) +} + +// AddNode creates a transaction invoking `addNode` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) AddNode(subnetID []byte, node *keys.PublicKey) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "addNode", subnetID, node) +} + +// AddNodeTransaction creates a transaction invoking `addNode` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) AddNodeTransaction(subnetID []byte, node *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "addNode", subnetID, node) +} + +// AddNodeUnsigned creates a transaction invoking `addNode` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) AddNodeUnsigned(subnetID []byte, node *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "addNode", nil, subnetID, node) +} + +// AddNodeAdmin creates a transaction invoking `addNodeAdmin` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) AddNodeAdmin(subnetID []byte, adminKey *keys.PublicKey) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "addNodeAdmin", subnetID, adminKey) +} + +// AddNodeAdminTransaction creates a transaction invoking `addNodeAdmin` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) AddNodeAdminTransaction(subnetID []byte, adminKey *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "addNodeAdmin", subnetID, adminKey) +} + +// AddNodeAdminUnsigned creates a transaction invoking `addNodeAdmin` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) AddNodeAdminUnsigned(subnetID []byte, adminKey *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "addNodeAdmin", nil, subnetID, adminKey) +} + +// AddUser creates a transaction invoking `addUser` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) AddUser(subnetID []byte, groupID []byte, userID []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "addUser", subnetID, groupID, userID) +} + +// AddUserTransaction creates a transaction invoking `addUser` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) AddUserTransaction(subnetID []byte, groupID []byte, userID []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "addUser", subnetID, groupID, userID) +} + +// AddUserUnsigned creates a transaction invoking `addUser` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) AddUserUnsigned(subnetID []byte, groupID []byte, userID []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "addUser", nil, subnetID, groupID, userID) +} + +// Delete creates a transaction invoking `delete` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Delete(id []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "delete", id) +} + +// DeleteTransaction creates a transaction invoking `delete` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) DeleteTransaction(id []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "delete", id) +} + +// DeleteUnsigned creates a transaction invoking `delete` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) DeleteUnsigned(id []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "delete", nil, id) +} + +// Get creates a transaction invoking `get` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Get(id []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "get", id) +} + +// GetTransaction creates a transaction invoking `get` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) GetTransaction(id []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "get", id) +} + +// GetUnsigned creates a transaction invoking `get` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) GetUnsigned(id []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "get", nil, id) +} + +func (c *Contract) scriptForNodeAllowed(subnetID []byte, node *keys.PublicKey) ([]byte, error) { + return smartcontract.CreateCallWithAssertScript(c.hash, "nodeAllowed", subnetID, node) +} + +// NodeAllowed creates a transaction invoking `nodeAllowed` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) NodeAllowed(subnetID []byte, node *keys.PublicKey) (util.Uint256, uint32, error) { + script, err := c.scriptForNodeAllowed(subnetID, node) + if err != nil { + return util.Uint256{}, 0, err + } + return c.actor.SendRun(script) +} + +// NodeAllowedTransaction creates a transaction invoking `nodeAllowed` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) NodeAllowedTransaction(subnetID []byte, node *keys.PublicKey) (*transaction.Transaction, error) { + script, err := c.scriptForNodeAllowed(subnetID, node) + if err != nil { + return nil, err + } + return c.actor.MakeRun(script) +} + +// NodeAllowedUnsigned creates a transaction invoking `nodeAllowed` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) NodeAllowedUnsigned(subnetID []byte, node *keys.PublicKey) (*transaction.Transaction, error) { + script, err := c.scriptForNodeAllowed(subnetID, node) + if err != nil { + return nil, err + } + return c.actor.MakeUnsignedRun(script, nil) +} + +// Put creates a transaction invoking `put` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Put(id []byte, ownerKey *keys.PublicKey, info []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "put", id, ownerKey, info) +} + +// PutTransaction creates a transaction invoking `put` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) PutTransaction(id []byte, ownerKey *keys.PublicKey, info []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "put", id, ownerKey, info) +} + +// PutUnsigned creates a transaction invoking `put` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) PutUnsigned(id []byte, ownerKey *keys.PublicKey, info []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "put", nil, id, ownerKey, info) +} + +// RemoveClientAdmin creates a transaction invoking `removeClientAdmin` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) RemoveClientAdmin(subnetID []byte, groupID []byte, adminPublicKey *keys.PublicKey) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "removeClientAdmin", subnetID, groupID, adminPublicKey) +} + +// RemoveClientAdminTransaction creates a transaction invoking `removeClientAdmin` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) RemoveClientAdminTransaction(subnetID []byte, groupID []byte, adminPublicKey *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "removeClientAdmin", subnetID, groupID, adminPublicKey) +} + +// RemoveClientAdminUnsigned creates a transaction invoking `removeClientAdmin` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) RemoveClientAdminUnsigned(subnetID []byte, groupID []byte, adminPublicKey *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "removeClientAdmin", nil, subnetID, groupID, adminPublicKey) +} + +// RemoveNode creates a transaction invoking `removeNode` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) RemoveNode(subnetID []byte, node *keys.PublicKey) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "removeNode", subnetID, node) +} + +// RemoveNodeTransaction creates a transaction invoking `removeNode` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) RemoveNodeTransaction(subnetID []byte, node *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "removeNode", subnetID, node) +} + +// RemoveNodeUnsigned creates a transaction invoking `removeNode` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) RemoveNodeUnsigned(subnetID []byte, node *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "removeNode", nil, subnetID, node) +} + +// RemoveNodeAdmin creates a transaction invoking `removeNodeAdmin` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) RemoveNodeAdmin(subnetID []byte, adminKey *keys.PublicKey) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "removeNodeAdmin", subnetID, adminKey) +} + +// RemoveNodeAdminTransaction creates a transaction invoking `removeNodeAdmin` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) RemoveNodeAdminTransaction(subnetID []byte, adminKey *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "removeNodeAdmin", subnetID, adminKey) +} + +// RemoveNodeAdminUnsigned creates a transaction invoking `removeNodeAdmin` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) RemoveNodeAdminUnsigned(subnetID []byte, adminKey *keys.PublicKey) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "removeNodeAdmin", nil, subnetID, adminKey) +} + +// RemoveUser creates a transaction invoking `removeUser` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) RemoveUser(subnetID []byte, groupID []byte, userID []byte) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "removeUser", subnetID, groupID, userID) +} + +// RemoveUserTransaction creates a transaction invoking `removeUser` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) RemoveUserTransaction(subnetID []byte, groupID []byte, userID []byte) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "removeUser", subnetID, groupID, userID) +} + +// RemoveUserUnsigned creates a transaction invoking `removeUser` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) RemoveUserUnsigned(subnetID []byte, groupID []byte, userID []byte) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "removeUser", nil, subnetID, groupID, userID) +} + +// Update creates a transaction invoking `update` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Update(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) { + return c.actor.SendCall(c.hash, "update", script, manifest, data) +} + +// UpdateTransaction creates a transaction invoking `update` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UpdateTransaction(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeCall(c.hash, "update", script, manifest, data) +} + +// UpdateUnsigned creates a transaction invoking `update` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data) +} + +func (c *Contract) scriptForUserAllowed(subnetID []byte, user []byte) ([]byte, error) { + return smartcontract.CreateCallWithAssertScript(c.hash, "userAllowed", subnetID, user) +} + +// UserAllowed creates a transaction invoking `userAllowed` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) UserAllowed(subnetID []byte, user []byte) (util.Uint256, uint32, error) { + script, err := c.scriptForUserAllowed(subnetID, user) + if err != nil { + return util.Uint256{}, 0, err + } + return c.actor.SendRun(script) +} + +// UserAllowedTransaction creates a transaction invoking `userAllowed` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) UserAllowedTransaction(subnetID []byte, user []byte) (*transaction.Transaction, error) { + script, err := c.scriptForUserAllowed(subnetID, user) + if err != nil { + return nil, err + } + return c.actor.MakeRun(script) +} + +// UserAllowedUnsigned creates a transaction invoking `userAllowed` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) UserAllowedUnsigned(subnetID []byte, user []byte) (*transaction.Transaction, error) { + script, err := c.scriptForUserAllowed(subnetID, user) + if err != nil { + return nil, err + } + return c.actor.MakeUnsignedRun(script, nil) +} + +// itemToCommonBallot converts stack item into *CommonBallot. +func itemToCommonBallot(item stackitem.Item, err error) (*CommonBallot, error) { + if err != nil { + return nil, err + } + var res = new(CommonBallot) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of CommonBallot from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *CommonBallot) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.Voters, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Voters: %w", err) + } + + index++ + res.Height, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Height: %w", err) + } + + return nil +} + +// itemToLedgerBlock converts stack item into *LedgerBlock. +func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 9 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + return nil +} + +// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. +func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 10 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + index++ + res.PrevStateRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevStateRoot: %w", err) + } + + return nil +} + +// itemToLedgerTransaction converts stack item into *LedgerTransaction. +func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Sender, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + + index++ + res.SysFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + + index++ + res.NetFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + + index++ + res.ValidUntilBlock, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + + index++ + res.Script, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + + return nil +} + +// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. +func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Account, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Account: %w", err) + } + + index++ + res.Scopes, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Scopes: %w", err) + } + + index++ + res.AllowedContracts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedContracts: %w", err) + } + + index++ + res.AllowedGroups, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedGroups: %w", err) + } + + index++ + res.Rules, err = func (item stackitem.Item) ([]*LedgerWitnessRule, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*LedgerWitnessRule, len(arr)) + for i := range res { + res[i], err = itemToLedgerWitnessRule(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Rules: %w", err) + } + + return nil +} + +// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. +func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + index++ + res.Value, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} + +// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. +func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Action, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Action: %w", err) + } + + index++ + res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) + if err != nil { + return fmt.Errorf("field Condition: %w", err) + } + + return nil +} + +// itemToManagementABI converts stack item into *ManagementABI. +func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { + if err != nil { + return nil, err + } + var res = new(ManagementABI) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementABI from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementABI) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Methods, err = func (item stackitem.Item) ([]*ManagementMethod, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementMethod, len(arr)) + for i := range res { + res[i], err = itemToManagementMethod(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + index++ + res.Events, err = func (item stackitem.Item) ([]*ManagementEvent, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementEvent, len(arr)) + for i := range res { + res[i], err = itemToManagementEvent(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Events: %w", err) + } + + return nil +} + +// itemToManagementContract converts stack item into *ManagementContract. +func itemToManagementContract(item stackitem.Item, err error) (*ManagementContract, error) { + if err != nil { + return nil, err + } + var res = new(ManagementContract) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementContract from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementContract) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.UpdateCounter, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field UpdateCounter: %w", err) + } + + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.NEF, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field NEF: %w", err) + } + + index++ + res.Manifest, err = itemToManagementManifest(arr[index], nil) + if err != nil { + return fmt.Errorf("field Manifest: %w", err) + } + + return nil +} + +// itemToManagementEvent converts stack item into *ManagementEvent. +func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, error) { + if err != nil { + return nil, err + } + var res = new(ManagementEvent) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementEvent from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + return nil +} + +// itemToManagementGroup converts stack item into *ManagementGroup. +func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, error) { + if err != nil { + return nil, err + } + var res = new(ManagementGroup) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementGroup from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + index++ + res.Signature, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Signature: %w", err) + } + + return nil +} + +// itemToManagementManifest converts stack item into *ManagementManifest. +func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManifest, error) { + if err != nil { + return nil, err + } + var res = new(ManagementManifest) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementManifest from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Groups, err = func (item stackitem.Item) ([]*ManagementGroup, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementGroup, len(arr)) + for i := range res { + res[i], err = itemToManagementGroup(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Groups: %w", err) + } + + index++ + res.Features, err = func (item stackitem.Item) (map[string]string, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string]string) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Features: %w", err) + } + + index++ + res.SupportedStandards, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field SupportedStandards: %w", err) + } + + index++ + res.ABI, err = itemToManagementABI(arr[index], nil) + if err != nil { + return fmt.Errorf("field ABI: %w", err) + } + + index++ + res.Permissions, err = func (item stackitem.Item) ([]*ManagementPermission, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementPermission, len(arr)) + for i := range res { + res[i], err = itemToManagementPermission(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Permissions: %w", err) + } + + index++ + res.Trusts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Trusts: %w", err) + } + + index++ + res.Extra, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Extra: %w", err) + } + + return nil +} + +// itemToManagementMethod converts stack item into *ManagementMethod. +func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, error) { + if err != nil { + return nil, err + } + var res = new(ManagementMethod) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementMethod from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + index++ + res.ReturnType, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ReturnType: %w", err) + } + + index++ + res.Offset, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Offset: %w", err) + } + + index++ + res.Safe, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field Safe: %w", err) + } + + return nil +} + +// itemToManagementParameter converts stack item into *ManagementParameter. +func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParameter, error) { + if err != nil { + return nil, err + } + var res = new(ManagementParameter) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementParameter from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + return nil +} + +// itemToManagementPermission converts stack item into *ManagementPermission. +func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPermission, error) { + if err != nil { + return nil, err + } + var res = new(ManagementPermission) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementPermission from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Contract, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Contract: %w", err) + } + + index++ + res.Methods, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + return nil +} + +// DeleteEventsFromApplicationLog retrieves a set of all emitted events +// with "Delete" name from the provided [result.ApplicationLog]. +func DeleteEventsFromApplicationLog(log *result.ApplicationLog) ([]*DeleteEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*DeleteEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Delete" { + continue + } + event := new(DeleteEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize DeleteEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to DeleteEvent or +// returns an error if it's not possible to do to so. +func (e *DeleteEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.Id, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Id: %w", err) + } + + return nil +} + +// RemoveNodeEventsFromApplicationLog retrieves a set of all emitted events +// with "RemoveNode" name from the provided [result.ApplicationLog]. +func RemoveNodeEventsFromApplicationLog(log *result.ApplicationLog) ([]*RemoveNodeEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*RemoveNodeEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "RemoveNode" { + continue + } + event := new(RemoveNodeEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize RemoveNodeEvent from stackitem (execution #%d, event #%d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to RemoveNodeEvent or +// returns an error if it's not possible to do to so. +func (e *RemoveNodeEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.SubnetID, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field SubnetID: %w", err) + } + + index++ + e.Node, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Node: %w", err) + } + + return nil +}