lockup

package
v0.1.0-merlin.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 9, 2023 License: Apache-2.0 Imports: 19 Imported by: 0

README

Lockup

Abstract

Lockup module provides an interface for users to lock tokens (also known as bonding) into the module to get incentives.

After tokens have been added to a specific pool and turned into LP shares through the GAMM module, users can then lock these LP shares with a specific duration in order to begin earing rewards.

To unlock these LP shares, users must trigger the unlock timer and wait for the unlock period that was set initially to be completed. After the unlock period is over, users can turn LP shares back into their respective share of tokens.

This module provides interfaces for other modules to iterate the locks efficiently and grpc query to check the status of locked coins.

Contents

  1. Concept
  2. State
  3. Messages
  4. Events
  5. Keeper
  6. Hooks
  7. Queries
  8. Transactions
  9. Params
  10. Endblocker

Concepts

The purpose of lockup module is to provide the functionality to lock tokens for specific period of time for LP token stakers to get incentives.

To unlock these LP shares, users must trigger the unlock timer and wait for the unlock period that was set initially to be completed. After the unlock period is over, users can turn LP shares back into their respective share of tokens.

This module provides interfaces for other modules to iterate the locks efficiently and grpc query to check the status of locked coins.

There are currently three incentivize lockup periods; 1 day (24h), 1 week (168h), and 2 weeks (336h). When locking tokens in the 2 week period, the liquidity provider is effectively earning rewards for a combination of the 1 day, 1 week, and 2 week bonding periods.

The 2 week period refers to how long it takes to unbond the LP shares. The liquidity provider can keep their LP shares bonded to the 2 week lockup period indefinitely. Unbonding is only required when the liquidity provider desires access to the underlying assets.

If the liquidity provider begins the unbonding process for their 2 week bonded LP shares, they will earn rewards for all three bonding periods during the first day of unbonding.

After the first day passes, they will only receive rewards for the 1 day and 1 week lockup periods. After seven days pass, they will only receive the 1 day rewards until the 2 weeks is complete and their LP shares are unlocked. The below chart is a visual example of what was just explained.




State

Locked coins management

Locked coins are all stored in module account for lockup module which is called LockPool. When user lock coins within lockup module, it's moved from user account to LockPool and a record (PeriodLock struct) is created.

Once the period is over, user can withdraw it at anytime from LockPool. User can withdraw by PeriodLock ID or withdraw all UnlockableCoins at a time.

Period Lock

A PeriodLock is a single unit of lock by period. It's a record of locked coin at a specific time. It stores owner, duration, unlock time and the amount of coins locked.

type PeriodLock struct {
  ID         uint64
  Owner      sdk.AccAddress
  Duration   time.Duration
  UnlockTime time.Time
  Coins      sdk.Coins
}

All locks are stored on the KVStore as value at {KeyPrefixPeriodLock}{ID} key.

Period lock reference queues

To provide time efficient queries, several reference queues are managed by denom, unlock time, and duration. There are two big queues to store the lock references. (a_prefix_key)

  1. Lock references that hasn't started with unlocking yet has prefix of KeyPrefixNotUnlocking.
  2. Lock references that has started unlocking already has prefix of KeyPrefixUnlocking.
  3. Lock references that has withdrawn, it's removed from the store.

Regardless the lock has started unlocking or not, it stores below references. (b_prefix_key)

  1. {KeyPrefixLockDuration}{Duration}
  2. {KeyPrefixAccountLockDuration}{Owner}{Duration}
  3. {KeyPrefixDenomLockDuration}{Denom}{Duration}
  4. {KeyPrefixAccountDenomLockDuration}{Owner}{Denom}{Duration}

If the lock is unlocking, it also stores the below referneces.

  1. {KeyPrefixLockTimestamp}{LockEndTime}
  2. {KeyPrefixAccountLockTimestamp}{Owner}{LockEndTime}
  3. {KeyPrefixDenomLockTimestamp}{Denom}{LockEndTime}
  4. {KeyPrefixAccountDenomLockTimestamp}{Owner}{Denom}{LockEndTime}

For end time keys, they are converted to sortable string by using sdk.FormatTimeBytes function.

Note: Additionally, for locks that hasn't started unlocking yet, it stores accumulation store for efficient rewards distribution mechanism.

For reference management, addLockRefByKey function is used a lot. Here key is the prefix key to be used for iteration. It is combination of two prefix keys.({a_prefix_key}{b_prefix_key})

// addLockRefByKey make a lockID iterable with the prefix `key`
func (k Keeper) addLockRefByKey(ctx sdk.Context, key []byte, lockID uint64) error {
 store := ctx.KVStore(k.storeKey)
 lockIDBz := sdk.Uint64ToBigEndian(lockID)
 endKey := combineKeys(key, lockIDBz)
 if store.Has(endKey) {
  return fmt.Errorf("lock with same ID exist: %d", lockID)
 }
 store.Set(endKey, lockIDBz)
 return nil
}
Synthetic Lockup

Synthetic Lockups are a concept that serve the following roles:

  • Add "restrictions" to an underlying PeriodLock, so that its bond status must be managed by a module rather than a BeginUnlockMessage
  • Allow issuing of a locked, "synthetic" denom type
  • Allow distribution of rewards to locked synthetic denominations.

The first goal can eventually be pushed into a new data structure, as it doesn't really relate to the synthetic component.

This is then used for superfluid staking. (Old docs below):

The goal of synthetic lockup is to support the querying of locks by denom especially for delegated staking. By combining native denom and synthetic suffix, lockup supports querying with synthetic denom with existing denom querying functions.

Synthetic lockup is creating virtual lockup where new denom is combination of original denom and synthetic suffix. At the time of synthetic lockup creation and deletion, accumulation store is also being updated and on querier side, they can query as freely as native lockup.

Note: The staking, distribution, slashing, superfluid module would be refactored to use lockup module and synthetic lockup. The following changes for synthetic lockup on native lockup change could be defined as per use case. For now we assume this change is made on hook receiver side which manages synthetic lockup, e.g. use cases are when user start / pause superfluid staking on a lockup, redelegation event, unbonding event etc.

External modules are managing synthetic locks to use it on their own logic implementation. (e.g. delegated staking and superfluid staking)

A SyntheticLock is a single unit of synthetic lockup. Each synthetic lockup has reference PeriodLock ID, synthetic suffix (Suffix) and synthetic lock's removal time (EndTime).

type SyntheticLock struct {
 LockId  uint64
 Suffix  string
 EndTime time.Time
}

All synthetic locks are stored on the KVStore as value at {KeyPrefixPeriodLock}{LockID}{Suffix} key.

Synthetic lock reference queues

To provide time efficient queries, several reference queues are managed by denom, unlock time, and duration.

  1. {KeyPrefixDenomLockTimestamp}{SyntheticDenom}{LockEndTime}
  2. {KeyPrefixDenomLockDuration}{SyntheticDenom}{Duration}
  3. {KeyPrefixAccountDenomLockTimestamp}{Owner}{SyntheticDenom}{LockEndTime}
  4. {KeyPrefixAccountDenomLockDuration}{Owner}{SyntheticDenom}{Duration}

SyntheticDenom is expressed as {Denom}{Suffix}. (Note: we can change this to {Prefix}{Denom} as per discussion with Dev)

For end time keys, they are converted to sortable string by using sdk.FormatTimeBytes function.

Note: To implement the auto removal of synthetic lockups that is already finished, we manage a separate time basis queue at {KeyPrefixSyntheticLockTimestamp}{EndTime}{LockId}{Suffix}

Messages

Lock Tokens

MsgLockTokens can be submitted by any token holder via a MsgLockTokens transaction.

type MsgLockTokens struct {
 Owner    sdk.AccAddress
 Duration time.Duration
 Coins    sdk.Coins
}

State modifications:

  • Validate Owner has enough tokens
  • Generate new PeriodLock record
  • Save the record inside the keeper's time basis unlock queue
  • Transfer the tokens from the Owner to lockup ModuleAccount.
Begin Unlock of all locks

Once time is over, users can withdraw unlocked coins from lockup ModuleAccount.

type MsgBeginUnlockingAll struct {
 Owner string
}

State modifications:

  • Fetch all unlockable PeriodLocks that has not started unlocking yet
  • Set PeriodLock's unlock time
  • Remove lock references from NotUnlocking queue
  • Add lock references to Unlocking queue
Begin unlock for a lock

Once time is over, users can withdraw unlocked coins from lockup ModuleAccount.

type MsgBeginUnlocking struct {
 Owner string
 ID    uint64
}

State modifications:

  • Check PeriodLock with ID specified by MsgBeginUnlocking is not started unlocking yet
  • Set PeriodLock's unlock time
  • Remove lock references from NotUnlocking queue
  • Add lock references to Unlocking queue

Note: If another module needs past PeriodLock item, it can log the details themselves using the hooks.

Events

The lockup module emits the following events:

Handlers
MsgLockTokens
Type Attribute Key Attribute Value
lock_tokens period_lock_id {periodLockID}
lock_tokens owner {owner}
lock_tokens amount {amount}
lock_tokens duration {duration}
lock_tokens unlock_time {unlockTime}
message action lock_tokens
message sender {owner}
transfer recipient {moduleAccount}
transfer sender {owner}
transfer amount {amount}
MsgBeginUnlocking
Type Attribute Key Attribute Value
begin_unlock period_lock_id {periodLockID}
begin_unlock owner {owner}
begin_unlock amount {amount}
begin_unlock duration {duration}
begin_unlock unlock_time {unlockTime}
message action begin_unlocking
message sender {owner}
MsgBeginUnlockingAll
Type Attribute Key Attribute Value
begin_unlock_all owner {owner}
begin_unlock_all unlocked_coins {unlockedCoins}
begin_unlock period_lock_id {periodLockID}
begin_unlock owner {owner}
begin_unlock amount {amount}
begin_unlock duration {duration}
begin_unlock unlock_time {unlockTime}
message action begin_unlocking_all
message sender {owner}
Endblocker
Automatic withdraw when unlock time mature
Type Attribute Key Attribute Value
message action unlock_tokens
message sender {owner}
transfer[] recipient {owner}
transfer[] sender {moduleAccount}
transfer[] amount {unlockAmount}
unlock[] period_lock_id {owner}
unlock[] owner {lockID}
unlock[] duration {lockDuration}
unlock[] unlock_time {unlockTime}
unlock_tokens owner {owner}
unlock_tokens unlocked_coins {totalAmount}

