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: add hook(s) for the farming module #330

Closed
wants to merge 3 commits into from
Closed
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
17 changes: 17 additions & 0 deletions x/farming/keeper/hooks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package keeper

import (
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/cosmosquad-labs/squad/v2/x/farming/types"
)

// Implements FarmingHooks interface
var _ types.FarmingHooks = Keeper{}

// AfterAllocateRewards - call hook if registered
func (k Keeper) AfterAllocateRewards(ctx sdk.Context) {
if k.hooks != nil {
k.hooks.AfterAllocateRewards(ctx)
}
}
43 changes: 43 additions & 0 deletions x/farming/keeper/hooks_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package keeper_test

import (
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/cosmosquad-labs/squad/v2/x/farming/types"

_ "github.com/stretchr/testify/suite"
)

var _ types.FarmingHooks = (*MockFarmingHooksReceiver)(nil)

// MockFarmingHooksReceiver event hooks for farming object (noalias)
type MockFarmingHooksReceiver struct {
AfterAllocateRewardsValid bool
}

func (h *MockFarmingHooksReceiver) AfterAllocateRewards(ctx sdk.Context) {
h.AfterAllocateRewardsValid = true
}

func (s *KeeperTestSuite) TestHooks() {
farmingHooksReceiver := MockFarmingHooksReceiver{}

// Set hooks
s.keeper.SetHooks(types.NewMultiFarmingHooks(&farmingHooksReceiver))

// Default must be false
s.Require().False(farmingHooksReceiver.AfterAllocateRewardsValid)

// Create sample farming plan
s.CreateFixedAmountPlan(s.addrs[5], map[string]string{denom1: "1"}, map[string]int64{denom3: 700000})

// Stake
s.Stake(s.addrs[0], sdk.NewCoins(sdk.NewInt64Coin(denom1, 1000000)))

// Advanced epoch twice to trigger AllocateRewards function
s.advanceEpochDays()
s.advanceEpochDays()

// Must be true
s.Require().True(farmingHooksReceiver.AfterAllocateRewardsValid)
}
12 changes: 12 additions & 0 deletions x/farming/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ type Keeper struct {

bankKeeper types.BankKeeper
accountKeeper types.AccountKeeper
hooks types.FarmingHooks
}

// NewKeeper returns a farming keeper. It handles:
Expand Down Expand Up @@ -75,6 +76,17 @@ func NewKeeper(cdc codec.BinaryCodec, key sdk.StoreKey, paramSpace paramtypes.Su
}
}

// SetHooks sets the farming hooks.
func (k *Keeper) SetHooks(fh types.FarmingHooks) *Keeper {
if k.hooks != nil {
panic("cannot set farming hooks twice")
}

k.hooks = fh

return k
}

// Logger returns a module-specific logger.
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
return ctx.Logger().With("module", "x/"+types.ModuleName)
Expand Down
3 changes: 3 additions & 0 deletions x/farming/keeper/reward.go
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,9 @@ func (k Keeper) AllocateRewards(ctx sdk.Context) error {
k.SetCurrentEpoch(ctx, stakingCoinDenom, currentEpoch+1)
}

// Call hook after successfully allocating rewards
k.AfterAllocateRewards(ctx)

return nil
}

Expand Down
11 changes: 11 additions & 0 deletions x/farming/spec/09_hooks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- order: 9 -->

# Hooks

Other modules may register operations to execute when a certain event has occurred within farming.
These events can be registered to execute right `Before` or `After` the farming event (as per the hook name).
The following hooks can be registered:

```go
AfterAllocateRewards(ctx sdk.Context)
```
1 change: 1 addition & 0 deletions x/farming/spec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ A primary use case of the farming module is to provide incentives for liquidity
6. **[Events](06_events.md)**
7. **[Parameters](07_params.md)**
8. **[Proposal](08_proposal.md)**
9. **[Hooks](09_hooks.md)**
9 changes: 9 additions & 0 deletions x/farming/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,12 @@ type AccountKeeper interface {
GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI
GetModuleAddress(name string) sdk.AccAddress
}

// Event hooks
// These can be utilized to communicate between a farming keeper and other keepers from other modules.
// The other keepers must implement this interface, which then the farming keeper can call.

// FarmingHooks event hooks for the farming object (noalias)
type FarmingHooks interface {
AfterAllocateRewards(ctx sdk.Context) // Must be called when farming rewards are allocated
}
19 changes: 19 additions & 0 deletions x/farming/types/hooks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package types

import (
sdk "github.com/cosmos/cosmos-sdk/types"
)

// MultiFarmingHooks combines multiple farming hooks.
// All hook functions are run in array sequence
type MultiFarmingHooks []FarmingHooks

func NewMultiFarmingHooks(hooks ...FarmingHooks) MultiFarmingHooks {
return hooks
}

func (h MultiFarmingHooks) AfterAllocateRewards(ctx sdk.Context) {
for i := range h {
h[i].AfterAllocateRewards(ctx)
}
}