Merge pull request #2778 from nspcc-dev/rpc-wrapper-writer
State-changing methods in RPC wrappers
This commit is contained in:
commit
695f00cfeb
10 changed files with 891 additions and 95 deletions
|
@ -294,6 +294,7 @@ package myspacecontract
|
|||
import (
|
||||
"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"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
|
@ -328,34 +329,37 @@ func TestGenerateRPCBindings(t *testing.T) {
|
|||
app := cli.NewApp()
|
||||
app.Commands = []cli.Command{generateWrapperCmd, generateRPCWrapperCmd}
|
||||
|
||||
outFile := filepath.Join(tmpDir, "out.go")
|
||||
require.NoError(t, app.Run([]string{"", "generate-rpcwrapper",
|
||||
"--manifest", filepath.Join("testdata", "nex", "nex.manifest.json"),
|
||||
"--out", outFile,
|
||||
"--hash", "0xa2a67f09e8cf22c6bfd5cea24adc0f4bf0a11aa8",
|
||||
}))
|
||||
var checkBinding = func(manifest string, hash string, good string) {
|
||||
t.Run(manifest, func(t *testing.T) {
|
||||
outFile := filepath.Join(tmpDir, "out.go")
|
||||
require.NoError(t, app.Run([]string{"", "generate-rpcwrapper",
|
||||
"--manifest", manifest,
|
||||
"--out", outFile,
|
||||
"--hash", hash,
|
||||
}))
|
||||
|
||||
data, err := os.ReadFile(outFile)
|
||||
require.NoError(t, err)
|
||||
data = bytes.ReplaceAll(data, []byte("\r"), []byte{}) // Windows.
|
||||
expected, err := os.ReadFile(filepath.Join("testdata", "nex", "nex.go"))
|
||||
require.NoError(t, err)
|
||||
expected = bytes.ReplaceAll(expected, []byte("\r"), []byte{}) // Windows.
|
||||
require.Equal(t, string(expected), string(data))
|
||||
data, err := os.ReadFile(outFile)
|
||||
require.NoError(t, err)
|
||||
data = bytes.ReplaceAll(data, []byte("\r"), []byte{}) // Windows.
|
||||
expected, err := os.ReadFile(good)
|
||||
require.NoError(t, err)
|
||||
expected = bytes.ReplaceAll(expected, []byte("\r"), []byte{}) // Windows.
|
||||
require.Equal(t, string(expected), string(data))
|
||||
})
|
||||
}
|
||||
|
||||
require.NoError(t, app.Run([]string{"", "generate-rpcwrapper",
|
||||
"--manifest", filepath.Join("testdata", "nameservice", "nns.manifest.json"),
|
||||
"--out", outFile,
|
||||
"--hash", "0x50ac1c37690cc2cfc594472833cf57505d5f46de",
|
||||
}))
|
||||
|
||||
data, err = os.ReadFile(outFile)
|
||||
require.NoError(t, err)
|
||||
data = bytes.ReplaceAll(data, []byte("\r"), []byte{}) // Windows.
|
||||
expected, err = os.ReadFile(filepath.Join("testdata", "nameservice", "nns.go"))
|
||||
require.NoError(t, err)
|
||||
expected = bytes.ReplaceAll(expected, []byte("\r"), []byte{}) // Windows.
|
||||
require.Equal(t, string(expected), string(data))
|
||||
checkBinding(filepath.Join("testdata", "nex", "nex.manifest.json"),
|
||||
"0xa2a67f09e8cf22c6bfd5cea24adc0f4bf0a11aa8",
|
||||
filepath.Join("testdata", "nex", "nex.go"))
|
||||
checkBinding(filepath.Join("testdata", "nameservice", "nns.manifest.json"),
|
||||
"0x50ac1c37690cc2cfc594472833cf57505d5f46de",
|
||||
filepath.Join("testdata", "nameservice", "nns.go"))
|
||||
checkBinding(filepath.Join("testdata", "gas", "gas.manifest.json"),
|
||||
"0xd2a4cff31913016155e38e474a2c06d08be276cf",
|
||||
filepath.Join("testdata", "gas", "gas.go"))
|
||||
checkBinding(filepath.Join("testdata", "verifyrpc", "verify.manifest.json"),
|
||||
"0x00112233445566778899aabbccddeeff00112233",
|
||||
filepath.Join("testdata", "verifyrpc", "verify.go"))
|
||||
}
|
||||
|
||||
func TestGenerate_Errors(t *testing.T) {
|
||||
|
|
47
cli/smartcontract/testdata/gas/gas.go
vendored
Normal file
47
cli/smartcontract/testdata/gas/gas.go
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
// Package gastoken contains RPC wrappers for GasToken contract.
|
||||
package gastoken
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
// Hash contains contract hash.
|
||||
var Hash = util.Uint160{0xcf, 0x76, 0xe2, 0x8b, 0xd0, 0x6, 0x2c, 0x4a, 0x47, 0x8e, 0xe3, 0x55, 0x61, 0x1, 0x13, 0x19, 0xf3, 0xcf, 0xa4, 0xd2}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// ContractReader implements safe contract methods.
|
||||
type ContractReader struct {
|
||||
nep17.TokenReader
|
||||
invoker Invoker
|
||||
}
|
||||
|
||||
// Contract implements all contract methods.
|
||||
type Contract struct {
|
||||
ContractReader
|
||||
nep17.TokenWriter
|
||||
actor Actor
|
||||
}
|
||||
|
||||
// NewReader creates an instance of ContractReader using Hash and the given Invoker.
|
||||
func NewReader(invoker Invoker) *ContractReader {
|
||||
return &ContractReader{*nep17.NewReader(invoker, Hash), invoker}
|
||||
}
|
||||
|
||||
// New creates an instance of Contract using Hash and the given Actor.
|
||||
func New(actor Actor) *Contract {
|
||||
var nep17t = nep17.New(actor, Hash)
|
||||
return &Contract{ContractReader{nep17t.TokenReader, actor}, nep17t.TokenWriter, actor}
|
||||
}
|
||||
|
1
cli/smartcontract/testdata/gas/gas.manifest.json
vendored
Normal file
1
cli/smartcontract/testdata/gas/gas.manifest.json
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"name":"GasToken","groups":[],"features":{},"supportedstandards":["NEP-17"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"symbol","parameters":[],"returntype":"String","offset":14,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":21,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":28,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}
|
245
cli/smartcontract/testdata/nameservice/nns.go
vendored
245
cli/smartcontract/testdata/nameservice/nns.go
vendored
|
@ -2,9 +2,10 @@
|
|||
package nameservice
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"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"
|
||||
|
@ -16,7 +17,20 @@ var Hash = util.Uint160{0xde, 0x46, 0x5f, 0x5d, 0x50, 0x57, 0xcf, 0x33, 0x28, 0x
|
|||
// Invoker is used by ContractReader to call various safe methods.
|
||||
type Invoker interface {
|
||||
nep11.Invoker
|
||||
Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error)
|
||||
}
|
||||
|
||||
// Actor is used by Contract to call state-changing methods.
|
||||
type Actor interface {
|
||||
Invoker
|
||||
|
||||
nep11.Actor
|
||||
|
||||
MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error)
|
||||
MakeRun(script []byte) (*transaction.Transaction, error)
|
||||
MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error)
|
||||
MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error)
|
||||
SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error)
|
||||
SendRun(script []byte) (util.Uint256, uint32, error)
|
||||
}
|
||||
|
||||
// ContractReader implements safe contract methods.
|
||||
|
@ -25,11 +39,24 @@ type ContractReader struct {
|
|||
invoker Invoker
|
||||
}
|
||||
|
||||
// Contract implements all contract methods.
|
||||
type Contract struct {
|
||||
ContractReader
|
||||
nep11.BaseWriter
|
||||
actor Actor
|
||||
}
|
||||
|
||||
// NewReader creates an instance of ContractReader using Hash and the given Invoker.
|
||||
func NewReader(invoker Invoker) *ContractReader {
|
||||
return &ContractReader{*nep11.NewNonDivisibleReader(invoker, Hash), invoker}
|
||||
}
|
||||
|
||||
// New creates an instance of Contract using Hash and the given Actor.
|
||||
func New(actor Actor) *Contract {
|
||||
var nep11ndt = nep11.NewNonDivisible(actor, Hash)
|
||||
return &Contract{ContractReader{nep11ndt.NonDivisibleReader, actor}, nep11ndt.BaseWriter, actor}
|
||||
}
|
||||
|
||||
|
||||
// Roots invokes `roots` method of contract.
|
||||
func (c *ContractReader) Roots() (stackitem.Item, error) {
|
||||
|
@ -60,3 +87,217 @@ func (c *ContractReader) GetAllRecords(name string) (stackitem.Item, error) {
|
|||
func (c *ContractReader) Resolve(name string, typev *big.Int) (string, error) {
|
||||
return unwrap.UTF8String(c.invoker.Call(Hash, "resolve", name, typev))
|
||||
}
|
||||
|
||||
// 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) (util.Uint256, uint32, error) {
|
||||
return c.actor.SendCall(Hash, "update", nef, manifest)
|
||||
}
|
||||
|
||||
// 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) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeCall(Hash, "update", nef, manifest)
|
||||
}
|
||||
|
||||
// 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) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeUnsignedCall(Hash, "update", nil, nef, manifest)
|
||||
}
|
||||
|
||||
// AddRoot creates a transaction invoking `addRoot` 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) AddRoot(root string) (util.Uint256, uint32, error) {
|
||||
return c.actor.SendCall(Hash, "addRoot", root)
|
||||
}
|
||||
|
||||
// AddRootTransaction creates a transaction invoking `addRoot` method of the contract.
|
||||
// This transaction is signed, but not sent to the network, instead it's
|
||||
// returned to the caller.
|
||||
func (c *Contract) AddRootTransaction(root string) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeCall(Hash, "addRoot", root)
|
||||
}
|
||||
|
||||
// AddRootUnsigned creates a transaction invoking `addRoot` 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) AddRootUnsigned(root string) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeUnsignedCall(Hash, "addRoot", nil, root)
|
||||
}
|
||||
|
||||
// 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(priceList []interface{}) (util.Uint256, uint32, error) {
|
||||
return c.actor.SendCall(Hash, "setPrice", priceList)
|
||||
}
|
||||
|
||||
// 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(priceList []interface{}) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeCall(Hash, "setPrice", priceList)
|
||||
}
|
||||
|
||||
// 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(priceList []interface{}) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeUnsignedCall(Hash, "setPrice", nil, priceList)
|
||||
}
|
||||
|
||||
func scriptForRegister(name string, owner util.Uint160) ([]byte, error) {
|
||||
return smartcontract.CreateCallWithAssertScript(Hash, "register", name, owner)
|
||||
}
|
||||
|
||||
// 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) (util.Uint256, uint32, error) {
|
||||
script, err := scriptForRegister(name, owner)
|
||||
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) (*transaction.Transaction, error) {
|
||||
script, err := scriptForRegister(name, owner)
|
||||
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) (*transaction.Transaction, error) {
|
||||
script, err := scriptForRegister(name, owner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.actor.MakeUnsignedRun(script, nil)
|
||||
}
|
||||
|
||||
// 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(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(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(Hash, "renew", nil, name)
|
||||
}
|
||||
|
||||
// Renew_2 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_2(name string, years *big.Int) (util.Uint256, uint32, error) {
|
||||
return c.actor.SendCall(Hash, "renew", name, years)
|
||||
}
|
||||
|
||||
// Renew_2Transaction 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) Renew_2Transaction(name string, years *big.Int) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeCall(Hash, "renew", name, years)
|
||||
}
|
||||
|
||||
// Renew_2Unsigned 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) Renew_2Unsigned(name string, years *big.Int) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeUnsignedCall(Hash, "renew", nil, name, years)
|
||||
}
|
||||
|
||||
// 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(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(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(Hash, "setAdmin", nil, name, admin)
|
||||
}
|
||||
|
||||
// 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, typev *big.Int, data string) (util.Uint256, uint32, error) {
|
||||
return c.actor.SendCall(Hash, "setRecord", name, typev, 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, typev *big.Int, data string) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeCall(Hash, "setRecord", name, typev, 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, typev *big.Int, data string) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeUnsignedCall(Hash, "setRecord", nil, name, typev, data)
|
||||
}
|
||||
|
||||
// DeleteRecord creates a transaction invoking `deleteRecord` 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) DeleteRecord(name string, typev *big.Int) (util.Uint256, uint32, error) {
|
||||
return c.actor.SendCall(Hash, "deleteRecord", name, typev)
|
||||
}
|
||||
|
||||
// DeleteRecordTransaction creates a transaction invoking `deleteRecord` method of the contract.
|
||||
// This transaction is signed, but not sent to the network, instead it's
|
||||
// returned to the caller.
|
||||
func (c *Contract) DeleteRecordTransaction(name string, typev *big.Int) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeCall(Hash, "deleteRecord", name, typev)
|
||||
}
|
||||
|
||||
// DeleteRecordUnsigned creates a transaction invoking `deleteRecord` 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) DeleteRecordUnsigned(name string, typev *big.Int) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeUnsignedCall(Hash, "deleteRecord", nil, name, typev)
|
||||
}
|
||||
|
|
184
cli/smartcontract/testdata/nex/nex.go
vendored
184
cli/smartcontract/testdata/nex/nex.go
vendored
|
@ -2,8 +2,8 @@
|
|||
package nextoken
|
||||
|
||||
import (
|
||||
"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"
|
||||
|
@ -16,7 +16,20 @@ var Hash = util.Uint160{0xa8, 0x1a, 0xa1, 0xf0, 0x4b, 0xf, 0xdc, 0x4a, 0xa2, 0xc
|
|||
// Invoker is used by ContractReader to call various safe methods.
|
||||
type Invoker interface {
|
||||
nep17.Invoker
|
||||
Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error)
|
||||
}
|
||||
|
||||
// Actor is used by Contract to call state-changing methods.
|
||||
type Actor interface {
|
||||
Invoker
|
||||
|
||||
nep17.Actor
|
||||
|
||||
MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error)
|
||||
MakeRun(script []byte) (*transaction.Transaction, error)
|
||||
MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error)
|
||||
MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error)
|
||||
SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error)
|
||||
SendRun(script []byte) (util.Uint256, uint32, error)
|
||||
}
|
||||
|
||||
// ContractReader implements safe contract methods.
|
||||
|
@ -25,11 +38,24 @@ type ContractReader struct {
|
|||
invoker Invoker
|
||||
}
|
||||
|
||||
// Contract implements all contract methods.
|
||||
type Contract struct {
|
||||
ContractReader
|
||||
nep17.TokenWriter
|
||||
actor Actor
|
||||
}
|
||||
|
||||
// NewReader creates an instance of ContractReader using Hash and the given Invoker.
|
||||
func NewReader(invoker Invoker) *ContractReader {
|
||||
return &ContractReader{*nep17.NewReader(invoker, Hash), invoker}
|
||||
}
|
||||
|
||||
// New creates an instance of Contract using Hash and the given Actor.
|
||||
func New(actor Actor) *Contract {
|
||||
var nep17t = nep17.New(actor, Hash)
|
||||
return &Contract{ContractReader{nep17t.TokenReader, actor}, nep17t.TokenWriter, actor}
|
||||
}
|
||||
|
||||
|
||||
// Cap invokes `cap` method of contract.
|
||||
func (c *ContractReader) Cap() (*big.Int, error) {
|
||||
|
@ -50,3 +76,157 @@ func (c *ContractReader) GetOwner() (util.Uint160, error) {
|
|||
func (c *ContractReader) TotalMinted() (*big.Int, error) {
|
||||
return unwrap.BigInt(c.invoker.Call(Hash, "totalMinted"))
|
||||
}
|
||||
|
||||
// ChangeMinter creates a transaction invoking `changeMinter` 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) ChangeMinter(newMinter *keys.PublicKey) (util.Uint256, uint32, error) {
|
||||
return c.actor.SendCall(Hash, "changeMinter", newMinter)
|
||||
}
|
||||
|
||||
// ChangeMinterTransaction creates a transaction invoking `changeMinter` method of the contract.
|
||||
// This transaction is signed, but not sent to the network, instead it's
|
||||
// returned to the caller.
|
||||
func (c *Contract) ChangeMinterTransaction(newMinter *keys.PublicKey) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeCall(Hash, "changeMinter", newMinter)
|
||||
}
|
||||
|
||||
// ChangeMinterUnsigned creates a transaction invoking `changeMinter` 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) ChangeMinterUnsigned(newMinter *keys.PublicKey) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeUnsignedCall(Hash, "changeMinter", nil, newMinter)
|
||||
}
|
||||
|
||||
// ChangeOwner creates a transaction invoking `changeOwner` 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) ChangeOwner(newOwner util.Uint160) (util.Uint256, uint32, error) {
|
||||
return c.actor.SendCall(Hash, "changeOwner", newOwner)
|
||||
}
|
||||
|
||||
// ChangeOwnerTransaction creates a transaction invoking `changeOwner` method of the contract.
|
||||
// This transaction is signed, but not sent to the network, instead it's
|
||||
// returned to the caller.
|
||||
func (c *Contract) ChangeOwnerTransaction(newOwner util.Uint160) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeCall(Hash, "changeOwner", newOwner)
|
||||
}
|
||||
|
||||
// ChangeOwnerUnsigned creates a transaction invoking `changeOwner` 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) ChangeOwnerUnsigned(newOwner util.Uint160) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeUnsignedCall(Hash, "changeOwner", nil, newOwner)
|
||||
}
|
||||
|
||||
// Destroy creates a transaction invoking `destroy` 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) Destroy() (util.Uint256, uint32, error) {
|
||||
return c.actor.SendCall(Hash, "destroy")
|
||||
}
|
||||
|
||||
// DestroyTransaction creates a transaction invoking `destroy` method of the contract.
|
||||
// This transaction is signed, but not sent to the network, instead it's
|
||||
// returned to the caller.
|
||||
func (c *Contract) DestroyTransaction() (*transaction.Transaction, error) {
|
||||
return c.actor.MakeCall(Hash, "destroy")
|
||||
}
|
||||
|
||||
// DestroyUnsigned creates a transaction invoking `destroy` 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) DestroyUnsigned() (*transaction.Transaction, error) {
|
||||
return c.actor.MakeUnsignedCall(Hash, "destroy", nil)
|
||||
}
|
||||
|
||||
// MaxSupply creates a transaction invoking `maxSupply` 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) MaxSupply() (util.Uint256, uint32, error) {
|
||||
return c.actor.SendCall(Hash, "maxSupply")
|
||||
}
|
||||
|
||||
// MaxSupplyTransaction creates a transaction invoking `maxSupply` method of the contract.
|
||||
// This transaction is signed, but not sent to the network, instead it's
|
||||
// returned to the caller.
|
||||
func (c *Contract) MaxSupplyTransaction() (*transaction.Transaction, error) {
|
||||
return c.actor.MakeCall(Hash, "maxSupply")
|
||||
}
|
||||
|
||||
// MaxSupplyUnsigned creates a transaction invoking `maxSupply` 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) MaxSupplyUnsigned() (*transaction.Transaction, error) {
|
||||
return c.actor.MakeUnsignedCall(Hash, "maxSupply", nil)
|
||||
}
|
||||
|
||||
// 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(from util.Uint160, to util.Uint160, amount *big.Int, swapId *big.Int, signature []byte, data interface{}) (util.Uint256, uint32, error) {
|
||||
return c.actor.SendCall(Hash, "mint", from, to, amount, swapId, signature, data)
|
||||
}
|
||||
|
||||
// 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(from util.Uint160, to util.Uint160, amount *big.Int, swapId *big.Int, signature []byte, data interface{}) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeCall(Hash, "mint", from, to, amount, swapId, signature, data)
|
||||
}
|
||||
|
||||
// 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(from util.Uint160, to util.Uint160, amount *big.Int, swapId *big.Int, signature []byte, data interface{}) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeUnsignedCall(Hash, "mint", nil, from, to, amount, swapId, signature, 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 []byte) (util.Uint256, uint32, error) {
|
||||
return c.actor.SendCall(Hash, "update", nef, manifest)
|
||||
}
|
||||
|
||||
// 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 []byte) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeCall(Hash, "update", nef, manifest)
|
||||
}
|
||||
|
||||
// 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 []byte) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeUnsignedCall(Hash, "update", nil, nef, manifest)
|
||||
}
|
||||
|
||||
// UpdateCap creates a transaction invoking `updateCap` 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) UpdateCap(newCap *big.Int) (util.Uint256, uint32, error) {
|
||||
return c.actor.SendCall(Hash, "updateCap", newCap)
|
||||
}
|
||||
|
||||
// UpdateCapTransaction creates a transaction invoking `updateCap` method of the contract.
|
||||
// This transaction is signed, but not sent to the network, instead it's
|
||||
// returned to the caller.
|
||||
func (c *Contract) UpdateCapTransaction(newCap *big.Int) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeCall(Hash, "updateCap", newCap)
|
||||
}
|
||||
|
||||
// UpdateCapUnsigned creates a transaction invoking `updateCap` 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) UpdateCapUnsigned(newCap *big.Int) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeUnsignedCall(Hash, "updateCap", nil, newCap)
|
||||
}
|
||||
|
|
70
cli/smartcontract/testdata/verifyrpc/verify.go
vendored
Normal file
70
cli/smartcontract/testdata/verifyrpc/verify.go
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
// Package verify contains RPC wrappers for verify contract.
|
||||
package verify
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
// Hash contains contract hash.
|
||||
var Hash = util.Uint160{0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x0}
|
||||
|
||||
// Actor is used by Contract to call state-changing methods.
|
||||
type Actor interface {
|
||||
MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error)
|
||||
MakeRun(script []byte) (*transaction.Transaction, error)
|
||||
MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error)
|
||||
MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error)
|
||||
SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error)
|
||||
SendRun(script []byte) (util.Uint256, uint32, error)
|
||||
}
|
||||
|
||||
// Contract implements all contract methods.
|
||||
type Contract struct {
|
||||
actor Actor
|
||||
}
|
||||
|
||||
// New creates an instance of Contract using Hash and the given Actor.
|
||||
func New(actor Actor) *Contract {
|
||||
return &Contract{actor}
|
||||
}
|
||||
|
||||
|
||||
func scriptForVerify() ([]byte, error) {
|
||||
return smartcontract.CreateCallWithAssertScript(Hash, "verify")
|
||||
}
|
||||
|
||||
// Verify creates a transaction invoking `verify` 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) Verify() (util.Uint256, uint32, error) {
|
||||
script, err := scriptForVerify()
|
||||
if err != nil {
|
||||
return util.Uint256{}, 0, err
|
||||
}
|
||||
return c.actor.SendRun(script)
|
||||
}
|
||||
|
||||
// VerifyTransaction creates a transaction invoking `verify` method of the contract.
|
||||
// This transaction is signed, but not sent to the network, instead it's
|
||||
// returned to the caller.
|
||||
func (c *Contract) VerifyTransaction() (*transaction.Transaction, error) {
|
||||
script, err := scriptForVerify()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.actor.MakeRun(script)
|
||||
}
|
||||
|
||||
// VerifyUnsigned creates a transaction invoking `verify` 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) VerifyUnsigned() (*transaction.Transaction, error) {
|
||||
script, err := scriptForVerify()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.actor.MakeUnsignedRun(script, nil)
|
||||
}
|
79
cli/smartcontract/testdata/verifyrpc/verify.manifest.json
vendored
Executable file
79
cli/smartcontract/testdata/verifyrpc/verify.manifest.json
vendored
Executable file
|
@ -0,0 +1,79 @@
|
|||
{
|
||||
"groups" : [],
|
||||
"extra" : null,
|
||||
"supportedstandards" : [],
|
||||
"name" : "verify",
|
||||
"trusts" : [],
|
||||
"permissions" : [
|
||||
{
|
||||
"methods" : "*",
|
||||
"contract" : "*"
|
||||
}
|
||||
],
|
||||
"abi" : {
|
||||
"methods" : [
|
||||
{
|
||||
"safe" : false,
|
||||
"offset" : 0,
|
||||
"parameters" : [],
|
||||
"name" : "verify",
|
||||
"returntype" : "Boolean"
|
||||
},
|
||||
{
|
||||
"returntype" : "Void",
|
||||
"safe" : false,
|
||||
"offset" : 5,
|
||||
"parameters" : [
|
||||
{
|
||||
"type" : "Hash160",
|
||||
"name" : "from"
|
||||
},
|
||||
{
|
||||
"type" : "Integer",
|
||||
"name" : "amount"
|
||||
},
|
||||
{
|
||||
"type" : "Any",
|
||||
"name" : "data"
|
||||
}
|
||||
],
|
||||
"name" : "onNEP17Payment"
|
||||
},
|
||||
{
|
||||
"returntype" : "Void",
|
||||
"safe" : false,
|
||||
"offset" : 5,
|
||||
"parameters" : [
|
||||
{
|
||||
"type" : "Hash160",
|
||||
"name" : "from"
|
||||
},
|
||||
{
|
||||
"type" : "Integer",
|
||||
"name" : "amount"
|
||||
},
|
||||
{
|
||||
"type" : "ByteArray",
|
||||
"name" : "tokenid"
|
||||
},
|
||||
{
|
||||
"type" : "Any",
|
||||
"name" : "data"
|
||||
}
|
||||
],
|
||||
"name" : "onNEP11Payment"
|
||||
}
|
||||
],
|
||||
"events" : [
|
||||
{
|
||||
"parameters" : [
|
||||
{
|
||||
"type" : "Array",
|
||||
"name" : "args"
|
||||
}
|
||||
],
|
||||
"name" : "Hello world!"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -436,12 +436,20 @@ $ ./bin/neo-go contract generate-wrapper --manifest manifest.json --config contr
|
|||
|
||||
### Generating RPC contract bindings
|
||||
To simplify interacting with the contract via RPC you can generate
|
||||
contract-specific RPC bindings with the "generate-rpcwrapper" command. At the
|
||||
moment it only works for safe (read-only) methods. If your contract is NEP-11
|
||||
or NEP-17 that's autodetected and an appropriate package is included as
|
||||
well. Notice that the type data available in the manifest is limited, so in
|
||||
some cases the interface generated may use generic stackitem types. Iterators
|
||||
are not supported yet.
|
||||
contract-specific RPC bindings with the "generate-rpcwrapper" command. It
|
||||
generates ContractReader structure for safe methods that accept appropriate
|
||||
data for input and return things returned by the contract. State-changing
|
||||
methods are contained in Contract structure with each contract method
|
||||
represented by three wrapper methods that create/send transaction with a
|
||||
script performing appropriate action. This script invokes contract method and
|
||||
does not do anything else unless the method's returned value is of a boolean
|
||||
type, in this case an ASSERT is added to script making it fail when the method
|
||||
returns false.
|
||||
|
||||
If your contract is NEP-11 or NEP-17 that's autodetected and an appropriate
|
||||
package is included as well. Notice that the type data available in the
|
||||
manifest is limited, so in some cases the interface generated may use generic
|
||||
stackitem types. Iterators are not supported yet.
|
||||
|
||||
```
|
||||
$ ./bin/neo-go contract generate-rpcwrapper --manifest manifest.json --out rpcwrapper.go --hash 0x1b4357bff5a01bdf2a6581247cf9ed1e24629176
|
||||
|
|
|
@ -16,10 +16,17 @@ type DivisibleReader struct {
|
|||
BaseReader
|
||||
}
|
||||
|
||||
// Divisible is a state-changing interface for divisible NEP-11 contract.
|
||||
// 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.
|
||||
type DivisibleWriter struct {
|
||||
BaseWriter
|
||||
}
|
||||
|
||||
// Divisible is a full reader interface for divisible NEP-11 contract.
|
||||
type Divisible struct {
|
||||
DivisibleReader
|
||||
BaseWriter
|
||||
DivisibleWriter
|
||||
}
|
||||
|
||||
// OwnerIterator is used for iterating over OwnerOf (for divisible NFTs) results.
|
||||
|
@ -38,7 +45,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{*NewDivisibleReader(actor, hash), BaseWriter{hash, actor}}
|
||||
return &Divisible{*NewDivisibleReader(actor, hash), DivisibleWriter{BaseWriter{hash, actor}}}
|
||||
}
|
||||
|
||||
// OwnerOf returns returns an iterator that allows to walk through all owners of
|
||||
|
@ -72,7 +79,7 @@ func (t *DivisibleReader) BalanceOfD(owner util.Uint160, token []byte) (*big.Int
|
|||
// 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 *Divisible) TransferD(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data interface{}) (util.Uint256, uint32, error) {
|
||||
func (t *DivisibleWriter) TransferD(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data interface{}) (util.Uint256, uint32, error) {
|
||||
script, err := t.transferScript(from, to, amount, id, data)
|
||||
if err != nil {
|
||||
return util.Uint256{}, 0, err
|
||||
|
@ -85,7 +92,7 @@ func (t *Divisible) TransferD(from util.Uint160, to util.Uint160, amount *big.In
|
|||
// `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 *Divisible) TransferDTransaction(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data interface{}) (*transaction.Transaction, error) {
|
||||
func (t *DivisibleWriter) TransferDTransaction(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data interface{}) (*transaction.Transaction, error) {
|
||||
script, err := t.transferScript(from, to, amount, id, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -98,7 +105,7 @@ func (t *Divisible) TransferDTransaction(from util.Uint160, to util.Uint160, amo
|
|||
// `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 *Divisible) TransferDUnsigned(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data interface{}) (*transaction.Transaction, error) {
|
||||
func (t *DivisibleWriter) TransferDUnsigned(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data interface{}) (*transaction.Transaction, error) {
|
||||
script, err := t.transferScript(from, to, amount, id, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
)
|
||||
|
||||
const srcTmpl = `
|
||||
{{- define "METHOD" -}}
|
||||
{{- define "SAFEMETHOD" -}}
|
||||
// {{.Name}} {{.Comment}}
|
||||
func (c *ContractReader) {{.Name}}({{range $index, $arg := .Arguments -}}
|
||||
{{- if ne $index 0}}, {{end}}
|
||||
|
@ -26,6 +26,60 @@ func (c *ContractReader) {{.Name}}({{range $index, $arg := .Arguments -}}
|
|||
{{- end}}
|
||||
}
|
||||
{{- end -}}
|
||||
{{- define "METHOD" -}}
|
||||
{{- if eq .ReturnType "bool"}}func scriptFor{{.Name}}({{range $index, $arg := .Arguments -}}
|
||||
{{- if ne $index 0}}, {{end}}
|
||||
{{- .Name}} {{.Type}}
|
||||
{{- end}}) ([]byte, error) {
|
||||
return smartcontract.CreateCallWithAssertScript(Hash, "{{ .NameABI }}"{{- range $index, $arg := .Arguments -}}, {{.Name}}{{end}})
|
||||
}
|
||||
|
||||
{{end}}// {{.Name}} {{.Comment}}
|
||||
// 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) {{.Name}}({{range $index, $arg := .Arguments -}}
|
||||
{{- if ne $index 0}}, {{end}}
|
||||
{{- .Name}} {{.Type}}
|
||||
{{- end}}) (util.Uint256, uint32, error) {
|
||||
{{if ne .ReturnType "bool"}}return c.actor.SendCall(Hash, "{{ .NameABI }}"
|
||||
{{- range $index, $arg := .Arguments -}}, {{.Name}}{{end}}){{else}}script, err := scriptFor{{.Name}}({{- range $index, $arg := .Arguments -}}{{- if ne $index 0}}, {{end}}{{.Name}}{{end}})
|
||||
if err != nil {
|
||||
return util.Uint256{}, 0, err
|
||||
}
|
||||
return c.actor.SendRun(script){{end}}
|
||||
}
|
||||
|
||||
// {{.Name}}Transaction {{.Comment}}
|
||||
// This transaction is signed, but not sent to the network, instead it's
|
||||
// returned to the caller.
|
||||
func (c *Contract) {{.Name}}Transaction({{range $index, $arg := .Arguments -}}
|
||||
{{- if ne $index 0}}, {{end}}
|
||||
{{- .Name}} {{.Type}}
|
||||
{{- end}}) (*transaction.Transaction, error) {
|
||||
{{if ne .ReturnType "bool"}}return c.actor.MakeCall(Hash, "{{ .NameABI }}"
|
||||
{{- range $index, $arg := .Arguments -}}, {{.Name}}{{end}}){{else}}script, err := scriptFor{{.Name}}({{- range $index, $arg := .Arguments -}}{{- if ne $index 0}}, {{end}}{{.Name}}{{end}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.actor.MakeRun(script){{end}}
|
||||
}
|
||||
|
||||
// {{.Name}}Unsigned {{.Comment}}
|
||||
// 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) {{.Name}}Unsigned({{range $index, $arg := .Arguments -}}
|
||||
{{- if ne $index 0}}, {{end}}
|
||||
{{- .Name}} {{.Type}}
|
||||
{{- end}}) (*transaction.Transaction, error) {
|
||||
{{if ne .ReturnType "bool"}}return c.actor.MakeUnsignedCall(Hash, "{{ .NameABI }}", nil
|
||||
{{- range $index, $arg := .Arguments -}}, {{.Name}}{{end}}){{else}}script, err := scriptFor{{.Name}}({{- range $index, $arg := .Arguments -}}{{- if ne $index 0}}, {{end}}{{.Name}}{{end}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.actor.MakeUnsignedRun(script, nil){{end}}
|
||||
}
|
||||
{{- end -}}
|
||||
// Package {{.PackageName}} contains RPC wrappers for {{.ContractName}} contract.
|
||||
package {{.PackageName}}
|
||||
|
||||
|
@ -36,16 +90,37 @@ import (
|
|||
// Hash contains contract hash.
|
||||
var Hash = {{ .Hash }}
|
||||
|
||||
// Invoker is used by ContractReader to call various safe methods.
|
||||
{{if .HasReader}}// Invoker is used by ContractReader to call various safe methods.
|
||||
type Invoker interface {
|
||||
{{if or .IsNep11D .IsNep11ND}}nep11.Invoker
|
||||
{{end -}}
|
||||
{{if .IsNep17}}nep17.Invoker
|
||||
{{end -}}
|
||||
Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error)
|
||||
{{if or .IsNep11D .IsNep11ND}} nep11.Invoker
|
||||
{{else if .IsNep17}} nep17.Invoker
|
||||
{{else if len .SafeMethods}} Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error)
|
||||
{{end -}}
|
||||
}
|
||||
|
||||
// ContractReader implements safe contract methods.
|
||||
{{end -}}
|
||||
{{if .HasWriter}}// Actor is used by Contract to call state-changing methods.
|
||||
type Actor interface {
|
||||
{{- if .HasReader}}
|
||||
Invoker
|
||||
{{end}}
|
||||
{{- if or .IsNep11D .IsNep11ND}}
|
||||
nep11.Actor
|
||||
{{else if .IsNep17}}
|
||||
nep17.Actor
|
||||
{{end}}
|
||||
{{- if len .Methods}}
|
||||
MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error)
|
||||
MakeRun(script []byte) (*transaction.Transaction, error)
|
||||
MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error)
|
||||
MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error)
|
||||
SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error)
|
||||
SendRun(script []byte) (util.Uint256, uint32, error)
|
||||
{{end -}}
|
||||
}
|
||||
|
||||
{{end -}}
|
||||
{{if .HasReader}}// ContractReader implements safe contract methods.
|
||||
type ContractReader struct {
|
||||
{{if .IsNep11D}}nep11.DivisibleReader
|
||||
{{end -}}
|
||||
|
@ -56,7 +131,22 @@ type ContractReader struct {
|
|||
invoker Invoker
|
||||
}
|
||||
|
||||
// NewReader creates an instance of ContractReader using Hash and the given Invoker.
|
||||
{{end -}}
|
||||
{{if .HasWriter}}// Contract implements all contract methods.
|
||||
type Contract struct {
|
||||
{{if .HasReader}}ContractReader
|
||||
{{end -}}
|
||||
{{if .IsNep11D}}nep11.DivisibleWriter
|
||||
{{end -}}
|
||||
{{if .IsNep11ND}}nep11.BaseWriter
|
||||
{{end -}}
|
||||
{{if .IsNep17}}nep17.TokenWriter
|
||||
{{end -}}
|
||||
actor Actor
|
||||
}
|
||||
|
||||
{{end -}}
|
||||
{{if .HasReader}}// NewReader creates an instance of ContractReader using Hash and the given Invoker.
|
||||
func NewReader(invoker Invoker) *ContractReader {
|
||||
return &ContractReader{
|
||||
{{- if .IsNep11D}}*nep11.NewDivisibleReader(invoker, Hash), {{end}}
|
||||
|
@ -65,7 +155,32 @@ func NewReader(invoker Invoker) *ContractReader {
|
|||
invoker}
|
||||
}
|
||||
|
||||
{{range $m := .Methods}}
|
||||
{{end -}}
|
||||
{{if .HasWriter}}// New creates an instance of Contract using Hash and the given Actor.
|
||||
func New(actor Actor) *Contract {
|
||||
{{if .IsNep11D}}var nep11dt = nep11.NewDivisible(actor, Hash)
|
||||
{{end -}}
|
||||
{{if .IsNep11ND}}var nep11ndt = nep11.NewNonDivisible(actor, Hash)
|
||||
{{end -}}
|
||||
{{if .IsNep17}}var nep17t = nep17.New(actor, Hash)
|
||||
{{end -}}
|
||||
return &Contract{
|
||||
{{- if .HasReader}}ContractReader{
|
||||
{{- if .IsNep11D}}nep11dt.DivisibleReader, {{end -}}
|
||||
{{- if .IsNep11ND}}nep11ndt.NonDivisibleReader, {{end -}}
|
||||
{{- if .IsNep17}}nep17t.TokenReader, {{end -}}
|
||||
actor}, {{end -}}
|
||||
{{- if .IsNep11D}}nep11dt.DivisibleWriter, {{end -}}
|
||||
{{- if .IsNep11ND}}nep11ndt.BaseWriter, {{end -}}
|
||||
{{- if .IsNep17}}nep17t.TokenWriter, {{end -}}
|
||||
actor}
|
||||
}
|
||||
|
||||
{{end -}}
|
||||
{{range $m := .SafeMethods}}
|
||||
{{template "SAFEMETHOD" $m }}
|
||||
{{end}}
|
||||
{{- range $m := .Methods}}
|
||||
{{template "METHOD" $m }}
|
||||
{{end}}`
|
||||
|
||||
|
@ -74,9 +189,15 @@ var srcTemplate = template.Must(template.New("generate").Parse(srcTmpl))
|
|||
type (
|
||||
ContractTmpl struct {
|
||||
binding.ContractTmpl
|
||||
|
||||
SafeMethods []binding.MethodTmpl
|
||||
|
||||
IsNep11D bool
|
||||
IsNep11ND bool
|
||||
IsNep17 bool
|
||||
|
||||
HasReader bool
|
||||
HasWriter bool
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -87,19 +208,58 @@ func NewConfig() binding.Config {
|
|||
|
||||
// Generate writes Go file containing smartcontract bindings to the `cfg.Output`.
|
||||
func Generate(cfg binding.Config) error {
|
||||
// Avoid changing *cfg.Manifest.
|
||||
mfst := *cfg.Manifest
|
||||
mfst.ABI.Methods = make([]manifest.Method, len(mfst.ABI.Methods))
|
||||
copy(mfst.ABI.Methods, cfg.Manifest.ABI.Methods)
|
||||
cfg.Manifest = &mfst
|
||||
|
||||
var imports = make(map[string]struct{})
|
||||
var ctr ContractTmpl
|
||||
|
||||
// Strip standard methods from NEP-XX packages.
|
||||
for _, std := range cfg.Manifest.SupportedStandards {
|
||||
if std == manifest.NEP11StandardName {
|
||||
imports["github.com/nspcc-dev/neo-go/pkg/rpcclient/nep11"] = struct{}{}
|
||||
if standard.ComplyABI(cfg.Manifest, standard.Nep11Divisible) == nil {
|
||||
mfst.ABI.Methods = dropStdMethods(mfst.ABI.Methods, standard.Nep11Divisible)
|
||||
ctr.IsNep11D = true
|
||||
} else if standard.ComplyABI(cfg.Manifest, standard.Nep11NonDivisible) == nil {
|
||||
mfst.ABI.Methods = dropStdMethods(mfst.ABI.Methods, standard.Nep11NonDivisible)
|
||||
ctr.IsNep11ND = true
|
||||
}
|
||||
break // Can't be NEP-17 at the same time.
|
||||
}
|
||||
if std == manifest.NEP17StandardName && standard.ComplyABI(cfg.Manifest, standard.Nep17) == nil {
|
||||
mfst.ABI.Methods = dropStdMethods(mfst.ABI.Methods, standard.Nep17)
|
||||
imports["github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17"] = struct{}{}
|
||||
ctr.IsNep17 = true
|
||||
break // Can't be NEP-11 at the same time.
|
||||
}
|
||||
}
|
||||
|
||||
// OnNepXXPayment handlers normally can't be called directly.
|
||||
if standard.ComplyABI(cfg.Manifest, standard.Nep11Payable) == nil {
|
||||
mfst.ABI.Methods = dropStdMethods(mfst.ABI.Methods, standard.Nep11Payable)
|
||||
}
|
||||
if standard.ComplyABI(cfg.Manifest, standard.Nep17Payable) == nil {
|
||||
mfst.ABI.Methods = dropStdMethods(mfst.ABI.Methods, standard.Nep17Payable)
|
||||
}
|
||||
|
||||
bctr, err := binding.TemplateFromManifest(cfg, scTypeToGo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctr := scTemplateToRPC(cfg, bctr)
|
||||
ctr.ContractTmpl = bctr
|
||||
ctr = scTemplateToRPC(cfg, ctr, imports)
|
||||
|
||||
return srcTemplate.Execute(cfg.Output, ctr)
|
||||
}
|
||||
|
||||
func dropManifestMethods(meths []binding.MethodTmpl, manifested []manifest.Method) []binding.MethodTmpl {
|
||||
func dropManifestMethods(meths []manifest.Method, manifested []manifest.Method) []manifest.Method {
|
||||
for _, m := range manifested {
|
||||
for i := 0; i < len(meths); i++ {
|
||||
if meths[i].NameABI == m.Name && len(meths[i].Arguments) == len(m.Parameters) {
|
||||
if meths[i].Name == m.Name && len(meths[i].Parameters) == len(m.Parameters) {
|
||||
meths = append(meths[:i], meths[i+1:]...)
|
||||
i--
|
||||
}
|
||||
|
@ -108,7 +268,7 @@ func dropManifestMethods(meths []binding.MethodTmpl, manifested []manifest.Metho
|
|||
return meths
|
||||
}
|
||||
|
||||
func dropStdMethods(meths []binding.MethodTmpl, std *standard.Standard) []binding.MethodTmpl {
|
||||
func dropStdMethods(meths []manifest.Method, std *standard.Standard) []manifest.Method {
|
||||
meths = dropManifestMethods(meths, std.Manifest.ABI.Methods)
|
||||
if std.Optional != nil {
|
||||
meths = dropManifestMethods(meths, std.Optional)
|
||||
|
@ -152,71 +312,70 @@ func scTypeToGo(name string, typ smartcontract.ParamType, overrides map[string]b
|
|||
}
|
||||
}
|
||||
|
||||
func scTemplateToRPC(cfg binding.Config, bctr binding.ContractTmpl) ContractTmpl {
|
||||
var imports = make(map[string]struct{})
|
||||
var ctr = ContractTmpl{ContractTmpl: bctr}
|
||||
func scTemplateToRPC(cfg binding.Config, ctr ContractTmpl, imports map[string]struct{}) ContractTmpl {
|
||||
for i := range ctr.Imports {
|
||||
imports[ctr.Imports[i]] = struct{}{}
|
||||
}
|
||||
ctr.Hash = fmt.Sprintf("%#v", cfg.Hash)
|
||||
for _, std := range cfg.Manifest.SupportedStandards {
|
||||
if std == manifest.NEP11StandardName {
|
||||
imports["github.com/nspcc-dev/neo-go/pkg/rpcclient/nep11"] = struct{}{}
|
||||
if standard.ComplyABI(cfg.Manifest, standard.Nep11Divisible) == nil {
|
||||
ctr.Methods = dropStdMethods(ctr.Methods, standard.Nep11Divisible)
|
||||
ctr.IsNep11D = true
|
||||
} else if standard.ComplyABI(cfg.Manifest, standard.Nep11NonDivisible) == nil {
|
||||
ctr.Methods = dropStdMethods(ctr.Methods, standard.Nep11NonDivisible)
|
||||
ctr.IsNep11ND = true
|
||||
}
|
||||
break // Can't be NEP-17 at the same time.
|
||||
}
|
||||
if std == manifest.NEP17StandardName && standard.ComplyABI(cfg.Manifest, standard.Nep17) == nil {
|
||||
ctr.Methods = dropStdMethods(ctr.Methods, standard.Nep17)
|
||||
imports["github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17"] = struct{}{}
|
||||
ctr.IsNep17 = true
|
||||
break // Can't be NEP-11 at the same time.
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(ctr.Methods); i++ {
|
||||
abim := cfg.Manifest.ABI.GetMethod(ctr.Methods[i].NameABI, len(ctr.Methods[i].Arguments))
|
||||
if !abim.Safe {
|
||||
if abim.Safe {
|
||||
ctr.SafeMethods = append(ctr.SafeMethods, ctr.Methods[i])
|
||||
ctr.Methods = append(ctr.Methods[:i], ctr.Methods[i+1:]...)
|
||||
i--
|
||||
} else {
|
||||
ctr.Methods[i].Comment = fmt.Sprintf("creates a transaction invoking `%s` method of the contract.", ctr.Methods[i].NameABI)
|
||||
if ctr.Methods[i].ReturnType == "bool" {
|
||||
imports["github.com/nspcc-dev/neo-go/pkg/smartcontract"] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
// We're misusing CallFlag field for function name here.
|
||||
for i := range ctr.Methods {
|
||||
switch ctr.Methods[i].ReturnType {
|
||||
for i := range ctr.SafeMethods {
|
||||
switch ctr.SafeMethods[i].ReturnType {
|
||||
case "interface{}":
|
||||
imports["github.com/nspcc-dev/neo-go/pkg/vm/stackitem"] = struct{}{}
|
||||
ctr.Methods[i].ReturnType = "stackitem.Item"
|
||||
ctr.Methods[i].CallFlag = "Item"
|
||||
ctr.SafeMethods[i].ReturnType = "stackitem.Item"
|
||||
ctr.SafeMethods[i].CallFlag = "Item"
|
||||
case "bool":
|
||||
ctr.Methods[i].CallFlag = "Bool"
|
||||
ctr.SafeMethods[i].CallFlag = "Bool"
|
||||
case "*big.Int":
|
||||
ctr.Methods[i].CallFlag = "BigInt"
|
||||
ctr.SafeMethods[i].CallFlag = "BigInt"
|
||||
case "string":
|
||||
ctr.Methods[i].CallFlag = "UTF8String"
|
||||
ctr.SafeMethods[i].CallFlag = "UTF8String"
|
||||
case "util.Uint160":
|
||||
ctr.Methods[i].CallFlag = "Uint160"
|
||||
ctr.SafeMethods[i].CallFlag = "Uint160"
|
||||
case "util.Uint256":
|
||||
ctr.Methods[i].CallFlag = "Uint256"
|
||||
ctr.SafeMethods[i].CallFlag = "Uint256"
|
||||
case "*keys.PublicKey":
|
||||
ctr.Methods[i].CallFlag = "PublicKey"
|
||||
ctr.SafeMethods[i].CallFlag = "PublicKey"
|
||||
case "[]byte":
|
||||
ctr.Methods[i].CallFlag = "Bytes"
|
||||
ctr.SafeMethods[i].CallFlag = "Bytes"
|
||||
case "[]interface{}":
|
||||
imports["github.com/nspcc-dev/neo-go/pkg/vm/stackitem"] = struct{}{}
|
||||
ctr.Methods[i].ReturnType = "[]stackitem.Item"
|
||||
ctr.Methods[i].CallFlag = "Array"
|
||||
ctr.SafeMethods[i].ReturnType = "[]stackitem.Item"
|
||||
ctr.SafeMethods[i].CallFlag = "Array"
|
||||
case "*stackitem.Map":
|
||||
ctr.Methods[i].CallFlag = "Map"
|
||||
ctr.SafeMethods[i].CallFlag = "Map"
|
||||
}
|
||||
}
|
||||
|
||||
imports["github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"] = struct{}{}
|
||||
imports["github.com/nspcc-dev/neo-go/pkg/neorpc/result"] = struct{}{}
|
||||
imports["github.com/nspcc-dev/neo-go/pkg/util"] = struct{}{}
|
||||
if len(ctr.SafeMethods) > 0 {
|
||||
imports["github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"] = struct{}{}
|
||||
if !(ctr.IsNep17 || ctr.IsNep11D || ctr.IsNep11ND) {
|
||||
imports["github.com/nspcc-dev/neo-go/pkg/neorpc/result"] = struct{}{}
|
||||
}
|
||||
}
|
||||
if len(ctr.Methods) > 0 {
|
||||
imports["github.com/nspcc-dev/neo-go/pkg/core/transaction"] = struct{}{}
|
||||
}
|
||||
if len(ctr.Methods) > 0 || ctr.IsNep17 || ctr.IsNep11D || ctr.IsNep11ND {
|
||||
ctr.HasWriter = true
|
||||
}
|
||||
if len(ctr.SafeMethods) > 0 || ctr.IsNep17 || ctr.IsNep11D || ctr.IsNep11ND {
|
||||
ctr.HasReader = true
|
||||
}
|
||||
ctr.Imports = ctr.Imports[:0]
|
||||
for imp := range imports {
|
||||
ctr.Imports = append(ctr.Imports, imp)
|
||||
|
|
Loading…
Reference in a new issue