112 lines
3.8 KiB
Go
112 lines
3.8 KiB
Go
|
/*
|
||
|
Package nep17 contains RPC wrappers to work with NEP-17 contracts.
|
||
|
|
||
|
Safe methods are encapsulated into TokenReader structure while Token provides
|
||
|
various methods to perform the only NEP-17 state-changing call, Transfer.
|
||
|
*/
|
||
|
package nep17
|
||
|
|
||
|
import (
|
||
|
"math/big"
|
||
|
|
||
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/neptoken"
|
||
|
"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"
|
||
|
)
|
||
|
|
||
|
// Invoker is used by TokenReader to call various safe methods.
|
||
|
type Invoker interface {
|
||
|
neptoken.Invoker
|
||
|
}
|
||
|
|
||
|
// Actor is used by Token to create and send transactions.
|
||
|
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)
|
||
|
}
|
||
|
|
||
|
// TokenReader represents safe (read-only) methods of NEP-17 token. It can be
|
||
|
// used to query various data.
|
||
|
type TokenReader struct {
|
||
|
neptoken.Base
|
||
|
|
||
|
invoker Invoker
|
||
|
hash util.Uint160
|
||
|
}
|
||
|
|
||
|
// Token provides full NEP-17 interface, both safe and state-changing methods.
|
||
|
type Token struct {
|
||
|
TokenReader
|
||
|
|
||
|
actor Actor
|
||
|
}
|
||
|
|
||
|
// TransferEvent represents a Transfer event as defined in the NEP-17 standard.
|
||
|
type TransferEvent struct {
|
||
|
From util.Uint160
|
||
|
To util.Uint160
|
||
|
Amount *big.Int
|
||
|
}
|
||
|
|
||
|
// NewReader creates an instance of TokenReader for contract with the given hash
|
||
|
// using the given Invoker.
|
||
|
func NewReader(invoker Invoker, hash util.Uint160) *TokenReader {
|
||
|
return &TokenReader{*neptoken.New(invoker, hash), invoker, hash}
|
||
|
}
|
||
|
|
||
|
// New creates an instance of Token for contract with the given hash
|
||
|
// using the given Actor.
|
||
|
func New(actor Actor, hash util.Uint160) *Token {
|
||
|
return &Token{*NewReader(actor, hash), actor}
|
||
|
}
|
||
|
|
||
|
// BalanceOf returns the token balance of the given account.
|
||
|
func (t *TokenReader) BalanceOf(account util.Uint160) (*big.Int, error) {
|
||
|
return unwrap.BigInt(t.invoker.Call(t.hash, "balanceOf", account))
|
||
|
}
|
||
|
|
||
|
// 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. The returned values are transaction hash, its
|
||
|
// ValidUntilBlock value and an error if any.
|
||
|
func (t *Token) Transfer(from util.Uint160, to util.Uint160, amount *big.Int, data interface{}) (util.Uint256, uint32, error) {
|
||
|
script, err := t.transferScript(from, to, amount, data)
|
||
|
if err != nil {
|
||
|
return util.Uint256{}, 0, err
|
||
|
}
|
||
|
return t.actor.SendRun(script)
|
||
|
}
|
||
|
|
||
|
// 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. This transaction is signed, but not sent to the
|
||
|
// network, instead it's returned to the caller.
|
||
|
func (t *Token) TransferTransaction(from util.Uint160, to util.Uint160, amount *big.Int, data interface{}) (*transaction.Transaction, error) {
|
||
|
script, err := t.transferScript(from, to, amount, data)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return t.actor.MakeRun(script)
|
||
|
}
|
||
|
|
||
|
// 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. This transaction is not signed and just returned
|
||
|
// to the caller.
|
||
|
func (t *Token) TransferUnsigned(from util.Uint160, to util.Uint160, amount *big.Int, data interface{}) (*transaction.Transaction, error) {
|
||
|
script, err := t.transferScript(from, to, amount, data)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return t.actor.MakeUnsignedRun(script, nil)
|
||
|
}
|
||
|
|
||
|
func (t *Token) transferScript(from util.Uint160, to util.Uint160, amount *big.Int, data interface{}) ([]byte, error) {
|
||
|
return smartcontract.CreateCallWithAssertScript(t.hash, "transfer", from, to, amount, data)
|
||
|
}
|