Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: account event for Core and Account contracts #68

Merged
merged 1 commit into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ generate-erc7412-mainnet-c:
go run ./utils/getAbis/get-abis.go --get-mkdir ./cannon-synthetix/base/pyth_erc7412_wrapper/PythERC7412Wrapper.json ./contracts/ERC7412
abigen --abi=./contracts/PythERC7412Wrapper.json --pkg=ERC7412 --out=./contracts/ERC7412/contract.go

generate-account-mainnet-c:
go run ./utils/getAbis/get-abis.go --get-mkdir ./cannon-synthetix/base/system/AccountProxy.json ./contracts/Account
abigen --abi=./contracts/AccountProxy.json --pkg=Account --out=./contracts/Account/contract.go


# update Synthetix-Gitbook-v3 subtree
update-subtree:
git subtree pull --prefix Synthetix-Gitbook-v3 [email protected]:Synthetixio/Synthetix-Gitbook-v3.git en --squash
Expand Down
4 changes: 4 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ type ContractAddresses struct {
PerpsMarket string
ERC7412 string
Forwarder string
Account string
}

// FirstContractBlocks is a part of a config struct with default first block numbers used to filters contract logs
type FirstContractBlocks struct {
Core uint64
PerpsMarket uint64
Account uint64
}

// GetOptimismGoerliDefaultConfig is used to get default lib config for goerli optimism test net
Expand Down Expand Up @@ -130,10 +132,12 @@ func GetBaseMainnetDefaultConfig(rpcURL string) *PerpsvConfig {
PerpsMarket: "0x0A2AF931eFFd34b81ebcc57E3d3c9B1E1dE1C9Ce",
Forwarder: "0xE2C5658cC5C448B48141168f3e475dF8f65A1e3e",
ERC7412: "0xEb38e347F24ea04ffA945a475BdD949E0c383A0F",
Account: "0x63f4Dd0434BEB5baeCD27F3778a909278d8cf5b8",
},
FirstContractBlocks: &FirstContractBlocks{
Core: 7889212,
PerpsMarket: 7889389,
Account: 8394165,
},
ConnectionTimeout: time.Second * 30,
ReadTimeout: time.Second * 15,
Expand Down
4 changes: 2 additions & 2 deletions contracts/core/contract.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

87 changes: 87 additions & 0 deletions events/accountPermissionRevokedCore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package events

import (
"strings"

"github.com/ethereum/go-ethereum/event"

"github.com/gateway-fm/perpsv3-Go/contracts/core"
"github.com/gateway-fm/perpsv3-Go/errors"
"github.com/gateway-fm/perpsv3-Go/models"
"github.com/gateway-fm/perpsv3-Go/pkg/logger"
)

// AccountCorePermissionRevokedSubscription is a struct for listening to all 'PermissionRevoked' contract events and return them as models.PermissionChanged struct
type AccountCorePermissionRevokedSubscription struct {
*basicSubscription
PermissionChangeChan chan *models.PermissionChanged
contractEventChan chan *core.CorePermissionRevoked
}

func (e *Events) ListenAccountCorePermissionRevoked() (*AccountCorePermissionRevokedSubscription, error) {
revokedChan := make(chan *core.CorePermissionRevoked)

revokedSub, err := e.core.WatchPermissionRevoked(nil, revokedChan, nil, nil, nil)
if err != nil {
logger.Log().WithField("layer", "Events-AccountCorePermissionRevoked").Errorf("error watch permission revoked: %v", err.Error())
return nil, errors.GetEventListenErr(err, "AccountCorePermissionRevoked")
}

accountsSub := newAccountCorePermissionRevokedSubscription(revokedSub, revokedChan)

go accountsSub.listen(e.core)

return accountsSub, nil
}

// newAccountCorePermissionRevokedSubscription is used to get new AccountCorePermissionRevokedSubscription instance
func newAccountCorePermissionRevokedSubscription(
eventSub event.Subscription,
revoked chan *core.CorePermissionRevoked,
) *AccountCorePermissionRevokedSubscription {
return &AccountCorePermissionRevokedSubscription{
basicSubscription: newBasicSubscription(eventSub),
PermissionChangeChan: make(chan *models.PermissionChanged),
contractEventChan: revoked,
}
}

