github.com/Finschia/finschia-sdk@v0.48.1/x/auth/vesting/msg_server.go (about)

     1  package vesting
     2  
     3  import (
     4  	"context"
     5  
     6  	authtypes "github.com/Finschia/finschia-sdk/x/auth/types"
     7  
     8  	"github.com/armon/go-metrics"
     9  
    10  	"github.com/Finschia/finschia-sdk/telemetry"
    11  	sdk "github.com/Finschia/finschia-sdk/types"
    12  	sdkerrors "github.com/Finschia/finschia-sdk/types/errors"
    13  	"github.com/Finschia/finschia-sdk/x/auth/keeper"
    14  	"github.com/Finschia/finschia-sdk/x/auth/vesting/types"
    15  )
    16  
    17  type msgServer struct {
    18  	keeper.AccountKeeper
    19  	types.BankKeeper
    20  }
    21  
    22  // NewMsgServerImpl returns an implementation of the vesting MsgServer interface,
    23  // wrapping the corresponding AccountKeeper and BankKeeper.
    24  func NewMsgServerImpl(k keeper.AccountKeeper, bk types.BankKeeper) types.MsgServer {
    25  	return &msgServer{AccountKeeper: k, BankKeeper: bk}
    26  }
    27  
    28  var _ types.MsgServer = msgServer{}
    29  
    30  func (s msgServer) CreateVestingAccount(goCtx context.Context, msg *types.MsgCreateVestingAccount) (*types.MsgCreateVestingAccountResponse, error) {
    31  	ctx := sdk.UnwrapSDKContext(goCtx)
    32  	ak := s.AccountKeeper
    33  	bk := s.BankKeeper
    34  
    35  	if err := bk.IsSendEnabledCoins(ctx, msg.Amount...); err != nil {
    36  		return nil, err
    37  	}
    38  
    39  	from, err := sdk.AccAddressFromBech32(msg.FromAddress)
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	to, err := sdk.AccAddressFromBech32(msg.ToAddress)
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  
    48  	if bk.BlockedAddr(to) {
    49  		return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", msg.ToAddress)
    50  	}
    51  
    52  	if acc := ak.GetAccount(ctx, to); acc != nil {
    53  		return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "account %s already exists", msg.ToAddress)
    54  	}
    55  
    56  	baseAccount := ak.NewAccountWithAddress(ctx, to)
    57  	if _, ok := baseAccount.(*authtypes.BaseAccount); !ok {
    58  		return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid account type; expected: BaseAccount, got: %T", baseAccount)
    59  	}
    60  
    61  	baseVestingAccount := types.NewBaseVestingAccount(baseAccount.(*authtypes.BaseAccount), msg.Amount.Sort(), msg.EndTime)
    62  
    63  	var acc authtypes.AccountI
    64  
    65  	if msg.Delayed {
    66  		acc = types.NewDelayedVestingAccountRaw(baseVestingAccount)
    67  	} else {
    68  		acc = types.NewContinuousVestingAccountRaw(baseVestingAccount, ctx.BlockTime().Unix())
    69  	}
    70  
    71  	ak.SetAccount(ctx, acc)
    72  
    73  	defer func() {
    74  		telemetry.IncrCounter(1, "new", "account")
    75  
    76  		for _, a := range msg.Amount {
    77  			if a.Amount.IsInt64() {
    78  				telemetry.SetGaugeWithLabels(
    79  					[]string{"tx", "msg", "create_vesting_account"},
    80  					float32(a.Amount.Int64()),
    81  					[]metrics.Label{telemetry.NewLabel("denom", a.Denom)},
    82  				)
    83  			}
    84  		}
    85  	}()
    86  
    87  	err = bk.SendCoins(ctx, from, to, msg.Amount)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	return &types.MsgCreateVestingAccountResponse{}, nil
    93  }