Skip to content

Commit

Permalink
before market update hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
technicallyty committed Nov 13, 2024
1 parent 52734d2 commit f47e595
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 6 deletions.
6 changes: 3 additions & 3 deletions x/marketmap/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,12 @@ func (k *Keeper) CreateMarket(ctx context.Context, market types.Market) error {
// The Ticker.String corresponds to a market, and exists uniquely.
func (k *Keeper) UpdateMarket(ctx context.Context, market types.Market) error {
// Check if Ticker already exists for the provider
alreadyExists, err := k.markets.Has(ctx, types.TickerString(market.Ticker.String()))
existing, err := k.markets.Get(ctx, types.TickerString(market.Ticker.String()))
if err != nil {
return err
}
if !alreadyExists {
return types.NewMarketDoesNotExistsError(types.TickerString(market.Ticker.String()))
if err := k.hooks.BeforeMarketUpdate(sdk.UnwrapSDKContext(ctx), existing, market); err != nil {
return fmt.Errorf("BeforeMarketUpdate hook returned an error, aborting market update: %w", err)
}
// Create the config
return k.setMarket(ctx, market)
Expand Down
33 changes: 33 additions & 0 deletions x/marketmap/keeper/keeper_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package keeper_test

import (
"fmt"
"testing"

"github.com/skip-mev/chaintestutil/sample"

mmmocks "github.com/skip-mev/connect/v2/x/marketmap/types/mocks"
oraclekeeper "github.com/skip-mev/connect/v2/x/oracle/keeper"
oracletypes "github.com/skip-mev/connect/v2/x/oracle/types"

Expand Down Expand Up @@ -276,6 +278,37 @@ func (s *KeeperTestSuite) TestValidUpdate() {
s.Require().NoError(s.keeper.ValidateState(s.ctx, []types.Market{validMarket}))
}

func (s *KeeperTestSuite) TestBeforeUpdateHook() {
hooks := mmmocks.NewMarketMapHooks(s.T())
// init keeper w/ mocked hooks
s.keeper = s.initKeeperWithHooks(hooks)

s.Require().NoError(s.keeper.CreateMarket(s.ctx, btcusdt))
s.Require().NoError(s.keeper.CreateMarket(s.ctx, ethusdt))

// valid market with a normalize pair that is in state
validMarket := btcusdt
validMarket.ProviderConfigs = append(validMarket.ProviderConfigs, types.ProviderConfig{
Name: "huobi",
OffChainTicker: "btc-usdt",
NormalizeByPair: &ethusdt.Ticker.CurrencyPair,
})

// when the hook returns an error, market should remain the same.
hooks.EXPECT().BeforeMarketUpdate(s.ctx, btcusdt, validMarket).Return(fmt.Errorf("not today, batman")).Once()
s.Require().Error(s.keeper.UpdateMarket(s.ctx, validMarket))
updated, err := s.keeper.GetMarket(s.ctx, btcusdt.Ticker.String())
s.Require().NoError(err)
s.Require().True(updated.Equal(btcusdt))

// when the hook returns nil, market should update.
hooks.EXPECT().BeforeMarketUpdate(s.ctx, btcusdt, validMarket).Return(nil).Once()
s.Require().NoError(s.keeper.UpdateMarket(s.ctx, validMarket))
updated, err = s.keeper.GetMarket(s.ctx, btcusdt.Ticker.String())
s.Require().NoError(err)
s.Require().True(updated.Equal(validMarket))
}

func (s *KeeperTestSuite) TestInvalidUpdateDisabledNormalizeBy() {
marketBTCUSDT := btcusdt
marketETHUSDT := ethusdt
Expand Down
16 changes: 16 additions & 0 deletions x/marketmap/types/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ type MarketMapHooks interface {

// AfterMarketRemoved is called after a market is removed.
AfterMarketRemoved(ctx sdk.Context, key string) error

// BeforeMarketUpdate is called with the current market state and the pending market update.
// Return an error to abort updating the market.
BeforeMarketUpdate(ctx sdk.Context, current, update Market) error
}

var _ MarketMapHooks = &MultiMarketMapHooks{}
Expand Down Expand Up @@ -68,6 +72,16 @@ func (mh MultiMarketMapHooks) AfterMarketRemoved(ctx sdk.Context, key string) er
return nil
}

func (mh MultiMarketMapHooks) BeforeMarketUpdate(ctx sdk.Context, current, update Market) error {
for i := range mh {
if err := mh[i].BeforeMarketUpdate(ctx, current, update); err != nil {
return err
}
}

return nil
}

// MarketMapHooksWrapper is a wrapper for modules to inject MarketMapHooks using depinject.
type MarketMapHooksWrapper struct{ MarketMapHooks }

Expand All @@ -91,3 +105,5 @@ func (n *NoopMarketMapHooks) AfterMarketGenesis(_ sdk.Context, _ map[string]Mark
func (n *NoopMarketMapHooks) AfterMarketRemoved(_ sdk.Context, _ string) error {
return nil
}

func (n *NoopMarketMapHooks) BeforeMarketUpdate(_ sdk.Context, _, _ Market) error { return nil }
53 changes: 50 additions & 3 deletions x/marketmap/types/mocks/MarketMapHooks.go

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

5 changes: 5 additions & 0 deletions x/oracle/keeper/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,8 @@ func (h Hooks) AfterMarketRemoved(ctx sdk.Context, key string) error {

return nil
}

func (h Hooks) BeforeMarketUpdate(ctx sdk.Context, current, update marketmaptypes.Market) error {

Check failure on line 58 in x/oracle/keeper/hooks.go

View workflow job for this annotation

GitHub Actions / golangci-lint

unused-parameter: parameter 'update' seems to be unused, consider removing or renaming it as _ (revive)
ctx.Logger().Info(fmt.Sprintf("attempting to update market %q", current.Ticker.String()))
return nil
}

0 comments on commit f47e595

Please sign in to comment.