// listen is used to run events listen goroutine
func (s *AccountCorePermissionRevokedSubscription) listen(perps *core.Core) {
defer func() {
close(s.PermissionChangeChan)
close(s.contractEventChan)
}()

for {
select {
case <-s.stop:
return
case err := <-s.eventSub.Err():
if err != nil {
logger.Log().WithField("layer", "Events-AccountCorePermissionRevoked").Errorf(
"error listening account permission revoked: %v", err.Error(),
)
s.ErrChan <- err
}
return
case contractEvent := <-s.contractEventChan:
p, err := models.PermissionFromString(strings.TrimRight(string(contractEvent.Permission[:]), string(rune(0))))
if err != nil {
logger.Log().WithField("layer", "Events-AccountCorePermissionRevoked").Errorf(
"error decode permission %v: %v", string(contractEvent.Permission[:]), err.Error(),
)
s.ErrChan <- err
continue
}

change := &models.PermissionChanged{
AccountID: contractEvent.AccountId,
User: contractEvent.User,
Permission: p,
}

s.PermissionChangeChan <- change
}
}
}
87 changes: 87 additions & 0 deletions events/accountPermissionsGrantedCore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package events

import (
"strings"

"github.com/ethereum/go-ethereum/event"

"github.com/gateway-fm/perpsv3-Go/contracts/core"
"github.com/gateway-fm/perpsv3-Go/errors"
"github.com/gateway-fm/perpsv3-Go/models"
"github.com/gateway-fm/perpsv3-Go/pkg/logger"
)

// AccountCorePermissionGrantedSubscription is a struct for listening to all 'PermissionGranted' contract events and return them as models.PermissionChanged struct
type AccountCorePermissionGrantedSubscription struct {
*basicSubscription
PermissionChangeChan chan *models.PermissionChanged
contractEventChan chan *core.CorePermissionGranted
}

func (e *Events) ListenAccountCorePermissionGranted() (*AccountCorePermissionGrantedSubscription, error) {
createdChan := make(chan *core.CorePermissionGranted)

createdSub, err := e.core.WatchPermissionGranted(nil, createdChan, nil, nil, nil)
if err != nil {
logger.Log().WithField("layer", "Events-AccountCorePermissionGranted").Errorf("error watch permission granted: %v", err.Error())
return nil, errors.GetEventListenErr(err, "AccountCorePermissionGranted")
}

accountsSub := newAccountCorePermissionGrantedSubscription(createdSub, createdChan)

go accountsSub.listen(e.core)

return accountsSub, nil
}

// newAccountCorePermissionGrantedSubscription is used to get new AccountCorePermissionGrantedSubscription instance
func newAccountCorePermissionGrantedSubscription(
eventSub event.Subscription,
created chan *core.CorePermissionGranted,
) *AccountCorePermissionGrantedSubscription {
return &AccountCorePermissionGrantedSubscription{
basicSubscription: newBasicSubscription(eventSub),
PermissionChangeChan: make(chan *models.PermissionChanged),
contractEventChan: created,
}
}

// listen is used to run events listen goroutine
func (s *AccountCorePermissionGrantedSubscription) listen(perps *core.Core) {
defer func() {
close(s.PermissionChangeChan)
close(s.contractEventChan)
}()

for {
select {
case <-s.stop:
return
case err := <-s.eventSub.Err():
if err != nil {
logger.Log().WithField("layer", "Events-AccountCorePermissionGranted").Errorf(
"error listening account permission granted: %v", err.Error(),
)
s.ErrChan <- err
}
return
case contractEvent := <-s.contractEventChan:
p, err := models.PermissionFromString(strings.TrimRight(string(contractEvent.Permission[:]), string(rune(0))))
if err != nil {
logger.Log().WithField("layer", "Events-AccountCorePermissionGranted").Errorf(
"error decode permission %v: %v", string(contractEvent.Permission[:]), err.Error(),
)
s.ErrChan <- err
continue
}

change := &models.PermissionChanged{
AccountID: contractEvent.AccountId,
User: contractEvent.User,
Permission: p,
}

s.PermissionChangeChan <- change
}
}
}
84 changes: 84 additions & 0 deletions events/accountTransfer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package events

import (
"context"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/event"
"github.com/gateway-fm/perpsv3-Go/contracts/Account"
"github.com/gateway-fm/perpsv3-Go/errors"
"github.com/gateway-fm/perpsv3-Go/models"
"github.com/gateway-fm/perpsv3-Go/pkg/logger"
"math/big"
)

// AccountTransferSubscription is a struct for listening to all 'AccountTransfer' contract events and return them as models.AccountTransfer struct
type AccountTransferSubscription struct {
*basicSubscription
NewAccountChan chan *models.AccountTransfer
contractEventChan chan *Account.AccountTransfer
}

func (e *Events) ListenAccountTransfer() (*AccountTransferSubscription, error) {
transferChan := make(chan *Account.AccountTransfer)

transferSub, err := e.account.WatchTransfer(nil, transferChan, nil, nil, nil)
if err != nil {
logger.Log().WithField("layer", "Events-Accounts").Errorf("error watch account transfer: %v", err.Error())
return nil, errors.GetEventListenErr(err, "AccountTransfer")
}

accountsSub := newAccountTransferSubscription(transferSub, transferChan)

go accountsSub.listen(e.rpcClient)

return accountsSub, nil
}

// newAccountTransferSubscription is used to get new AccountTransferSubscription instance
func newAccountTransferSubscription(
eventSub event.Subscription,
transfer chan *Account.AccountTransfer,
) *AccountTransferSubscription {
return &AccountTransferSubscription{
basicSubscription: newBasicSubscription(eventSub),
NewAccountChan: make(chan *models.AccountTransfer),
contractEventChan: transfer,
}
}

// listen is used to run events listen goroutine
func (s *AccountTransferSubscription) listen(rpcClient *ethclient.Client) {
defer func() {
close(s.NewAccountChan)
close(s.contractEventChan)
}()

for {
select {
case <-s.stop:
return
case err := <-s.eventSub.Err():
if err != nil {
logger.Log().WithField("layer", "Events-AccountTransfer").Errorf(
"error listening account transfer info: %v", err.Error(),
)
s.ErrChan <- err
}
return
case transfer := <-s.contractEventChan:
block, err := rpcClient.HeaderByNumber(context.Background(), big.NewInt(int64(transfer.Raw.BlockNumber)))
time := uint64(0)
if err != nil {
logger.Log().WithField("layer", "Events-AccountTransfer").Warningf(
"error fetching block number %v: %v; transfer event time set to 0 ",
transfer.Raw.BlockNumber, err.Error(),
)
s.ErrChan <- err
} else {
time = block.Time
}

s.NewAccountChan <- models.GetAccountTransferFromEvent(transfer, time)
}
}
}
16 changes: 16 additions & 0 deletions events/events.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package events

import (
"github.com/gateway-fm/perpsv3-Go/contracts/Account"
"math/big"

"github.com/ethereum/go-ethereum/ethclient"
Expand Down Expand Up @@ -104,25 +105,40 @@ type IEvents interface {
// ListenLiquidationsCore is used to listen to all 'Liquidations' Core contract events and return them as models.CoreLiquidation
// struct and return errors on ErrChan chanel
ListenLiquidationsCore() (*LiquidationsCoreSubscription, error)

// ListenAccountTransfer is used to listen to all 'Transfer' Account contract events and return them as models.AccountTransfer
// struct and return errors on ErrChan chanel
ListenAccountTransfer() (*AccountTransferSubscription, error)

// ListenAccountCorePermissionRevoked is used to listen to all 'PermissionRevoked' Core contract events and return them as models.PermissionChanged
// struct and return errors on ErrChan chanel
ListenAccountCorePermissionRevoked() (*AccountCorePermissionRevokedSubscription, error)

// ListenAccountCorePermissionGranted is used to listen to all 'PermissionGranted' Core contract events and return them as models.PermissionChanged
// struct and return errors on ErrChan chanel
ListenAccountCorePermissionGranted() (*AccountCorePermissionGrantedSubscription, error)
}

// Events implements IEvents interface
type Events struct {
rpcClient *ethclient.Client
core *core.Core
perpsMarket *perpsMarket.PerpsMarket
account *Account.Account
}

// NewEvents is used to create new Events instance that implements IEvents interface
func NewEvents(
client *ethclient.Client,
core *core.Core,
perpsMarket *perpsMarket.PerpsMarket,
account *Account.Account,
) IEvents {
return &Events{
rpcClient: client,
core: core,
perpsMarket: perpsMarket,
account: account,
}
}

Expand Down
Loading