mukan-sdk/x/auth/vesting/client/cli/tx.go
Mukan Erkin Törük abb1ff956e
Some checks are pending
Build SimApp / build (amd64) (push) Waiting to run
Build SimApp / build (arm64) (push) Waiting to run
CodeQL / Analyze (push) Waiting to run
Build & Push / build (push) Waiting to run
Run Gosec / Gosec (push) Waiting to run
Lint / golangci-lint (push) Waiting to run
Checks dependencies and mocks generation / Check go mod tidy (push) Waiting to run
Checks dependencies and mocks generation / Check up to date mocks (push) Waiting to run
System Tests / setup (push) Waiting to run
System Tests / test-system (push) Blocked by required conditions
System Tests / test-system-legacy (push) Blocked by required conditions
Tests / Code Coverage / split-test-files (push) Waiting to run
Tests / Code Coverage / tests (00) (push) Blocked by required conditions
Tests / Code Coverage / tests (01) (push) Blocked by required conditions
Tests / Code Coverage / tests (02) (push) Blocked by required conditions
Tests / Code Coverage / tests (03) (push) Blocked by required conditions
Tests / Code Coverage / test-integration (push) Waiting to run
Tests / Code Coverage / test-e2e (push) Waiting to run
Tests / Code Coverage / repo-analysis (push) Blocked by required conditions
Tests / Code Coverage / test-sim-nondeterminism (push) Waiting to run
Tests / Code Coverage / test-clientv2 (push) Waiting to run
Tests / Code Coverage / test-core (push) Waiting to run
Tests / Code Coverage / test-depinject (push) Waiting to run
Tests / Code Coverage / test-errors (push) Waiting to run
Tests / Code Coverage / test-math (push) Waiting to run
Tests / Code Coverage / test-schema (push) Waiting to run
Tests / Code Coverage / test-collections (push) Waiting to run
Tests / Code Coverage / test-cosmovisor (push) Waiting to run
Tests / Code Coverage / test-confix (push) Waiting to run
Tests / Code Coverage / test-store (push) Waiting to run
Tests / Code Coverage / test-log (push) Waiting to run
Tests / Code Coverage / test-x-tx (push) Waiting to run
Tests / Code Coverage / test-x-nft (push) Waiting to run
Tests / Code Coverage / test-x-circuit (push) Waiting to run
Tests / Code Coverage / test-x-feegrant (push) Waiting to run
Tests / Code Coverage / test-x-evidence (push) Waiting to run
Tests / Code Coverage / test-x-upgrade (push) Waiting to run
Tests / Code Coverage / test-tools-benchmark (push) Waiting to run
refactor: complete sovereign stack cleanup — all github.com upstream refs purged
2026-05-11 03:46:06 +03:00

215 lines
6 KiB
Go

package cli
import (
"encoding/json"
"errors"
"fmt"
"os"
"strconv"
"github.com/spf13/cobra"
"cosmossdk.io/core/address"
"git.cw.tr/mukan-network/mukan-sdk/client"
"git.cw.tr/mukan-network/mukan-sdk/client/flags"
"git.cw.tr/mukan-network/mukan-sdk/client/tx"
sdk "git.cw.tr/mukan-network/mukan-sdk/types"
"git.cw.tr/mukan-network/mukan-sdk/x/auth/vesting/types"
)
// Transaction command flags
const (
FlagDelayed = "delayed"
)
// GetTxCmd returns vesting module's transaction commands.
func GetTxCmd(ac address.Codec) *cobra.Command {
txCmd := &cobra.Command{
Use: types.ModuleName,
Short: "Vesting transaction subcommands",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
txCmd.AddCommand(
NewMsgCreateVestingAccountCmd(ac),
NewMsgCreatePermanentLockedAccountCmd(ac),
NewMsgCreatePeriodicVestingAccountCmd(ac),
)
return txCmd
}
// NewMsgCreateVestingAccountCmd returns a CLI command handler for creating a
// MsgCreateVestingAccount transaction.
func NewMsgCreateVestingAccountCmd(ac address.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "create-vesting-account [to_address] [amount] [end_time]",
Short: "Create a new vesting account funded with an allocation of tokens.",
Long: `Create a new vesting account funded with an allocation of tokens. The
account can either be a delayed or continuous vesting account, which is determined
by the '--delayed' flag. All vesting accounts created will have their start time
set by the committed block's time. The end_time must be provided as a UNIX epoch
timestamp.`,
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
toAddr, err := ac.StringToBytes(args[0])
if err != nil {
return err
}
if args[1] == "" {
return errors.New("amount is empty")
}
amount, err := sdk.ParseCoinsNormalized(args[1])
if err != nil {
return err
}
endTime, err := strconv.ParseInt(args[2], 10, 64)
if err != nil {
return err
}
delayed, _ := cmd.Flags().GetBool(FlagDelayed)
msg := types.NewMsgCreateVestingAccount(clientCtx.GetFromAddress(), toAddr, amount, endTime, delayed)
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
cmd.Flags().Bool(FlagDelayed, false, "Create a delayed vesting account if true")
flags.AddTxFlagsToCmd(cmd)
return cmd
}
// NewMsgCreatePermanentLockedAccountCmd returns a CLI command handler for creating a
// MsgCreatePermanentLockedAccount transaction.
func NewMsgCreatePermanentLockedAccountCmd(ac address.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "create-permanent-locked-account [to_address] [amount]",
Short: "Create a new permanently locked account funded with an allocation of tokens.",
Long: `Create a new account funded with an allocation of permanently locked tokens. These
tokens may be used for staking but are non-transferable. Staking rewards will acrue as liquid and transferable
tokens.`,
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
toAddr, err := ac.StringToBytes(args[0])
if err != nil {
return err
}
if args[1] == "" {
return errors.New("amount is empty")
}
amount, err := sdk.ParseCoinsNormalized(args[1])
if err != nil {
return err
}
msg := types.NewMsgCreatePermanentLockedAccount(clientCtx.GetFromAddress(), toAddr, amount)
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
flags.AddTxFlagsToCmd(cmd)
return cmd
}
type VestingData struct {
StartTime int64 `json:"start_time"`
Periods []InputPeriod `json:"periods"`
}
type InputPeriod struct {
Coins string `json:"coins"`
Length int64 `json:"length_seconds"`
}
// NewMsgCreatePeriodicVestingAccountCmd returns a CLI command handler for creating a
// MsgCreatePeriodicVestingAccountCmd transaction.
func NewMsgCreatePeriodicVestingAccountCmd(ac address.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "create-periodic-vesting-account [to_address] [periods_json_file]",
Short: "Create a new vesting account funded with an allocation of tokens.",
Long: `A sequence of coins and period length in seconds. Periods are sequential, in that the duration of of a period only starts at the end of the previous period. The duration of the first period starts upon account creation. For instance, the following periods.json file shows 20 "test" coins vesting 30 days apart from each other.
Where periods.json contains:
An array of coin strings and unix epoch times for coins to vest
{ "start_time": 1625204910,
"periods":[
{
"coins": "10test",
"length_seconds":2592000 //30 days
},
{
"coins": "10test",
"length_seconds":2592000 //30 days
},
]
}
`,
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
toAddr, err := ac.StringToBytes(args[0])
if err != nil {
return err
}
contents, err := os.ReadFile(args[1])
if err != nil {
return err
}
var vestingData VestingData
err = json.Unmarshal(contents, &vestingData)
if err != nil {
return err
}
var periods []types.Period
for i, p := range vestingData.Periods {
amount, err := sdk.ParseCoinsNormalized(p.Coins)
if err != nil {
return err
}
if p.Length < 0 {
return fmt.Errorf("invalid period length of %d in period %d, length must be greater than 0", p.Length, i)
}
period := types.Period{Length: p.Length, Amount: amount}
periods = append(periods, period)
}
msg := types.NewMsgCreatePeriodicVestingAccount(clientCtx.GetFromAddress(), toAddr, vestingData.StartTime, periods)
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
flags.AddTxFlagsToCmd(cmd)
return cmd
}