Commit e5ee4fd5 authored by mconcat's avatar mconcat Committed by ValarDragon
Browse files

Add x/incentives cli docs (#332)


* add README

* modify create gauge tx

* modify example

* modify examples

* fix cli

* Apply suggestions from code review

Co-authored-by: default avatarDev Ojha <ValarDragon@users.noreply.github.com>

* rm epoch duration

* Apply suggestions from code review

* apply review

Co-authored-by: default avatarDev Ojha <ValarDragon@users.noreply.github.com>
parent a6c29cb8
Showing with 117 additions and 45 deletions
+117 -45
# Incentives Module
The incentives module provides users the functionality to create gauges, which
distributes reward tokens to the qualified lockups. Each lockup has designated
lockup duration that indicates how much time that the user have to wait until
the token release after they request to unlock the tokens.
## Creating Gauges
To initialize a gauge, the creator should decide the following parameters:
- Distribution condition: denom to incentivize and minimum lockup duration.
- Rewards: tokens to be distributed to the lockup owners.
- Start time: time when the distribution will begin.
- Total epochs: number of epochs to distribute over. (Osmosis epochs are 1 day each, ending at 5PM UTC everyday)
Making transaction is done in the following format:
```bash
osmosisd tx incentives create-gauge [denom] [reward]
--duration [minimum duration for lockups, nullable]
--start-time [start time in RFC3339 or unix format, nullable]
# one of --perpetual or --epochs
--epochs [total distribution epoch]
--perpetual
```
### Examples
#### Case 1
```
I want to make incentives for LP tokens of pool X, namely LPToken, that have been locked up for at least 1 day.
I want to reward 1000 Mytoken to this pool over 2 days (2 epochs). (500 rewarded on each day)
I want the rewards to start disbursing at 2022 Jan 01.
MsgCreateGauge:
- Distribution condition: denom "LPToken", 1 day.
- Rewards: 1000 MyToken
- Start time: 1624000706 (in unix time format)
- Total epochs: 2 (days)
```bash
osmosisd tx incentives create-gauge LPToken 1000MyToken \
--duration 24h \
--start-time 2022-01-01T00:00:00Z \
--epochs 2
```
#### Case 2
I want to make incentives for atoms that have been locked up for at least 1 month.
I want to reward 1000 MyToken to atom holders perpetually. (Meaning I add more tokens to this gauge myself every epoch)
I want the reward to start disbursing immedietly.
MsgCreateGauge:
- Distribution condition: denom "atom", 720 hours.
- Rewards: 1000 MyTokens
- Start time: empty(immedietly)
- Total epochs: 1 (perpetual)
```bash
osmosisd tx incentives create-gauge atom 1000MyToken
--perpetual \
--duration 168h
```
I want to refill the gauge with 500 MyToken after the distribution.
MsgAddToGauge:
- Gauge ID: (id of the created gauge)
- Rewards: 500 MyTokens
```bash
osmosisd tx incentives add-to-gauge $GAUGE_ID 500MyToken
```
package cli
import (
"time"
flag "github.com/spf13/pflag"
)
// flags for lockup module tx commands
const (
FlagLockQueryType = "lock_query_type"
FlagDenom = "denom"
FlagDuration = "duration"
FlagTimestamp = "timestamp"
FlagOwner = "owner"
FlagLockIds = "lock-ids"
FlagEndEpoch = "end-epoch"
FlagDuration = "duration"
FlagStartTime = "start-time"
FlagEpochs = "epochs"
FlagPerpetual = "perpetual"
FlagTimestamp = "timestamp"
FlagOwner = "owner"
FlagLockIds = "lock-ids"
FlagEndEpoch = "end-epoch"
)
// FlagSetCreateGauge returns flags for creating gauge
func FlagSetCreateGauge() *flag.FlagSet {
fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.String(FlagLockQueryType, "ByDuration", "ByDuration | ByTime")
fs.String(FlagDenom, "stake", "locked denom to be queried")
fs.String(FlagDuration, "168h", "The duration token to be locked, default 1w(168h). Other examples are 1h, 1m, 1s, 0.1s. Maximum unit is hour.")
fs.Int64(FlagTimestamp, 1615917475, "Timestamp to that started tokens lock")
dur, _ := time.ParseDuration("24h")
fs.Duration(FlagDuration, dur, "The duration token to be locked, default 1d(24h). Other examples are 7d(168h), 14d(336h). Maximum unit is hour.")
fs.String(FlagStartTime, "", "Timestamp to begin distribution")
fs.Uint64(FlagEpochs, 0, "Total epochs to distribute tokens")
fs.Bool(FlagPerpetual, false, "Perpetual distribution")
return fs
}
......@@ -36,77 +36,71 @@ func GetTxCmd() *cobra.Command {
// NewCreateGaugeCmd broadcast MsgCreateGauge
func NewCreateGaugeCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create-gauge [coins] [start_time] [num_epochs_paid_over] [flags]",
Use: "create-gauge [lockup_denom] [reward] [flags]",
Short: "create a gauge to distribute rewards to users",
Args: cobra.ExactArgs(3),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
denom := args[0]
txf := tx.NewFactoryCLI(clientCtx, cmd.Flags()).WithTxConfig(clientCtx.TxConfig).WithAccountRetriever(clientCtx.AccountRetriever)
coins, err := sdk.ParseCoinsNormalized(args[0])
coins, err := sdk.ParseCoinsNormalized(args[1])
if err != nil {
return err
}
timeUnix, err := strconv.ParseInt(args[1], 10, 64)
startTime := time.Time{}
timeStr, err := cmd.Flags().GetString(FlagStartTime)
if err != nil {
return err
}
startTime := time.Unix(timeUnix, 0)
numEpochsPaidOver, err := strconv.ParseUint(args[2], 10, 64)
if err != nil {
return err
if timeStr == "" { // empty start time
// do nothing
} else if timeUnix, err := strconv.ParseInt(timeStr, 10, 64); err == nil { // unix time
startTime = time.Unix(timeUnix, 0)
} else if timeRFC, err := time.Parse(time.RFC3339, timeStr); err == nil { // RFC time
startTime = timeRFC
} else { // invalid input
return errors.New("Invalid start time format")
}
queryTypeStr, err := cmd.Flags().GetString(FlagLockQueryType)
if err != nil {
return err
}
queryType, ok := lockuptypes.LockQueryType_value[queryTypeStr]
if !ok {
return errors.New("invalid lock query type, should be one of ByDuration or ByTime.")
}
denom, err := cmd.Flags().GetString(FlagDenom)
epochs, err := cmd.Flags().GetUint64(FlagEpochs)
if err != nil {
return err
}
durationStr, err := cmd.Flags().GetString(FlagDuration)
perpetual, err := cmd.Flags().GetBool(FlagPerpetual)
if err != nil {
return err
}
duration, err := time.ParseDuration(durationStr)
if err != nil {
return err
if perpetual {
epochs = 1
}
timestamp, err := cmd.Flags().GetInt64(FlagTimestamp)
duration, err := cmd.Flags().GetDuration(FlagDuration)
if err != nil {
return err
}
distributeTo := lockuptypes.QueryCondition{
LockQueryType: lockuptypes.LockQueryType(queryType),
LockQueryType: lockuptypes.ByDuration,
Denom: denom,
Duration: duration,
Timestamp: time.Unix(timestamp, 0),
}
// TODO: Confirm this is correct logic
isPerpetual := false
if numEpochsPaidOver == 0 {
isPerpetual = true
Timestamp: time.Unix(0, 0), // XXX check
}
msg := types.NewMsgCreateGauge(
isPerpetual,
epochs == 1,
clientCtx.GetFromAddress(),
distributeTo,
coins,
startTime,
numEpochsPaidOver,
epochs,
)
return tx.GenerateOrBroadcastTxWithFactory(clientCtx, txf, msg)
......
package types
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment