cosmos-sdk/x/auth/vesting/msg_server.go

227 lines
6.0 KiB
Go

package vesting
import (
"context"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/armon/go-metrics"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth/keeper"
"github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
)
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(goCtx context.Context, msg *types.MsgCreateVestingAccount) (*types.MsgCreateVestingAccountResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
ak := s.AccountKeeper
bk := s.BankKeeper
if err := bk.IsSendEnabledCoins(ctx, msg.Amount...); err != nil {
return nil, err
}
from, err := sdk.AccAddressFromBech32(msg.FromAddress)
if err != nil {
return nil, err
}
to, err := sdk.AccAddressFromBech32(msg.ToAddress)
if err != nil {
return nil, err
}
if bk.BlockedAddr(to) {
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", msg.ToAddress)
}
if acc := ak.GetAccount(ctx, to); acc != nil {
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "account %s already exists", msg.ToAddress)
}
baseAccount := ak.NewAccountWithAddress(ctx, to)
if _, ok := baseAccount.(*authtypes.BaseAccount); !ok {
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid account type; expected: BaseAccount, got: %T", baseAccount)
}
baseVestingAccount := types.NewBaseVestingAccount(baseAccount.(*authtypes.BaseAccount), msg.Amount.Sort(), msg.EndTime)
var acc authtypes.AccountI
if msg.Delayed {
acc = types.NewDelayedVestingAccountRaw(baseVestingAccount)
} else {
acc = types.NewContinuousVestingAccountRaw(baseVestingAccount, ctx.BlockTime().Unix())
}
ak.SetAccount(ctx, acc)
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)},
)
}
}
}()
err = bk.SendCoins(ctx, from, to, msg.Amount)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
)
return &types.MsgCreateVestingAccountResponse{}, nil
}
func (s msgServer) CreatePermanentLockedAccount(goCtx context.Context, msg *types.MsgCreatePermanentLockedAccount) (*types.MsgCreatePermanentLockedAccountResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
ak := s.AccountKeeper
bk := s.BankKeeper
if err := bk.IsSendEnabledCoins(ctx, msg.Amount...); err != nil {
return nil, err
}
from, err := sdk.AccAddressFromBech32(msg.FromAddress)
if err != nil {
return nil, err
}
to, err := sdk.AccAddressFromBech32(msg.ToAddress)
if err != nil {
return nil, err
}
if bk.BlockedAddr(to) {
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", msg.ToAddress)
}
if acc := ak.GetAccount(ctx, to); acc != nil {
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "account %s already exists", msg.ToAddress)
}
baseAccountI := ak.NewAccountWithAddress(ctx, to)
baseAcc, ok := baseAccountI.(*authtypes.BaseAccount)
if !ok {
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid account type; expected: BaseAccount, got: %T", baseAccountI)
}
var acc authtypes.AccountI = types.NewPermanentLockedAccount(baseAcc, msg.Amount)
ak.SetAccount(ctx, acc)
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)},
)
}
}
}()
err = bk.SendCoins(ctx, from, to, msg.Amount)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
)
return &types.MsgCreatePermanentLockedAccountResponse{}, nil
}
func (s msgServer) CreatePeriodicVestingAccount(goCtx context.Context, msg *types.MsgCreatePeriodicVestingAccount) (*types.MsgCreatePeriodicVestingAccountResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
ak := s.AccountKeeper
bk := s.BankKeeper
from, err := sdk.AccAddressFromBech32(msg.FromAddress)
if err != nil {
return nil, err
}
to, err := sdk.AccAddressFromBech32(msg.ToAddress)
if err != nil {
return nil, err
}
if acc := ak.GetAccount(ctx, to); acc != nil {
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "account %s already exists", msg.ToAddress)
}
var totalCoins sdk.Coins
for _, period := range msg.VestingPeriods {
totalCoins = totalCoins.Add(period.Amount...)
}
baseAccount := ak.NewAccountWithAddress(ctx, to)
acc := types.NewPeriodicVestingAccount(baseAccount.(*authtypes.BaseAccount), totalCoins.Sort(), msg.StartTime, msg.VestingPeriods)
ak.SetAccount(ctx, acc)
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)},
)
}
}
}()
err = bk.SendCoins(ctx, from, to, totalCoins)
if err != nil {
return nil, err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
)
return &types.MsgCreatePeriodicVestingAccountResponse{}, nil
}