Keepers

Lockup Keeper

Lockup keeper provides utility functions to store lock queues and query locks.

// Keeper is the interface for lockup module keeper
type Keeper interface {
    // GetModuleBalance Returns full balance of the module
    GetModuleBalance(sdk.Context) sdk.Coins
    // GetModuleLockedCoins Returns locked balance of the module
    GetModuleLockedCoins(sdk.Context) sdk.Coins
    // GetAccountUnlockableCoins Returns whole unlockable coins which are not withdrawn yet
    GetAccountUnlockableCoins(sdk.Context, addr sdk.AccAddress) sdk.Coins
    // GetAccountUnlockingCoins Returns whole unlocking coins
    GetAccountUnlockingCoins(sdk.Context, addr sdk.AccAddress) sdk.Coins
    // GetAccountLockedCoins Returns a locked coins that can't be withdrawn
    GetAccountLockedCoins(sdk.Context, addr sdk.AccAddress) sdk.Coins
    // GetAccountLockedPastTime Returns the total locks of an account whose unlock time is beyond timestamp
    GetAccountLockedPastTime(sdk.Context, addr sdk.AccAddress, timestamp time.Time) []types.PeriodLock
    // GetAccountUnlockedBeforeTime Returns the total unlocks of an account whose unlock time is before timestamp
    GetAccountUnlockedBeforeTime(sdk.Context, addr sdk.AccAddress, timestamp time.Time) []types.PeriodLock
    // GetAccountLockedPastTimeDenom is equal to GetAccountLockedPastTime but denom specific
    GetAccountLockedPastTimeDenom(ctx sdk.Context, addr sdk.AccAddress, denom string, timestamp time.Time) []types.PeriodLock

    // GetAccountLockedLongerDuration Returns account locked with duration longer than specified
    GetAccountLockedLongerDuration(sdk.Context, addr sdk.AccAddress, duration time.Duration) []types.PeriodLock
    // GetAccountLockedLongerDurationDenom Returns account locked with duration longer than specified with specific denom
    GetAccountLockedLongerDurationDenom(sdk.Context, addr sdk.AccAddress, denom string, duration time.Duration) []types.PeriodLock
    // GetLocksPastTimeDenom Returns the locks whose unlock time is beyond timestamp
    GetLocksPastTimeDenom(ctx sdk.Context, addr sdk.AccAddress, denom string, timestamp time.Time) []types.PeriodLock
    // GetLocksLongerThanDurationDenom Returns the locks whose unlock duration is longer than duration
    GetLocksLongerThanDurationDenom(ctx sdk.Context, addr sdk.AccAddress, denom string, duration time.Duration) []types.PeriodLock
    // GetLockByID Returns lock from lockID
    GetLockByID(sdk.Context, lockID uint64) (*types.PeriodLock, error)
    // GetPeriodLocks Returns the period locks on pool
    GetPeriodLocks(sdk.Context) ([]types.PeriodLock, error)
    // UnlockAllUnlockableCoins Unlock all unlockable coins
    UnlockAllUnlockableCoins(sdk.Context, account sdk.AccAddress) (sdk.Coins, error)
    // LockTokens lock tokens from an account for specified duration
    LockTokens(sdk.Context, owner sdk.AccAddress, coins sdk.Coins, duration time.Duration) (types.PeriodLock, error)
    // AddTokensToLock locks more tokens into a lockup
    AddTokensToLock(ctx sdk.Context, owner sdk.AccAddress, lockID uint64, coins sdk.Coins) (*types.PeriodLock, error)
    // Lock is a utility to lock coins into module account
    Lock(sdk.Context, lock types.PeriodLock) error
    // Unlock is a utility to unlock coins from module account
    Unlock(sdk.Context, lock types.PeriodLock) error
    GetSyntheticLockup(ctx sdk.Context, lockID uint64, suffix string) (*types.SyntheticLock, error)
    GetAllSyntheticLockupsByLockup(ctx sdk.Context, lockID uint64) []types.SyntheticLock
    GetAllSyntheticLockups(ctx sdk.Context) []types.SyntheticLock
    // CreateSyntheticLockup create synthetic lockup with lock id and denom suffix
    CreateSyntheticLockup(ctx sdk.Context, lockID uint64, suffix string, unlockDuration time.Duration) error
    // DeleteSyntheticLockup delete synthetic lockup with lock id and suffix
    DeleteSyntheticLockup(ctx sdk.Context, lockID uint64, suffix string) error
    DeleteAllMaturedSyntheticLocks(ctx sdk.Context)
Lock Admin Keeper

Lockup admin keeper provides god privilege functions to remove tokens from locks and create new locks.

// AdminKeeper defines a god priviledge keeper functions to remove tokens from locks and create new locks
// For the governance system of token pools, we want a "ragequit" feature
// So governance changes will take 1 week to go into effect
// During that time, people can choose to "ragequit" which means they would leave the original pool
// and form a new pool with the old parameters but if they still had 2 months of lockup left,
// their liquidity still needs to be 2 month lockup-ed, just in the new pool
// And we need to replace their pool1 LP tokens with pool2 LP tokens with the same lock duration and end time

type AdminKeeper interface {
    Keeper

    // this unlock previous lockID and create a new lock with newCoins with same duration and endtime
    Relock(sdk.Context, lockID uint64, newCoins sdk.Coins) error
    // this unlock without time check with an admin priviledge
    BreakLock(sdk.Context, lockID uint64) error
}

Hooks

In this section we describe the "hooks" that lockup module provide for other modules.

Tokens Locked

On lock/unlock events, lockup module execute hooks for other modules to make following actions.

  OnTokenLocked(ctx sdk.Context, address sdk.AccAddress, lockID uint64, amount sdk.Coins, lockDuration time.Duration, unlockTime time.Time)
  OnTokenUnlocked(ctx sdk.Context, address sdk.AccAddress, lockID uint64, amount sdk.Coins, lockDuration time.Duration, unlockTime time.Time)

Parameters

The lockup module contains the following parameters:

Key Type Example

Note: Currently no parameters are set for lockup module, we will need to move lockable durations from incentives module to lockup module.

Endblocker

Withdraw tokens after unlock time mature

Once time is over, endblocker withdraw coins from matured locks and coins are sent from lockup ModuleAccount.

State modifications:

  • Fetch all unlockable PeriodLocks that Owner has not withdrawn yet
  • Remove PeriodLock records from the state
  • Transfer the tokens from lockup ModuleAccount to the MsgUnlockTokens.Owner.
Remove synthetic locks after removal time mature

For synthetic lockups, no coin movement is made, but lockup record and reference queues are removed.

State modifications:

  • Fetch all synthetic lockups that is matured
  • Remove SyntheticLock records from the state along with reference queues

Transactions

lock-tokens

Bond tokens in a LP for a set duration

merlind tx lockup lock-tokens [tokens] --duration --from --chain-id

::: details Example

To lockup 15.527546134174465309gamm/pool/3 tokens for a one day bonding period from WALLET_NAME on the merlin mainnet:

merlind tx lockup lock-tokens 15527546134174465309gamm/pool/3 --duration="24h" --from WALLET_NAME --chain-id merlin-1

To lockup 25.527546134174465309gamm/pool/13 tokens for a one week bonding period from WALLET_NAME on the merlin testnet:

merlind tx lockup lock-tokens 25527546134174465309gamm/pool/13 --duration="168h" --from WALLET_NAME --chain-id mer-test-4

To lockup 35.527546134174465309 gamm/pool/197 tokens for a two week bonding period from WALLET_NAME on the merlin mainnet:

merlind tx lockup lock-tokens 35527546134174465309gamm/pool/197 --duration="336h" --from WALLET_NAME --chain-id merlin-1

:::

begin-unlock-by-id

Begin the unbonding process for tokens given their unique lock ID

merlind tx lockup begin-unlock-by-id [id] --from --chain-id

::: details Example

To begin the unbonding time for all bonded tokens under id 75 from WALLET_NAME on the merlin mainnet:

merlind tx lockup begin-unlock-by-id 75 --from WALLET_NAME --chain-id merlin-1

::: ::: warning Note The ID corresponds to the unique ID given to your lockup transaction (explained more in lock-by-id section) :::

begin-unlock-tokens

Begin unbonding process for all bonded tokens in a wallet

merlind tx lockup begin-unlock-tokens --from --chain-id

::: details Example

To begin unbonding time for ALL pools and ALL bonded tokens in WALLET_NAME on the merlin mainnet:

merlind tx lockup begin-unlock-tokens --from=WALLET_NAME --chain-id=merlin-1 --yes

:::

Queries

In this section we describe the queries required on grpc server.

// Query defines the gRPC querier service.
service Query {
    // Return full balance of the module
 rpc ModuleBalance(ModuleBalanceRequest) returns (ModuleBalanceResponse);
 // Return locked balance of the module
 rpc ModuleLockedAmount(ModuleLockedAmountRequest) returns (ModuleLockedAmountResponse);

 // Returns unlockable coins which are not withdrawn yet
 rpc AccountUnlockableCoins(AccountUnlockableCoinsRequest) returns (AccountUnlockableCoinsResponse);
 // Returns unlocking coins
   rpc AccountUnlockingCoins(AccountUnlockingCoinsRequest) returns (AccountUnlockingCoinsResponse) {}
 // Return a locked coins that can't be withdrawn
 rpc AccountLockedCoins(AccountLockedCoinsRequest) returns (AccountLockedCoinsResponse);

 // Returns locked records of an account with unlock time beyond timestamp
 rpc AccountLockedPastTime(AccountLockedPastTimeRequest) returns (AccountLockedPastTimeResponse);
 // Returns locked records of an account with unlock time beyond timestamp excluding tokens started unlocking
 rpc AccountLockedPastTimeNotUnlockingOnly(AccountLockedPastTimeNotUnlockingOnlyRequest) returns (AccountLockedPastTimeNotUnlockingOnlyResponse) {}
 // Returns unlocked records with unlock time before timestamp
 rpc AccountUnlockedBeforeTime(AccountUnlockedBeforeTimeRequest) returns (AccountUnlockedBeforeTimeResponse);

 // Returns lock records by address, timestamp, denom
 rpc AccountLockedPastTimeDenom(AccountLockedPastTimeDenomRequest) returns (AccountLockedPastTimeDenomResponse);
 // Returns lock record by id
 rpc LockedByID(LockedRequest) returns (LockedResponse);

 // Returns account locked records with longer duration
 rpc AccountLockedLongerDuration(AccountLockedLongerDurationRequest) returns (AccountLockedLongerDurationResponse);
 // Returns account locked records with longer duration excluding tokens started unlocking
   rpc AccountLockedLongerDurationNotUnlockingOnly(AccountLockedLongerDurationNotUnlockingOnlyRequest) returns (AccountLockedLongerDurationNotUnlockingOnlyResponse) {}
 // Returns account's locked records for a denom with longer duration
 rpc AccountLockedLongerDurationDenom(AccountLockedLongerDurationDenomRequest) returns (AccountLockedLongerDurationDenomResponse);

 // Returns account locked records with a specific duration
 rpc AccountLockedDuration(AccountLockedDurationRequest) returns (AccountLockedDurationResponse);
}
account-locked-beforetime

Query an account's unlocked records after a specified time (UNIX) has passed

In other words, if an account unlocked all their bonded tokens the moment the query was executed, only the locks that would have completed their bond time requirement by the time the TIMESTAMP is reached will be returned.

::: details Example

In this example, the current UNIX time is 1639776682, 2 days from now is approx 1639971082, and 15 days from now is approx 1641094282.

An account's ADDRESS is locked in both the 1 day and 1 week gamm/pool/3. To query the ADDRESS with a timestamp 2 days from now 1639971082:

merlind query lockup account-locked-beforetime ADDRESS 1639971082

In this example will output the 1 day lock but not the 1 week lock:

locks:
- ID: "571839"
  coins:
  - amount: "15527546134174465309"
    denom: gamm/pool/3
  duration: 24h
  end_time: "2021-12-18T23:32:58.900715388Z"
  owner: mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259

If querying the same ADDRESS with a timestamp 15 days from now 1641094282:

merlind query lockup account-locked-beforetime ADDRESS 1641094282

In this example will output both the 1 day and 1 week lock:

locks:
- ID: "572027"
  coins:
  - amount: "16120691802759484268"
    denom: gamm/pool/3
  duration: 604800.000006193s
  end_time: "0001-01-01T00:00:00Z"
  owner: mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259
- ID: "571839"
  coins:
  - amount: "15527546134174465309"
    denom: gamm/pool/3
  duration: 24h
  end_time: "2021-12-18T23:32:58.900715388Z"
  owner: mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259

:::

account-locked-coins

Query an account's locked (bonded) LP tokens

merlind query lockup account-locked-coins [address]

:::: details Example

merlind query lockup account-locked-coins mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259

An example output:

coins:
- amount: "413553955105681228583"
  denom: gamm/pool/1
- amount: "32155370994266157441309"
  denom: gamm/pool/10
- amount: "220957857520769912023"
  denom: gamm/pool/3
- amount: "31648237936933949577"
  denom: gamm/pool/42
- amount: "14162624050980051053569"
  denom: gamm/pool/5
- amount: "1023186951315714985896914"
  denom: gamm/pool/9

::: warning Note All GAMM amounts listed are 10^18. Move the decimal place to the left 18 places to get the GAMM amount listed in the GUI.

You may also specify a --height flag to see bonded LP tokens at a specified height (note: if running a pruned node, this may result in an error) ::: ::::

account-locked-longer-duration

Query an account's locked records that are greater than or equal to a specified lock duration

merlind query lockup account-locked-longer-duration [address] [duration]

::: details Example

Here is an example of querying an ADDRESS for all 1 day or greater bonding periods:

merlind query lockup account-locked-longer-duration mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259 24h

An example output:

locks:
- ID: "572027"
  coins:
  - amount: "16120691802759484268"
    denom: gamm/pool/3
  duration: 604800.000006193s
  end_time: "0001-01-01T00:00:00Z"
  owner: mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259
- ID: "571839"
  coins:
  - amount: "15527546134174465309"
    denom: gamm/pool/3
  duration: 24h
  end_time: "2021-12-18T23:32:58.900715388Z"
  owner: mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259

:::

account-locked-longer-duration-denom

Query an account's locked records for a denom that is locked equal to or greater than the specified duration AND match a specified denom

merlind query lockup account-locked-longer-duration-denom [address] [duration] [denom]

::: details Example

Here is an example of an ADDRESS that is locked in both the 1 day and 1 week for both the gamm/pool/3 and gamm/pool/1, then queries the ADDRESS for all bonding periods equal to or greater than 1 day for just the gamm/pool/3:

merlind query lockup account-locked-longer-duration-denom mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259 24h gamm/pool/3

An example output:

locks:
- ID: "571839"
  coins:
  - amount: "15527546134174465309"
    denom: gamm/pool/3
  duration: 24h
  end_time: "0001-01-01T00:00:00Z"
  owner: mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259
- ID: "572027"
  coins:
  - amount: "16120691802759484268"
    denom: gamm/pool/3
  duration: 604800.000006193s
  end_time: "0001-01-01T00:00:00Z"
  owner: mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259

As shown, the gamm/pool/3 is returned but not the gamm/pool/1 due to the denom filter. :::

account-locked-longer-duration-not-unlocking

Query an account's locked records for a denom that is locked equal to or greater than the specified duration AND is not in the process of being unlocked

merlind query lockup account-locked-longer-duration-not-unlocking [address] [duration]

::: details Example

Here is an example of an ADDRESS that is locked in both the 1 day and 1 week gamm/pool/3, begins unlocking process for the 1 day bond, and queries the ADDRESS for all bonding periods equal to or greater than 1 day that are not unbonding:

merlind query lockup account-locked-longer-duration-not-unlocking mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259 24h

An example output:

locks:
- ID: "571839"
  coins:
  - amount: "16120691802759484268"
    denom: gamm/pool/3
  duration: 604800.000006193s
  end_time: "0001-01-01T00:00:00Z"
  owner: mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259

The 1 day bond does not show since it is in the process of unbonding. :::

account-locked-pasttime

Query the locked records of an account with the unlock time beyond timestamp (UNIX)

merlind query lockup account-locked-pasttime [address] [timestamp]

::: details Example

Here is an example of an account that is locked in both the 1 day and 1 week gamm/pool/3. In this example, the UNIX time is currently 1639776682 and queries an ADDRESS for UNIX time two days later from the current time (which in this example would be 1639971082)

merlind query lockup account-locked-pasttime mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259 1639971082

The example output:

locks:
- ID: "572027"
  coins:
  - amount: "16120691802759484268"
    denom: gamm/pool/3
  duration: 604800.000006193s
  end_time: "0001-01-01T00:00:00Z"
  owner: mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259

Note that the 1 day lock ID did not display because, if the unbonding time began counting down from the time the command was executed, the bonding period would be complete before the two day window given by the UNIX timestamp input. :::

account-locked-pasttime-denom

Query the locked records of an account with the unlock time beyond timestamp (unix) and filter by a specific denom

merlind query lockup account-locked-pasttime-denom mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259 [timestamp] [denom]

::: details Example

Here is an example of an account that is locked in both the 1 day and 1 week gamm/pool/3 and 1 day and 1 week gamm/pool/1. In this example, the UNIX time is currently 1639776682 and queries an ADDRESS for UNIX time two days later from the current time (which in this example would be 1639971082) and filters for gamm/pool/3

merlind query lockup account-locked-pasttime-denom mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259 1639971082 gamm/pool/3

The example output:

locks:
- ID: "572027"
  coins:
  - amount: "16120691802759484268"
    denom: gamm/pool/3
  duration: 604800.000006193s
  end_time: "0001-01-01T00:00:00Z"
  owner: mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259

Note that the 1 day lock ID did not display because, if the unbonding time began counting down from the time the command was executed, the bonding period would be complete before the two day window given by the UNIX timestamp input. Additionally, neither of the 1 day or 1 week lock IDs for gamm/pool/1 showed due to the denom filter. :::

account-locked-pasttime-not-unlocking

Query the locked records of an account with the unlock time beyond timestamp (unix) AND is not in the process of unlocking

merlind query lockup account-locked-pasttime [address] [timestamp]

::: details Example

Here is an example of an account that is locked in both the 1 day and 1 week gamm/pool/3. In this example, the UNIX time is currently 1639776682 and queries an ADDRESS for UNIX time two days later from the current time (which in this example would be 1639971082) AND is not unlocking:

merlind query lockup account-locked-pasttime mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259 1639971082

The example output:

locks:
- ID: "572027"
  coins:
  - amount: "16120691802759484268"
    denom: gamm/pool/3
  duration: 604800.000006193s
  end_time: "0001-01-01T00:00:00Z"
  owner: mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259

Note that the 1 day lock ID did not display because, if the unbonding time began counting down from the time the command was executed, the bonding period would be complete before the two day window given by the UNIX timestamp input. Additionally, if ID 572027 were to begin the unlocking process, the query would have returned blank. :::

account-unlockable-coins

Query an address's LP shares that have completed the unlocking period and are ready to be withdrawn

merlind query lockup account-unlockable-coins ADDRESS
account-unlocking-coins

Query an address's LP shares that are currently unlocking

merlind query lockup account-unlocking-coins [address]

::: details Example

merlind query lockup account-unlocking-coins mer1xqhlshlhs5g0acqgrkafdemvf5kz4pp4c2x259

Example output:

coins:
- amount: "15527546134174465309"
  denom: gamm/pool/3

:::

lock-by-id

Query a lock record by its ID

merlind query lockup lock-by-id [id]

::: details Example

Every time a user bonds tokens to an LP, a unique lock ID is created for that transaction.

Here is an example viewing the lock record for ID 9:

merlind query lockup lock-by-id 9

And its output:

lock:
  ID: "9"
  coins:
  - amount: "2449472670508255020346507"
    denom: gamm/pool/2
  duration: 336h
  end_time: "0001-01-01T00:00:00Z"
  owner: mer16r39ghhwqjcwxa8q3yswlz8jhzldygy66vlm82

In summary, this shows wallet mer16r39ghhwqjcwxa8q3yswlz8jhzldygy66vlm82 bonded 2449472.670 gamm/pool/2 LP shares for a 2 week locking period. :::

module-balance

Query the balance of all LP shares (bonded and unbonded)

merlind query lockup module-balance

::: details Example

merlind query lockup module-balance

An example output:

coins:
- amount: "118851922644152734549498647"
  denom: gamm/pool/1
- amount: "2165392672114512349039263626"
  denom: gamm/pool/10
- amount: "9346769826591025900804"
  denom: gamm/pool/13
- amount: "229347389639275840044722315"
  denom: gamm/pool/15
- amount: "81217698776012800247869"
  denom: gamm/pool/183
- amount: "284253336860259874753775"
  denom: gamm/pool/197
- amount: "664300804648059580124426710"
  denom: gamm/pool/2
- amount: "5087102794776326441530430"
  denom: gamm/pool/22
- amount: "178900843925960029029567880"
  denom: gamm/pool/3
- amount: "64845148811263846652326124"
  denom: gamm/pool/4
- amount: "177831279847453210600513"
  denom: gamm/pool/42
- amount: "18685913727862493301261661338"
  denom: gamm/pool/5
- amount: "23579028640963777558149250419"
  denom: gamm/pool/6
- amount: "1273329284855460149381904976"
  denom: gamm/pool/7
- amount: "625252103927082207683116933"
  denom: gamm/pool/8
- amount: "1148475247281090606949382402"
  denom: gamm/pool/9

:::

module-locked-amount

Query the balance of all bonded LP shares

merlind query lockup module-locked-amount

::: details Example

merlind query lockup module-locked-amount

An example output:


  "coins":
    {
      "denom": "gamm/pool/1",
      "amount": "247321084020868094262821308"
    },
    {
      "denom": "gamm/pool/10",
      "amount": "2866946821820635047398966697"
    },
    {
      "denom": "gamm/pool/13",
      "amount": "9366580741745176812984"
    },
    {
      "denom": "gamm/pool/15",
      "amount": "193294911294343602187680438"
    },
    {
      "denom": "gamm/pool/183",
      "amount": "196722012808526595790871"
    },
    {
      "denom": "gamm/pool/197",
      "amount": "1157025085661167198918241"
    },
    {
      "denom": "gamm/pool/2",
      "amount": "633051132033131378888258047"
    },
    {
      "denom": "gamm/pool/22",
      "amount": "3622601406125950733194696"
    },
...

NOTE: This command seems to only work on gRPC and on CLI returns an EOF error. :::

output-all-locks

Output all locks into a json file

merlind query lockup output-all-locks [max lock ID]

:::: details Example

This example command outputs locks 1-1000 and saves to a json file:

merlind query lockup output-all-locks 1000

::: warning Note If a lockup has been completed, the lockup status will show as "0" (or successful) and no further information will be available. To get further information on a completed lock, run the lock-by-id query. ::: ::::

total-locked-of-denom

Query locked amount for a specific denom in the duration provided

merlind query lockup total-locked-of-denom [denom] --min-duration

:::: details Example

This example command outputs the amount of gamm/pool/2 LP shares that locked in the 2 week bonding period:

merlind query lockup total-locked-of-denom gamm/pool/2 --min-duration "336h"

Which, at the time of this writing outputs 14106985399822075248947045 which is equivalent to 14106985.3998 gamm/pool/2

NOTE: As of this writing, there is a bug that defaults the min duration to days instead of seconds. Ensure you specify the time in seconds to get the correct response. :::

Commands

# 1 day 100stake lock-tokens command
merlind tx lockup lock-tokens 200stake --duration="86400s" --from=validator --chain-id=testing --keyring-backend=test --yes

# 5s 100stake lock-tokens command
merlind tx lockup lock-tokens 100stake --duration="5s" --from=validator --chain-id=testing --keyring-backend=test --yes

# begin unlock tokens, NOTE: add more gas when unlocking more than two locks in a same command
merlind tx lockup begin-unlock-tokens --from=validator --gas=500000 --chain-id=testing --keyring-backend=test --yes

# unlock tokens, NOTE: add more gas when unlocking more than two locks in a same command
merlind tx lockup unlock-tokens --from=validator --gas=500000 --chain-id=testing --keyring-backend=test --yes

# unlock specific period lock
merlind tx lockup unlock-by-id 1 --from=validator --chain-id=testing --keyring-backend=test --yes

# account balance
merlind query bank balances $(merlind keys show -a validator --keyring-backend=test)

# query module balance
merlind query lockup module-balance

# query locked amount
merlind query lockup module-locked-amount

# query lock by id
merlind query lockup lock-by-id 1

# query account unlockable coins
merlind query lockup account-unlockable-coins $(merlind keys show -a validator --keyring-backend=test)

# query account locks by denom past time
merlind query lockup account-locked-pasttime-denom $(merlind keys show -a validator --keyring-backend=test) 1611879610 stake

# query account locks past time
merlind query lockup account-locked-pasttime $(merlind keys show -a validator --keyring-backend=test) 1611879610

# query account locks by denom with longer duration
merlind query lockup account-locked-longer-duration-denom $(merlind keys show -a validator --keyring-backend=test) 5.1s stake

# query account locks with longer duration
merlind query lockup account-locked-longer-duration $(merlind keys show -a validator --keyring-backend=test) 5.1s

# query account locked coins
merlind query lockup account-locked-coins $(merlind keys show -a validator --keyring-backend=test)

# query account locks before time
merlind query lockup account-locked-beforetime $(merlind keys show -a validator --keyring-backend=test) 1611879610

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BeginBlocker

func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper)

