forked from TrueCloudLab/neoneo-go
Merge pull request #3087 from nspcc-dev/smart-binding
rpcbinding: export any unexported fields of structures/events
This commit is contained in:
commit
4e61e8238a
34 changed files with 542 additions and 69 deletions
|
@ -437,12 +437,12 @@ func TestAssistedRPCBindings(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, hasDefinedHash := range []bool{true, false} {
|
for _, hasDefinedHash := range []bool{true, false} {
|
||||||
checkBinding(filepath.Join("testdata", "types"), hasDefinedHash, false)
|
checkBinding(filepath.Join("testdata", "rpcbindings", "types"), hasDefinedHash, false)
|
||||||
checkBinding(filepath.Join("testdata", "structs"), hasDefinedHash, false)
|
checkBinding(filepath.Join("testdata", "rpcbindings", "structs"), hasDefinedHash, false)
|
||||||
}
|
}
|
||||||
checkBinding(filepath.Join("testdata", "notifications"), true, false)
|
checkBinding(filepath.Join("testdata", "rpcbindings", "notifications"), true, false)
|
||||||
checkBinding(filepath.Join("testdata", "notifications"), true, false, "_extended")
|
checkBinding(filepath.Join("testdata", "rpcbindings", "notifications"), true, false, "_extended")
|
||||||
checkBinding(filepath.Join("testdata", "notifications"), true, true, "_guessed")
|
checkBinding(filepath.Join("testdata", "rpcbindings", "notifications"), true, true, "_guessed")
|
||||||
|
|
||||||
require.False(t, rewriteExpectedOutputs)
|
require.False(t, rewriteExpectedOutputs)
|
||||||
}
|
}
|
||||||
|
@ -540,10 +540,10 @@ func TestCompile_GuessEventTypes(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("not declared in manifest", func(t *testing.T) {
|
t.Run("not declared in manifest", func(t *testing.T) {
|
||||||
check(t, filepath.Join("testdata", "invalid5"), "inconsistent usages of event `Non declared event`: not declared in the contract config")
|
check(t, filepath.Join("testdata", "rpcbindings", "invalid1"), "inconsistent usages of event `Non declared event`: not declared in the contract config")
|
||||||
})
|
})
|
||||||
t.Run("invalid number of params", func(t *testing.T) {
|
t.Run("invalid number of params", func(t *testing.T) {
|
||||||
check(t, filepath.Join("testdata", "invalid6"), "inconsistent usages of event `SomeEvent` against config: number of params mismatch: 2 vs 1")
|
check(t, filepath.Join("testdata", "rpcbindings", "invalid2"), "inconsistent usages of event `SomeEvent` against config: number of params mismatch: 2 vs 1")
|
||||||
})
|
})
|
||||||
/*
|
/*
|
||||||
// TODO: this on is a controversial one. If event information is provided in the config file, then conversion code
|
// TODO: this on is a controversial one. If event information is provided in the config file, then conversion code
|
||||||
|
@ -552,13 +552,61 @@ func TestCompile_GuessEventTypes(t *testing.T) {
|
||||||
// Thus, this testcase is always failing (no compilation error occures).
|
// Thus, this testcase is always failing (no compilation error occures).
|
||||||
// Question: do we want to compare `RealType` of the emitted parameter with the one expected in the manifest?
|
// Question: do we want to compare `RealType` of the emitted parameter with the one expected in the manifest?
|
||||||
t.Run("SC parameter type mismatch", func(t *testing.T) {
|
t.Run("SC parameter type mismatch", func(t *testing.T) {
|
||||||
check(t, filepath.Join("testdata", "invalid7"), "inconsistent usages of event `SomeEvent` against config: number of params mismatch: 2 vs 1")
|
check(t, filepath.Join("testdata", "rpcbindings", "invalid3"), "inconsistent usages of event `SomeEvent` against config: number of params mismatch: 2 vs 1")
|
||||||
})
|
})
|
||||||
*/
|
*/
|
||||||
t.Run("extended types mismatch", func(t *testing.T) {
|
t.Run("extended types mismatch", func(t *testing.T) {
|
||||||
check(t, filepath.Join("testdata", "invalid8"), "inconsistent usages of event `SomeEvent`: extended type of param #0 mismatch")
|
check(t, filepath.Join("testdata", "rpcbindings", "invalid4"), "inconsistent usages of event `SomeEvent`: extended type of param #0 mismatch")
|
||||||
})
|
})
|
||||||
t.Run("named types redeclare", func(t *testing.T) {
|
t.Run("named types redeclare", func(t *testing.T) {
|
||||||
check(t, filepath.Join("testdata", "invalid9"), "configured declared named type intersects with the contract's one: `invalid9.NamedStruct`")
|
check(t, filepath.Join("testdata", "rpcbindings", "invalid5"), "configured declared named type intersects with the contract's one: `invalid5.NamedStruct`")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenerateRPCBindings_Errors(t *testing.T) {
|
||||||
|
app := cli.NewApp()
|
||||||
|
app.Commands = NewCommands()
|
||||||
|
app.ExitErrHandler = func(*cli.Context, error) {}
|
||||||
|
|
||||||
|
t.Run("duplicating resulting fields", func(t *testing.T) {
|
||||||
|
check := func(t *testing.T, packageName string, autogen bool, expectedError string) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
source := filepath.Join("testdata", "rpcbindings", packageName)
|
||||||
|
configFile := filepath.Join(source, "invalid.yml")
|
||||||
|
out := filepath.Join(tmpDir, "rpcbindings.out")
|
||||||
|
manifestF := filepath.Join(tmpDir, "manifest.json")
|
||||||
|
bindingF := filepath.Join(tmpDir, "binding.yml")
|
||||||
|
nefF := filepath.Join(tmpDir, "out.nef")
|
||||||
|
cmd := []string{"", "contract", "compile",
|
||||||
|
"--in", source,
|
||||||
|
"--config", configFile,
|
||||||
|
"--manifest", manifestF,
|
||||||
|
"--bindings", bindingF,
|
||||||
|
"--out", nefF,
|
||||||
|
}
|
||||||
|
if autogen {
|
||||||
|
cmd = append(cmd, "--guess-eventtypes")
|
||||||
|
}
|
||||||
|
require.NoError(t, app.Run(cmd))
|
||||||
|
|
||||||
|
cmds := []string{"", "contract", "generate-rpcwrapper",
|
||||||
|
"--config", bindingF,
|
||||||
|
"--manifest", manifestF,
|
||||||
|
"--out", out,
|
||||||
|
}
|
||||||
|
err := app.Run(cmds)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.True(t, strings.Contains(err.Error(), expectedError), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("event", func(t *testing.T) {
|
||||||
|
check(t, "invalid6", false, "error during generation: named type `SomeStruct` has two fields with identical resulting binding name `Field`")
|
||||||
|
})
|
||||||
|
t.Run("autogen event", func(t *testing.T) {
|
||||||
|
check(t, "invalid7", true, "error during generation: named type `invalid7.SomeStruct` has two fields with identical resulting binding name `Field`")
|
||||||
|
})
|
||||||
|
t.Run("struct", func(t *testing.T) {
|
||||||
|
check(t, "invalid8", false, "error during generation: named type `invalid8.SomeStruct` has two fields with identical resulting binding name `Field`")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package invalid5
|
package invalid1
|
||||||
|
|
||||||
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package invalid6
|
package invalid2
|
||||||
|
|
||||||
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package invalid7
|
package invalid3
|
||||||
|
|
||||||
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package invalid8
|
package invalid4
|
||||||
|
|
||||||
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package invalid9
|
package invalid5
|
||||||
|
|
||||||
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||||
|
|
|
@ -6,11 +6,11 @@ events:
|
||||||
type: Array
|
type: Array
|
||||||
extendedtype:
|
extendedtype:
|
||||||
base: Array
|
base: Array
|
||||||
name: invalid9.NamedStruct
|
name: invalid5.NamedStruct
|
||||||
namedtypes:
|
namedtypes:
|
||||||
invalid9.NamedStruct:
|
invalid5.NamedStruct:
|
||||||
base: Array
|
base: Array
|
||||||
name: invalid9.NamedStruct
|
name: invalid5.NamedStruct
|
||||||
fields:
|
fields:
|
||||||
- field: SomeInt
|
- field: SomeInt
|
||||||
base: Integer
|
base: Integer
|
14
cli/smartcontract/testdata/rpcbindings/invalid6/invalid.go
vendored
Normal file
14
cli/smartcontract/testdata/rpcbindings/invalid6/invalid.go
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package invalid6
|
||||||
|
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||||
|
|
||||||
|
type SomeStruct struct {
|
||||||
|
Field int
|
||||||
|
// RPC binding generator will convert this field into exported, which matches
|
||||||
|
// exactly the existing Field.
|
||||||
|
field int
|
||||||
|
}
|
||||||
|
|
||||||
|
func Main() {
|
||||||
|
runtime.Notify("SomeEvent", SomeStruct{Field: 123, field: 123})
|
||||||
|
}
|
18
cli/smartcontract/testdata/rpcbindings/invalid6/invalid.yml
vendored
Normal file
18
cli/smartcontract/testdata/rpcbindings/invalid6/invalid.yml
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
name: Test duplicating event fields
|
||||||
|
events:
|
||||||
|
- name: SomeEvent
|
||||||
|
parameters:
|
||||||
|
- name: p1
|
||||||
|
type: Struct
|
||||||
|
extendedtype:
|
||||||
|
base: Struct
|
||||||
|
name: SomeStruct
|
||||||
|
namedtypes:
|
||||||
|
SomeStruct:
|
||||||
|
base: Struct
|
||||||
|
name: SomeStruct
|
||||||
|
fields:
|
||||||
|
- field: Field
|
||||||
|
base: Integer
|
||||||
|
- field: field
|
||||||
|
base: Integer
|
14
cli/smartcontract/testdata/rpcbindings/invalid7/invalid.go
vendored
Normal file
14
cli/smartcontract/testdata/rpcbindings/invalid7/invalid.go
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package invalid7
|
||||||
|
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||||
|
|
||||||
|
type SomeStruct struct {
|
||||||
|
Field int
|
||||||
|
// RPC binding generator will convert this field into exported, which matches
|
||||||
|
// exactly the existing Field.
|
||||||
|
field int
|
||||||
|
}
|
||||||
|
|
||||||
|
func Main() {
|
||||||
|
runtime.Notify("SomeEvent", SomeStruct{Field: 123, field: 123})
|
||||||
|
}
|
6
cli/smartcontract/testdata/rpcbindings/invalid7/invalid.yml
vendored
Normal file
6
cli/smartcontract/testdata/rpcbindings/invalid7/invalid.yml
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
name: Test duplicating autogenerated event fields
|
||||||
|
events:
|
||||||
|
- name: SomeEvent
|
||||||
|
parameters:
|
||||||
|
- name: p1
|
||||||
|
type: Struct
|
16
cli/smartcontract/testdata/rpcbindings/invalid8/invalid.go
vendored
Normal file
16
cli/smartcontract/testdata/rpcbindings/invalid8/invalid.go
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package invalid8
|
||||||
|
|
||||||
|
type SomeStruct struct {
|
||||||
|
Field int
|
||||||
|
// RPC binding generator will convert this field into exported, which matches
|
||||||
|
// exactly the existing Field.
|
||||||
|
field int
|
||||||
|
}
|
||||||
|
|
||||||
|
func Main() SomeStruct {
|
||||||
|
s := SomeStruct{
|
||||||
|
Field: 1,
|
||||||
|
field: 2,
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
1
cli/smartcontract/testdata/rpcbindings/invalid8/invalid.yml
vendored
Normal file
1
cli/smartcontract/testdata/rpcbindings/invalid8/invalid.yml
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
name: Test duplicating struct fields
|
|
@ -17,3 +17,7 @@ events:
|
||||||
parameters:
|
parameters:
|
||||||
- name: a
|
- name: a
|
||||||
type: Array
|
type: Array
|
||||||
|
- name: "SomeUnexportedField"
|
||||||
|
parameters:
|
||||||
|
- name: s
|
||||||
|
type: Struct
|
|
@ -36,6 +36,13 @@ events:
|
||||||
base: Array
|
base: Array
|
||||||
value:
|
value:
|
||||||
base: Integer
|
base: Integer
|
||||||
|
- name: "SomeUnexportedField"
|
||||||
|
parameters:
|
||||||
|
- name: s
|
||||||
|
type: Struct
|
||||||
|
extendedtype:
|
||||||
|
base: Struct
|
||||||
|
name: simpleStruct
|
||||||
namedtypes:
|
namedtypes:
|
||||||
crazyStruct:
|
crazyStruct:
|
||||||
base: Struct
|
base: Struct
|
||||||
|
@ -45,3 +52,9 @@ namedtypes:
|
||||||
base: Integer
|
base: Integer
|
||||||
- field: B
|
- field: B
|
||||||
base: Boolean
|
base: Boolean
|
||||||
|
simpleStruct:
|
||||||
|
base: Struct
|
||||||
|
name: simpleStruct
|
||||||
|
fields:
|
||||||
|
- field: i
|
||||||
|
base: Integer
|
|
@ -17,3 +17,7 @@ events:
|
||||||
parameters:
|
parameters:
|
||||||
- name: a
|
- name: a
|
||||||
type: Array
|
type: Array
|
||||||
|
- name: "SomeUnexportedField"
|
||||||
|
parameters:
|
||||||
|
- name: s
|
||||||
|
type: Struct
|
|
@ -23,3 +23,11 @@ func Struct() {
|
||||||
func Array() {
|
func Array() {
|
||||||
runtime.Notify("SomeArray", [][]int{})
|
runtime.Notify("SomeArray", [][]int{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnexportedField emits notification with unexported field that must be converted
|
||||||
|
// to exported in the resulting RPC binding.
|
||||||
|
func UnexportedField() {
|
||||||
|
runtime.Notify("SomeUnexportedField", struct {
|
||||||
|
i int
|
||||||
|
}{i: 123})
|
||||||
|
}
|
|
@ -97,6 +97,11 @@ type SomeArrayEvent struct {
|
||||||
A []any
|
A []any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SomeUnexportedFieldEvent represents "SomeUnexportedField" event emitted by the contract.
|
||||||
|
type SomeUnexportedFieldEvent struct {
|
||||||
|
S []any
|
||||||
|
}
|
||||||
|
|
||||||
// Actor is used by Contract to call state-changing methods.
|
// Actor is used by Contract to call state-changing methods.
|
||||||
type Actor interface {
|
type Actor interface {
|
||||||
MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error)
|
MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error)
|
||||||
|
@ -207,6 +212,28 @@ func (c *Contract) StructUnsigned() (*transaction.Transaction, error) {
|
||||||
return c.actor.MakeUnsignedCall(c.hash, "struct", nil)
|
return c.actor.MakeUnsignedCall(c.hash, "struct", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnexportedField creates a transaction invoking `unexportedField` 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) UnexportedField() (util.Uint256, uint32, error) {
|
||||||
|
return c.actor.SendCall(c.hash, "unexportedField")
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnexportedFieldTransaction creates a transaction invoking `unexportedField` method of the contract.
|
||||||
|
// This transaction is signed, but not sent to the network, instead it's
|
||||||
|
// returned to the caller.
|
||||||
|
func (c *Contract) UnexportedFieldTransaction() (*transaction.Transaction, error) {
|
||||||
|
return c.actor.MakeCall(c.hash, "unexportedField")
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnexportedFieldUnsigned creates a transaction invoking `unexportedField` 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) UnexportedFieldUnsigned() (*transaction.Transaction, error) {
|
||||||
|
return c.actor.MakeUnsignedCall(c.hash, "unexportedField", nil)
|
||||||
|
}
|
||||||
|
|
||||||
// itemToLedgerBlock converts stack item into *LedgerBlock.
|
// itemToLedgerBlock converts stack item into *LedgerBlock.
|
||||||
func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) {
|
func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1030,3 +1057,68 @@ func (e *SomeArrayEvent) FromStackItem(item *stackitem.Array) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SomeUnexportedFieldEventsFromApplicationLog retrieves a set of all emitted events
|
||||||
|
// with "SomeUnexportedField" name from the provided [result.ApplicationLog].
|
||||||
|
func SomeUnexportedFieldEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeUnexportedFieldEvent, error) {
|
||||||
|
if log == nil {
|
||||||
|
return nil, errors.New("nil application log")
|
||||||
|
}
|
||||||
|
|
||||||
|
var res []*SomeUnexportedFieldEvent
|
||||||
|
for i, ex := range log.Executions {
|
||||||
|
for j, e := range ex.Events {
|
||||||
|
if e.Name != "SomeUnexportedField" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
event := new(SomeUnexportedFieldEvent)
|
||||||
|
err := event.FromStackItem(e.Item)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to deserialize SomeUnexportedFieldEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
|
||||||
|
}
|
||||||
|
res = append(res, event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromStackItem converts provided [stackitem.Array] to SomeUnexportedFieldEvent or
|
||||||
|
// returns an error if it's not possible to do to so.
|
||||||
|
func (e *SomeUnexportedFieldEvent) FromStackItem(item *stackitem.Array) error {
|
||||||
|
if item == nil {
|
||||||
|
return errors.New("nil item")
|
||||||
|
}
|
||||||
|
arr, ok := item.Value().([]stackitem.Item)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("not an array")
|
||||||
|
}
|
||||||
|
if len(arr) != 1 {
|
||||||
|
return errors.New("wrong number of structure elements")
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
index = -1
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
index++
|
||||||
|
e.S, err = func (item stackitem.Item) ([]any, error) {
|
||||||
|
arr, ok := item.Value().([]stackitem.Item)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("not an array")
|
||||||
|
}
|
||||||
|
res := make([]any, len(arr))
|
||||||
|
for i := range res {
|
||||||
|
res[i], err = arr[i].Value(), error(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("item %d: %w", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
} (arr[index])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("field S: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -83,6 +83,11 @@ type LedgerWitnessRule struct {
|
||||||
Condition *LedgerWitnessCondition
|
Condition *LedgerWitnessCondition
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SimpleStruct is a contract-specific simpleStruct type used by its methods.
|
||||||
|
type SimpleStruct struct {
|
||||||
|
I *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
// ComplicatedNameEvent represents "! complicated name %$#" event emitted by the contract.
|
// ComplicatedNameEvent represents "! complicated name %$#" event emitted by the contract.
|
||||||
type ComplicatedNameEvent struct {
|
type ComplicatedNameEvent struct {
|
||||||
ComplicatedParam string
|
ComplicatedParam string
|
||||||
|
@ -103,6 +108,11 @@ type SomeArrayEvent struct {
|
||||||
A [][]*big.Int
|
A [][]*big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SomeUnexportedFieldEvent represents "SomeUnexportedField" event emitted by the contract.
|
||||||
|
type SomeUnexportedFieldEvent struct {
|
||||||
|
S *SimpleStruct
|
||||||
|
}
|
||||||
|
|
||||||
// Actor is used by Contract to call state-changing methods.
|
// Actor is used by Contract to call state-changing methods.
|
||||||
type Actor interface {
|
type Actor interface {
|
||||||
MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error)
|
MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error)
|
||||||
|
@ -213,6 +223,28 @@ func (c *Contract) StructUnsigned() (*transaction.Transaction, error) {
|
||||||
return c.actor.MakeUnsignedCall(c.hash, "struct", nil)
|
return c.actor.MakeUnsignedCall(c.hash, "struct", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnexportedField creates a transaction invoking `unexportedField` 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) UnexportedField() (util.Uint256, uint32, error) {
|
||||||
|
return c.actor.SendCall(c.hash, "unexportedField")
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnexportedFieldTransaction creates a transaction invoking `unexportedField` method of the contract.
|
||||||
|
// This transaction is signed, but not sent to the network, instead it's
|
||||||
|
// returned to the caller.
|
||||||
|
func (c *Contract) UnexportedFieldTransaction() (*transaction.Transaction, error) {
|
||||||
|
return c.actor.MakeCall(c.hash, "unexportedField")
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnexportedFieldUnsigned creates a transaction invoking `unexportedField` 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) UnexportedFieldUnsigned() (*transaction.Transaction, error) {
|
||||||
|
return c.actor.MakeUnsignedCall(c.hash, "unexportedField", nil)
|
||||||
|
}
|
||||||
|
|
||||||
// itemToCrazyStruct converts stack item into *CrazyStruct.
|
// itemToCrazyStruct converts stack item into *CrazyStruct.
|
||||||
func itemToCrazyStruct(item stackitem.Item, err error) (*CrazyStruct, error) {
|
func itemToCrazyStruct(item stackitem.Item, err error) (*CrazyStruct, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -816,6 +848,40 @@ func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// itemToSimpleStruct converts stack item into *SimpleStruct.
|
||||||
|
func itemToSimpleStruct(item stackitem.Item, err error) (*SimpleStruct, error) {
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var res = new(SimpleStruct)
|
||||||
|
err = res.FromStackItem(item)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromStackItem retrieves fields of SimpleStruct from the given
|
||||||
|
// [stackitem.Item] or returns an error if it's not possible to do to so.
|
||||||
|
func (res *SimpleStruct) FromStackItem(item stackitem.Item) error {
|
||||||
|
arr, ok := item.Value().([]stackitem.Item)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("not an array")
|
||||||
|
}
|
||||||
|
if len(arr) != 1 {
|
||||||
|
return errors.New("wrong number of structure elements")
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
index = -1
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
index++
|
||||||
|
res.I, err = arr[index].TryInteger()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("field I: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ComplicatedNameEventsFromApplicationLog retrieves a set of all emitted events
|
// ComplicatedNameEventsFromApplicationLog retrieves a set of all emitted events
|
||||||
// with "! complicated name %$#" name from the provided [result.ApplicationLog].
|
// with "! complicated name %$#" name from the provided [result.ApplicationLog].
|
||||||
func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*ComplicatedNameEvent, error) {
|
func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*ComplicatedNameEvent, error) {
|
||||||
|
@ -1126,3 +1192,55 @@ func (e *SomeArrayEvent) FromStackItem(item *stackitem.Array) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SomeUnexportedFieldEventsFromApplicationLog retrieves a set of all emitted events
|
||||||
|
// with "SomeUnexportedField" name from the provided [result.ApplicationLog].
|
||||||
|
func SomeUnexportedFieldEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeUnexportedFieldEvent, error) {
|
||||||
|
if log == nil {
|
||||||
|
return nil, errors.New("nil application log")
|
||||||
|
}
|
||||||
|
|
||||||
|
var res []*SomeUnexportedFieldEvent
|
||||||
|
for i, ex := range log.Executions {
|
||||||
|
for j, e := range ex.Events {
|
||||||
|
if e.Name != "SomeUnexportedField" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
event := new(SomeUnexportedFieldEvent)
|
||||||
|
err := event.FromStackItem(e.Item)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to deserialize SomeUnexportedFieldEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
|
||||||
|
}
|
||||||
|
res = append(res, event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromStackItem converts provided [stackitem.Array] to SomeUnexportedFieldEvent or
|
||||||
|
// returns an error if it's not possible to do to so.
|
||||||
|
func (e *SomeUnexportedFieldEvent) FromStackItem(item *stackitem.Array) error {
|
||||||
|
if item == nil {
|
||||||
|
return errors.New("nil item")
|
||||||
|
}
|
||||||
|
arr, ok := item.Value().([]stackitem.Item)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("not an array")
|
||||||
|
}
|
||||||
|
if len(arr) != 1 {
|
||||||
|
return errors.New("wrong number of structure elements")
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
index = -1
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
index++
|
||||||
|
e.S, err = itemToSimpleStruct(arr[index], nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("field S: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -103,6 +103,11 @@ type SomeArrayEvent struct {
|
||||||
A [][]*big.Int
|
A [][]*big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SomeUnexportedFieldEvent represents "SomeUnexportedField" event emitted by the contract.
|
||||||
|
type SomeUnexportedFieldEvent struct {
|
||||||
|
S *Unnamed
|
||||||
|
}
|
||||||
|
|
||||||
// Actor is used by Contract to call state-changing methods.
|
// Actor is used by Contract to call state-changing methods.
|
||||||
type Actor interface {
|
type Actor interface {
|
||||||
MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error)
|
MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error)
|
||||||
|
@ -213,6 +218,28 @@ func (c *Contract) StructUnsigned() (*transaction.Transaction, error) {
|
||||||
return c.actor.MakeUnsignedCall(c.hash, "struct", nil)
|
return c.actor.MakeUnsignedCall(c.hash, "struct", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnexportedField creates a transaction invoking `unexportedField` 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) UnexportedField() (util.Uint256, uint32, error) {
|
||||||
|
return c.actor.SendCall(c.hash, "unexportedField")
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnexportedFieldTransaction creates a transaction invoking `unexportedField` method of the contract.
|
||||||
|
// This transaction is signed, but not sent to the network, instead it's
|
||||||
|
// returned to the caller.
|
||||||
|
func (c *Contract) UnexportedFieldTransaction() (*transaction.Transaction, error) {
|
||||||
|
return c.actor.MakeCall(c.hash, "unexportedField")
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnexportedFieldUnsigned creates a transaction invoking `unexportedField` 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) UnexportedFieldUnsigned() (*transaction.Transaction, error) {
|
||||||
|
return c.actor.MakeUnsignedCall(c.hash, "unexportedField", nil)
|
||||||
|
}
|
||||||
|
|
||||||
// itemToLedgerBlock converts stack item into *LedgerBlock.
|
// itemToLedgerBlock converts stack item into *LedgerBlock.
|
||||||
func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) {
|
func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1139,3 +1166,55 @@ func (e *SomeArrayEvent) FromStackItem(item *stackitem.Array) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SomeUnexportedFieldEventsFromApplicationLog retrieves a set of all emitted events
|
||||||
|
// with "SomeUnexportedField" name from the provided [result.ApplicationLog].
|
||||||
|
func SomeUnexportedFieldEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeUnexportedFieldEvent, error) {
|
||||||
|
if log == nil {
|
||||||
|
return nil, errors.New("nil application log")
|
||||||
|
}
|
||||||
|
|
||||||
|
var res []*SomeUnexportedFieldEvent
|
||||||
|
for i, ex := range log.Executions {
|
||||||
|
for j, e := range ex.Events {
|
||||||
|
if e.Name != "SomeUnexportedField" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
event := new(SomeUnexportedFieldEvent)
|
||||||
|
err := event.FromStackItem(e.Item)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to deserialize SomeUnexportedFieldEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
|
||||||
|
}
|
||||||
|
res = append(res, event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromStackItem converts provided [stackitem.Array] to SomeUnexportedFieldEvent or
|
||||||
|
// returns an error if it's not possible to do to so.
|
||||||
|
func (e *SomeUnexportedFieldEvent) FromStackItem(item *stackitem.Array) error {
|
||||||
|
if item == nil {
|
||||||
|
return errors.New("nil item")
|
||||||
|
}
|
||||||
|
arr, ok := item.Value().([]stackitem.Item)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("not an array")
|
||||||
|
}
|
||||||
|
if len(arr) != 1 {
|
||||||
|
return errors.New("wrong number of structure elements")
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
index = -1
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
index++
|
||||||
|
e.S, err = itemToUnnamed(arr[index], nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("field S: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -152,6 +152,7 @@ type StructsInternal struct {
|
||||||
ArrOfH160 []util.Uint160
|
ArrOfH160 []util.Uint160
|
||||||
Map map[*big.Int]keys.PublicKeys
|
Map map[*big.Int]keys.PublicKeys
|
||||||
Struct *StructsInternal
|
Struct *StructsInternal
|
||||||
|
UnexportedField *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoker is used by ContractReader to call various safe methods.
|
// Invoker is used by ContractReader to call various safe methods.
|
||||||
|
@ -1410,7 +1411,7 @@ func (res *StructsInternal) FromStackItem(item stackitem.Item) error {
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("not an array")
|
return errors.New("not an array")
|
||||||
}
|
}
|
||||||
if len(arr) != 13 {
|
if len(arr) != 14 {
|
||||||
return errors.New("wrong number of structure elements")
|
return errors.New("wrong number of structure elements")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1622,5 +1623,11 @@ func (res *StructsInternal) FromStackItem(item stackitem.Item) error {
|
||||||
return fmt.Errorf("field Struct: %w", err)
|
return fmt.Errorf("field Struct: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
index++
|
||||||
|
res.UnexportedField, err = arr[index].TryInteger()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("field UnexportedField: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
|
@ -149,6 +149,7 @@ type StructsInternal struct {
|
||||||
ArrOfH160 []util.Uint160
|
ArrOfH160 []util.Uint160
|
||||||
Map map[*big.Int]keys.PublicKeys
|
Map map[*big.Int]keys.PublicKeys
|
||||||
Struct *StructsInternal
|
Struct *StructsInternal
|
||||||
|
UnexportedField *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoker is used by ContractReader to call various safe methods.
|
// Invoker is used by ContractReader to call various safe methods.
|
||||||
|
@ -1406,7 +1407,7 @@ func (res *StructsInternal) FromStackItem(item stackitem.Item) error {
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("not an array")
|
return errors.New("not an array")
|
||||||
}
|
}
|
||||||
if len(arr) != 13 {
|
if len(arr) != 14 {
|
||||||
return errors.New("wrong number of structure elements")
|
return errors.New("wrong number of structure elements")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1618,5 +1619,11 @@ func (res *StructsInternal) FromStackItem(item stackitem.Item) error {
|
||||||
return fmt.Errorf("field Struct: %w", err)
|
return fmt.Errorf("field Struct: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
index++
|
||||||
|
res.UnexportedField, err = arr[index].TryInteger()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("field UnexportedField: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
40
cli/smartcontract/testdata/rpcbindings/structs/structs.go
vendored
Normal file
40
cli/smartcontract/testdata/rpcbindings/structs/structs.go
vendored
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
package structs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/interop"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/interop/native/ledger"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/interop/native/management"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Internal struct {
|
||||||
|
Bool bool
|
||||||
|
Int int
|
||||||
|
Bytes []byte
|
||||||
|
String string
|
||||||
|
H160 interop.Hash160
|
||||||
|
H256 interop.Hash256
|
||||||
|
PK interop.PublicKey
|
||||||
|
PubKey interop.PublicKey
|
||||||
|
Sign interop.Signature
|
||||||
|
ArrOfBytes [][]byte
|
||||||
|
ArrOfH160 []interop.Hash160
|
||||||
|
Map map[int][]interop.PublicKey
|
||||||
|
Struct *Internal
|
||||||
|
unexportedField int // this one should be exported in the resulting RPC binding.
|
||||||
|
}
|
||||||
|
|
||||||
|
func Contract(mc management.Contract) management.Contract {
|
||||||
|
return mc
|
||||||
|
}
|
||||||
|
|
||||||
|
func Block(b *ledger.Block) *ledger.Block {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func Transaction(t *ledger.Transaction) *ledger.Transaction {
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
func Struct(s *Internal) *Internal {
|
||||||
|
return s
|
||||||
|
}
|
39
cli/smartcontract/testdata/structs/structs.go
vendored
39
cli/smartcontract/testdata/structs/structs.go
vendored
|
@ -1,39 +0,0 @@
|
||||||
package structs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/native/ledger"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/native/management"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Internal struct {
|
|
||||||
Bool bool
|
|
||||||
Int int
|
|
||||||
Bytes []byte
|
|
||||||
String string
|
|
||||||
H160 interop.Hash160
|
|
||||||
H256 interop.Hash256
|
|
||||||
PK interop.PublicKey
|
|
||||||
PubKey interop.PublicKey
|
|
||||||
Sign interop.Signature
|
|
||||||
ArrOfBytes [][]byte
|
|
||||||
ArrOfH160 []interop.Hash160
|
|
||||||
Map map[int][]interop.PublicKey
|
|
||||||
Struct *Internal
|
|
||||||
}
|
|
||||||
|
|
||||||
func Contract(mc management.Contract) management.Contract {
|
|
||||||
return mc
|
|
||||||
}
|
|
||||||
|
|
||||||
func Block(b *ledger.Block) *ledger.Block {
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
func Transaction(t *ledger.Transaction) *ledger.Transaction {
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
func Struct(s *Internal) *Internal {
|
|
||||||
return s
|
|
||||||
}
|
|
|
@ -23,7 +23,7 @@ const (
|
||||||
// {{.Name}} represents "{{.ManifestName}}" event emitted by the contract.
|
// {{.Name}} represents "{{.ManifestName}}" event emitted by the contract.
|
||||||
type {{.Name}} struct {
|
type {{.Name}} struct {
|
||||||
{{- range $index, $arg := .Parameters}}
|
{{- range $index, $arg := .Parameters}}
|
||||||
{{.Name}} {{.Type}}
|
{{ upperFirst .Name}} {{.Type}}
|
||||||
{{- end}}
|
{{- end}}
|
||||||
}
|
}
|
||||||
{{ end }}`
|
{{ end }}`
|
||||||
|
@ -126,7 +126,7 @@ var Hash = {{ .Hash }}
|
||||||
// {{toTypeName $name}} is a contract-specific {{$name}} type used by its methods.
|
// {{toTypeName $name}} is a contract-specific {{$name}} type used by its methods.
|
||||||
type {{toTypeName $name}} struct {
|
type {{toTypeName $name}} struct {
|
||||||
{{- range $m := $typ.Fields}}
|
{{- range $m := $typ.Fields}}
|
||||||
{{.Field}} {{etTypeToStr .ExtendedType}}
|
{{ upperFirst .Field}} {{etTypeToStr .ExtendedType}}
|
||||||
{{- end}}
|
{{- end}}
|
||||||
}
|
}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -262,9 +262,9 @@ func (res *{{toTypeName $name}}) FromStackItem(item stackitem.Item) error {
|
||||||
)
|
)
|
||||||
{{- range $m := $typ.Fields}}
|
{{- range $m := $typ.Fields}}
|
||||||
index++
|
index++
|
||||||
res.{{.Field}}, err = {{etTypeConverter .ExtendedType "arr[index]"}}
|
res.{{ upperFirst .Field}}, err = {{etTypeConverter .ExtendedType "arr[index]"}}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("field {{.Field}}: %w", err)
|
return fmt.Errorf("field {{ upperFirst .Field}}: %w", err)
|
||||||
}
|
}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
@ -317,9 +317,9 @@ func (e *{{$e.Name}}) FromStackItem(item *stackitem.Array) error {
|
||||||
)
|
)
|
||||||
{{- range $p := $e.Parameters}}
|
{{- range $p := $e.Parameters}}
|
||||||
index++
|
index++
|
||||||
e.{{.Name}}, err = {{etTypeConverter .ExtType "arr[index]"}}
|
e.{{ upperFirst .Name}}, err = {{etTypeConverter .ExtType "arr[index]"}}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("field {{.Name}}: %w", err)
|
return fmt.Errorf("field {{ upperFirst .Name}}: %w", err)
|
||||||
}
|
}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
@ -430,6 +430,28 @@ func Generate(cfg binding.Config) error {
|
||||||
ctr = scTemplateToRPC(cfg, ctr, imports, scTypeToGo)
|
ctr = scTemplateToRPC(cfg, ctr, imports, scTypeToGo)
|
||||||
ctr.NamedTypes = cfg.NamedTypes
|
ctr.NamedTypes = cfg.NamedTypes
|
||||||
|
|
||||||
|
// Check resulting named types and events don't have duplicating field names.
|
||||||
|
for _, t := range ctr.NamedTypes {
|
||||||
|
fDict := make(map[string]struct{})
|
||||||
|
for _, n := range t.Fields {
|
||||||
|
name := upperFirst(n.Field)
|
||||||
|
if _, ok := fDict[name]; ok {
|
||||||
|
return fmt.Errorf("named type `%s` has two fields with identical resulting binding name `%s`", t.Name, name)
|
||||||
|
}
|
||||||
|
fDict[name] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, e := range ctr.CustomEvents {
|
||||||
|
fDict := make(map[string]struct{})
|
||||||
|
for _, n := range e.Parameters {
|
||||||
|
name := upperFirst(n.Name)
|
||||||
|
if _, ok := fDict[name]; ok {
|
||||||
|
return fmt.Errorf("event `%s` has two fields with identical resulting binding name `%s`", e.Name, name)
|
||||||
|
}
|
||||||
|
fDict[name] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var srcTemplate = template.Must(template.New("generate").Funcs(template.FuncMap{
|
var srcTemplate = template.Must(template.New("generate").Funcs(template.FuncMap{
|
||||||
"addIndent": addIndent,
|
"addIndent": addIndent,
|
||||||
"etTypeConverter": etTypeConverter,
|
"etTypeConverter": etTypeConverter,
|
||||||
|
@ -439,6 +461,7 @@ func Generate(cfg binding.Config) error {
|
||||||
},
|
},
|
||||||
"toTypeName": toTypeName,
|
"toTypeName": toTypeName,
|
||||||
"cutPointer": cutPointer,
|
"cutPointer": cutPointer,
|
||||||
|
"upperFirst": upperFirst,
|
||||||
}).Parse(srcTmpl))
|
}).Parse(srcTmpl))
|
||||||
|
|
||||||
return srcTemplate.Execute(cfg.Output, ctr)
|
return srcTemplate.Execute(cfg.Output, ctr)
|
||||||
|
@ -863,7 +886,7 @@ func toTypeName(s string) string {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}, strings.ToUpper(s[0:1])+s[1:])
|
}, upperFirst(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
func addIndent(str string, ind string) string {
|
func addIndent(str string, ind string) string {
|
||||||
|
|
Loading…
Reference in a new issue