refactor(vesting): remove vesting account creation (#19535)
This commit is contained in:
parent
8b83a2e29d
commit
72e4134710
File diff suppressed because it is too large
Load Diff
@ -1,203 +0,0 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc (unknown)
|
||||
// source: cosmos/vesting/v1beta1/tx.proto
|
||||
|
||||
package vestingv1beta1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
const (
|
||||
Msg_CreateVestingAccount_FullMethodName = "/cosmos.vesting.v1beta1.Msg/CreateVestingAccount"
|
||||
Msg_CreatePermanentLockedAccount_FullMethodName = "/cosmos.vesting.v1beta1.Msg/CreatePermanentLockedAccount"
|
||||
Msg_CreatePeriodicVestingAccount_FullMethodName = "/cosmos.vesting.v1beta1.Msg/CreatePeriodicVestingAccount"
|
||||
)
|
||||
|
||||
// MsgClient is the client API for Msg service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type MsgClient interface {
|
||||
// CreateVestingAccount defines a method that enables creating a vesting
|
||||
// account.
|
||||
CreateVestingAccount(ctx context.Context, in *MsgCreateVestingAccount, opts ...grpc.CallOption) (*MsgCreateVestingAccountResponse, error)
|
||||
// CreatePermanentLockedAccount defines a method that enables creating a permanent
|
||||
// locked account.
|
||||
//
|
||||
// Since: cosmos-sdk 0.46
|
||||
CreatePermanentLockedAccount(ctx context.Context, in *MsgCreatePermanentLockedAccount, opts ...grpc.CallOption) (*MsgCreatePermanentLockedAccountResponse, error)
|
||||
// CreatePeriodicVestingAccount defines a method that enables creating a
|
||||
// periodic vesting account.
|
||||
//
|
||||
// Since: cosmos-sdk 0.46
|
||||
CreatePeriodicVestingAccount(ctx context.Context, in *MsgCreatePeriodicVestingAccount, opts ...grpc.CallOption) (*MsgCreatePeriodicVestingAccountResponse, error)
|
||||
}
|
||||
|
||||
type msgClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewMsgClient(cc grpc.ClientConnInterface) MsgClient {
|
||||
return &msgClient{cc}
|
||||
}
|
||||
|
||||
func (c *msgClient) CreateVestingAccount(ctx context.Context, in *MsgCreateVestingAccount, opts ...grpc.CallOption) (*MsgCreateVestingAccountResponse, error) {
|
||||
out := new(MsgCreateVestingAccountResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_CreateVestingAccount_FullMethodName, in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *msgClient) CreatePermanentLockedAccount(ctx context.Context, in *MsgCreatePermanentLockedAccount, opts ...grpc.CallOption) (*MsgCreatePermanentLockedAccountResponse, error) {
|
||||
out := new(MsgCreatePermanentLockedAccountResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_CreatePermanentLockedAccount_FullMethodName, in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *msgClient) CreatePeriodicVestingAccount(ctx context.Context, in *MsgCreatePeriodicVestingAccount, opts ...grpc.CallOption) (*MsgCreatePeriodicVestingAccountResponse, error) {
|
||||
out := new(MsgCreatePeriodicVestingAccountResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_CreatePeriodicVestingAccount_FullMethodName, in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// MsgServer is the server API for Msg service.
|
||||
// All implementations must embed UnimplementedMsgServer
|
||||
// for forward compatibility
|
||||
type MsgServer interface {
|
||||
// CreateVestingAccount defines a method that enables creating a vesting
|
||||
// account.
|
||||
CreateVestingAccount(context.Context, *MsgCreateVestingAccount) (*MsgCreateVestingAccountResponse, error)
|
||||
// CreatePermanentLockedAccount defines a method that enables creating a permanent
|
||||
// locked account.
|
||||
//
|
||||
// Since: cosmos-sdk 0.46
|
||||
CreatePermanentLockedAccount(context.Context, *MsgCreatePermanentLockedAccount) (*MsgCreatePermanentLockedAccountResponse, error)
|
||||
// CreatePeriodicVestingAccount defines a method that enables creating a
|
||||
// periodic vesting account.
|
||||
//
|
||||
// Since: cosmos-sdk 0.46
|
||||
CreatePeriodicVestingAccount(context.Context, *MsgCreatePeriodicVestingAccount) (*MsgCreatePeriodicVestingAccountResponse, error)
|
||||
mustEmbedUnimplementedMsgServer()
|
||||
}
|
||||
|
||||
// UnimplementedMsgServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedMsgServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedMsgServer) CreateVestingAccount(context.Context, *MsgCreateVestingAccount) (*MsgCreateVestingAccountResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateVestingAccount not implemented")
|
||||
}
|
||||
func (UnimplementedMsgServer) CreatePermanentLockedAccount(context.Context, *MsgCreatePermanentLockedAccount) (*MsgCreatePermanentLockedAccountResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreatePermanentLockedAccount not implemented")
|
||||
}
|
||||
func (UnimplementedMsgServer) CreatePeriodicVestingAccount(context.Context, *MsgCreatePeriodicVestingAccount) (*MsgCreatePeriodicVestingAccountResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreatePeriodicVestingAccount not implemented")
|
||||
}
|
||||
func (UnimplementedMsgServer) mustEmbedUnimplementedMsgServer() {}
|
||||
|
||||
// UnsafeMsgServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to MsgServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeMsgServer interface {
|
||||
mustEmbedUnimplementedMsgServer()
|
||||
}
|
||||
|
||||
func RegisterMsgServer(s grpc.ServiceRegistrar, srv MsgServer) {
|
||||
s.RegisterService(&Msg_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _Msg_CreateVestingAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(MsgCreateVestingAccount)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MsgServer).CreateVestingAccount(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Msg_CreateVestingAccount_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MsgServer).CreateVestingAccount(ctx, req.(*MsgCreateVestingAccount))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Msg_CreatePermanentLockedAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(MsgCreatePermanentLockedAccount)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MsgServer).CreatePermanentLockedAccount(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Msg_CreatePermanentLockedAccount_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MsgServer).CreatePermanentLockedAccount(ctx, req.(*MsgCreatePermanentLockedAccount))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Msg_CreatePeriodicVestingAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(MsgCreatePeriodicVestingAccount)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MsgServer).CreatePeriodicVestingAccount(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Msg_CreatePeriodicVestingAccount_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MsgServer).CreatePeriodicVestingAccount(ctx, req.(*MsgCreatePeriodicVestingAccount))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Msg_ServiceDesc is the grpc.ServiceDesc for Msg service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var Msg_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "cosmos.vesting.v1beta1.Msg",
|
||||
HandlerType: (*MsgServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "CreateVestingAccount",
|
||||
Handler: _Msg_CreateVestingAccount_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "CreatePermanentLockedAccount",
|
||||
Handler: _Msg_CreatePermanentLockedAccount_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "CreatePeriodicVestingAccount",
|
||||
Handler: _Msg_CreatePeriodicVestingAccount_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "cosmos/vesting/v1beta1/tx.proto",
|
||||
}
|
||||
@ -47,6 +47,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
* [#19161](https://github.com/cosmos/cosmos-sdk/pull/19161) Remove `simulate` from `SetGasMeter`
|
||||
* [#19363](https://github.com/cosmos/cosmos-sdk/pull/19363) Remove `IterateAccounts` and `GetAllAccounts` methods from the AccountKeeper interface and Keeper.
|
||||
* [#19290](https://github.com/cosmos/cosmos-sdk/issues/19290) Pass `appmodule.Environment` to NewKeeper instead of passing individual services.
|
||||
* [#19535](https://github.com/cosmos/cosmos-sdk/pull/19535) Remove vesting account creation when the chain is running. The accounts module is required for creating vesting accounts on a running chain.
|
||||
<!-- TODO add a link to lockup accounts docs -->
|
||||
|
||||
### Consensus Breaking Changes
|
||||
|
||||
|
||||
@ -1,47 +0,0 @@
|
||||
package vesting
|
||||
|
||||
import (
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
vestingv1beta1 "cosmossdk.io/api/cosmos/vesting/v1beta1"
|
||||
)
|
||||
|
||||
// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface.
|
||||
func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
|
||||
return &autocliv1.ModuleOptions{
|
||||
Tx: &autocliv1.ServiceCommandDescriptor{
|
||||
Service: vestingv1beta1.Msg_ServiceDesc.ServiceName,
|
||||
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
||||
{
|
||||
RpcMethod: "CreateVestingAccount",
|
||||
Use: "create-vesting-account [to_address] [end_time] [amount]",
|
||||
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.`,
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
|
||||
{ProtoField: "to_address"},
|
||||
{ProtoField: "end_time"},
|
||||
{ProtoField: "amount", Varargs: true},
|
||||
},
|
||||
FlagOptions: map[string]*autocliv1.FlagOptions{
|
||||
"delayed": {Name: "delayed", Usage: "Create a delayed vesting account if true"},
|
||||
},
|
||||
},
|
||||
{
|
||||
RpcMethod: "CreatePermanentLockedAccount",
|
||||
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 accrue as liquid and transferable tokens.`,
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
|
||||
{ProtoField: "to_address"},
|
||||
{ProtoField: "amount", Varargs: true},
|
||||
},
|
||||
},
|
||||
},
|
||||
EnhanceCustomCommand: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -1,248 +0,0 @@
|
||||
package vesting
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/go-metrics"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"cosmossdk.io/x/auth/keeper"
|
||||
authtypes "cosmossdk.io/x/auth/types"
|
||||
"cosmossdk.io/x/auth/vesting/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/telemetry"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
)
|
||||
|
||||
type msgServer struct {
|
||||
keeper.AccountKeeper
|
||||
types.BankKeeper
|
||||
}
|
||||
|
||||
// NewMsgServerImpl returns an implementation of the vesting MsgServer interface,
|
||||
// wrapping the corresponding AccountKeeper and BankKeeper.
|
||||
func NewMsgServerImpl(k keeper.AccountKeeper, bk types.BankKeeper) types.MsgServer {
|
||||
return &msgServer{AccountKeeper: k, BankKeeper: bk}
|
||||
}
|
||||
|
||||
var _ types.MsgServer = msgServer{}
|
||||
|
||||
func (s msgServer) CreateVestingAccount(ctx context.Context, msg *types.MsgCreateVestingAccount) (*types.MsgCreateVestingAccountResponse, error) {
|
||||
from, err := s.AccountKeeper.AddressCodec().StringToBytes(msg.FromAddress)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid 'from' address: %s", err)
|
||||
}
|
||||
|
||||
to, err := s.AccountKeeper.AddressCodec().StringToBytes(msg.ToAddress)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid 'to' address: %s", err)
|
||||
}
|
||||
|
||||
if err := validateAmount(msg.Amount); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if msg.StartTime < 0 {
|
||||
return nil, sdkerrors.ErrInvalidRequest.Wrap("invalid start time")
|
||||
}
|
||||
|
||||
if msg.EndTime <= 0 {
|
||||
return nil, sdkerrors.ErrInvalidRequest.Wrap("invalid end time")
|
||||
}
|
||||
|
||||
if msg.EndTime <= msg.StartTime {
|
||||
return nil, sdkerrors.ErrInvalidRequest.Wrap("invalid start and end time (must be start < end)")
|
||||
}
|
||||
|
||||
if err := s.BankKeeper.IsSendEnabledCoins(ctx, msg.Amount...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if s.BankKeeper.BlockedAddr(to) {
|
||||
return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", msg.ToAddress)
|
||||
}
|
||||
|
||||
if acc := s.AccountKeeper.GetAccount(ctx, to); acc != nil {
|
||||
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "account %s already exists", msg.ToAddress)
|
||||
}
|
||||
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(to)
|
||||
baseAccount = s.AccountKeeper.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount)
|
||||
baseVestingAccount, err := types.NewBaseVestingAccount(baseAccount, msg.Amount.Sort(), msg.EndTime)
|
||||
if err != nil {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, err.Error())
|
||||
}
|
||||
|
||||
var vestingAccount sdk.AccountI
|
||||
if msg.Delayed {
|
||||
vestingAccount = types.NewDelayedVestingAccountRaw(baseVestingAccount)
|
||||
} else {
|
||||
start := msg.StartTime
|
||||
if msg.StartTime == 0 {
|
||||
start = s.AccountKeeper.Environment.HeaderService.GetHeaderInfo(ctx).Time.Unix()
|
||||
}
|
||||
vestingAccount = types.NewContinuousVestingAccountRaw(baseVestingAccount, start)
|
||||
}
|
||||
|
||||
s.AccountKeeper.SetAccount(ctx, vestingAccount)
|
||||
|
||||
defer func() {
|
||||
telemetry.IncrCounter(1, "new", "account")
|
||||
|
||||
for _, a := range msg.Amount {
|
||||
if a.Amount.IsInt64() {
|
||||
telemetry.SetGaugeWithLabels(
|
||||
[]string{"tx", "msg", "create_vesting_account"},
|
||||
float32(a.Amount.Int64()),
|
||||
[]metrics.Label{telemetry.NewLabel("denom", a.Denom)},
|
||||
)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if err = s.BankKeeper.SendCoins(ctx, from, to, msg.Amount); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.MsgCreateVestingAccountResponse{}, nil
|
||||
}
|
||||
|
||||
func (s msgServer) CreatePermanentLockedAccount(ctx context.Context, msg *types.MsgCreatePermanentLockedAccount) (*types.MsgCreatePermanentLockedAccountResponse, error) {
|
||||
from, err := s.AccountKeeper.AddressCodec().StringToBytes(msg.FromAddress)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid 'from' address: %s", err)
|
||||
}
|
||||
|
||||
to, err := s.AccountKeeper.AddressCodec().StringToBytes(msg.ToAddress)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid 'to' address: %s", err)
|
||||
}
|
||||
|
||||
if err := validateAmount(msg.Amount); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.BankKeeper.IsSendEnabledCoins(ctx, msg.Amount...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if s.BankKeeper.BlockedAddr(to) {
|
||||
return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", msg.ToAddress)
|
||||
}
|
||||
|
||||
if acc := s.AccountKeeper.GetAccount(ctx, to); acc != nil {
|
||||
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "account %s already exists", msg.ToAddress)
|
||||
}
|
||||
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(to)
|
||||
baseAccount = s.AccountKeeper.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount)
|
||||
vestingAccount, err := types.NewPermanentLockedAccount(baseAccount, msg.Amount)
|
||||
if err != nil {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, err.Error())
|
||||
}
|
||||
|
||||
s.AccountKeeper.SetAccount(ctx, vestingAccount)
|
||||
|
||||
defer func() {
|
||||
telemetry.IncrCounter(1, "new", "account")
|
||||
|
||||
for _, a := range msg.Amount {
|
||||
if a.Amount.IsInt64() {
|
||||
telemetry.SetGaugeWithLabels(
|
||||
[]string{"tx", "msg", "create_permanent_locked_account"},
|
||||
float32(a.Amount.Int64()),
|
||||
[]metrics.Label{telemetry.NewLabel("denom", a.Denom)},
|
||||
)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if err = s.BankKeeper.SendCoins(ctx, from, to, msg.Amount); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.MsgCreatePermanentLockedAccountResponse{}, nil
|
||||
}
|
||||
|
||||
func (s msgServer) CreatePeriodicVestingAccount(ctx context.Context, msg *types.MsgCreatePeriodicVestingAccount) (*types.MsgCreatePeriodicVestingAccountResponse, error) {
|
||||
from, err := s.AccountKeeper.AddressCodec().StringToBytes(msg.FromAddress)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid 'from' address: %s", err)
|
||||
}
|
||||
|
||||
to, err := s.AccountKeeper.AddressCodec().StringToBytes(msg.ToAddress)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid 'to' address: %s", err)
|
||||
}
|
||||
|
||||
if msg.StartTime < 1 {
|
||||
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "invalid start time of %d, length must be greater than 0", msg.StartTime)
|
||||
}
|
||||
|
||||
var totalCoins sdk.Coins
|
||||
for i, period := range msg.VestingPeriods {
|
||||
if period.Length < 1 {
|
||||
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "invalid period length of %d in period %d, length must be greater than 0", period.Length, i)
|
||||
}
|
||||
|
||||
if err := validateAmount(period.Amount); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
totalCoins = totalCoins.Add(period.Amount...)
|
||||
}
|
||||
|
||||
if s.BankKeeper.BlockedAddr(to) {
|
||||
return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", msg.ToAddress)
|
||||
}
|
||||
|
||||
if acc := s.AccountKeeper.GetAccount(ctx, to); acc != nil {
|
||||
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "account %s already exists", msg.ToAddress)
|
||||
}
|
||||
|
||||
if err := s.BankKeeper.IsSendEnabledCoins(ctx, totalCoins...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(to)
|
||||
baseAccount = s.AccountKeeper.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount)
|
||||
vestingAccount, err := types.NewPeriodicVestingAccount(baseAccount, totalCoins.Sort(), msg.StartTime, msg.VestingPeriods)
|
||||
if err != nil {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, err.Error())
|
||||
}
|
||||
|
||||
s.AccountKeeper.SetAccount(ctx, vestingAccount)
|
||||
|
||||
defer func() {
|
||||
telemetry.IncrCounter(1, "new", "account")
|
||||
|
||||
for _, a := range totalCoins {
|
||||
if a.Amount.IsInt64() {
|
||||
telemetry.SetGaugeWithLabels(
|
||||
[]string{"tx", "msg", "create_periodic_vesting_account"},
|
||||
float32(a.Amount.Int64()),
|
||||
[]metrics.Label{telemetry.NewLabel("denom", a.Denom)},
|
||||
)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if err = s.BankKeeper.SendCoins(ctx, from, to, totalCoins); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.MsgCreatePeriodicVestingAccountResponse{}, nil
|
||||
}
|
||||
|
||||
func validateAmount(amount sdk.Coins) error {
|
||||
if !amount.IsValid() {
|
||||
return sdkerrors.ErrInvalidCoins.Wrap(amount.String())
|
||||
}
|
||||
|
||||
if !amount.IsAllPositive() {
|
||||
return sdkerrors.ErrInvalidCoins.Wrap(amount.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -1,481 +0,0 @@
|
||||
package vesting_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"cosmossdk.io/core/header"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/math"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
authcodec "cosmossdk.io/x/auth/codec"
|
||||
authkeeper "cosmossdk.io/x/auth/keeper"
|
||||
authtypes "cosmossdk.io/x/auth/types"
|
||||
"cosmossdk.io/x/auth/vesting"
|
||||
vestingtestutil "cosmossdk.io/x/auth/vesting/testutil"
|
||||
vestingtypes "cosmossdk.io/x/auth/vesting/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
)
|
||||
|
||||
var (
|
||||
fromAddr = sdk.AccAddress([]byte("from1________________"))
|
||||
to1Addr = sdk.AccAddress([]byte("to1__________________"))
|
||||
to2Addr = sdk.AccAddress([]byte("to2__________________"))
|
||||
to3Addr = sdk.AccAddress([]byte("to3__________________"))
|
||||
fooCoin = sdk.NewInt64Coin("foo", 100)
|
||||
periodCoin = sdk.NewInt64Coin("foo", 20)
|
||||
)
|
||||
|
||||
type VestingTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
ctx sdk.Context
|
||||
accountKeeper authkeeper.AccountKeeper
|
||||
bankKeeper *vestingtestutil.MockBankKeeper
|
||||
msgServer vestingtypes.MsgServer
|
||||
}
|
||||
|
||||
func (s *VestingTestSuite) SetupTest() {
|
||||
key := storetypes.NewKVStoreKey(authtypes.StoreKey)
|
||||
|
||||
env := runtime.NewEnvironment(runtime.NewKVStoreService(key), log.NewNopLogger())
|
||||
testCtx := testutil.DefaultContextWithDB(s.T(), key, storetypes.NewTransientStoreKey("transient_test"))
|
||||
s.ctx = testCtx.Ctx.WithHeaderInfo(header.Info{Time: time.Now()})
|
||||
|
||||
encCfg := moduletestutil.MakeTestEncodingConfig()
|
||||
|
||||
maccPerms := map[string][]string{}
|
||||
|
||||
ctrl := gomock.NewController(s.T())
|
||||
s.bankKeeper = vestingtestutil.NewMockBankKeeper(ctrl)
|
||||
s.accountKeeper = authkeeper.NewAccountKeeper(
|
||||
env,
|
||||
encCfg.Codec,
|
||||
authtypes.ProtoBaseAccount,
|
||||
maccPerms,
|
||||
authcodec.NewBech32Codec("cosmos"),
|
||||
"cosmos",
|
||||
authtypes.NewModuleAddress("gov").String(),
|
||||
)
|
||||
|
||||
vestingtypes.RegisterInterfaces(encCfg.InterfaceRegistry)
|
||||
authtypes.RegisterInterfaces(encCfg.InterfaceRegistry)
|
||||
s.msgServer = vesting.NewMsgServerImpl(s.accountKeeper, s.bankKeeper)
|
||||
}
|
||||
|
||||
func (s *VestingTestSuite) TestCreateVestingAccount() {
|
||||
testCases := map[string]struct {
|
||||
preRun func()
|
||||
input *vestingtypes.MsgCreateVestingAccount
|
||||
expErr bool
|
||||
expErrMsg string
|
||||
}{
|
||||
"empty from address": {
|
||||
input: vestingtypes.NewMsgCreateVestingAccount(
|
||||
[]byte{},
|
||||
to1Addr,
|
||||
sdk.Coins{fooCoin},
|
||||
time.Now().Unix(),
|
||||
true,
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "invalid 'from' address",
|
||||
},
|
||||
"empty to address": {
|
||||
input: vestingtypes.NewMsgCreateVestingAccount(
|
||||
fromAddr,
|
||||
[]byte{},
|
||||
sdk.Coins{fooCoin},
|
||||
time.Now().Unix(),
|
||||
true,
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "invalid 'to' address",
|
||||
},
|
||||
"invalid coins": {
|
||||
input: vestingtypes.NewMsgCreateVestingAccount(
|
||||
fromAddr,
|
||||
to1Addr,
|
||||
sdk.Coins{sdk.Coin{Denom: "stake", Amount: math.NewInt(-1)}},
|
||||
time.Now().Unix(),
|
||||
true,
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "-1stake: invalid coins",
|
||||
},
|
||||
"invalid end time": {
|
||||
input: vestingtypes.NewMsgCreateVestingAccount(
|
||||
fromAddr,
|
||||
to1Addr,
|
||||
sdk.Coins{fooCoin},
|
||||
-10,
|
||||
true,
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "invalid end time",
|
||||
},
|
||||
"create for existing account": {
|
||||
preRun: func() {
|
||||
toAcc := s.accountKeeper.NewAccountWithAddress(s.ctx, to1Addr)
|
||||
s.bankKeeper.EXPECT().IsSendEnabledCoins(gomock.Any(), fooCoin).Return(nil)
|
||||
s.accountKeeper.SetAccount(s.ctx, toAcc)
|
||||
s.bankKeeper.EXPECT().BlockedAddr(to1Addr).Return(false)
|
||||
},
|
||||
input: vestingtypes.NewMsgCreateVestingAccount(
|
||||
fromAddr,
|
||||
to1Addr,
|
||||
sdk.Coins{fooCoin},
|
||||
time.Now().Unix(),
|
||||
true,
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "already exists",
|
||||
},
|
||||
"create for blocked account": {
|
||||
preRun: func() {
|
||||
s.bankKeeper.EXPECT().IsSendEnabledCoins(gomock.Any(), fooCoin).Return(nil)
|
||||
s.bankKeeper.EXPECT().BlockedAddr(to1Addr).Return(true)
|
||||
},
|
||||
input: vestingtypes.NewMsgCreateVestingAccount(
|
||||
fromAddr,
|
||||
to1Addr,
|
||||
sdk.Coins{fooCoin},
|
||||
time.Now().Unix(),
|
||||
true,
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "not allowed to receive funds",
|
||||
},
|
||||
"create a valid delayed vesting account": {
|
||||
preRun: func() {
|
||||
s.bankKeeper.EXPECT().IsSendEnabledCoins(gomock.Any(), fooCoin).Return(nil)
|
||||
s.bankKeeper.EXPECT().BlockedAddr(to2Addr).Return(false)
|
||||
s.bankKeeper.EXPECT().SendCoins(gomock.Any(), fromAddr, to2Addr, sdk.Coins{fooCoin}).Return(nil)
|
||||
},
|
||||
input: vestingtypes.NewMsgCreateVestingAccount(
|
||||
fromAddr,
|
||||
to2Addr,
|
||||
sdk.Coins{fooCoin},
|
||||
time.Now().Unix(),
|
||||
true,
|
||||
),
|
||||
expErr: false,
|
||||
expErrMsg: "",
|
||||
},
|
||||
"create a valid continuous vesting account": {
|
||||
preRun: func() {
|
||||
s.bankKeeper.EXPECT().IsSendEnabledCoins(gomock.Any(), fooCoin).Return(nil)
|
||||
s.bankKeeper.EXPECT().BlockedAddr(to3Addr).Return(false)
|
||||
s.bankKeeper.EXPECT().SendCoins(gomock.Any(), fromAddr, to3Addr, sdk.Coins{fooCoin}).Return(nil)
|
||||
},
|
||||
input: vestingtypes.NewMsgCreateVestingAccount(
|
||||
fromAddr,
|
||||
to3Addr,
|
||||
sdk.Coins{fooCoin},
|
||||
time.Now().Unix(),
|
||||
false,
|
||||
),
|
||||
expErr: false,
|
||||
expErrMsg: "",
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
s.Run(name, func() {
|
||||
if tc.preRun != nil {
|
||||
tc.preRun()
|
||||
}
|
||||
_, err := s.msgServer.CreateVestingAccount(s.ctx, tc.input)
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.expErrMsg)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *VestingTestSuite) TestCreatePermanentLockedAccount() {
|
||||
testCases := map[string]struct {
|
||||
preRun func()
|
||||
input *vestingtypes.MsgCreatePermanentLockedAccount
|
||||
expErr bool
|
||||
expErrMsg string
|
||||
}{
|
||||
"empty from address": {
|
||||
input: vestingtypes.NewMsgCreatePermanentLockedAccount(
|
||||
[]byte{},
|
||||
to1Addr,
|
||||
sdk.Coins{fooCoin},
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "invalid 'from' address",
|
||||
},
|
||||
"empty to address": {
|
||||
input: vestingtypes.NewMsgCreatePermanentLockedAccount(
|
||||
fromAddr,
|
||||
[]byte{},
|
||||
sdk.Coins{fooCoin},
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "invalid 'to' address",
|
||||
},
|
||||
"invalid coins": {
|
||||
input: vestingtypes.NewMsgCreatePermanentLockedAccount(
|
||||
fromAddr,
|
||||
to1Addr,
|
||||
sdk.Coins{sdk.Coin{Denom: "stake", Amount: math.NewInt(-1)}},
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "-1stake: invalid coins",
|
||||
},
|
||||
"create for existing account": {
|
||||
preRun: func() {
|
||||
toAcc := s.accountKeeper.NewAccountWithAddress(s.ctx, to1Addr)
|
||||
s.bankKeeper.EXPECT().IsSendEnabledCoins(gomock.Any(), fooCoin).Return(nil)
|
||||
s.bankKeeper.EXPECT().BlockedAddr(to1Addr).Return(false)
|
||||
s.accountKeeper.SetAccount(s.ctx, toAcc)
|
||||
},
|
||||
input: vestingtypes.NewMsgCreatePermanentLockedAccount(
|
||||
fromAddr,
|
||||
to1Addr,
|
||||
sdk.Coins{fooCoin},
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "already exists",
|
||||
},
|
||||
"create for blocked account": {
|
||||
preRun: func() {
|
||||
toAcc := s.accountKeeper.NewAccountWithAddress(s.ctx, to1Addr)
|
||||
s.bankKeeper.EXPECT().IsSendEnabledCoins(gomock.Any(), fooCoin).Return(nil)
|
||||
s.bankKeeper.EXPECT().BlockedAddr(to1Addr).Return(true)
|
||||
s.accountKeeper.SetAccount(s.ctx, toAcc)
|
||||
},
|
||||
input: vestingtypes.NewMsgCreatePermanentLockedAccount(
|
||||
fromAddr,
|
||||
to1Addr,
|
||||
sdk.Coins{fooCoin},
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "not allowed to receive funds",
|
||||
},
|
||||
|
||||
"create a valid permanent locked account": {
|
||||
preRun: func() {
|
||||
s.bankKeeper.EXPECT().IsSendEnabledCoins(gomock.Any(), fooCoin).Return(nil)
|
||||
s.bankKeeper.EXPECT().BlockedAddr(to2Addr).Return(false)
|
||||
s.bankKeeper.EXPECT().SendCoins(gomock.Any(), fromAddr, to2Addr, sdk.Coins{fooCoin}).Return(nil)
|
||||
},
|
||||
input: vestingtypes.NewMsgCreatePermanentLockedAccount(
|
||||
fromAddr,
|
||||
to2Addr,
|
||||
sdk.Coins{fooCoin},
|
||||
),
|
||||
expErr: false,
|
||||
expErrMsg: "",
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
s.Run(name, func() {
|
||||
if tc.preRun != nil {
|
||||
tc.preRun()
|
||||
}
|
||||
|
||||
_, err := s.msgServer.CreatePermanentLockedAccount(s.ctx, tc.input)
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.expErrMsg)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *VestingTestSuite) TestCreatePeriodicVestingAccount() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
preRun func()
|
||||
input *vestingtypes.MsgCreatePeriodicVestingAccount
|
||||
expErr bool
|
||||
expErrMsg string
|
||||
}{
|
||||
{
|
||||
name: "empty from address",
|
||||
input: vestingtypes.NewMsgCreatePeriodicVestingAccount(
|
||||
[]byte{},
|
||||
to1Addr,
|
||||
time.Now().Unix(),
|
||||
[]vestingtypes.Period{
|
||||
{
|
||||
Length: 10,
|
||||
Amount: sdk.NewCoins(periodCoin),
|
||||
},
|
||||
},
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "invalid 'from' address",
|
||||
},
|
||||
{
|
||||
name: "empty to address",
|
||||
input: vestingtypes.NewMsgCreatePeriodicVestingAccount(
|
||||
fromAddr,
|
||||
[]byte{},
|
||||
time.Now().Unix(),
|
||||
[]vestingtypes.Period{
|
||||
{
|
||||
Length: 10,
|
||||
Amount: sdk.NewCoins(periodCoin),
|
||||
},
|
||||
},
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "invalid 'to' address",
|
||||
},
|
||||
{
|
||||
name: "invalid start time",
|
||||
input: vestingtypes.NewMsgCreatePeriodicVestingAccount(
|
||||
fromAddr,
|
||||
to1Addr,
|
||||
0,
|
||||
[]vestingtypes.Period{
|
||||
{
|
||||
Length: 10,
|
||||
Amount: sdk.NewCoins(periodCoin),
|
||||
},
|
||||
},
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "invalid start time",
|
||||
},
|
||||
{
|
||||
name: "invalid period",
|
||||
input: vestingtypes.NewMsgCreatePeriodicVestingAccount(
|
||||
fromAddr,
|
||||
to1Addr,
|
||||
time.Now().Unix(),
|
||||
[]vestingtypes.Period{
|
||||
{
|
||||
Length: 0,
|
||||
Amount: sdk.NewCoins(periodCoin),
|
||||
},
|
||||
},
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "invalid period",
|
||||
},
|
||||
{
|
||||
name: "invalid coins",
|
||||
input: vestingtypes.NewMsgCreatePeriodicVestingAccount(
|
||||
fromAddr,
|
||||
to1Addr,
|
||||
time.Now().Unix(),
|
||||
[]vestingtypes.Period{
|
||||
{
|
||||
Length: 1,
|
||||
Amount: sdk.Coins{sdk.Coin{Denom: "stake", Amount: math.NewInt(-1)}},
|
||||
},
|
||||
},
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "-1stake: invalid coins",
|
||||
},
|
||||
{
|
||||
name: "create for existing account",
|
||||
preRun: func() {
|
||||
s.bankKeeper.EXPECT().BlockedAddr(to1Addr).Return(false)
|
||||
toAcc := s.accountKeeper.NewAccountWithAddress(s.ctx, to1Addr)
|
||||
s.accountKeeper.SetAccount(s.ctx, toAcc)
|
||||
},
|
||||
input: vestingtypes.NewMsgCreatePeriodicVestingAccount(
|
||||
fromAddr,
|
||||
to1Addr,
|
||||
time.Now().Unix(),
|
||||
[]vestingtypes.Period{
|
||||
{
|
||||
Length: 10,
|
||||
Amount: sdk.NewCoins(periodCoin),
|
||||
},
|
||||
},
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "already exists",
|
||||
},
|
||||
{
|
||||
name: "create for blocked address",
|
||||
preRun: func() {
|
||||
s.bankKeeper.EXPECT().BlockedAddr(to2Addr).Return(true)
|
||||
},
|
||||
input: vestingtypes.NewMsgCreatePeriodicVestingAccount(
|
||||
fromAddr,
|
||||
to2Addr,
|
||||
time.Now().Unix(),
|
||||
[]vestingtypes.Period{
|
||||
{
|
||||
Length: 10,
|
||||
Amount: sdk.NewCoins(periodCoin),
|
||||
},
|
||||
{
|
||||
Length: 20,
|
||||
Amount: sdk.NewCoins(fooCoin),
|
||||
},
|
||||
},
|
||||
),
|
||||
expErr: true,
|
||||
expErrMsg: "not allowed to receive funds",
|
||||
},
|
||||
{
|
||||
name: "create a valid periodic vesting account",
|
||||
preRun: func() {
|
||||
s.bankKeeper.EXPECT().IsSendEnabledCoins(gomock.Any(), periodCoin.Add(fooCoin)).Return(nil)
|
||||
s.bankKeeper.EXPECT().BlockedAddr(to2Addr).Return(false)
|
||||
s.bankKeeper.EXPECT().SendCoins(gomock.Any(), fromAddr, to2Addr, gomock.Any()).Return(nil)
|
||||
},
|
||||
input: vestingtypes.NewMsgCreatePeriodicVestingAccount(
|
||||
fromAddr,
|
||||
to2Addr,
|
||||
time.Now().Unix(),
|
||||
[]vestingtypes.Period{
|
||||
{
|
||||
Length: 10,
|
||||
Amount: sdk.NewCoins(periodCoin),
|
||||
},
|
||||
{
|
||||
Length: 20,
|
||||
Amount: sdk.NewCoins(fooCoin),
|
||||
},
|
||||
},
|
||||
),
|
||||
expErr: false,
|
||||
expErrMsg: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
if tc.preRun != nil {
|
||||
tc.preRun()
|
||||
}
|
||||
_, err := s.msgServer.CreatePeriodicVestingAccount(s.ctx, tc.input)
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.expErrMsg)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVestingTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(VestingTestSuite))
|
||||
}
|
||||
@ -1,106 +0,0 @@
|
||||
syntax = "proto3";
|
||||
package cosmos.vesting.v1beta1;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
import "cosmos/base/v1beta1/coin.proto";
|
||||
import "cosmos_proto/cosmos.proto";
|
||||
import "cosmos/vesting/v1beta1/vesting.proto";
|
||||
import "cosmos/msg/v1/msg.proto";
|
||||
import "amino/amino.proto";
|
||||
|
||||
option go_package = "cosmossdk.io/x/auth/vesting/types";
|
||||
|
||||
// Msg defines the bank Msg service.
|
||||
service Msg {
|
||||
option (cosmos.msg.v1.service) = true;
|
||||
|
||||
// CreateVestingAccount defines a method that enables creating a vesting
|
||||
// account.
|
||||
rpc CreateVestingAccount(MsgCreateVestingAccount) returns (MsgCreateVestingAccountResponse);
|
||||
// CreatePermanentLockedAccount defines a method that enables creating a permanent
|
||||
// locked account.
|
||||
//
|
||||
// Since: cosmos-sdk 0.46
|
||||
rpc CreatePermanentLockedAccount(MsgCreatePermanentLockedAccount) returns (MsgCreatePermanentLockedAccountResponse);
|
||||
// CreatePeriodicVestingAccount defines a method that enables creating a
|
||||
// periodic vesting account.
|
||||
//
|
||||
// Since: cosmos-sdk 0.46
|
||||
rpc CreatePeriodicVestingAccount(MsgCreatePeriodicVestingAccount) returns (MsgCreatePeriodicVestingAccountResponse);
|
||||
}
|
||||
|
||||
// MsgCreateVestingAccount defines a message that enables creating a vesting
|
||||
// account.
|
||||
message MsgCreateVestingAccount {
|
||||
option (cosmos.msg.v1.signer) = "from_address";
|
||||
option (amino.name) = "cosmos-sdk/MsgCreateVestingAccount";
|
||||
|
||||
option (gogoproto.equal) = true;
|
||||
|
||||
string from_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
|
||||
string to_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
|
||||
repeated cosmos.base.v1beta1.Coin amount = 3 [
|
||||
(gogoproto.nullable) = false,
|
||||
(amino.dont_omitempty) = true,
|
||||
(amino.encoding) = "legacy_coins",
|
||||
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
|
||||
];
|
||||
|
||||
// end of vesting as unix time (in seconds).
|
||||
int64 end_time = 4;
|
||||
bool delayed = 5;
|
||||
// start of vesting as unix time (in seconds).
|
||||
//
|
||||
// Since 0.51.x
|
||||
int64 start_time = 6;
|
||||
}
|
||||
|
||||
// MsgCreateVestingAccountResponse defines the Msg/CreateVestingAccount response type.
|
||||
message MsgCreateVestingAccountResponse {}
|
||||
|
||||
// MsgCreatePermanentLockedAccount defines a message that enables creating a permanent
|
||||
// locked account.
|
||||
//
|
||||
// Since: cosmos-sdk 0.46
|
||||
message MsgCreatePermanentLockedAccount {
|
||||
option (cosmos.msg.v1.signer) = "from_address";
|
||||
option (amino.name) = "cosmos-sdk/MsgCreatePermLockedAccount";
|
||||
option (gogoproto.equal) = true;
|
||||
|
||||
string from_address = 1 [(gogoproto.moretags) = "yaml:\"from_address\""];
|
||||
string to_address = 2 [(gogoproto.moretags) = "yaml:\"to_address\""];
|
||||
repeated cosmos.base.v1beta1.Coin amount = 3 [
|
||||
(gogoproto.nullable) = false,
|
||||
(amino.dont_omitempty) = true,
|
||||
(amino.encoding) = "legacy_coins",
|
||||
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
|
||||
];
|
||||
}
|
||||
|
||||
// MsgCreatePermanentLockedAccountResponse defines the Msg/CreatePermanentLockedAccount response type.
|
||||
//
|
||||
// Since: cosmos-sdk 0.46
|
||||
message MsgCreatePermanentLockedAccountResponse {}
|
||||
|
||||
// MsgCreateVestingAccount defines a message that enables creating a vesting
|
||||
// account.
|
||||
//
|
||||
// Since: cosmos-sdk 0.46
|
||||
message MsgCreatePeriodicVestingAccount {
|
||||
option (cosmos.msg.v1.signer) = "from_address";
|
||||
option (amino.name) = "cosmos-sdk/MsgCreatePeriodVestAccount";
|
||||
|
||||
option (gogoproto.equal) = false;
|
||||
|
||||
string from_address = 1;
|
||||
string to_address = 2;
|
||||
// start of vesting as unix time (in seconds).
|
||||
int64 start_time = 3;
|
||||
repeated Period vesting_periods = 4 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true];
|
||||
}
|
||||
|
||||
// MsgCreateVestingAccountResponse defines the Msg/CreatePeriodicVestingAccount
|
||||
// response type.
|
||||
//
|
||||
// Since: cosmos-sdk 0.46
|
||||
message MsgCreatePeriodicVestingAccountResponse {}
|
||||
Loading…
Reference in New Issue
Block a user