BeginBlocker is called on every block.

func EndBlocker

func EndBlocker(ctx sdk.Context, k keeper.Keeper) []abci.ValidatorUpdate

Called every block to automatically unlock matured locks.

Types

type AppModule

type AppModule struct {
	AppModuleBasic
	// contains filtered or unexported fields
}

AppModule implements the AppModule interface for the capability module.

func NewAppModule

func NewAppModule(keeper keeper.Keeper,
	accountKeeper stakingtypes.AccountKeeper, bankKeeper stakingtypes.BankKeeper,
) AppModule

func (AppModule) Actions

func (am AppModule) Actions() []simtypes.Action

WeightedOperations returns the all the lockup module operations with their respective weights.

func (AppModule) BeginBlock

func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock)

BeginBlock executes all ABCI BeginBlock logic respective to the capability module.

func (AppModule) ConsensusVersion

func (AppModule) ConsensusVersion() uint64

ConsensusVersion implements AppModule/ConsensusVersion.

func (AppModule) EndBlock

EndBlock executes all ABCI EndBlock logic respective to the capability module. It returns no validator updates.

func (AppModule) ExportGenesis

func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage

ExportGenesis returns the capability module's exported genesis state as raw JSON bytes.

func (AppModule) InitGenesis

func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) []abci.ValidatorUpdate

