diff --git a/cli/smartcontract/testdata/gas/gas.go b/cli/smartcontract/testdata/gas/gas.go index 2b4cf920a..d12bbb8ee 100644 --- a/cli/smartcontract/testdata/gas/gas.go +++ b/cli/smartcontract/testdata/gas/gas.go @@ -2,25 +2,13 @@ package gastoken import ( - "errors" - "fmt" - "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/util" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "math/big" ) // 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} -// TransferEvent represents "Transfer" event emitted by the contract. -type TransferEvent struct { - From util.Uint160 - To util.Uint160 - Amount *big.Int -} - // Invoker is used by ContractReader to call various safe methods. type Invoker interface { nep17.Invoker @@ -56,87 +44,3 @@ func New(actor Actor) *Contract { var nep17t = nep17.New(actor, Hash) return &Contract{ContractReader{nep17t.TokenReader, actor}, nep17t.TokenWriter, actor} } - -// TransferEventsFromApplicationLog retrieves a set of all emitted events -// with "Transfer" name from the provided ApplicationLog. -func TransferEventsFromApplicationLog(log *result.ApplicationLog) ([]*TransferEvent, error) { - if log == nil { - return nil, errors.New("nil application log") - } - - var res []*TransferEvent - for i, ex := range log.Executions { - for j, e := range ex.Events { - if e.Name != "Transfer" { - continue - } - event := new(TransferEvent) - err := event.FromStackItem(e.Item) - if err != nil { - return nil, fmt.Errorf("failed to deserialize TransferEvent from stackitem (execution %d, event %d): %w", i, j, err) - } - res = append(res, event) - } - } - - return res, nil -} - -// FromStackItem converts provided stackitem.Array to TransferEvent and -// returns an error if so. -func (e *TransferEvent) 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) != 3 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - e.From, err = func (item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - } (arr[index]) - if err != nil { - return fmt.Errorf("field From: %w", err) - } - - index++ - e.To, err = func (item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - } (arr[index]) - if err != nil { - return fmt.Errorf("field To: %w", err) - } - - index++ - e.Amount, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Amount: %w", err) - } - - return nil -} diff --git a/cli/smartcontract/testdata/nameservice/nns.go b/cli/smartcontract/testdata/nameservice/nns.go index 8bb311bb9..2b19af793 100644 --- a/cli/smartcontract/testdata/nameservice/nns.go +++ b/cli/smartcontract/testdata/nameservice/nns.go @@ -18,14 +18,6 @@ import ( // Hash contains contract hash. var Hash = util.Uint160{0xde, 0x46, 0x5f, 0x5d, 0x50, 0x57, 0xcf, 0x33, 0x28, 0x47, 0x94, 0xc5, 0xcf, 0xc2, 0xc, 0x69, 0x37, 0x1c, 0xac, 0x50} -// TransferEvent represents "Transfer" event emitted by the contract. -type TransferEvent struct { - From util.Uint160 - To util.Uint160 - Amount *big.Int - TokenId []byte -} - // SetAdminEvent represents "SetAdmin" event emitted by the contract. type SetAdminEvent struct { Name string @@ -345,96 +337,6 @@ func (c *Contract) DeleteRecordUnsigned(name string, typev *big.Int) (*transacti return c.actor.MakeUnsignedCall(Hash, "deleteRecord", nil, name, typev) } -// TransferEventsFromApplicationLog retrieves a set of all emitted events -// with "Transfer" name from the provided ApplicationLog. -func TransferEventsFromApplicationLog(log *result.ApplicationLog) ([]*TransferEvent, error) { - if log == nil { - return nil, errors.New("nil application log") - } - - var res []*TransferEvent - for i, ex := range log.Executions { - for j, e := range ex.Events { - if e.Name != "Transfer" { - continue - } - event := new(TransferEvent) - err := event.FromStackItem(e.Item) - if err != nil { - return nil, fmt.Errorf("failed to deserialize TransferEvent from stackitem (execution %d, event %d): %w", i, j, err) - } - res = append(res, event) - } - } - - return res, nil -} - -// FromStackItem converts provided stackitem.Array to TransferEvent and -// returns an error if so. -func (e *TransferEvent) 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) != 4 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - e.From, err = func (item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - } (arr[index]) - if err != nil { - return fmt.Errorf("field From: %w", err) - } - - index++ - e.To, err = func (item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - } (arr[index]) - if err != nil { - return fmt.Errorf("field To: %w", err) - } - - index++ - e.Amount, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Amount: %w", err) - } - - index++ - e.TokenId, err = arr[index].TryBytes() - if err != nil { - return fmt.Errorf("field TokenId: %w", err) - } - - return nil -} - // SetAdminEventsFromApplicationLog retrieves a set of all emitted events // with "SetAdmin" name from the provided ApplicationLog. func SetAdminEventsFromApplicationLog(log *result.ApplicationLog) ([]*SetAdminEvent, error) { diff --git a/cli/smartcontract/testdata/nex/nex.go b/cli/smartcontract/testdata/nex/nex.go index 41de92d02..f558fb513 100644 --- a/cli/smartcontract/testdata/nex/nex.go +++ b/cli/smartcontract/testdata/nex/nex.go @@ -17,13 +17,6 @@ import ( // Hash contains contract hash. var Hash = util.Uint160{0xa8, 0x1a, 0xa1, 0xf0, 0x4b, 0xf, 0xdc, 0x4a, 0xa2, 0xce, 0xd5, 0xbf, 0xc6, 0x22, 0xcf, 0xe8, 0x9, 0x7f, 0xa6, 0xa2} -// TransferEvent represents "Transfer" event emitted by the contract. -type TransferEvent struct { - From util.Uint160 - To util.Uint160 - Amount *big.Int -} - // OnMintEvent represents "OnMint" event emitted by the contract. type OnMintEvent struct { From util.Uint160 @@ -249,90 +242,6 @@ func (c *Contract) UpdateCapUnsigned(newCap *big.Int) (*transaction.Transaction, return c.actor.MakeUnsignedCall(Hash, "updateCap", nil, newCap) } -// TransferEventsFromApplicationLog retrieves a set of all emitted events -// with "Transfer" name from the provided ApplicationLog. -func TransferEventsFromApplicationLog(log *result.ApplicationLog) ([]*TransferEvent, error) { - if log == nil { - return nil, errors.New("nil application log") - } - - var res []*TransferEvent - for i, ex := range log.Executions { - for j, e := range ex.Events { - if e.Name != "Transfer" { - continue - } - event := new(TransferEvent) - err := event.FromStackItem(e.Item) - if err != nil { - return nil, fmt.Errorf("failed to deserialize TransferEvent from stackitem (execution %d, event %d): %w", i, j, err) - } - res = append(res, event) - } - } - - return res, nil -} - -// FromStackItem converts provided stackitem.Array to TransferEvent and -// returns an error if so. -func (e *TransferEvent) 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) != 3 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - e.From, err = func (item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - } (arr[index]) - if err != nil { - return fmt.Errorf("field From: %w", err) - } - - index++ - e.To, err = func (item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - } (arr[index]) - if err != nil { - return fmt.Errorf("field To: %w", err) - } - - index++ - e.Amount, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Amount: %w", err) - } - - return nil -} - // OnMintEventsFromApplicationLog retrieves a set of all emitted events // with "OnMint" name from the provided ApplicationLog. func OnMintEventsFromApplicationLog(log *result.ApplicationLog) ([]*OnMintEvent, error) { diff --git a/pkg/rpcclient/nep11/base.go b/pkg/rpcclient/nep11/base.go index ed30df2af..db906cb3d 100644 --- a/pkg/rpcclient/nep11/base.go +++ b/pkg/rpcclient/nep11/base.go @@ -10,6 +10,7 @@ purposes, otherwise more specific types are recommended. package nep11 import ( + "errors" "fmt" "math/big" "unicode/utf8" @@ -246,3 +247,71 @@ func UnwrapKnownProperties(m *stackitem.Map, err error) (map[string]string, erro } return res, nil } + +// TransferEventsFromApplicationLog retrieves all emitted TransferEvents from the +// provided [result.ApplicationLog]. +func TransferEventsFromApplicationLog(log *result.ApplicationLog) ([]*TransferEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + var res []*TransferEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Transfer" { + continue + } + event := new(TransferEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to decode event from stackitem (event #%d, execution #%d): %w", j, i, err) + } + res = append(res, event) + } + } + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to TransferEvent or returns an +// error if it's not possible to do to so. +func (e *TransferEvent) 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) != 4 { + return errors.New("wrong number of event parameters") + } + + b, err := arr[0].TryBytes() + if err != nil { + return fmt.Errorf("invalid From: %w", err) + } + e.From, err = util.Uint160DecodeBytesBE(b) + if err != nil { + return fmt.Errorf("failed to decode From: %w", err) + } + + b, err = arr[1].TryBytes() + if err != nil { + return fmt.Errorf("invalid To: %w", err) + } + e.To, err = util.Uint160DecodeBytesBE(b) + if err != nil { + return fmt.Errorf("failed to decode To: %w", err) + } + + e.Amount, err = arr[2].TryInteger() + if err != nil { + return fmt.Errorf("field to decode Avount: %w", err) + } + + e.ID, err = arr[3].TryBytes() + if err != nil { + return fmt.Errorf("failed to decode ID: %w", err) + } + + return nil +} diff --git a/pkg/rpcclient/nep17/nep17.go b/pkg/rpcclient/nep17/nep17.go index f91488e82..dec570a22 100644 --- a/pkg/rpcclient/nep17/nep17.go +++ b/pkg/rpcclient/nep17/nep17.go @@ -8,12 +8,15 @@ package nep17 import ( "errors" + "fmt" "math/big" "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" "github.com/nspcc-dev/neo-go/pkg/rpcclient/neptoken" "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" ) // Invoker is used by TokenReader to call various safe methods. @@ -147,3 +150,66 @@ func (t *TokenWriter) MultiTransferUnsigned(params []TransferParameters) (*trans } return t.actor.MakeUnsignedRun(script, nil) } + +// TransferEventsFromApplicationLog retrieves all emitted TransferEvents from the +// provided [result.ApplicationLog]. +func TransferEventsFromApplicationLog(log *result.ApplicationLog) ([]*TransferEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + var res []*TransferEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Transfer" { + continue + } + event := new(TransferEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to decode event from stackitem (event #%d, execution #%d): %w", j, i, err) + } + res = append(res, event) + } + } + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to TransferEvent or returns an +// error if it's not possible to do to so. +func (e *TransferEvent) 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) != 3 { + return errors.New("wrong number of event parameters") + } + + b, err := arr[0].TryBytes() + if err != nil { + return fmt.Errorf("invalid From: %w", err) + } + e.From, err = util.Uint160DecodeBytesBE(b) + if err != nil { + return fmt.Errorf("failed to decode From: %w", err) + } + + b, err = arr[1].TryBytes() + if err != nil { + return fmt.Errorf("invalid To: %w", err) + } + e.To, err = util.Uint160DecodeBytesBE(b) + if err != nil { + return fmt.Errorf("failed to decode To: %w", err) + } + + e.Amount, err = arr[2].TryInteger() + if err != nil { + return fmt.Errorf("field to decode Avount: %w", err) + } + + return nil +} diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index 973264c78..ba65361f1 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -396,12 +396,14 @@ func Generate(cfg binding.Config) error { mfst.ABI.Methods = dropStdMethods(mfst.ABI.Methods, standard.Nep11NonDivisible) ctr.IsNep11ND = true } + mfst.ABI.Events = dropStdEvents(mfst.ABI.Events, standard.Nep11Base) 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 + mfst.ABI.Events = dropStdEvents(mfst.ABI.Events, standard.Nep17) break // Can't be NEP-11 at the same time. } } @@ -445,6 +447,18 @@ func dropManifestMethods(meths []manifest.Method, manifested []manifest.Method) return meths } +func dropManifestEvents(events []manifest.Event, manifested []manifest.Event) []manifest.Event { + for _, e := range manifested { + for i := 0; i < len(events); i++ { + if events[i].Name == e.Name && len(events[i].Parameters) == len(e.Parameters) { + events = append(events[:i], events[i+1:]...) + i-- + } + } + } + return events +} + func dropStdMethods(meths []manifest.Method, std *standard.Standard) []manifest.Method { meths = dropManifestMethods(meths, std.Manifest.ABI.Methods) if std.Optional != nil { @@ -456,6 +470,14 @@ func dropStdMethods(meths []manifest.Method, std *standard.Standard) []manifest. return meths } +func dropStdEvents(events []manifest.Event, std *standard.Standard) []manifest.Event { + events = dropManifestEvents(events, std.Manifest.ABI.Events) + if std.Base != nil { + return dropStdEvents(events, std.Base) + } + return events +} + func extendedTypeToGo(et binding.ExtendedType, named map[string]binding.ExtendedType) (string, string) { switch et.Base { case smartcontract.AnyType: