nep11

package
v0.107.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 6, 2024 License: MIT Imports: 12 Imported by: 3

Documentation

Overview

Package nep11 contains RPC wrappers for NEP-11 contracts.

The set of types provided is split between common NEP-11 methods (BaseReader and Base types) and divisible (DivisibleReader and Divisible) and non-divisible (NonDivisibleReader and NonDivisible). If you don't know the type of NEP-11 contract you're going to use you can use Base and BaseReader types for many purposes, otherwise more specific types are recommended.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func UnwrapKnownProperties

func UnwrapKnownProperties(m *stackitem.Map, err error) (map[string]string, error)

UnwrapKnownProperties can be used as a proxy function to extract well-known NEP-11 properties (name/description/image/tokenURI) defined in the standard. These properties are checked to be valid UTF-8 strings, but can contain control codes or special characters.

Types

type Actor

type Actor interface {
	Invoker

	MakeRun(script []byte) (*transaction.Transaction, error)
	MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error)
	SendRun(script []byte) (util.Uint256, uint32, error)
}

Actor is used by complete NEP-11 types to create and send transactions.

type Base

type Base struct {
	BaseReader
	BaseWriter
}

Base is a state-changing interface for common divisible and non-divisible NEP-11 methods.

func NewBase

func NewBase(actor Actor, hash util.Uint160) *Base

NewBase creates an instance of Base for contract with the given hash using the given actor.

type BaseReader

type BaseReader struct {
	neptoken.Base
	// contains filtered or unexported fields
}

BaseReader is a reader interface for common divisible and non-divisible NEP-11 methods. It allows to invoke safe methods.

func NewBaseReader

func NewBaseReader(invoker Invoker, hash util.Uint160) *BaseReader

NewBaseReader creates an instance of BaseReader for a contract with the given hash using the given invoker.

func (*BaseReader) Properties

func (t *BaseReader) Properties(token []byte) (*stackitem.Map, error)

Properties returns a set of token's properties such as name or URL. The map is returned as is from this method (stack item) for maximum flexibility, contracts can return a lot of specific data there. Most of the time though they return well-defined properties outlined in NEP-11 and UnwrapKnownProperties can be used to get them in more convenient way. It's an optional method per NEP-11 specification, so it can fail.

func (*BaseReader) Tokens

func (t *BaseReader) Tokens() (*TokenIterator, error)

Tokens returns an iterator that allows to retrieve all tokens minted by the contract. It depends on the server to provide proper session-based iterator, but can also work with expanded one. The method itself is optional per NEP-11 specification, so it can fail.

func (*BaseReader) TokensExpanded

func (t *BaseReader) TokensExpanded(num int) ([][]byte, error)

TokensExpanded uses the same NEP-11 method as Tokens, but can be useful if the server used doesn't support sessions and doesn't expand iterators. It creates a script that will get num of result items from the iterator right in the VM and return them to you. It's only limited by VM stack and GAS available for RPC invocations.

func (*BaseReader) TokensOf

func (t *BaseReader) TokensOf(account util.Uint160) (*TokenIterator, error)

TokensOf returns an iterator that allows to walk through all tokens owned by the given account. It depends on the server to provide proper session-based iterator, but can also work with expanded one.

func (*BaseReader) TokensOfExpanded

func (t *BaseReader) TokensOfExpanded(account util.Uint160, num int) ([][]byte, error)

TokensOfExpanded uses the same NEP-11 method as TokensOf, but can be useful if the server used doesn't support sessions and doesn't expand iterators. It creates a script that will get num of result items from the iterator right in the VM and return them to you. It's only limited by VM stack and GAS available for RPC invocations.

type BaseWriter

type BaseWriter struct {
	// contains filtered or unexported fields
}

BaseWriter is a transaction-creating interface for common divisible and non-divisible NEP-11 methods. It simplifies reusing this set of methods, but a complete Base is expected to be used in other packages.

func (*BaseWriter) Transfer

func (t *BaseWriter) Transfer(to util.Uint160, id []byte, data any) (util.Uint256, uint32, error)

Transfer creates and sends a transaction that performs a `transfer` method call using the given parameters and checks for this call result, failing the transaction if it's not true. It works for divisible NFTs only when there is one owner for the particular token. The returned values are transaction hash, its ValidUntilBlock value and an error if any.

func (*BaseWriter) TransferTransaction

func (t *BaseWriter) TransferTransaction(to util.Uint160, id []byte, data any) (*transaction.Transaction, error)

TransferTransaction creates a transaction that performs a `transfer` method call using the given parameters and checks for this call result, failing the transaction if it's not true. It works for divisible NFTs only when there is one owner for the particular token. This transaction is signed, but not sent to the network, instead it's returned to the caller.

