Skip to content

Commit

Permalink
SNX-12: add collateral deposited and withdrawn events
Browse files Browse the repository at this point in the history
  • Loading branch information
asolovov committed Jan 17, 2024
1 parent 7b61913 commit 3fd1953
Show file tree
Hide file tree
Showing 9 changed files with 462 additions and 6 deletions.
2 changes: 1 addition & 1 deletion contracts/core/contract.go

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

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

import (
"context"
"math/big"

"github.com/ethereum/go-ethereum/ethclient"
"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"
)

// CollateralDepositedSubscription is a struct for listening to all 'Deposited' contract events and return them as models.CollateralDeposited struct
type CollateralDepositedSubscription struct {
*basicSubscription
CollateralDepositedChan chan *models.CollateralDeposited
contractEventChan chan *core.CoreDeposited
}

func (e *Events) ListenCollateralDeposited() (*CollateralDepositedSubscription, error) {
contractEventChan := make(chan *core.CoreDeposited)

contractSub, err := e.core.WatchDeposited(nil, contractEventChan, nil, nil, nil)
if err != nil {
logger.Log().WithField("layer", "Events-ListenCollateralDeposited").Errorf("error watch withdrawn: %v", err.Error())
return nil, errors.GetEventListenErr(err, "CollateralDeposited")
}

depositSub := newCollateralDepositedSubscription(contractSub, contractEventChan)

go depositSub.listen(e.rpcClient)

return depositSub, nil
}

// newCollateralDepositedSubscription is used to create new CollateralDepositedSubscription instance
func newCollateralDepositedSubscription(eventSub event.Subscription, contractEventChan chan *core.CoreDeposited) *CollateralDepositedSubscription {
return &CollateralDepositedSubscription{
basicSubscription: newBasicSubscription(eventSub),
contractEventChan: contractEventChan,
CollateralDepositedChan: make(chan *models.CollateralDeposited),
}
}

// listen is used to run a goroutine
func (s *CollateralDepositedSubscription) listen(rpcClient *ethclient.Client) {
defer func() {
close(s.CollateralDepositedChan)
close(s.contractEventChan)
}()

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

deposit := models.GetCollateralDepositedFromEvent(eventCollateralDeposited, time)

s.CollateralDepositedChan <- deposit
}
}
}
83 changes: 83 additions & 0 deletions events/collateralWithdrawn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package events

import (
"context"
"math/big"

"github.com/ethereum/go-ethereum/ethclient"
"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"
)

// CollateralWithdrawnSubscription is a struct for listening to all 'Withdrawn' contract events and return them as models.CollateralWithdrawn struct
type CollateralWithdrawnSubscription struct {
*basicSubscription
CollateralWithdrawnChan chan *models.CollateralWithdrawn
contractEventChan chan *core.CoreWithdrawn
}

func (e *Events) ListenCollateralWithdrawn() (*CollateralWithdrawnSubscription, error) {
contractEventChan := make(chan *core.CoreWithdrawn)

contractSub, err := e.core.WatchWithdrawn(nil, contractEventChan, nil, nil, nil)
if err != nil {
logger.Log().WithField("layer", "Events-ListenCollateralWithdrawn").Errorf("error watch withdrawn: %v", err.Error())
return nil, errors.GetEventListenErr(err, "CollateralWithdrawn")
}

withdrawnSub := newCollateralWithdrawnSubscription(contractSub, contractEventChan)

go withdrawnSub.listen(e.rpcClient)

return withdrawnSub, nil
}

// newCollateralWithdrawnSubscription is used to create new CollateralWithdrawnSubscription instance
func newCollateralWithdrawnSubscription(eventSub event.Subscription, contractEventChan chan *core.CoreWithdrawn) *CollateralWithdrawnSubscription {
return &CollateralWithdrawnSubscription{
basicSubscription: newBasicSubscription(eventSub),
contractEventChan: contractEventChan,
CollateralWithdrawnChan: make(chan *models.CollateralWithdrawn),
}
}

// listen is used to run a goroutine
func (s *CollateralWithdrawnSubscription) listen(rpcClient *ethclient.Client) {
defer func() {
close(s.CollateralWithdrawnChan)
close(s.contractEventChan)
}()

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

withdraw := models.GetCollateralWithdrawnFromEvent(eventCollateralWithdrawn, time)

s.CollateralWithdrawnChan <- withdraw
}
}
}
8 changes: 8 additions & 0 deletions events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ type IEvents interface {
// ListenDelegationUpdated is used to listen to all 'DelegationUpdated' Core contract events and return them as models.DelegationUpdated
// struct and return errors on ErrChan chanel
ListenDelegationUpdated() (*DelegationUpdatedSubscription, error)

// ListenCollateralWithdrawn is used to listen to all 'Withdrawn' Core contract events and return them as models.CollateralWithdrawn
// struct and return errors on ErrChan chanel
ListenCollateralWithdrawn() (*CollateralWithdrawnSubscription, error)

// ListenCollateralDeposited is used to listen to all 'Deposited' Core contract events and return them as models.CollateralDeposited
// struct and return errors on ErrChan chanel
ListenCollateralDeposited() (*CollateralDepositedSubscription, error)
}

// Events implements IEvents interface
Expand Down
64 changes: 64 additions & 0 deletions models/collateral.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package models

import (
"math/big"

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

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

// CollateralDeposited is a `Deposited` Core smart-contract event struct
type CollateralDeposited struct {
AccountId *big.Int
CollateralType common.Address
TokenAmount *big.Int
Sender common.Address
BlockNumber uint64
BlockTimestamp uint64
}

// CollateralWithdrawn is a `Withdrawn` Core smart-contract event struct
type CollateralWithdrawn struct {
AccountId *big.Int
CollateralType common.Address
TokenAmount *big.Int
Sender common.Address
BlockNumber uint64
BlockTimestamp uint64
}

// GetCollateralDepositedFromEvent is used to get CollateralDeposited struct from given contract event
func GetCollateralDepositedFromEvent(event *core.CoreDeposited, time uint64) *CollateralDeposited {
if event == nil {
logger.Log().WithField("layer", "Models-CoreDeposited").Warning("nil event received")
return &CollateralDeposited{}
}

return &CollateralDeposited{
AccountId: event.AccountId,
CollateralType: event.CollateralType,
TokenAmount: event.TokenAmount,
Sender: event.Sender,
BlockNumber: event.Raw.BlockNumber,
BlockTimestamp: time,
}
}

// GetCollateralWithdrawnFromEvent is used to get CollateralWithdrawn struct from given contract event
func GetCollateralWithdrawnFromEvent(event *core.CoreWithdrawn, time uint64) *CollateralWithdrawn {
if event == nil {
logger.Log().WithField("layer", "Models-CoreWithdrawn").Warning("nil event received")
return &CollateralWithdrawn{}
}

return &CollateralWithdrawn{
AccountId: event.AccountId,
CollateralType: event.CollateralType,
TokenAmount: event.TokenAmount,
Sender: event.Sender,
BlockNumber: event.Raw.BlockNumber,
BlockTimestamp: time,
}
}
4 changes: 3 additions & 1 deletion models/delegationUpdated.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package models

import (
"math/big"

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

"github.com/gateway-fm/perpsv3-Go/contracts/core"
"github.com/gateway-fm/perpsv3-Go/pkg/logger"
"math/big"
)

// DelegationUpdated is a `DelegationUpdated` Core smart-contract event struct
Expand Down
35 changes: 34 additions & 1 deletion perpsv3.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package perpsv3_Go

import (
"github.com/ethereum/go-ethereum/ethclient"
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"

"github.com/gateway-fm/perpsv3-Go/config"
"github.com/gateway-fm/perpsv3-Go/contracts/core"
"github.com/gateway-fm/perpsv3-Go/contracts/perpsMarket"
Expand Down Expand Up @@ -83,6 +84,14 @@ type IPerpsv3 interface {
// limit. For most public RPC providers the value for limit is 20 000 blocks
RetrieveDelegationUpdatedLimit(limit uint64) ([]*models.DelegationUpdated, error)

// RetrieveCollateralWithdrawnLimit is used to get all `Withdrawn` events from the Core contract with given block search
// limit. For most public RPC providers the value for limit is 20 000 blocks
RetrieveCollateralWithdrawnLimit(limit uint64) ([]*models.CollateralWithdrawn, error)

// RetrieveCollateralDepositedLimit is used to get all `Deposited` events from the Core contract with given block search
// limit. For most public RPC providers the value for limit is 20 000 blocks
RetrieveCollateralDepositedLimit(limit uint64) ([]*models.CollateralDeposited, error)

// ListenTrades is used to subscribe on the contract "OrderSettled" event. The goroutine will return events on the
// TradesChan chanel and errors on the ErrChan chanel.
// To close the subscription use events.TradeSubscription `Close` function
Expand Down Expand Up @@ -136,6 +145,14 @@ type IPerpsv3 interface {
// struct and return errors on ErrChan chanel
ListenDelegationUpdated() (*events.DelegationUpdatedSubscription, error)

// ListenCollateralWithdrawn is used to listen to all 'Withdrawn' Core contract events and return them as models.CollateralWithdrawn
// struct and return errors on ErrChan chanel
ListenCollateralWithdrawn() (*events.CollateralWithdrawnSubscription, error)

// ListenCollateralDeposited is used to listen to all 'Deposited' Core contract events and return them as models.CollateralDeposited
// struct and return errors on ErrChan chanel
ListenCollateralDeposited() (*events.CollateralDepositedSubscription, error)

// GetPosition is used to get position data struct from latest block with given params
// Function can return contract error if market ID is invalid
GetPosition(accountID *big.Int, marketID *big.Int) (*models.Position, error)
Expand Down Expand Up @@ -284,6 +301,14 @@ func (p *Perpsv3) RetrieveDelegationUpdatedLimit(limit uint64) ([]*models.Delega
return p.service.RetrieveDelegationUpdatedLimit(limit)
}

func (p *Perpsv3) RetrieveCollateralWithdrawnLimit(limit uint64) ([]*models.CollateralWithdrawn, error) {
return p.service.RetrieveCollateralWithdrawnLimit(limit)
}

func (p *Perpsv3) RetrieveCollateralDepositedLimit(limit uint64) ([]*models.CollateralDeposited, error) {
return p.service.RetrieveCollateralDepositedLimit(limit)
}

func (p *Perpsv3) ListenTrades() (*events.TradeSubscription, error) {
return p.events.ListenTrades()
}
Expand Down Expand Up @@ -332,6 +357,14 @@ func (p *Perpsv3) ListenDelegationUpdated() (*events.DelegationUpdatedSubscripti
return p.events.ListenDelegationUpdated()
}

func (p *Perpsv3) ListenCollateralWithdrawn() (*events.CollateralWithdrawnSubscription, error) {
return p.events.ListenCollateralWithdrawn()
}

func (p *Perpsv3) ListenCollateralDeposited() (*events.CollateralDepositedSubscription, error) {
return p.events.ListenCollateralDeposited()
}

func (p *Perpsv3) GetPosition(accountID *big.Int, marketID *big.Int) (*models.Position, error) {
return p.service.GetPosition(accountID, marketID)
}
Expand Down
Loading

0 comments on commit 3fd1953

Please sign in to comment.