diff --git a/pkg/rpcclient/neo/neo.go b/pkg/rpcclient/neo/neo.go index da2fe0d45..b9b17ed33 100644 --- a/pkg/rpcclient/neo/neo.go +++ b/pkg/rpcclient/neo/neo.go @@ -63,7 +63,7 @@ type ContractReader struct { // Contract provides full NEO interface, both safe and state-changing methods. type Contract struct { ContractReader - nep17.Token + nep17.TokenWriter actor Actor } @@ -102,7 +102,8 @@ func NewReader(invoker Invoker) *ContractReader { // New creates an instance of Contract to perform state-changing actions in the // NEO contract. func New(actor Actor) *Contract { - return &Contract{*NewReader(actor), *nep17.New(actor, Hash), actor} + nep := nep17.New(actor, Hash) + return &Contract{ContractReader{nep.TokenReader, actor}, nep.TokenWriter, actor} } // GetAccountState returns current NEO balance state for the account which diff --git a/pkg/rpcclient/nep11/base.go b/pkg/rpcclient/nep11/base.go index 8aaf06a89..71c75ef7a 100644 --- a/pkg/rpcclient/nep11/base.go +++ b/pkg/rpcclient/nep11/base.go @@ -51,12 +51,19 @@ type BaseReader struct { hash util.Uint160 } +// 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. +type BaseWriter struct { + hash util.Uint160 + actor Actor +} + // Base is a state-changing interface for common divisible and non-divisible NEP-11 // methods. type Base struct { BaseReader - - actor Actor + BaseWriter } // TransferEvent represents a Transfer event as defined in the NEP-11 standard. @@ -83,7 +90,7 @@ func NewBaseReader(invoker Invoker, hash util.Uint160) *BaseReader { // NewBase creates an instance of Base for contract with the given // hash using the given actor. func NewBase(actor Actor, hash util.Uint160) *Base { - return &Base{*NewBaseReader(actor, hash), actor} + return &Base{*NewBaseReader(actor, hash), BaseWriter{hash, actor}} } // Properties returns a set of token's properties such as name or URL. The map @@ -142,7 +149,7 @@ func (t *BaseReader) TokensOfExpanded(account util.Uint160, num int) ([][]byte, // 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 (t *Base) Transfer(to util.Uint160, id []byte, data interface{}) (util.Uint256, uint32, error) { +func (t *BaseWriter) Transfer(to util.Uint160, id []byte, data interface{}) (util.Uint256, uint32, error) { script, err := t.transferScript(to, id, data) if err != nil { return util.Uint256{}, 0, err @@ -155,7 +162,7 @@ func (t *Base) Transfer(to util.Uint160, id []byte, data interface{}) (util.Uint // 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 (t *Base) TransferTransaction(to util.Uint160, id []byte, data interface{}) (*transaction.Transaction, error) { +func (t *BaseWriter) TransferTransaction(to util.Uint160, id []byte, data interface{}) (*transaction.Transaction, error) { script, err := t.transferScript(to, id, data) if err != nil { return nil, err @@ -168,7 +175,7 @@ func (t *Base) TransferTransaction(to util.Uint160, id []byte, data interface{}) // 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. -func (t *Base) TransferUnsigned(to util.Uint160, id []byte, data interface{}) (*transaction.Transaction, error) { +func (t *BaseWriter) TransferUnsigned(to util.Uint160, id []byte, data interface{}) (*transaction.Transaction, error) { script, err := t.transferScript(to, id, data) if err != nil { return nil, err @@ -176,7 +183,7 @@ func (t *Base) TransferUnsigned(to util.Uint160, id []byte, data interface{}) (* return t.actor.MakeUnsignedRun(script, nil) } -func (t *Base) transferScript(params ...interface{}) ([]byte, error) { +func (t *BaseWriter) transferScript(params ...interface{}) ([]byte, error) { return smartcontract.CreateCallWithAssertScript(t.hash, "transfer", params...) } diff --git a/pkg/rpcclient/nep11/divisible.go b/pkg/rpcclient/nep11/divisible.go index 107efb307..29a3b4055 100644 --- a/pkg/rpcclient/nep11/divisible.go +++ b/pkg/rpcclient/nep11/divisible.go @@ -18,7 +18,8 @@ type DivisibleReader struct { // Divisible is a state-changing interface for divisible NEP-11 contract. type Divisible struct { - Base + DivisibleReader + BaseWriter } // OwnerIterator is used for iterating over OwnerOf (for divisible NFTs) results. @@ -37,7 +38,7 @@ func NewDivisibleReader(invoker Invoker, hash util.Uint160) *DivisibleReader { // NewDivisible creates an instance of Divisible for a contract // with the given hash using the given actor. func NewDivisible(actor Actor, hash util.Uint160) *Divisible { - return &Divisible{*NewBase(actor, hash)} + return &Divisible{*NewDivisibleReader(actor, hash), BaseWriter{hash, actor}} } // OwnerOf returns returns an iterator that allows to walk through all owners of @@ -66,24 +67,6 @@ func (t *DivisibleReader) BalanceOfD(owner util.Uint160, token []byte) (*big.Int return unwrap.BigInt(t.invoker.Call(t.hash, "balanceOf", owner, token)) } -// OwnerOf is the same as (*DivisibleReader).OwnerOf. -func (t *Divisible) OwnerOf(token []byte) (*OwnerIterator, error) { - r := DivisibleReader{t.BaseReader} - return r.OwnerOf(token) -} - -// OwnerOfExpanded is the same as (*DivisibleReader).OwnerOfExpanded. -func (t *Divisible) OwnerOfExpanded(token []byte, num int) ([]util.Uint160, error) { - r := DivisibleReader{t.BaseReader} - return r.OwnerOfExpanded(token, num) -} - -// BalanceOfD is the same as (*DivisibleReader).BalanceOfD. -func (t *Divisible) BalanceOfD(owner util.Uint160, token []byte) (*big.Int, error) { - r := DivisibleReader{t.BaseReader} - return r.BalanceOfD(owner, token) -} - // 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, diff --git a/pkg/rpcclient/nep11/nondivisible.go b/pkg/rpcclient/nep11/nondivisible.go index f0b48cf75..1ca28452d 100644 --- a/pkg/rpcclient/nep11/nondivisible.go +++ b/pkg/rpcclient/nep11/nondivisible.go @@ -12,7 +12,8 @@ type NonDivisibleReader struct { // NonDivisible is a state-changing interface for non-divisble NEP-11 contract. type NonDivisible struct { - Base + NonDivisibleReader + BaseWriter } // NewNonDivisibleReader creates an instance of NonDivisibleReader for a contract @@ -24,16 +25,10 @@ func NewNonDivisibleReader(invoker Invoker, hash util.Uint160) *NonDivisibleRead // NewNonDivisible creates an instance of NonDivisible for a contract // with the given hash using the given actor. func NewNonDivisible(actor Actor, hash util.Uint160) *NonDivisible { - return &NonDivisible{*NewBase(actor, hash)} + return &NonDivisible{*NewNonDivisibleReader(actor, hash), BaseWriter{hash, actor}} } // OwnerOf returns the owner of the given NFT. func (t *NonDivisibleReader) OwnerOf(token []byte) (util.Uint160, error) { return unwrap.Uint160(t.invoker.Call(t.hash, "ownerOf", token)) } - -// OwnerOf is the same as (*NonDivisibleReader).OwnerOf. -func (t *NonDivisible) OwnerOf(token []byte) (util.Uint160, error) { - r := NonDivisibleReader{t.BaseReader} - return r.OwnerOf(token) -} diff --git a/pkg/rpcclient/nep17/nep17.go b/pkg/rpcclient/nep17/nep17.go index d6c263747..e2f1d71e4 100644 --- a/pkg/rpcclient/nep17/nep17.go +++ b/pkg/rpcclient/nep17/nep17.go @@ -36,12 +36,19 @@ type TokenReader struct { neptoken.Base } +// TokenWriter contains NEP-17 token methods that change state. It's not meant +// to be used directly (Token that includes it is more convenient) and just +// separates one set of methods from another to simplify reusing this package +// for other contracts that extend NEP-17 interface. +type TokenWriter struct { + hash util.Uint160 + actor Actor +} + // Token provides full NEP-17 interface, both safe and state-changing methods. type Token struct { TokenReader - - hash util.Uint160 - actor Actor + TokenWriter } // TransferEvent represents a Transfer event as defined in the NEP-17 standard. @@ -68,14 +75,14 @@ func NewReader(invoker Invoker, hash util.Uint160) *TokenReader { // 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), hash, actor} + return &Token{*NewReader(actor, hash), TokenWriter{hash, actor}} } // 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) { +func (t *TokenWriter) Transfer(from util.Uint160, to util.Uint160, amount *big.Int, data interface{}) (util.Uint256, uint32, error) { return t.MultiTransfer([]TransferParameters{{from, to, amount, data}}) } @@ -83,7 +90,7 @@ func (t *Token) Transfer(from util.Uint160, to util.Uint160, amount *big.Int, da // 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) { +func (t *TokenWriter) TransferTransaction(from util.Uint160, to util.Uint160, amount *big.Int, data interface{}) (*transaction.Transaction, error) { return t.MultiTransferTransaction([]TransferParameters{{from, to, amount, data}}) } @@ -91,11 +98,11 @@ func (t *Token) TransferTransaction(from util.Uint160, to util.Uint160, amount * // 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) { +func (t *TokenWriter) TransferUnsigned(from util.Uint160, to util.Uint160, amount *big.Int, data interface{}) (*transaction.Transaction, error) { return t.MultiTransferUnsigned([]TransferParameters{{from, to, amount, data}}) } -func (t *Token) multiTransferScript(params []TransferParameters) ([]byte, error) { +func (t *TokenWriter) multiTransferScript(params []TransferParameters) ([]byte, error) { if len(params) == 0 { return nil, errors.New("at least one transfer parameter required") } @@ -113,7 +120,7 @@ func (t *Token) multiTransferScript(params []TransferParameters) ([]byte, error) // many times as needed (with ASSERTs added, so if any of these transfers fail // whole transaction (with all transfers) fails). The values returned are the // same as in Transfer. -func (t *Token) MultiTransfer(params []TransferParameters) (util.Uint256, uint32, error) { +func (t *TokenWriter) MultiTransfer(params []TransferParameters) (util.Uint256, uint32, error) { script, err := t.multiTransferScript(params) if err != nil { return util.Uint256{}, 0, err @@ -123,7 +130,7 @@ func (t *Token) MultiTransfer(params []TransferParameters) (util.Uint256, uint32 // MultiTransferTransaction is similar to MultiTransfer, but returns the same values // as TransferTransaction (signed transaction that is not yet sent). -func (t *Token) MultiTransferTransaction(params []TransferParameters) (*transaction.Transaction, error) { +func (t *TokenWriter) MultiTransferTransaction(params []TransferParameters) (*transaction.Transaction, error) { script, err := t.multiTransferScript(params) if err != nil { return nil, err @@ -133,7 +140,7 @@ func (t *Token) MultiTransferTransaction(params []TransferParameters) (*transact // MultiTransferUnsigned is similar to MultiTransfer, but returns the same values // as TransferUnsigned (not yet signed transaction). -func (t *Token) MultiTransferUnsigned(params []TransferParameters) (*transaction.Transaction, error) { +func (t *TokenWriter) MultiTransferUnsigned(params []TransferParameters) (*transaction.Transaction, error) { script, err := t.multiTransferScript(params) if err != nil { return nil, err