Skip to content

Commit

Permalink
Merge pull request #17 from gateway-fm/API-161
Browse files Browse the repository at this point in the history
API-161: Implement get market updates functions with big.Int values
  • Loading branch information
asolovov authored Sep 14, 2023
2 parents d64c7a1 + 1200dd5 commit ba51063
Show file tree
Hide file tree
Showing 8 changed files with 478 additions and 0 deletions.
30 changes: 30 additions & 0 deletions mocks/service/mockService.go

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

46 changes: 46 additions & 0 deletions models/marketData.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,31 @@ type MarketUpdate struct {
TransactionHash string
}

// MarketUpdateBig is a MarketUpdate model struct with big.Int value types to return data as it is received from
// the contract
// - MarketID: ID of the market.
// - Price: Price at the time of the event.
// - Skew: Market skew at the time of the event. Positive values indicate more longs.
// - Size: Size of the entire market after settlement.
// - SizeDelta: Change in market size during the update.
// - CurrentFundingRate: Current funding rate of the market.
// - CurrentFundingVelocity: Current rate of change of the funding rate.
// - BlockNumber: Block number at which the market data was fetched.
// - BlockTimestamp: Timestamp of the block at which the market data was fetched.
// - TransactionHash: Hash of the transaction where the market update occurred.
type MarketUpdateBig struct {
MarketID *big.Int
Price *big.Int
Skew *big.Int
Size *big.Int
SizeDelta *big.Int
CurrentFundingRate *big.Int
CurrentFundingVelocity *big.Int
BlockNumber uint64
BlockTimestamp uint64
TransactionHash string
}

// MarketMetadata is a market metadata model
// - MarketID is a market ID value
// - Name is a market name value
Expand Down Expand Up @@ -114,6 +139,27 @@ func GetMarketUpdateFromEvent(event *perpsMarketGoerli.PerpsMarketGoerliMarketUp
}
}

// GetMarketUpdateBigFromEvent is used to get MarketUpdateBig model from given event and block timestamp
func GetMarketUpdateBigFromEvent(event *perpsMarketGoerli.PerpsMarketGoerliMarketUpdated, time uint64) *MarketUpdateBig {
if event == nil {
logger.Log().WithField("layer", "Models-GetMarketUpdateBigFromEvent").Warning("nil event received")
return &MarketUpdateBig{BlockTimestamp: time}
}

return &MarketUpdateBig{
MarketID: event.MarketId,
Price: event.Price,
Skew: event.Skew,
Size: event.Size,
SizeDelta: event.SizeDelta,
CurrentFundingRate: event.CurrentFundingRate,
CurrentFundingVelocity: event.CurrentFundingVelocity,
BlockNumber: event.Raw.BlockNumber,
BlockTimestamp: time,
TransactionHash: event.Raw.TxHash.Hex(),
}
}

// GetMarketMetadataFromContractResponse is used to get MarketMetadata model from given values
func GetMarketMetadataFromContractResponse(id *big.Int, name string, symbol string) *MarketMetadata {
return &MarketMetadata{
Expand Down
53 changes: 53 additions & 0 deletions models/marketData_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,59 @@ func TestGetMarketUpdateFromEvent(t *testing.T) {
}
}

func TestGetMarketUpdateBigFromEvent(t *testing.T) {
timeNow := time.Now()

testCases := []struct {
name string
event *perpsMarketGoerli.PerpsMarketGoerliMarketUpdated
time uint64
want *MarketUpdateBig
}{
{
name: "nil event",
want: &MarketUpdateBig{},
},
{
name: "full event",
event: &perpsMarketGoerli.PerpsMarketGoerliMarketUpdated{
MarketId: big.NewInt(1),
Price: big.NewInt(2),
Skew: big.NewInt(3),
Size: big.NewInt(4),
SizeDelta: big.NewInt(5),
CurrentFundingRate: big.NewInt(6),
CurrentFundingVelocity: big.NewInt(7),
Raw: types.Log{
BlockNumber: 8,
TxHash: common.BytesToHash([]byte("tx hash")),
},
},
time: uint64(timeNow.Unix()),
want: &MarketUpdateBig{
MarketID: big.NewInt(1),
Price: big.NewInt(2),
Skew: big.NewInt(3),
Size: big.NewInt(4),
SizeDelta: big.NewInt(5),
CurrentFundingRate: big.NewInt(6),
CurrentFundingVelocity: big.NewInt(7),
BlockNumber: 8,
TransactionHash: common.BytesToHash([]byte("tx hash")).Hex(),
BlockTimestamp: uint64(timeNow.Unix()),
},
},
}

for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
res := GetMarketUpdateBigFromEvent(tt.event, tt.time)

require.Equal(t, tt.want, res)
})
}
}

func TestGetMarketMetadataFromContractResponse(t *testing.T) {
testCases := []struct {
name string
Expand Down
20 changes: 20 additions & 0 deletions perpsv3.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,22 @@ type IPerpsv3 interface {
// - use nil for toBlock to use default value of a last blockchain block
RetrieveMarketUpdates(fromBlock uint64, toBLock *uint64) ([]*models.MarketUpdate, error)

// RetrieveMarketUpdatesBig is used to get logs from the "MarketUpdated" event perps market contract within given block
// range
// - use 0 for fromBlock to use default value of a first contract block
// - use nil for toBlock to use default value of a last blockchain block
// It will return a MarketUpdateBig model with big.Int values
RetrieveMarketUpdatesBig(fromBlock uint64, toBLock *uint64) ([]*models.MarketUpdateBig, error)

// RetrieveMarketUpdatesLimit is used to get all "MarketUpdated" events and their additional data from the contract
// with given block search limit. If given limit is 0 function will set default value to 20 000 blocks
RetrieveMarketUpdatesLimit(limit uint64) ([]*models.MarketUpdate, error)

// RetrieveMarketUpdatesBigLimit is used to get all "MarketUpdated" events and their additional data from the contract
// with given block search limit. If given limit is 0 function will set default value to 20 000 blocks
// It will return a MarketUpdateBig model with big.Int values
RetrieveMarketUpdatesBigLimit(limit uint64) ([]*models.MarketUpdateBig, error)

// RetrieveLiquidations is used to get logs from the "PositionLiquidated" event perps market contract within given block
// range
// - use 0 for fromBlock to use default value of a first contract block
Expand Down Expand Up @@ -149,10 +161,18 @@ func (p *Perpsv3) RetrieveMarketUpdates(fromBlock uint64, toBLock *uint64) ([]*m
return p.service.RetrieveMarketUpdates(fromBlock, toBLock)
}

func (p *Perpsv3) RetrieveMarketUpdatesBig(fromBlock uint64, toBLock *uint64) ([]*models.MarketUpdateBig, error) {
return p.service.RetrieveMarketUpdatesBig(fromBlock, toBLock)
}

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

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

func (p *Perpsv3) RetrieveLiquidations(fromBlock uint64, toBLock *uint64) ([]*models.Liquidation, error) {
return p.service.RetrieveLiquidations(fromBlock, toBLock)
}
Expand Down
147 changes: 147 additions & 0 deletions perpsv3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,153 @@ func TestPerpsv3_RetrieveMarketUpdatesLimit(t *testing.T) {
}
}

func TestPerpsv3_RetrieveMarketUpdatesBig(t *testing.T) {
blockN := uint64(10000)

marketUpdate := &models.MarketUpdateBig{
MarketID: big.NewInt(200),
Price: big.NewInt(3780527432113118208),
Skew: big.NewInt(527000000000000000),
Size: big.NewInt(1049000000000000000),
SizeDelta: big.NewInt(-255300000000000000),
CurrentFundingRate: big.NewInt(62031943958317),
CurrentFundingVelocity: big.NewInt(47430000000000),
BlockNumber: 13739029,
BlockTimestamp: 1692906126,
TransactionHash: "0x16704162005c11d71c745f7392a71a5ede8eb5f042e7fa917f210748773c57bf",
}

testCases := []struct {
name string
conf *config.PerpsvConfig
startBlock uint64
endBlock *uint64
wantRes []*models.MarketUpdateBig
wantErr error
}{
{
name: "no error default values",
conf: config.GetGoerliDefaultPerpsvConfig(),
startBlock: 0,
endBlock: nil,
wantRes: []*models.MarketUpdateBig{marketUpdate, marketUpdate, marketUpdate},
},
{
name: "no error custom values",
conf: config.GetGoerliDefaultPerpsvConfig(),
startBlock: blockN,
endBlock: &blockN,
wantRes: []*models.MarketUpdateBig{marketUpdate},
},
{
name: "no error custom values blank result",
conf: config.GetGoerliDefaultPerpsvConfig(),
startBlock: blockN,
endBlock: &blockN,
wantRes: []*models.MarketUpdateBig{},
},
{
name: "error",
conf: config.GetGoerliDefaultPerpsvConfig(),
startBlock: 0,
endBlock: nil,
wantErr: errors.FilterErr,
},
}

for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockService := mock_services.NewMockIService(ctrl)

p, _ := createTest(tt.conf)
p.service = mockService

mockService.EXPECT().RetrieveMarketUpdatesBig(tt.startBlock, tt.endBlock).Return(tt.wantRes, tt.wantErr)

res, err := p.RetrieveMarketUpdatesBig(tt.startBlock, tt.endBlock)

if tt.wantErr == nil {
require.NoError(t, err)
require.Equal(t, tt.wantRes, res)
} else {
require.ErrorIs(t, tt.wantErr, err)
}
})
}
}

func TestPerpsv3_RetrieveMarketUpdatesBigLimit(t *testing.T) {
marketUpdate := &models.MarketUpdateBig{
MarketID: big.NewInt(200),
Price: big.NewInt(3780527432113118208),
Skew: big.NewInt(527000000000000000),
Size: big.NewInt(1049000000000000000),
SizeDelta: big.NewInt(-255300000000000000),
CurrentFundingRate: big.NewInt(62031943958317),
CurrentFundingVelocity: big.NewInt(47430000000000),
BlockNumber: 13739029,
BlockTimestamp: 1692906126,
TransactionHash: "0x16704162005c11d71c745f7392a71a5ede8eb5f042e7fa917f210748773c57bf",
}

testCases := []struct {
name string
conf *config.PerpsvConfig
limit uint64
wantRes []*models.MarketUpdateBig
wantErr error
}{
{
name: "no error default values",
conf: config.GetGoerliDefaultPerpsvConfig(),
limit: 0,
wantRes: []*models.MarketUpdateBig{marketUpdate, marketUpdate, marketUpdate},
},
{
name: "no error custom values",
conf: config.GetGoerliDefaultPerpsvConfig(),
limit: 1,
wantRes: []*models.MarketUpdateBig{marketUpdate},
},
{
name: "no error custom values blank result",
conf: config.GetGoerliDefaultPerpsvConfig(),
limit: 1,
wantRes: []*models.MarketUpdateBig{},
},
{
name: "error",
conf: config.GetGoerliDefaultPerpsvConfig(),
limit: 1,
wantErr: errors.FilterErr,
},
}

for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockService := mock_services.NewMockIService(ctrl)

p, _ := createTest(tt.conf)
p.service = mockService

mockService.EXPECT().RetrieveMarketUpdatesBigLimit(tt.limit).Return(tt.wantRes, tt.wantErr)

res, err := p.RetrieveMarketUpdatesBigLimit(tt.limit)

if tt.wantErr == nil {
require.NoError(t, err)
require.Equal(t, tt.wantRes, res)
} else {
require.ErrorIs(t, tt.wantErr, err)
}
})
}
}

func TestPerpsv3_ListenTrades(t *testing.T) {
testCases := []struct {
name string
Expand Down
Loading

0 comments on commit ba51063

Please sign in to comment.