InitGenesis performs the capability module's genesis initialization It returns no validator updates.

func (AppModule) LegacyQuerierHandler

func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier

LegacyQuerierHandler returns the x/lockup module's Querier.

func (AppModule) Name

func (am AppModule) Name() string

Name returns the capability module's name.

func (AppModule) QuerierRoute

func (AppModule) QuerierRoute() string

QuerierRoute returns the capability module's query routing key.

func (AppModule) RegisterInvariants

func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry)

RegisterInvariants registers the capability module's invariants.

func (AppModule) RegisterServices

func (am AppModule) RegisterServices(cfg module.Configurator)

RegisterServices registers module services.

func (AppModule) Route

func (am AppModule) Route() sdk.Route

Route returns the capability module's message routing key.

type AppModuleBasic

type AppModuleBasic struct{}

AppModuleBasic implements the AppModuleBasic interface for the capability module.

func NewAppModuleBasic

func NewAppModuleBasic() AppModuleBasic

func (AppModuleBasic) DefaultGenesis

func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage

DefaultGenesis returns the capability module's default genesis state.

func (AppModuleBasic) GetQueryCmd

func (AppModuleBasic) GetQueryCmd() *cobra.Command

GetQueryCmd returns the capability module's root query command.

func (AppModuleBasic) GetTxCmd

func (a AppModuleBasic) GetTxCmd() *cobra.Command

GetTxCmd returns the capability module's root tx command.

func (AppModuleBasic) Name

func (AppModuleBasic) Name() string

Name returns the capability module's name.

func (AppModuleBasic) RegisterGRPCGatewayRoutes

func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux)

RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the module.

func (AppModuleBasic) RegisterInterfaces

func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry)

RegisterInterfaces registers the module's interface types.

func (AppModuleBasic) RegisterLegacyAminoCodec

func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino)

func (AppModuleBasic) RegisterRESTRoutes

func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router)

RegisterRESTRoutes registers the capability module's REST service handlers.

func (AppModuleBasic) ValidateGenesis

func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error

ValidateGenesis performs genesis state validation for the capability module.

Directories

Path Synopsis
client
cli
Package types is a reverse proxy.
Package types is a reverse proxy.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL