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

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