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: backport basket proto updates #772

Merged
merged 17 commits into from
Feb 15, 2022
Merged
Show file tree
Hide file tree
Changes from 16 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
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ require (
github.com/prometheus/procfs v0.6.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
github.com/regen-network/cosmos-proto v0.3.1 // indirect
github.com/regen-network/regen-ledger/api v0.3.0 // indirect
github.com/regen-network/regen-ledger/api v0.4.0 // indirect
github.com/regen-network/regen-ledger/orm v1.0.0-beta1 // indirect
github.com/rs/cors v1.7.0 // indirect
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -916,8 +916,8 @@ github.com/regen-network/cosmos-sdk v0.44.2-regen-1/go.mod h1:fwQJdw+aECatpTvQTo
github.com/regen-network/protobuf v1.3.2-alpha.regen.4 h1:c9jEnU+xm6vqyrQe3M94UFWqiXxRIKKnqBOh2EACmBE=
github.com/regen-network/protobuf v1.3.2-alpha.regen.4/go.mod h1:/J8/bR1T/NXyIdQDLUaq15LjNE83nRzkyrLAMcPewig=
github.com/regen-network/regen-ledger/api v0.2.0/go.mod h1:kWly2pK0u3fDfyoYYilpEoTEg61pCjV/f5XSY0KzJQY=
github.com/regen-network/regen-ledger/api v0.3.0 h1:gam9DzeklPi9OySQoS2RIwzQhUBwd5UDK8joe0YqHA4=
github.com/regen-network/regen-ledger/api v0.3.0/go.mod h1:kWly2pK0u3fDfyoYYilpEoTEg61pCjV/f5XSY0KzJQY=
github.com/regen-network/regen-ledger/api v0.4.0 h1:klcMljLCHU3MpkRyjrEXL6KKsDGeqFBt2aFUwFdpEH8=
github.com/regen-network/regen-ledger/api v0.4.0/go.mod h1:kWly2pK0u3fDfyoYYilpEoTEg61pCjV/f5XSY0KzJQY=
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
Expand Down
52 changes: 52 additions & 0 deletions proto/regen/ecocredit/basket/v1/events.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
syntax = "proto3";

package regen.ecocredit.basket.v1;

import "regen/ecocredit/basket/v1/types.proto";

option go_package = "github.com/regen-network/regen-ledger/x/ecocredit/basket";

// EventCreate is an event emitted when a basket is created.
message EventCreate {

// basket_denom is the basket bank denom.
string basket_denom = 1;

// curator is the address of the basket curator who is able to change certain
// basket settings.
string curator = 2;
}

// EventPut is an event emitted when credits are put into a basket in return
// for basket tokens.
message EventPut {

// owner is the owner of the credits put into the basket.
string owner = 1;

// basket_denom is the basket bank denom that the credits were added to.
string basket_denom = 2;

// credits are the credits that were added to the basket.
repeated BasketCredit credits = 3;

// amount is the integer number of basket tokens converted from credits.
string amount = 4;
}

// EventTake is an event emitted when credits are taken from a basket starting
// from the oldest credits first.
message EventTake {

// owner is the owner of the credits taken from the basket.
string owner = 1;

// basket_denom is the basket bank denom that credits were taken from.
string basket_denom = 2;

// credits are the credits that were taken from the basket.
repeated BasketCredit credits = 3;

// amount is the integer number of basket tokens converted to credits.
string amount = 4;
}
97 changes: 97 additions & 0 deletions proto/regen/ecocredit/basket/v1/query.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
syntax = "proto3";

package regen.ecocredit.basket.v1;

import "google/api/annotations.proto";
import "regen/ecocredit/basket/v1/state.proto";
import "cosmos/base/query/v1beta1/pagination.proto";

option go_package = "github.com/regen-network/regen-ledger/x/ecocredit/basket";

// Msg is the regen.ecocredit.basket.v1beta1 Query service.
service Query {

// Basket queries one basket by denom.
rpc Basket(QueryBasketRequest) returns (QueryBasketResponse) {
option (google.api.http).get =
"/regen/ecocredit/basket/v1/baskets/{basket_denom}";
}

// Baskets lists all baskets in the ecocredit module.
rpc Baskets(QueryBasketsRequest) returns (QueryBasketsResponse) {
option (google.api.http).get =
"/regen/ecocredit/basket/v1/baskets";
}

// BasketBalances lists the balance of each credit batch in the basket.
rpc BasketBalances(QueryBasketBalancesRequest) returns (QueryBasketBalancesResponse) {
option (google.api.http).get =
"/regen/ecocredit/basket/v1/baskets/{basket_denom}/balances";
}

// BasketBalance queries the balance of a specific credit batch in the basket.
rpc BasketBalance(QueryBasketBalanceRequest) returns (QueryBasketBalanceResponse) {
option (google.api.http).get =
"/regen/ecocredit/basket/v1/baskets/{basket_denom}/balances/{batch_denom}";
}
}

// QueryBasketRequest is the Query/Basket request type.
message QueryBasketRequest {
// basket_denom represents the denom of the basket to query.
string basket_denom = 1;
}

// QueryBasketResponse is the Query/Basket response type.
message QueryBasketResponse {
// basket is the queried basket.
Basket basket = 1;
}

// QueryBasketsRequest is the Query/Baskets request type.
message QueryBasketsRequest {
// pagination defines an optional pagination for the request.
cosmos.base.query.v1beta1.PageRequest pagination = 1;
}

// QueryBasketsResponse is the Query/Baskets response type.
message QueryBasketsResponse {
// baskets are the fetched baskets.
repeated Basket baskets = 1;

// pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

// QueryBasketBalancesRequest is the Query/BasketBalances request type.
message QueryBasketBalancesRequest {
// basket_denom is the denom of the basket.
string basket_denom = 1;

// pagination defines an optional pagination for the request.
cosmos.base.query.v1beta1.PageRequest pagination = 2;
}

// QueryBasketBalancesResponse is the Query/BasketBalances response type.
message QueryBasketBalancesResponse {
// balances is a list of credit balances in the basket.
repeated BasketBalance balances = 1;

// pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

// QueryBasketBalanceRequest is the Query/BasketBalance request type.
message QueryBasketBalanceRequest {
// basket_denom is the denom of the basket.
string basket_denom = 1;

// batch_denom is the denom of the credit batch.
string batch_denom = 2;
}

// QueryBasketBalanceResponse is the Query/BasketBalance response type.
message QueryBasketBalanceResponse {
// balance is the amount of the queried credit batch in the basket.
string balance = 1;
}
42 changes: 28 additions & 14 deletions proto/regen/ecocredit/basket/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -28,45 +28,59 @@ message MsgCreate {
// basket settings.
string curator = 1;

// name will be used to create a bank denom for this basket token.
// name will be used to together with prefix to create a bank denom for this
// basket token. It can be between 3-8 alphanumeric characters, with the
// first character being alphabetic. The bank denom will be
// `eco/<prefix><name>` and its display name will be `eco/<name>`.
string name = 2;

// display_name will be used to create a bank Metadata display name for this
// basket token.
string display_name = 3;
// prefix is a single alphabetic character that denotes
// the denom prefix and indicates in some way what relationship is between
// the denom and display denom. Standard conventions are that m indicates
// milli (10^3), u indicates micro (10^6), n indicates nano (10^9).
// Typical usage of prefix should correspond with the `exponent` field,
// which is used to convert decimal ecocredit amounts to integral
// basket tokens.
string prefix = 3;

// description is a human-readable description of the basket denom that should
// be at most 256 characters.
string description = 4;


// exponent is the exponent that will be used for converting credits to basket
// tokens and for bank denom metadata. It also limits the precision of
// credit amounts when putting credits into a basket. An exponent of 6 will
// mean that 10^6 units of a basket token will be issued for 1.0 credits and
// that this should be displayed as one unit in user interfaces. It also means
// mean that 10^6 units of a basket token will be issued for 1.0 credits and that
// this should be displayed as one unit in user interfaces. It also means
// that the maximum precision of credit amounts is 6 decimal places so that
// the need to round is eliminated. The exponent must be >= the precision of
// the credit type at the time the basket is created.
uint32 exponent = 4;
uint32 exponent = 5;

// disable_auto_retire allows auto-retirement to be disabled.
// The credits will be auto-retired if disable_auto_retire is
// false unless the credits were previously put into the basket by the
// address picking them from the basket, in which case they will remain
// tradable.
bool disable_auto_retire = 5;
bool disable_auto_retire = 6;

// credit_type_name filters against credits from this credit type name.
string credit_type_name = 6;
// credit_type_abbrev is the abbreviation of the credit type this basket is
// able to hold.
string credit_type_abbrev = 7;

// allowed_classes are the credit classes allowed to be put in the basket
repeated string allowed_classes = 7;
repeated string allowed_classes = 8;

// date_criteria is the date criteria for batches admitted to the basket.
DateCriteria date_criteria = 8;
DateCriteria date_criteria = 9;

// fee is the fee that the curator will pay to create the basket. It must be
// >= the required Params.basket_creation_fee. We include the fee explicitly
// here so that the curator explicitly acknowledges paying this fee and
// is not surprised to learn that the paid a big fee and didn't know
// beforehand.
repeated cosmos.base.v1beta1.Coin fee = 9 [
repeated cosmos.base.v1beta1.Coin fee = 10 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
Expand Down Expand Up @@ -108,7 +122,7 @@ message MsgTake {
// owner is the owner of the basket tokens.
string owner = 1;

// basket_denom is the basket denom to take credits from.
// basket_denom is the basket bank denom to take credits from.
string basket_denom = 2;

// amount is the integer number of basket tokens to convert into credits.
Expand Down
5 changes: 2 additions & 3 deletions proto/regen/ecocredit/basket/v1/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ message DateCriteria {
// start_date_window is a duration of time measured into the past which sets
// a cutoff for batch start dates when adding new credits to the basket.
// Based on the current block timestamp, credits whose start date is before
// `block_timestamp - batch_date_window` will not be allowed into the
// basket.
// `block_timestamp - batch_date_window` will not be allowed into the basket.
google.protobuf.Duration start_date_window = 2;
}
}
}
60 changes: 39 additions & 21 deletions x/ecocredit/basket/msg_create.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package basket

import (
"fmt"
"regexp"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
Expand All @@ -12,39 +15,37 @@ var (
_ legacytx.LegacyMsg = &MsgCreate{}
)

const nameMaxLen = 32
const displayNameMinLen = 3
const displayNameMaxLen = 32
const exponentMax = 32
const creditNameMaxLen = 32
const nameMinLen = 3
const nameMaxLen = 8
const descrMaxLen = 200
robert-zaremba marked this conversation as resolved.
Show resolved Hide resolved
const creditTypeAbbrMaxLen = 3

var errBadReq = sdkerrors.ErrInvalidRequest

// first character must be alphabetic, the rest can be alphanumeric. We reduce length constraints by one to account for
// the first character being forced to alphabetic.
var reName = regexp.MustCompile(fmt.Sprintf("^[[:alpha:]][[:alnum:]]{%d,%d}$", nameMinLen-1, nameMaxLen-1))

// ValidateBasic does a stateless sanity check on the provided data.
func (m MsgCreate) ValidateBasic() error {
if _, err := sdk.AccAddressFromBech32(m.Curator); err != nil {
return sdkerrors.ErrInvalidAddress.Wrap("malformed curator address " + err.Error())
}
// TODO: add proper validation once we will have proper requirements.
// https://github.com/regen-network/regen-ledger/issues/732
if m.Name == "" || len(m.Name) > nameMaxLen {
return errBadReq.Wrapf("name must not be empty and must not be longer than %d characters long", nameMaxLen)
}
if len(m.DisplayName) < displayNameMinLen || len(m.DisplayName) > displayNameMaxLen {
return errBadReq.Wrapf("display_name must be between %d and %d characters long", displayNameMinLen, displayNameMaxLen)
if !reName.MatchString(m.Name) {
return errBadReq.Wrapf("name must start with an alphabetic character, and be between %d and %d alphanumeric characters long", nameMinLen, nameMaxLen)
}
if m.Exponent > exponentMax {
return errBadReq.Wrapf("exponent must not be bigger than %d", exponentMax)
}
if m.CreditTypeName == "" {
return errBadReq.Wrap("credit_type_name must be defined")
if _, err := ecocredit.ExponentToPrefix(m.Exponent); err != nil {
return err
}
if len(m.CreditTypeName) > creditNameMaxLen {
return errBadReq.Wrapf("credit_type_name must not be longer than %d", creditNameMaxLen)
if err := ecocredit.ValidateCreditTypeAbbreviation(m.CreditTypeAbbrev); err != nil {
return err
}
if err := validateDateCriteria(m.DateCriteria); err != nil {
return err
}
if len(m.Description) > descrMaxLen {
return errBadReq.Wrapf("description can't be longer than %d characters", descrMaxLen)
}
if len(m.AllowedClasses) == 0 {
return errBadReq.Wrap("allowed_classes is required")
}
Expand All @@ -56,9 +57,9 @@ func (m MsgCreate) ValidateBasic() error {
return m.Fee.Validate()
}

// ValidateCreateFee additional validation with access to the state data.
// ValidateMsgCreate additional validation with access to the state data.
// minFee must be sorted.
func ValidateCreateFee(m *MsgCreate, minFee sdk.Coins) error {
func ValidateMsgCreate(m *MsgCreate, minFee sdk.Coins) error {
if !m.Fee.IsAllGTE(minFee) {
return sdkerrors.ErrInsufficientFee.Wrapf("minimum fee %s, got %s", minFee, m.Fee)
}
Expand Down Expand Up @@ -100,3 +101,20 @@ func validateDateCriteria(d *DateCriteria) error {
}
return nil
}

// MsgCreateDenom formats denom and display denom:
// * denom: eco.<m.Exponent><m.CreditTypeAbbrev>.<m.Name>
// * display denom: eco.<m.Exponent><m.CreditTypeAbbrev>.<m.Name>
// Returns error if MsgCrete.Exponent is not supported
func MsgCreateDenom(m *MsgCreate) (string, string, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reminder to refrain from adding interface methods to proto types 😉

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a method - it's a function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah you're right... read it wrong 👍

const basketDenomPrefix = "eco."
denomPrefix, err := ecocredit.ExponentToPrefix(m.Exponent)
if err != nil {
return "", "", err
}

denomTail := m.CreditTypeAbbrev + "." + m.Name
displayDenomName := basketDenomPrefix + denomTail //
denom := basketDenomPrefix + denomPrefix + denomTail // eco.<credit-class>.<name>
return denom, displayDenomName, nil
}
Loading