Skip to content

Commit

Permalink
chore: finished multiple coins implementation for x/funders
Browse files Browse the repository at this point in the history
  • Loading branch information
troykessler committed Apr 29, 2024
1 parent bd272c9 commit 8941a06
Show file tree
Hide file tree
Showing 12 changed files with 247 additions and 217 deletions.
12 changes: 6 additions & 6 deletions proto/kyve/funders/v1beta1/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,17 @@ message EventFundPool {
uint64 pool_id = 1;
// address is the account address of the pool funder.
string address = 2;
// amount is the amount the funder has funded
cosmos.base.v1beta1.Coin amount = 3 [
// amounts is a list of coins the funder has funded
repeated cosmos.base.v1beta1.Coin amounts = 3 [
(gogoproto.nullable) = false,
(amino.dont_omitempty) = true,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coin"
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
// amount_per_bundle is the amount the funder pays for each finalized bundle
cosmos.base.v1beta1.Coin amount_per_bundle = 4 [
// amounts_per_bundle is a list of coins the funder wants to distribute per finalized bundle
repeated cosmos.base.v1beta1.Coin amounts_per_bundle = 4 [
(gogoproto.nullable) = false,
(amino.dont_omitempty) = true,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coin"
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
}

Expand Down
12 changes: 6 additions & 6 deletions proto/kyve/funders/v1beta1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,18 @@ message MsgFundPool {
string creator = 1;
// pool_id is the identifier of the pool
uint64 pool_id = 2;
// amount is the amount of a coin the creator wants to fund
cosmos.base.v1beta1.Coin amount = 3 [
// amounts is a list of coins the creator wants to fund
repeated cosmos.base.v1beta1.Coin amounts = 3 [
(gogoproto.nullable) = false,
(amino.dont_omitempty) = true,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coin"
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
// amount_per_bundle is the amount of the coin the creator wants to distribute
// amounts_per_bundle is a list of coins the creator wants to distribute
// per finalized bundle
cosmos.base.v1beta1.Coin amount_per_bundle = 4 [
repeated cosmos.base.v1beta1.Coin amounts_per_bundle = 4 [
(gogoproto.nullable) = false,
(amino.dont_omitempty) = true,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coin"
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
}

Expand Down
6 changes: 4 additions & 2 deletions x/funders/client/cli/tx_defund_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/spf13/cast"
"github.com/spf13/cobra"
)
Expand All @@ -19,7 +20,8 @@ func CmdDefundPool() *cobra.Command {
if err != nil {
return err
}
argAmount, err := cast.ToUint64E(args[1])

argAmounts, err := sdk.ParseCoinsNormalized(args[1])
if err != nil {
return err
}
Expand All @@ -32,7 +34,7 @@ func CmdDefundPool() *cobra.Command {
msg := &types.MsgDefundPool{
Creator: clientCtx.GetFromAddress().String(),
PoolId: argId,
Amount: argAmount,
Amounts: argAmounts,
}
if err := msg.ValidateBasic(); err != nil {
return err
Expand Down
13 changes: 7 additions & 6 deletions x/funders/client/cli/tx_fund_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/spf13/cast"
"github.com/spf13/cobra"
)
Expand All @@ -19,11 +20,11 @@ func CmdFundPool() *cobra.Command {
if err != nil {
return err
}
argAmount, err := cast.ToUint64E(args[1])
argAmounts, err := sdk.ParseCoinsNormalized(args[1])
if err != nil {
return err
}
argAmountPerBundle, err := cast.ToUint64E(args[2])
argAmountsPerBundle, err := sdk.ParseCoinsNormalized(args[2])
if err != nil {
return err
}
Expand All @@ -34,10 +35,10 @@ func CmdFundPool() *cobra.Command {
}

msg := &types.MsgFundPool{
Creator: clientCtx.GetFromAddress().String(),
PoolId: argId,
Amount: argAmount,
AmountPerBundle: argAmountPerBundle,
Creator: clientCtx.GetFromAddress().String(),
PoolId: argId,
Amounts: argAmounts,
AmountsPerBundle: argAmountsPerBundle,
}
if err := msg.ValidateBasic(); err != nil {
return err
Expand Down
1 change: 1 addition & 0 deletions x/funders/keeper/msg_server_defund_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func (k msgServer) DefundPool(goCtx context.Context, msg *types.MsgDefundPool) (
return nil, errors.Wrapf(errorsTypes.ErrNotFound, types.ErrFundingDoesNotExist.Error(), msg.PoolId, msg.Creator)
}

// Verify if funder has enough coins to defund
if !msg.Amounts.IsAllLTE(funding.Amounts) {
return nil, errors.Wrapf(errorsTypes.ErrInvalidRequest, types.ErrFundingIsUsedUp.Error(), msg.PoolId, msg.Creator)
}
Expand Down
43 changes: 15 additions & 28 deletions x/funders/keeper/msg_server_fund_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,42 +33,29 @@ func (k msgServer) FundPool(goCtx context.Context, msg *types.MsgFundPool) (*typ
return nil, errors.Wrapf(errorsTypes.ErrNotFound, types.ErrFundingStateDoesNotExist.Error(), msg.PoolId)
}

// TODO:
// iterate through msg.Amounts
// -> check if each coin has an amount per bundle
// -> if a single coin is not in the whitelist we fail
// -> check for each coin if the min funding amount is reached
// -> check for each coin if the min funding amount per bundle is reached
// -> check for each coin if the min funding multiple is reached
// calculate funders value score
// ensureFreeSlot
// emit event

// Check if amount and amount_per_bundle have the same denom
if msg.Amount.Denom != msg.AmountPerBundle.Denom {
return nil, errors.Wrapf(errorsTypes.ErrNotFound, types.ErrDifferentDenom.Error(), msg.Amount.Denom, msg.AmountPerBundle.Denom)
}
amountsPerBundle := msg.AmountsPerBundle

// Check if funding already exists
funding, found := k.GetFunding(ctx, msg.Creator, msg.PoolId)
if found {
// If so, update funding amounts
funding.Amounts = funding.Amounts.Add(msg.Amount)
funding.Amounts = funding.Amounts.Add(msg.Amounts...)

// If the amount per bundle is set, update it
if msg.AmountPerBundle.IsPositive() {
if f, c := funding.AmountsPerBundle.Find(msg.AmountPerBundle.Denom); f {
c.Amount = msg.AmountPerBundle.Amount
// Replace all coins in funding.AmountsPerBundle with the values of msg.AmountsPerBundle
for _, coin := range funding.AmountsPerBundle {
if f, _ := amountsPerBundle.Find(coin.Denom); !f {
amountsPerBundle = amountsPerBundle.Add(coin)
}
}
funding.AmountsPerBundle = amountsPerBundle
} else {
// If not, create new funding
funding = types.Funding{
FunderAddress: msg.Creator,
PoolId: msg.PoolId,
Amounts: sdk.NewCoins(msg.Amount),
AmountsPerBundle: sdk.NewCoins(msg.AmountPerBundle),
TotalFunded: sdk.Coins{},
Amounts: msg.Amounts,
AmountsPerBundle: amountsPerBundle,
TotalFunded: sdk.NewCoins(),
}
}

Expand All @@ -86,7 +73,7 @@ func (k msgServer) FundPool(goCtx context.Context, msg *types.MsgFundPool) (*typ

// All checks passed, transfer funds from funder to module
sender := sdk.MustAccAddressFromBech32(msg.Creator)
if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, sender, types.ModuleName, sdk.NewCoins(msg.Amount)); err != nil {
if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, sender, types.ModuleName, msg.Amounts); err != nil {
return nil, err
}

Expand All @@ -99,10 +86,10 @@ func (k msgServer) FundPool(goCtx context.Context, msg *types.MsgFundPool) (*typ

// Emit a fund event.
_ = ctx.EventManager().EmitTypedEvent(&types.EventFundPool{
PoolId: msg.PoolId,
Address: msg.Creator,
Amount: msg.Amount,
AmountPerBundle: msg.AmountPerBundle,
PoolId: msg.PoolId,
Address: msg.Creator,
Amounts: msg.Amounts,
AmountsPerBundle: msg.AmountsPerBundle,
})

return &types.MsgFundPoolResponse{}, nil
Expand Down
2 changes: 1 addition & 1 deletion x/funders/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ var (
ErrFundingStateDoesNotExist = errors.Register(ModuleName, 1107, "funding state for pool %v does not exist")
ErrMinFundingMultiple = errors.Register(ModuleName, 1108, "per_bundle_amount times min_funding_multiple is smaller than funded_amount")
ErrCoinNotWhitelisted = errors.Register(ModuleName, 1109, "coin not in whitelist")
ErrDifferentDenom = errors.Register(ModuleName, 1110, "found denom %s in amount and denom %s in amount_per_bundle")
ErrCoinsNegative = errors.Register(ModuleName, 1110, "all coins must be greater than zero")
)
Loading

0 comments on commit 8941a06

Please sign in to comment.