func (*BaseWriter) TransferUnsigned

func (t *BaseWriter) TransferUnsigned(to util.Uint160, id []byte, data any) (*transaction.Transaction, error)

TransferUnsigned creates a transaction that performs a `transfer` method call using the given parameters and checks for this call result, failing the transaction if it's not true. It works for divisible NFTs only when there is one owner for the particular token. This transaction is not signed and just returned to the caller.

type Divisible

type Divisible struct {
	DivisibleReader
	DivisibleWriter
}

Divisible is a full reader interface for divisible NEP-11 contract.

Example
package main

import (
	"context"

	"github.com/nspcc-dev/neo-go/pkg/encoding/address"
	"github.com/nspcc-dev/neo-go/pkg/rpcclient"
	"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
	"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep11"
	"github.com/nspcc-dev/neo-go/pkg/util"
	"github.com/nspcc-dev/neo-go/pkg/wallet"
)

func main() {
	// No error checking done at all, intentionally.
	w, _ := wallet.NewWalletFromFile("somewhere")
	defer w.Close()

	c, _ := rpcclient.New(context.Background(), "url", rpcclient.Options{})

	// Create a simple CalledByEntry-scoped actor (assuming there is an account
	// inside the wallet).
	a, _ := actor.NewSimple(c, w.Accounts[0])

	// NEP-11 contract hash.
	nep11Hash := util.Uint160{9, 8, 7}

	// Create a complete divisible contract representation.
	n11 := nep11.NewDivisible(a, nep11Hash)

	tgtAcc, _ := address.StringToUint160("NdypBhqkz2CMMnwxBgvoC9X2XjKF5axgKo")

	// Let's tranfer all of account's tokens to some other account.
	tokIter, _ := n11.TokensOf(a.Sender())
	for toks, err := tokIter.Next(10); err == nil && len(toks) > 0; toks, err = tokIter.Next(10) {
		for i := range toks {
			// It's a divisible token, so balance data is required in general case.
			balance, _ := n11.BalanceOfD(a.Sender(), toks[i])

			// This creates a transaction for every token, but you can
			// create a script that will move multiple tokens in one
			// transaction with Builder from smartcontract package.
			txid, vub, _ := n11.TransferD(a.Sender(), tgtAcc, balance, toks[i], nil)
			_ = txid
			_ = vub
		}
	}
}
Output:

func NewDivisible

func NewDivisible(actor Actor, hash util.Uint160) *Divisible

NewDivisible creates an instance of Divisible for a contract with the given hash using the given actor.

type DivisibleReader

type DivisibleReader struct {
	BaseReader
}

DivisibleReader is a reader interface for divisible NEP-11 contract.

Example
package main

import (
	"context"
	"math/big"

	"github.com/nspcc-dev/neo-go/pkg/encoding/address"
	"github.com/nspcc-dev/neo-go/pkg/rpcclient"
	"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
	"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep11"
	"github.com/nspcc-dev/neo-go/pkg/util"
)

func main() {
	// No error checking done at all, intentionally.
	c, _ := rpcclient.New(context.Background(), "url", rpcclient.Options{})

	// Safe methods are reachable with just an invoker, no need for an account there.
	inv := invoker.New(c, nil)

	// NEP-11 contract hash.
	nep11Hash := util.Uint160{9, 8, 7}

	// Divisible contract are more rare, but we can handle them too.
	n11 := nep11.NewDivisibleReader(inv, nep11Hash)

	// Get the metadata. Even though these methods are implemented in neptoken package,
	// they're available for NEP-11 wrappers.
	symbol, _ := n11.Symbol()
	supply, _ := n11.TotalSupply()
	_ = symbol
	_ = supply

	// Account hash we're interested in.
	accHash, _ := address.StringToUint160("NdypBhqkz2CMMnwxBgvoC9X2XjKF5axgKo")

	// Get account balance.
	balance, _ := n11.BalanceOf(accHash)
	if balance.Sign() > 0 && balance.Cmp(big.NewInt(10)) < 0 {
		// We know we have a low number of tokens, so we can use a simple API to get them.
		toks, _ := n11.TokensOfExpanded(accHash, 10)

		// We can build a list of all owners of account's tokens.
		var owners = make([]util.Uint160, 0)
		for i := range toks {
			ownIter, _ := n11.OwnerOf(toks[i])
			for ows, err := ownIter.Next(10); err == nil && len(ows) > 0; ows, err = ownIter.Next(10) {
				// Notice that it includes accHash too.
				owners = append(owners, ows...)
			}
		}
		// The list can be sorted/deduplicated if needed.
		_ = owners
	}
}
Output:

func NewDivisibleReader

func NewDivisibleReader(invoker Invoker, hash util.Uint160) *DivisibleReader

NewDivisibleReader creates an instance of DivisibleReader for a contract with the given hash using the given invoker.

func (*DivisibleReader) BalanceOfD

func (t *DivisibleReader) BalanceOfD(owner util.Uint160, token []byte) (*big.Int, error)

BalanceOfD is a BalanceOf for divisible NFTs, it returns the amount of token owned by a particular account.

func (*DivisibleReader) OwnerOf

func (t *DivisibleReader) OwnerOf(token []byte) (*OwnerIterator, error)

OwnerOf returns an iterator that allows to walk through all owners of the given token. It depends on the server to provide proper session-based iterator, but can also work with expanded one.

func (*DivisibleReader) OwnerOfExpanded

func (t *DivisibleReader) OwnerOfExpanded(token []byte, num int) ([]util.Uint160, error)

OwnerOfExpanded uses the same NEP-11 method as OwnerOf, but can be useful if the server used doesn't support sessions and doesn't expand iterators. It creates a script that will get num of result items from the iterator right in the VM and return them to you. It's only limited by VM stack and GAS available for RPC invocations.

type DivisibleWriter added in v0.99.5

type DivisibleWriter struct {
	BaseWriter
}

DivisibleWriter is a state-changing interface for divisible NEP-11 contract. It's mostly useful not directly, but as a reusable layer for higher-level structures.

func (*DivisibleWriter) TransferD added in v0.99.5

func (t *DivisibleWriter) TransferD(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data any) (util.Uint256, uint32, error)

TransferD is a divisible version of (*Base).Transfer, allowing to transfer a part of NFT. It creates and sends a transaction that performs a `transfer` method call using the given parameters and checks for this call result, failing the transaction if it's not true. The returned values are transaction hash, its ValidUntilBlock value and an error if any.

func (*DivisibleWriter) TransferDTransaction added in v0.99.5

func (t *DivisibleWriter) TransferDTransaction(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data any) (*transaction.Transaction, error)

TransferDTransaction is a divisible version of (*Base).TransferTransaction, allowing to transfer a part of NFT. It creates a transaction that performs a `transfer` method call using the given parameters and checks for this call result, failing the transaction if it's not true. This transaction is signed, but not sent to the network, instead it's returned to the caller.

func (*DivisibleWriter) TransferDUnsigned added in v0.99.5

func (t *DivisibleWriter) TransferDUnsigned(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data any) (*transaction.Transaction, error)

TransferDUnsigned is a divisible version of (*Base).TransferUnsigned, allowing to transfer a part of NFT. It creates a transaction that performs a `transfer` method call using the given parameters and checks for this call result, failing the transaction if it's not true. This transaction is not signed and just returned to the caller.

type Invoker

type Invoker interface {
	neptoken.Invoker

	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)
}

Invoker is used by reader types to call various methods.

type NonDivisible

type NonDivisible struct {
	NonDivisibleReader
	BaseWriter
}

NonDivisible is a state-changing interface for non-divisble NEP-11 contract.

Example
package main

import (
	"context"

	"github.com/nspcc-dev/neo-go/pkg/encoding/address"
	"github.com/nspcc-dev/neo-go/pkg/rpcclient"
	"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
	"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep11"
	"github.com/nspcc-dev/neo-go/pkg/util"
	"github.com/nspcc-dev/neo-go/pkg/wallet"
)

func main() {
	// No error checking done at all, intentionally.
	w, _ := wallet.NewWalletFromFile("somewhere")
	defer w.Close()

	c, _ := rpcclient.New(context.Background(), "url", rpcclient.Options{})

	// Create a simple CalledByEntry-scoped actor (assuming there is an account
	// inside the wallet).
	a, _ := actor.NewSimple(c, w.Accounts[0])

	// NEP-11 contract hash.
	nep11Hash := util.Uint160{9, 8, 7}

	// Create a complete non-divisible contract representation.
	n11 := nep11.NewNonDivisible(a, nep11Hash)

	tgtAcc, _ := address.StringToUint160("NdypBhqkz2CMMnwxBgvoC9X2XjKF5axgKo")

	// Let's tranfer all of account's tokens to some other account.
	tokIter, _ := n11.TokensOf(a.Sender())
	for toks, err := tokIter.Next(10); err == nil && len(toks) > 0; toks, err = tokIter.Next(10) {
		for i := range toks {
			// This creates a transaction for every token, but you can
			// create a script that will move multiple tokens in one
			// transaction with Builder from smartcontract package.
			txid, vub, _ := n11.Transfer(tgtAcc, toks[i], nil)
			_ = txid
			_ = vub
		}
	}
}
Output:

func NewNonDivisible

func NewNonDivisible(actor Actor, hash util.Uint160) *NonDivisible

NewNonDivisible creates an instance of NonDivisible for a contract with the given hash using the given actor.

type NonDivisibleReader

type NonDivisibleReader struct {
	BaseReader
}

NonDivisibleReader is a reader interface for non-divisble NEP-11 contract.

Example
package main

import (
	"context"

	"github.com/nspcc-dev/neo-go/pkg/encoding/address"
	"github.com/nspcc-dev/neo-go/pkg/rpcclient"
	"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
	"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep11"
	"github.com/nspcc-dev/neo-go/pkg/util"
)

func main() {
	// No error checking done at all, intentionally.
	c, _ := rpcclient.New(context.Background(), "url", rpcclient.Options{})

	// Safe methods are reachable with just an invoker, no need for an account there.
	inv := invoker.New(c, nil)

	// NEP-11 contract hash.
	nep11Hash := util.Uint160{9, 8, 7}

	// Most of the time contracts are non-divisible, create a reader for nep11Hash.
	n11 := nep11.NewNonDivisibleReader(inv, nep11Hash)

	// Get the metadata. Even though these methods are implemented in neptoken package,
	// they're available for NEP-11 wrappers.
	symbol, _ := n11.Symbol()
	supply, _ := n11.TotalSupply()
	_ = symbol
	_ = supply

	// Account hash we're interested in.
	accHash, _ := address.StringToUint160("NdypBhqkz2CMMnwxBgvoC9X2XjKF5axgKo")

	// Get account balance.
	balance, _ := n11.BalanceOf(accHash)
	if balance.Sign() > 0 {
		// There are some tokens there, let's look at them.
		tokIter, _ := n11.TokensOf(accHash)

		for toks, err := tokIter.Next(10); err == nil && len(toks) > 0; toks, err = tokIter.Next(10) {
			for i := range toks {
				// We know the owner of the token, but let's check internal contract consistency.
				owner, _ := n11.OwnerOf(toks[i])
				if !owner.Equals(accHash) {
					panic("NEP-11 contract is broken!")
				}
			}
		}
	}
}
Output:

func NewNonDivisibleReader

func NewNonDivisibleReader(invoker Invoker, hash util.Uint160) *NonDivisibleReader

NewNonDivisibleReader creates an instance of NonDivisibleReader for a contract with the given hash using the given invoker.

func (*NonDivisibleReader) OwnerOf

func (t *NonDivisibleReader) OwnerOf(token []byte) (util.Uint160, error)

OwnerOf returns the owner of the given NFT.

type OwnerIterator

type OwnerIterator struct {
	// contains filtered or unexported fields
}

OwnerIterator is used for iterating over OwnerOf (for divisible NFTs) results.

func (*OwnerIterator) Next

func (v *OwnerIterator) Next(num int) ([]util.Uint160, error)

Next returns the next set of elements from the iterator (up to num of them). It can return less than num elements in case iterator doesn't have that many or zero elements if the iterator has no more elements or the session is expired.

func (*OwnerIterator) Terminate

func (v *OwnerIterator) Terminate() error

Terminate closes the iterator session used by OwnerIterator (if it's session-based).

type TokenIterator

type TokenIterator struct {
	// contains filtered or unexported fields
}

TokenIterator is used for iterating over TokensOf results.

func (*TokenIterator) Next

func (v *TokenIterator) Next(num int) ([][]byte, error)

Next returns the next set of elements from the iterator (up to num of them). It can return less than num elements in case iterator doesn't have that many or zero elements if the iterator has no more elements or the session is expired.

func (*TokenIterator) Terminate

func (v *TokenIterator) Terminate() error

Terminate closes the iterator session used by TokenIterator (if it's session-based).

type TransferEvent

type TransferEvent struct {
	From   util.Uint160
	To     util.Uint160
	Amount *big.Int
	ID     []byte
}

TransferEvent represents a Transfer event as defined in the NEP-11 standard.

func TransferEventsFromApplicationLog added in v0.102.0

func TransferEventsFromApplicationLog(log *result.ApplicationLog) ([]*TransferEvent, error)

TransferEventsFromApplicationLog retrieves all emitted TransferEvents from the provided result.ApplicationLog.

func (*TransferEvent) FromStackItem added in v0.102.0

func (e *TransferEvent) FromStackItem(item *stackitem.Array) error

FromStackItem converts provided stackitem.Array to TransferEvent or returns an error if it's not possible to do to so.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL