From 521a4ad5c2e0baaad704caf1d97947e738897b0d Mon Sep 17 00:00:00 2001 From: kogisin Date: Mon, 27 Sep 2021 11:21:17 +0900 Subject: [PATCH 1/4] feat: add markdown link checker workflow --- .github/workflows/linkchecker.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/linkchecker.yml diff --git a/.github/workflows/linkchecker.yml b/.github/workflows/linkchecker.yml new file mode 100644 index 00000000..bc4c3ad7 --- /dev/null +++ b/.github/workflows/linkchecker.yml @@ -0,0 +1,19 @@ +name: Check Markdown links + +on: + pull_request: + push: + branches: + - master + - develop + schedule: + - cron: '* */24 * * *' + +jobs: + markdown-link-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - uses: gaurav-nelson/github-action-markdown-link-check@1.0.13 + with: + folder-path: "." From 5ad9c2e2acd22c2d07c40f4a3ec6716d6e7b96ff Mon Sep 17 00:00:00 2001 From: kogisin Date: Mon, 27 Sep 2021 13:40:22 +0900 Subject: [PATCH 2/4] chore: fix broken links and add CONTRIBUTING.md --- CONTRIBUTING.md | 3 +++ docs/Explanation/ADR/README.md | 2 +- docs/Explanation/README.md | 21 +-------------------- docs/How-To/api/README.md | 13 +++++++++++-- docs/How-To/cli/README.md | 2 +- docs/README.md | 1 - docs/Tutorials/demo/demo_2021_08_06.md | 2 +- 7 files changed, 18 insertions(+), 26 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..02d3f84b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +# Contributing + +TODO: add context \ No newline at end of file diff --git a/docs/Explanation/ADR/README.md b/docs/Explanation/ADR/README.md index af9fe942..441e70d9 100644 --- a/docs/Explanation/ADR/README.md +++ b/docs/Explanation/ADR/README.md @@ -36,4 +36,4 @@ When writing ADRs, follow the same best practices for writing RFCs. When writing ## ADR Table of Contents -- [ADR XXX: Self Sovereign Identity](./adr-001-self-sovereign-identity.md) \ No newline at end of file +- [ADR 002: Documentation Structure](./adr-002-docs-structure.md) \ No newline at end of file diff --git a/docs/Explanation/README.md b/docs/Explanation/README.md index 9cf32d87..ebf9df81 100644 --- a/docs/Explanation/README.md +++ b/docs/Explanation/README.md @@ -5,10 +5,7 @@ How to use the farming module Explanation Documentation. - [Explanation Documentation](#explanation-documentation) - [Introduction](#introduction) - [Layout](#layout) - - [Topics](#topics) - - [Presentations](#presentations) - [Architecture Decisions Records (ADRs)](#architecture-decisions-records-adrs) - - [Articles](#articles) - [Discussions](#discussions) - [Contributing](#contributing) - [Reference](#reference) @@ -24,28 +21,12 @@ For further background information please see [the ADR relating to the documenta The scope and structure of the Explanation documentation follows this layout. -### Topics - -Topics are discursive documents that explore some particular feature or theme. For example, an article might investigate Decentralised Identity Documents or Self-Sovereign Identity. - -To contribute, create a folder in [topics](./topics) with a self-descriptive name. Add your content as needed. - -### Presentations - -The [Presentations](PRESENTATIONS.md) file describes and links to presentations about farming module at various events. Presentations also include YouTube videos, podcasts, interviews, and so on. - - ### Architecture Decisions Records (ADRs) ADRs are the mechanism for contributors to raise design proposals. In turn, the ADRs explain for subsequent contributors the rationale behind farming module design and implementation. For example, [ADR 002: Documentation Structure](./ADR/adr-002-docs-structure.md) explains why the farming module documentation structure was chosen. See the Architecture Decision Records (ADR) [README](./ADR/README.md) file for more details about how to raise and propose an ADR. -### Articles - -This folder contains all articles relating to farming module, includes papers, blog posts, and so on. For details, see [Articles README](articles/README.md). - - ## Discussions The explanation content includes articles, topics, and so on, and also includes discussion on relevant channels, including [Pull Requests](https://github.com/tendermint/farming/pulls) and [Issues](https://github.com/tendermint/farming/issues). Important Pull Requests are listed in this document. @@ -57,7 +38,7 @@ Future: farming module currently doesn't have a Discord or Telegram Channel. Whe * All documentation is written following [Google Documentation Best Practice](https://google.github.io/styleguide/docguide/best_practices.html) * Autogenerate documentation from the code whenever possible. * Raise a PR for all documentation changes -* Follow our [Code of Conduct](../CONTRIBUTING.md) +* Follow our [Code of Conduct](../../CONTRIBUTING.md) ## Reference diff --git a/docs/How-To/api/README.md b/docs/How-To/api/README.md index a1808022..da49650c 100644 --- a/docs/How-To/api/README.md +++ b/docs/How-To/api/README.md @@ -22,6 +22,7 @@ In order to test out the following REST routes, you need to set up a local node ### Params Query the values set as farming parameters + http://localhost:1317/cosmos/farming/v1beta1/params ```json @@ -43,6 +44,7 @@ http://localhost:1317/cosmos/farming/v1beta1/params Query all the farming plans exist in the network + http://localhost:1317/cosmos/farming/v1beta1/plans ```json @@ -91,6 +93,7 @@ http://localhost:1317/cosmos/farming/v1beta1/plans Query a particular plan + http://localhost:1317/cosmos/farming/v1beta1/plans/1 ```json @@ -133,6 +136,7 @@ http://localhost:1317/cosmos/farming/v1beta1/plans/1 Query for all stakings by a farmer + http://localhost:1317/cosmos/farming/v1beta1/stakings/cosmos185fflsvwrz0cx46w6qada7mdy92m6kx4gqx0ny ```json @@ -150,7 +154,8 @@ http://localhost:1317/cosmos/farming/v1beta1/stakings/cosmos185fflsvwrz0cx46w6qa Query for all stakings by a farmer with the given staking coin denom -http://localhost:1317/cosmos/farming/v1beta1/stakings/cosmos185fflsvwrz0cx46w6qada7mdy92m6kx4gqx0ny?staking_coin_denom=poolD35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A23A4 + +http://localhost:1317/cosmos/farming/v1beta1/stakings/cosmos185fflsvwrz0cx46w6qada7mdy92m6kx4gqx0ny?staking_coin_denom=poolD35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A23A4 ```json { @@ -168,7 +173,8 @@ http://localhost:1317/cosmos/farming/v1beta1/stakings/cosmos185fflsvwrz0cx46w6qa Query for total stakings by a staking coin denom -http://localhost:1317/cosmos/farming/v1beta1/total_stakings/poolD35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A23A4 + +http://localhost:1317/cosmos/farming/v1beta1/total_stakings/poolD35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A23A4 ```json { @@ -180,6 +186,7 @@ http://localhost:1317/cosmos/farming/v1beta1/total_stakings/poolD35A0CC16EE598F9 Query for all rewards by a farmer + http://localhost:1317/cosmos/farming/v1beta1/rewards/cosmos185fflsvwrz0cx46w6qada7mdy92m6kx4gqx0ny ```json @@ -196,6 +203,7 @@ http://localhost:1317/cosmos/farming/v1beta1/rewards/cosmos185fflsvwrz0cx46w6qad Query for all rewards by a farmer with the staking coin denom + http://localhost:1317/cosmos/farming/v1beta1/rewards/cosmos185fflsvwrz0cx46w6qada7mdy92m6kx4gqx0ny?staking_coin_denom=poolD35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A23A4 ```json @@ -213,6 +221,7 @@ http://localhost:1317/cosmos/farming/v1beta1/rewards/cosmos185fflsvwrz0cx46w6qad Query for the current epoch days + http://localhost:1317/cosmos/farming/v1beta1/current_epoch_days ```json diff --git a/docs/How-To/cli/README.md b/docs/How-To/cli/README.md index e0d5e6f0..36a294d8 100644 --- a/docs/How-To/cli/README.md +++ b/docs/How-To/cli/README.md @@ -9,7 +9,7 @@ This document provides a high-level overview of how the command-line (CLI) inter ## Command-Line Interfaces -In order to test out the following command-line interfaces, you need to set up a local node to either send transaction or query from. You can refer to this [localnet tutorial](./Tutorials/localnet) on how to build `farmingd` binary and bootstrap a local network in your local machine. +In order to test out the following command-line interfaces, you need to set up a local node to either send transaction or query from. You can refer to this [localnet tutorial](../../Tutorials/localnet) on how to build `farmingd` binary and bootstrap a local network in your local machine. - [Transaction](#Transaction) * [MsgCreateFixedAmountPlan](#MsgCreateFixedAmountPlan) diff --git a/docs/README.md b/docs/README.md index e68c505b..01dfc887 100644 --- a/docs/README.md +++ b/docs/README.md @@ -16,7 +16,6 @@ This approach outlines four specific use cases for documentation: * [Tutorials](./Tutorials/README.md) * [How-Tos](./How-To/README.md) * [Explanation](./Explanation/README.md) -* [Reference](./Reference/README.md) For further background please see [the ADR relating to the documentation structure](./Explanation/ADR/adr-002-docs-structure.md). diff --git a/docs/Tutorials/demo/demo_2021_08_06.md b/docs/Tutorials/demo/demo_2021_08_06.md index 3e37a732..553c8780 100644 --- a/docs/Tutorials/demo/demo_2021_08_06.md +++ b/docs/Tutorials/demo/demo_2021_08_06.md @@ -15,7 +15,7 @@ Farming module is in active development by the Gravity DEX team in Tendermint. T - [Github Repo](https://github.com/tendermint/farming) - [Spec Docs](https://github.com/tendermint/farming/blob/master/x/farming/spec/01_concepts.md) - MVP branch uses [local-testing](https://github.com/tendermint/farming/tree/local-testing) -- Other useful resources are available in [docs](https://github.com/tendermint/farming/blob/master/docs/How-To/client.md) folder +- Other useful resources are available in [docs](https://github.com/tendermint/farming/blob/master/docs) folder - [Swagger Docs v0.1.0](https://app.swaggerhub.com/apis-docs/gravity-devs/farming/0.1.0) ## Build From d0b85e6448406b67a77262aee16efe813664fbb6 Mon Sep 17 00:00:00 2001 From: kogisin Date: Mon, 27 Sep 2021 13:43:41 +0900 Subject: [PATCH 3/4] fix: broken link --- docs/How-To/api/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/How-To/api/README.md b/docs/How-To/api/README.md index da49650c..6a4c614f 100644 --- a/docs/How-To/api/README.md +++ b/docs/How-To/api/README.md @@ -9,7 +9,7 @@ Description: A high-level overview of gRPC-gateway REST Routes in farming module ## gRPC-gateway REST Routes -In order to test out the following REST routes, you need to set up a local node to query from. You can refer to this [localnet tutorial](./Tutorials/localnet) on how to build `farmingd` binary and bootstrap a local network in your local machine. +In order to test out the following REST routes, you need to set up a local node to query from. You can refer to this [localnet tutorial](../../Tutorials/localnet) on how to build `farmingd` binary and bootstrap a local network in your local machine. - [Params](#Params) - [Plans](#Plans) From 97b297b45a792b0ffc6616e24595c314aecf89b6 Mon Sep 17 00:00:00 2001 From: JayB Date: Mon, 27 Sep 2021 18:18:19 +0900 Subject: [PATCH 4/4] feat: fix update public plan proposal & disable codecov patch (#133) * feat: work in progress * feat: add logic to change plan type if there is a update request proposal * test: add more cases * chore: improve code coverage and update nil check to IsAllPositive * test: remove nolint comments * test: disable codecov patch * test: add codecov.yml and revert the prev commit * test: update codecov.yml * chore: apply feedback --- .github/.codecov.yml | 23 + x/farming/keeper/proposal_handler.go | 43 +- x/farming/keeper/proposal_handler_test.go | 661 +++++++++++----------- x/farming/types/plan.go | 18 + x/farming/types/proposal.go | 57 ++ 5 files changed, 444 insertions(+), 358 deletions(-) create mode 100644 .github/.codecov.yml diff --git a/.github/.codecov.yml b/.github/.codecov.yml new file mode 100644 index 00000000..6f590683 --- /dev/null +++ b/.github/.codecov.yml @@ -0,0 +1,23 @@ +# To validate: +# cat codecov.yml | curl --data-binary @- https://codecov.io/validate + +codecov: + notify: + require_ci_to_pass: yes + +coverage: + precision: 2 + round: down + range: "50...80" + + status: + project: + default: + target: auto + threshold: 1% + patch: + default: + enabled: no # disable patch since it is noisy and not correct + if_not_found: success + +comment: false \ No newline at end of file diff --git a/x/farming/keeper/proposal_handler.go b/x/farming/keeper/proposal_handler.go index 6b1234a4..49ab8366 100644 --- a/x/farming/keeper/proposal_handler.go +++ b/x/farming/keeper/proposal_handler.go @@ -31,6 +31,7 @@ func HandlePublicPlanProposal(ctx sdk.Context, k Keeper, proposal *types.PublicP if err := types.ValidateName(plans); err != nil { return err } + if err := types.ValidateTotalEpochRatio(plans); err != nil { return err } @@ -45,12 +46,13 @@ func (k Keeper) AddPublicPlanProposal(ctx sdk.Context, proposals []*types.AddReq if err != nil { return err } + terminationAcc, err := sdk.AccAddressFromBech32(p.GetTerminationAddress()) if err != nil { return err } - if !p.EpochAmount.IsZero() && !p.EpochAmount.IsAnyNegative() { + if p.EpochAmount.IsAllPositive() { msg := types.NewMsgCreateFixedAmountPlan( p.GetName(), farmingPoolAddrAcc, @@ -68,7 +70,7 @@ func (k Keeper) AddPublicPlanProposal(ctx sdk.Context, proposals []*types.AddReq logger := k.Logger(ctx) logger.Info("created public fixed amount plan", "fixed_amount_plan", plan) - } else if !p.EpochRatio.IsZero() && !p.EpochRatio.IsNegative() && !p.EpochRatio.IsNil() { + } else if p.EpochRatio.IsPositive() { msg := types.NewMsgCreateRatioPlan( p.GetName(), farmingPoolAddrAcc, @@ -103,8 +105,13 @@ func (k Keeper) UpdatePublicPlanProposal(ctx sdk.Context, proposals []*types.Upd return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "plan %d is not found", p.GetPlanId()) } - switch plan := plan.(type) { - case *types.FixedAmountPlan: + if p.EpochAmount.IsAllPositive() { + if p.GetName() != "" { + if err := plan.SetName(p.GetName()); err != nil { + return err + } + } + if p.GetFarmingPoolAddress() != "" { farmingPoolAddrAcc, err := sdk.AccAddressFromBech32(p.GetFarmingPoolAddress()) if err != nil { @@ -143,12 +150,9 @@ func (k Keeper) UpdatePublicPlanProposal(ctx sdk.Context, proposals []*types.Upd } } - if p.GetName() != "" { - plan.Name = p.GetName() - } - - if p.GetEpochAmount() != nil { - plan.EpochAmount = p.GetEpochAmount() + // change the plan to fixed amount plan if an epoch amount exists + if p.GetEpochAmount().IsAllPositive() { + plan = types.NewFixedAmountPlan(plan.GetBasePlan(), p.GetEpochAmount()) } k.SetPlan(ctx, plan) @@ -156,9 +160,11 @@ func (k Keeper) UpdatePublicPlanProposal(ctx sdk.Context, proposals []*types.Upd logger := k.Logger(ctx) logger.Info("updated public fixed amount plan", "fixed_amount_plan", plan) - case *types.RatioPlan: - if err := plan.Validate(); err != nil { - return err + } else if p.EpochRatio.IsPositive() { + if p.GetName() != "" { + if err := plan.SetName(p.GetName()); err != nil { + return err + } } if p.GetFarmingPoolAddress() != "" { @@ -199,12 +205,9 @@ func (k Keeper) UpdatePublicPlanProposal(ctx sdk.Context, proposals []*types.Upd } } - if p.GetName() != "" { - plan.Name = p.GetName() - } - - if !p.EpochRatio.IsZero() { - plan.EpochRatio = p.EpochRatio + // change the plan to ratio plan if an epoch ratio exists + if p.EpochRatio.IsPositive() { + plan = types.NewRatioPlan(plan.GetBasePlan(), p.EpochRatio) } k.SetPlan(ctx, plan) @@ -212,8 +215,6 @@ func (k Keeper) UpdatePublicPlanProposal(ctx sdk.Context, proposals []*types.Upd logger := k.Logger(ctx) logger.Info("updated public ratio plan", "ratio_plan", plan) - default: - return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized plan type: %T", p) } } diff --git a/x/farming/keeper/proposal_handler_test.go b/x/farming/keeper/proposal_handler_test.go index ed17111b..79fe959c 100644 --- a/x/farming/keeper/proposal_handler_test.go +++ b/x/farming/keeper/proposal_handler_test.go @@ -4,124 +4,13 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/tendermint/farming/app" "github.com/tendermint/farming/x/farming/keeper" "github.com/tendermint/farming/x/farming/types" _ "github.com/stretchr/testify/suite" ) -func (suite *KeeperTestSuite) TestAddPublicPlanProposal() { - addrs := app.AddTestAddrs(suite.app, suite.ctx, 2, sdk.NewInt(100_000_000)) - farmerAddr := addrs[0] - name := "test" - terminationAddr := sdk.AccAddress("terminationAddr") - coinWeights := sdk.NewDecCoins( - sdk.DecCoin{ - Denom: "poolD35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A23A4", - Amount: sdk.MustNewDecFromStr("1.0"), - }, - ) - - // case1 - req := &types.AddRequestProposal{ - Name: name, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: coinWeights, - StartTime: types.ParseTime("2021-08-06T00:00:00Z"), - EndTime: types.ParseTime("2021-08-13T00:00:00Z"), - EpochAmount: sdk.NewCoins(sdk.NewInt64Coin("uatom", 100_000_000)), - EpochRatio: sdk.ZeroDec(), - } - case1 := []*types.AddRequestProposal{req} - - // case2 - req = &types.AddRequestProposal{ - Name: `OVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERMOVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERM - OVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERMOVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERM - OVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERMOVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERM - OVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERMOVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERM`, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: coinWeights, - StartTime: types.ParseTime("2021-08-06T00:00:00Z"), - EndTime: types.ParseTime("2021-08-13T00:00:00Z"), - EpochAmount: sdk.NewCoins(sdk.NewInt64Coin("uatom", 100_000_000)), - EpochRatio: sdk.ZeroDec(), - } - case2 := []*types.AddRequestProposal{req} - - // case3 - req = &types.AddRequestProposal{ - Name: name, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: sdk.NewDecCoins(), - StartTime: types.ParseTime("2021-08-06T00:00:00Z"), - EndTime: types.ParseTime("2021-08-13T00:00:00Z"), - EpochAmount: sdk.NewCoins(sdk.NewInt64Coin("uatom", 0)), - EpochRatio: sdk.ZeroDec(), - } - case3 := []*types.AddRequestProposal{req} - - // case4 - req = &types.AddRequestProposal{ - Name: name, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: sdk.NewDecCoins( - sdk.DecCoin{ - Denom: "poolD35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A23A4", - Amount: sdk.MustNewDecFromStr("0.1"), - }, - ), - StartTime: types.ParseTime("2021-08-06T00:00:00Z"), - EndTime: types.ParseTime("2021-08-13T00:00:00Z"), - EpochAmount: sdk.NewCoins(sdk.NewInt64Coin("uatom", 0)), - EpochRatio: sdk.ZeroDec(), - } - case4 := []*types.AddRequestProposal{req} - - // case5 - req = &types.AddRequestProposal{ - Name: name, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: coinWeights, - StartTime: types.ParseTime("2021-08-13T00:00:00Z"), - EndTime: types.ParseTime("2021-08-06T00:00:00Z"), - EpochAmount: sdk.NewCoins(sdk.NewInt64Coin("uatom", 0)), - EpochRatio: sdk.ZeroDec(), - } - case5 := []*types.AddRequestProposal{req} - - // case6 - req = &types.AddRequestProposal{ - Name: name, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: coinWeights, - StartTime: types.ParseTime("2021-08-06T00:00:00Z"), - EndTime: types.ParseTime("2021-08-13T00:00:00Z"), - EpochAmount: sdk.NewCoins(sdk.NewInt64Coin("uatom", 1)), - EpochRatio: sdk.NewDec(1), - } - case6 := []*types.AddRequestProposal{req} - - // case7 - req = &types.AddRequestProposal{ - Name: name, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: coinWeights, - StartTime: types.ParseTime("2021-08-06T00:00:00Z"), - EndTime: types.ParseTime("2021-08-13T00:00:00Z"), - EpochAmount: sdk.NewCoins(), - EpochRatio: sdk.ZeroDec(), - } - case7 := []*types.AddRequestProposal{req} - +func (suite *KeeperTestSuite) TestValidateAddPublicPlanProposal() { for _, tc := range []struct { name string addRequest []*types.AddRequestProposal @@ -129,7 +18,19 @@ func (suite *KeeperTestSuite) TestAddPublicPlanProposal() { }{ { "happy case", - case1, + []*types.AddRequestProposal{types.NewAddRequestProposal( + "testPlan", + suite.addrs[0].String(), + suite.addrs[0].String(), + sdk.NewDecCoins( + sdk.NewDecCoinFromDec(denom1, sdk.NewDecWithPrec(3, 1)), + sdk.NewDecCoinFromDec(denom2, sdk.NewDecWithPrec(7, 1)), + ), + types.ParseTime("2021-08-01T00:00:00Z"), + types.ParseTime("2021-08-30T00:00:00Z"), + sdk.NewCoins(sdk.NewInt64Coin(denom3, 100_000_000)), + sdk.ZeroDec(), + )}, nil, }, { @@ -137,41 +38,110 @@ func (suite *KeeperTestSuite) TestAddPublicPlanProposal() { nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "proposal request must not be empty"), }, - { - "request case #2", - []*types.AddRequestProposal{}, - sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "proposal request must not be empty"), - }, { "name case #1", - case2, + []*types.AddRequestProposal{types.NewAddRequestProposal( + `OVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERMOVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERM + OVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERMOVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERM + OVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERMOVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERM + OVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERMOVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERM`, + suite.addrs[0].String(), + suite.addrs[0].String(), + sdk.NewDecCoins( + sdk.NewDecCoinFromDec(denom1, sdk.NewDecWithPrec(3, 1)), + sdk.NewDecCoinFromDec(denom2, sdk.NewDecWithPrec(7, 1)), + ), + types.ParseTime("2021-08-01T00:00:00Z"), + types.ParseTime("2021-08-30T00:00:00Z"), + sdk.NewCoins(sdk.NewInt64Coin(denom3, 100_000_000)), + sdk.ZeroDec(), + )}, sdkerrors.Wrapf(types.ErrInvalidPlanNameLength, "plan name cannot be longer than max length of %d", types.MaxNameLength), }, { "staking coin weights case #1", - case3, + []*types.AddRequestProposal{types.NewAddRequestProposal( + "testPlan", + suite.addrs[0].String(), + suite.addrs[0].String(), + sdk.NewDecCoins(), + types.ParseTime("2021-08-01T00:00:00Z"), + types.ParseTime("2021-08-30T00:00:00Z"), + sdk.NewCoins(sdk.NewInt64Coin(denom3, 100_000_000)), + sdk.ZeroDec(), + )}, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "staking coin weights must not be empty"), }, { "staking coin weights case #2", - case4, + []*types.AddRequestProposal{types.NewAddRequestProposal( + "testPlan", + suite.addrs[0].String(), + suite.addrs[0].String(), + sdk.NewDecCoins( + sdk.DecCoin{ + Denom: "poolD35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A23A4", + Amount: sdk.MustNewDecFromStr("0.1"), + }, + ), + types.ParseTime("2021-08-01T00:00:00Z"), + types.ParseTime("2021-08-30T00:00:00Z"), + sdk.NewCoins(sdk.NewInt64Coin(denom3, 100_000_000)), + sdk.ZeroDec(), + )}, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "total weight must be 1"), }, { "start time & end time case #1", - case5, + []*types.AddRequestProposal{types.NewAddRequestProposal( + "testPlan", + suite.addrs[0].String(), + suite.addrs[0].String(), + sdk.NewDecCoins( + sdk.NewDecCoinFromDec(denom1, sdk.NewDecWithPrec(3, 1)), + sdk.NewDecCoinFromDec(denom2, sdk.NewDecWithPrec(7, 1)), + ), + types.ParseTime("2021-08-13T00:00:00Z"), + types.ParseTime("2021-08-06T00:00:00Z"), + sdk.NewCoins(sdk.NewInt64Coin(denom3, 100_000_000)), + sdk.ZeroDec(), + )}, sdkerrors.Wrapf(types.ErrInvalidPlanEndTime, "end time %s must be greater than start time %s", types.ParseTime("2021-08-06T00:00:00Z"), types.ParseTime("2021-08-13T00:00:00Z")), }, { "epoch amount & epoch ratio case #1", - case6, + []*types.AddRequestProposal{types.NewAddRequestProposal( + "testPlan", + suite.addrs[0].String(), + suite.addrs[0].String(), + sdk.NewDecCoins( + sdk.NewDecCoinFromDec(denom1, sdk.NewDecWithPrec(3, 1)), + sdk.NewDecCoinFromDec(denom2, sdk.NewDecWithPrec(7, 1)), + ), + types.ParseTime("2021-08-01T00:00:00Z"), + types.ParseTime("2021-08-30T00:00:00Z"), + sdk.NewCoins(sdk.NewInt64Coin(denom3, 1)), + sdk.NewDec(1), + )}, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "either epoch amount or epoch ratio should be provided"), }, { "epoch amount & epoch ratio case #2", - case7, + []*types.AddRequestProposal{types.NewAddRequestProposal( + "testPlan", + suite.addrs[0].String(), + suite.addrs[0].String(), + sdk.NewDecCoins( + sdk.NewDecCoinFromDec(denom1, sdk.NewDecWithPrec(3, 1)), + sdk.NewDecCoinFromDec(denom2, sdk.NewDecWithPrec(7, 1)), + ), + types.ParseTime("2021-08-01T00:00:00Z"), + types.ParseTime("2021-08-30T00:00:00Z"), + sdk.NewCoins(), + sdk.ZeroDec(), + )}, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "either epoch amount or epoch ratio must not be zero"), }, } { @@ -190,7 +160,6 @@ func (suite *KeeperTestSuite) TestAddPublicPlanProposal() { suite.Require().NoError(err) _, found := suite.keeper.GetPlan(suite.ctx, uint64(1)) - // TODO: need to check each field same as expected suite.Require().Equal(true, found) } else { suite.EqualError(err, tc.expectedErr.Error()) @@ -199,179 +168,52 @@ func (suite *KeeperTestSuite) TestAddPublicPlanProposal() { } } -func (suite *KeeperTestSuite) TestUpdatePublicPlanProposal() { - addrs := app.AddTestAddrs(suite.app, suite.ctx, 2, sdk.NewInt(100_000_000)) - farmerAddr := addrs[0] - name := "test" - terminationAddr := sdk.AccAddress("terminationAddr") - coinWeights := sdk.NewDecCoins( - sdk.DecCoin{ - Denom: "poolD35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A23A4", - Amount: sdk.MustNewDecFromStr("1.0"), - }, - ) - - // add request proposal - addReq := &types.AddRequestProposal{ - Name: name, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: coinWeights, - StartTime: types.ParseTime("2021-08-06T00:00:00Z"), - EndTime: types.ParseTime("2021-08-13T00:00:00Z"), - EpochAmount: sdk.NewCoins(sdk.NewInt64Coin("uatom", 100_000_000)), - EpochRatio: sdk.ZeroDec(), - } - addRequests := []*types.AddRequestProposal{addReq} - - proposal := &types.PublicPlanProposal{ - Title: "testTitle", - Description: "testDescription", - AddRequestProposals: addRequests, - UpdateRequestProposals: nil, - DeleteRequestProposals: nil, +func (suite *KeeperTestSuite) TestValidateUpdatePublicPlanProposal() { + // create a ratio public plan + addRequests := []*types.AddRequestProposal{ + types.NewAddRequestProposal( + "testPlan", + suite.addrs[0].String(), + suite.addrs[0].String(), + sdk.NewDecCoins( + sdk.NewDecCoinFromDec(denom1, sdk.NewDecWithPrec(3, 1)), // 30% + sdk.NewDecCoinFromDec(denom2, sdk.NewDecWithPrec(7, 1)), // 70% + ), + types.ParseTime("2021-08-01T00:00:00Z"), + types.ParseTime("2021-08-30T00:00:00Z"), + nil, + sdk.NewDecWithPrec(10, 2), // 10% + ), } - err := proposal.ValidateBasic() - suite.Require().NoError(err) - - err = keeper.HandlePublicPlanProposal(suite.ctx, suite.keeper, proposal) + err := keeper.HandlePublicPlanProposal( + suite.ctx, + suite.keeper, + types.NewPublicPlanProposal("testTitle", "testDescription", addRequests, nil, nil), + ) suite.Require().NoError(err) - _, found := suite.keeper.GetPlan(suite.ctx, uint64(1)) + plan, found := suite.keeper.GetPlan(suite.ctx, uint64(1)) suite.Require().Equal(true, found) - // case1 - startTime := types.ParseTime("2021-08-06T00:00:00Z") - endTime := types.ParseTime("2021-08-13T00:00:00Z") - - req := &types.UpdateRequestProposal{ - PlanId: uint64(1), - Name: name, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: coinWeights, - StartTime: &startTime, - EndTime: &endTime, - EpochAmount: sdk.NewCoins(sdk.NewInt64Coin("uatom", 100_000_000)), - EpochRatio: sdk.ZeroDec(), - } - case1 := []*types.UpdateRequestProposal{req} - - // case2 - req = &types.UpdateRequestProposal{ - PlanId: uint64(0), - Name: name, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: coinWeights, - StartTime: &startTime, - EndTime: &endTime, - EpochAmount: sdk.NewCoins(sdk.NewInt64Coin("uatom", 100_000_000)), - EpochRatio: sdk.ZeroDec(), - } - case2 := []*types.UpdateRequestProposal{req} - - // case3 - req = &types.UpdateRequestProposal{ - PlanId: uint64(1), - Name: `OVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERMOVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERM - OVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERMOVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERM - OVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERMOVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERM - OVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERMOVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERM`, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: coinWeights, - StartTime: &startTime, - EndTime: &endTime, - EpochAmount: sdk.NewCoins(sdk.NewInt64Coin("uatom", 100_000_000)), - EpochRatio: sdk.ZeroDec(), - } - case3 := []*types.UpdateRequestProposal{req} - - // case4 - req = &types.UpdateRequestProposal{ - PlanId: uint64(1), - Name: name, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: sdk.NewDecCoins(), - StartTime: &startTime, - EndTime: &endTime, - EpochAmount: sdk.NewCoins(sdk.NewInt64Coin("uatom", 0)), - EpochRatio: sdk.ZeroDec(), - } - case4 := []*types.UpdateRequestProposal{req} - - // case5 - req = &types.UpdateRequestProposal{ - PlanId: uint64(1), - Name: name, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: sdk.NewDecCoins( - sdk.DecCoin{ - Denom: "poolD35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A23A4", - Amount: sdk.MustNewDecFromStr("0.1"), - }, - ), - StartTime: &startTime, - EndTime: &endTime, - EpochAmount: sdk.NewCoins(sdk.NewInt64Coin("uatom", 0)), - EpochRatio: sdk.ZeroDec(), - } - case5 := []*types.UpdateRequestProposal{req} - - // case6 - req = &types.UpdateRequestProposal{ - PlanId: uint64(1), - Name: name, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: coinWeights, - StartTime: &endTime, - EndTime: &startTime, - EpochAmount: sdk.NewCoins(sdk.NewInt64Coin("uatom", 0)), - EpochRatio: sdk.ZeroDec(), - } - case6 := []*types.UpdateRequestProposal{req} - - // case7 - req = &types.UpdateRequestProposal{ - PlanId: uint64(1), - Name: name, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: coinWeights, - StartTime: &startTime, - EndTime: &endTime, - EpochAmount: sdk.NewCoins(sdk.NewInt64Coin("uatom", 1)), - EpochRatio: sdk.NewDec(1), - } - case7 := []*types.UpdateRequestProposal{req} - - // case8 - req = &types.UpdateRequestProposal{ - PlanId: uint64(1), - Name: name, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: coinWeights, - StartTime: &startTime, - EndTime: &endTime, - EpochAmount: sdk.NewCoins(), - EpochRatio: sdk.ZeroDec(), - } - case8 := []*types.UpdateRequestProposal{req} - for _, tc := range []struct { name string updateRequest []*types.UpdateRequestProposal expectedErr error }{ { - "happy case", - case1, + "happy case #1 - decrease epoch ratio to 5%", + []*types.UpdateRequestProposal{types.NewUpdateRequestProposal( + plan.GetId(), + plan.GetName(), + plan.GetFarmingPoolAddress().String(), + plan.GetTerminationAddress().String(), + plan.GetStakingCoinWeights(), + plan.GetStartTime(), + plan.GetEndTime(), + nil, + sdk.NewDecWithPrec(5, 2), + )}, nil, }, { @@ -379,46 +221,121 @@ func (suite *KeeperTestSuite) TestUpdatePublicPlanProposal() { nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "proposal request must not be empty"), }, - { - "request case #2", - []*types.UpdateRequestProposal{}, - sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "proposal request must not be empty"), - }, { "plan id case #1", - case2, + []*types.UpdateRequestProposal{types.NewUpdateRequestProposal( + uint64(0), + plan.GetName(), + plan.GetFarmingPoolAddress().String(), + plan.GetTerminationAddress().String(), + plan.GetStakingCoinWeights(), + plan.GetStartTime(), + plan.GetEndTime(), + nil, + plan.(*types.RatioPlan).EpochRatio, + )}, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid plan id: %d", uint64(0)), }, { "name case #1", - case3, + []*types.UpdateRequestProposal{types.NewUpdateRequestProposal( + plan.GetId(), + `OVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERMOVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERM + OVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERMOVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERM + OVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERMOVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERM + OVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERMOVERMAXLENGTHOVERMAXLENGTHOVERMAXLENGTHOVERM`, // max length of name + plan.GetFarmingPoolAddress().String(), + plan.GetTerminationAddress().String(), + plan.GetStakingCoinWeights(), + plan.GetStartTime(), + plan.GetEndTime(), + nil, + plan.(*types.RatioPlan).EpochRatio, + )}, sdkerrors.Wrapf(types.ErrInvalidPlanNameLength, "plan name cannot be longer than max length of %d", types.MaxNameLength), }, { "staking coin weights case #1", - case4, + []*types.UpdateRequestProposal{types.NewUpdateRequestProposal( + plan.GetId(), + plan.GetName(), + plan.GetFarmingPoolAddress().String(), + plan.GetTerminationAddress().String(), + sdk.NewDecCoins(), + plan.GetStartTime(), + plan.GetEndTime(), + nil, + plan.(*types.RatioPlan).EpochRatio, + )}, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "staking coin weights must not be empty"), }, { "staking coin weights case #2", - case5, + []*types.UpdateRequestProposal{types.NewUpdateRequestProposal( + plan.GetId(), + plan.GetName(), + plan.GetFarmingPoolAddress().String(), + plan.GetTerminationAddress().String(), + sdk.NewDecCoins( + sdk.DecCoin{ + Denom: "poolD35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A23A4", + Amount: sdk.MustNewDecFromStr("0.1"), + }, + ), + plan.GetStartTime(), + plan.GetEndTime(), + nil, + plan.(*types.RatioPlan).EpochRatio, + )}, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "total weight must be 1"), }, { "start time & end time case #1", - case6, + []*types.UpdateRequestProposal{types.NewUpdateRequestProposal( + plan.GetId(), + plan.GetName(), + plan.GetFarmingPoolAddress().String(), + plan.GetTerminationAddress().String(), + plan.GetStakingCoinWeights(), + types.ParseTime("2021-08-13T00:00:00Z"), + types.ParseTime("2021-08-06T00:00:00Z"), + nil, + plan.(*types.RatioPlan).EpochRatio, + )}, sdkerrors.Wrapf(types.ErrInvalidPlanEndTime, "end time %s must be greater than start time %s", types.ParseTime("2021-08-06T00:00:00Z"), types.ParseTime("2021-08-13T00:00:00Z")), }, { "epoch amount & epoch ratio case #1", - case7, + []*types.UpdateRequestProposal{ + types.NewUpdateRequestProposal( + plan.GetId(), + plan.GetName(), + plan.GetFarmingPoolAddress().String(), + plan.GetTerminationAddress().String(), + plan.GetStakingCoinWeights(), + plan.GetStartTime(), + plan.GetEndTime(), + sdk.NewCoins(sdk.NewInt64Coin("stake", 100_000)), + plan.(*types.RatioPlan).EpochRatio, + )}, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "either epoch amount or epoch ratio should be provided"), }, { "epoch amount & epoch ratio case #2", - case8, + []*types.UpdateRequestProposal{ + types.NewUpdateRequestProposal( + plan.GetId(), + plan.GetName(), + plan.GetFarmingPoolAddress().String(), + plan.GetTerminationAddress().String(), + plan.GetStakingCoinWeights(), + plan.GetStartTime(), + plan.GetEndTime(), + sdk.NewCoins(sdk.NewInt64Coin("stake", 0)), + sdk.ZeroDec(), + )}, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "either epoch amount or epoch ratio must not be zero"), }, } { @@ -436,7 +353,7 @@ func (suite *KeeperTestSuite) TestUpdatePublicPlanProposal() { err := keeper.HandlePublicPlanProposal(suite.ctx, suite.keeper, proposal) suite.Require().NoError(err) - _, found := suite.keeper.GetPlan(suite.ctx, uint64(1)) + _, found := suite.keeper.GetPlan(suite.ctx, tc.updateRequest[0].GetPlanId()) suite.Require().Equal(true, found) } else { suite.EqualError(err, tc.expectedErr.Error()) @@ -445,54 +362,124 @@ func (suite *KeeperTestSuite) TestUpdatePublicPlanProposal() { } } -func (suite *KeeperTestSuite) TestDeletePublicPlanProposal() { - addrs := app.AddTestAddrs(suite.app, suite.ctx, 2, sdk.NewInt(100_000_000)) - farmerAddr := addrs[0] - name := "test" - terminationAddr := sdk.AccAddress("terminationAddr") - coinWeights := sdk.NewDecCoins( - sdk.DecCoin{ - Denom: "poolD35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A23A4", - Amount: sdk.MustNewDecFromStr("1.0"), - }, +func (suite *KeeperTestSuite) TestValidateDeletePublicPlanProposal() { + // create a ratio public plan + addRequests := []*types.AddRequestProposal{types.NewAddRequestProposal( + "testPlan", + suite.addrs[0].String(), + suite.addrs[0].String(), + sdk.NewDecCoins( + sdk.NewDecCoinFromDec(denom1, sdk.NewDecWithPrec(3, 1)), // 30% + sdk.NewDecCoinFromDec(denom2, sdk.NewDecWithPrec(7, 1)), // 70% + ), + types.ParseTime("2021-08-01T00:00:00Z"), + types.ParseTime("2021-08-30T00:00:00Z"), + nil, + sdk.NewDecWithPrec(10, 2), // 10% + )} + + err := keeper.HandlePublicPlanProposal( + suite.ctx, + suite.keeper, + types.NewPublicPlanProposal("testTitle", "testDescription", addRequests, nil, nil), + ) + suite.Require().NoError(err) + + // should exist + _, found := suite.keeper.GetPlan(suite.ctx, uint64(1)) + suite.Require().Equal(true, found) + + // delete the proposal + deleteRequests := []*types.DeleteRequestProposal{types.NewDeleteRequestProposal(uint64(1))} + + err = keeper.HandlePublicPlanProposal( + suite.ctx, + suite.keeper, + types.NewPublicPlanProposal("testTitle", "testDescription", nil, nil, deleteRequests), ) + suite.Require().NoError(err) - // add request proposal - addReq := &types.AddRequestProposal{ - Name: name, - FarmingPoolAddress: farmerAddr.String(), - TerminationAddress: terminationAddr.String(), - StakingCoinWeights: coinWeights, - StartTime: types.ParseTime("2021-08-06T00:00:00Z"), - EndTime: types.ParseTime("2021-08-13T00:00:00Z"), - EpochAmount: sdk.NewCoins(sdk.NewInt64Coin("uatom", 100_000_000)), - EpochRatio: sdk.ZeroDec(), - } - addRequests := []*types.AddRequestProposal{addReq} + // shouldn't exist + _, found = suite.keeper.GetPlan(suite.ctx, uint64(1)) + suite.Require().Equal(false, found) +} - proposal := &types.PublicPlanProposal{ - Title: "testTitle", - Description: "testDescription", - AddRequestProposals: addRequests, - UpdateRequestProposals: nil, - DeleteRequestProposals: nil, +func (suite *KeeperTestSuite) TestUpdatePlanType() { + // create a ratio public plan + addRequests := []*types.AddRequestProposal{ + types.NewAddRequestProposal( + "testPlan", + suite.addrs[0].String(), + suite.addrs[0].String(), + sdk.NewDecCoins( + sdk.NewDecCoinFromDec(denom1, sdk.NewDecWithPrec(3, 1)), // 30% + sdk.NewDecCoinFromDec(denom2, sdk.NewDecWithPrec(7, 1)), // 70% + ), + types.ParseTime("2021-08-01T00:00:00Z"), + types.ParseTime("2021-08-30T00:00:00Z"), + nil, + sdk.NewDecWithPrec(10, 2), // 10% + ), } - err := proposal.ValidateBasic() + err := keeper.HandlePublicPlanProposal( + suite.ctx, + suite.keeper, + types.NewPublicPlanProposal("testTitle", "testDescription", addRequests, nil, nil), + ) suite.Require().NoError(err) - err = keeper.HandlePublicPlanProposal(suite.ctx, suite.keeper, proposal) + plan, found := suite.keeper.GetPlan(suite.ctx, uint64(1)) + suite.Require().Equal(true, found) + suite.Require().Equal(plan.(*types.RatioPlan).EpochRatio, sdk.NewDecWithPrec(10, 2)) + + // update the ratio plan to fixed amount plan type + updateRequests := []*types.UpdateRequestProposal{ + types.NewUpdateRequestProposal( + plan.GetId(), + plan.GetName(), + plan.GetFarmingPoolAddress().String(), + plan.GetTerminationAddress().String(), + plan.GetStakingCoinWeights(), + plan.GetStartTime(), + plan.GetEndTime(), + sdk.NewCoins(sdk.NewInt64Coin("stake", 100_000)), + sdk.ZeroDec(), + )} + + err = keeper.HandlePublicPlanProposal( + suite.ctx, + suite.keeper, + types.NewPublicPlanProposal("testTitle", "testDescription", nil, updateRequests, nil), + ) suite.Require().NoError(err) - _, found := suite.keeper.GetPlan(suite.ctx, uint64(1)) + plan, found = suite.keeper.GetPlan(suite.ctx, uint64(1)) suite.Require().Equal(true, found) + suite.Require().Equal(plan.(*types.FixedAmountPlan).EpochAmount, sdk.NewCoins(sdk.NewInt64Coin("stake", 100_000))) + + // update the fixed amount plan back to ratio plan + updateRequests = []*types.UpdateRequestProposal{ + types.NewUpdateRequestProposal( + plan.GetId(), + plan.GetName(), + plan.GetFarmingPoolAddress().String(), + plan.GetTerminationAddress().String(), + plan.GetStakingCoinWeights(), + plan.GetStartTime(), + plan.GetEndTime(), + nil, + sdk.NewDecWithPrec(7, 2), // 7% + )} - // delete the proposal - req := &types.DeleteRequestProposal{ - PlanId: uint64(1), - } - proposals := []*types.DeleteRequestProposal{req} - - err = suite.keeper.DeletePublicPlanProposal(suite.ctx, proposals) + err = keeper.HandlePublicPlanProposal( + suite.ctx, + suite.keeper, + types.NewPublicPlanProposal("testTitle", "testDescription", nil, updateRequests, nil), + ) suite.Require().NoError(err) + + plan, found = suite.keeper.GetPlan(suite.ctx, uint64(1)) + suite.Require().Equal(true, found) + suite.Require().Equal(plan.(*types.RatioPlan).EpochRatio, sdk.NewDecWithPrec(7, 2)) } diff --git a/x/farming/types/plan.go b/x/farming/types/plan.go index 50647b50..b9aa2916 100644 --- a/x/farming/types/plan.go +++ b/x/farming/types/plan.go @@ -144,6 +144,22 @@ func (plan *BasePlan) SetDistributedCoins(distributedCoins sdk.Coins) error { return nil } +func (plan BasePlan) GetBasePlan() *BasePlan { + return &BasePlan{ + Id: plan.GetId(), + Name: plan.GetName(), + Type: plan.GetType(), + FarmingPoolAddress: plan.GetFarmingPoolAddress().String(), + TerminationAddress: plan.GetTerminationAddress().String(), + StakingCoinWeights: plan.GetStakingCoinWeights(), + StartTime: plan.GetStartTime(), + EndTime: plan.GetEndTime(), + Terminated: plan.GetTerminated(), + LastDistributionTime: plan.GetLastDistributionTime(), + DistributedCoins: plan.GetDistributedCoins(), + } +} + // Validate checks for errors on the Plan fields func (plan BasePlan) Validate() error { if plan.Type != PlanTypePrivate && plan.Type != PlanTypePublic { @@ -244,6 +260,8 @@ type PlanI interface { GetDistributedCoins() sdk.Coins SetDistributedCoins(sdk.Coins) error + GetBasePlan() *BasePlan + String() string Validate() error diff --git a/x/farming/types/proposal.go b/x/farming/types/proposal.go index 63f4fa36..d88637fc 100644 --- a/x/farming/types/proposal.go +++ b/x/farming/types/proposal.go @@ -2,6 +2,7 @@ package types import ( "fmt" + time "time" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -20,6 +21,7 @@ func init() { gov.RegisterProposalTypeCodec(&PublicPlanProposal{}, "cosmos-sdk/PublicPlanProposal") } +// NewPublicPlanProposal creates a new PublicPlanProposal object. func NewPublicPlanProposal( title string, description string, @@ -83,6 +85,29 @@ func (p PublicPlanProposal) String() string { `, p.Title, p.Description, p.AddRequestProposals, p.UpdateRequestProposals, p.DeleteRequestProposals) } +// NewAddRequestProposal creates a new AddRequestProposal object +func NewAddRequestProposal( + name string, + farmingPoolAddr string, + terminationAddr string, + stakingCoinWeights sdk.DecCoins, + startTime time.Time, + endTime time.Time, + epochAmount sdk.Coins, + epochRatio sdk.Dec, +) *AddRequestProposal { + return &AddRequestProposal{ + Name: name, + FarmingPoolAddress: farmingPoolAddr, + TerminationAddress: terminationAddr, + StakingCoinWeights: stakingCoinWeights, + StartTime: startTime, + EndTime: endTime, + EpochAmount: epochAmount, + EpochRatio: epochRatio, + } +} + func (p *AddRequestProposal) Validate() error { if len(p.Name) > MaxNameLength { return sdkerrors.Wrapf(ErrInvalidPlanNameLength, "plan name cannot be longer than max length of %d", MaxNameLength) @@ -114,6 +139,31 @@ func (p *AddRequestProposal) Validate() error { return nil } +// NewUpdateRequestProposal creates a new UpdateRequestProposal object. +func NewUpdateRequestProposal( + id uint64, + name string, + farmingPoolAddr string, + terminationAddr string, + stakingCoinWeights sdk.DecCoins, + startTime time.Time, + endTime time.Time, + epochAmount sdk.Coins, + epochRatio sdk.Dec, +) *UpdateRequestProposal { + return &UpdateRequestProposal{ + PlanId: id, + Name: name, + FarmingPoolAddress: farmingPoolAddr, + TerminationAddress: terminationAddr, + StakingCoinWeights: stakingCoinWeights, + StartTime: &startTime, + EndTime: &endTime, + EpochAmount: epochAmount, + EpochRatio: epochRatio, + } +} + func (p *UpdateRequestProposal) Validate() error { if p.PlanId == 0 { return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid plan id: %d", p.PlanId) @@ -148,6 +198,13 @@ func (p *UpdateRequestProposal) Validate() error { return nil } +// NewDeleteRequestProposal creates a new DeleteRequestProposal object. +func NewDeleteRequestProposal(id uint64) *DeleteRequestProposal { + return &DeleteRequestProposal{ + PlanId: id, + } +} + func (p *DeleteRequestProposal) Validate() error { if p.PlanId == 0 { return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid plan id: %d", p.PlanId)