Get current campaign configurations from the state.
Validate the payload of the campaign update.
Check the Authorization if the creator and the campaign promoter are not the same.
Calculate the top-up amount of the campaign pool.
Update the end timestamp of the campaign.
Update the active or inactive status of the campaign.
func (k msgServer) UpdateCampaign(goCtx context.Context, msg *types.MsgUpdateCampaign) (*types.MsgUpdateCampaignResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx)var payload types.UpdateCampaignPayloadif err := k.ovmKeeper.VerifyTicketUnmarshal(goCtx, msg.Ticket, &payload); err !=nil {returnnil, sdkerrors.Wrapf(types.ErrInTicketVerification, "%s", err) }if err := payload.Validate(cast.ToUint64(ctx.BlockTime().Unix())); err !=nil {returnnil, err }// Check if the value exists campaign, isFound := k.GetCampaign(ctx, msg.Uid)if!isFound {returnnil, sdkerrors.Wrapf(sdkerrtypes.ErrKeyNotFound, "campaign with the id: %s does not exist", msg.Uid) }if!campaign.IsActive {returnnil, sdkerrors.Wrap(sdkerrtypes.ErrInvalidRequest, "inactive campaign can not be updated") }// Checks if the msg creator is the same as the current ownerif msg.Creator != campaign.Promoter {if err := utils.ValidateMsgAuthorization(k.authzKeeper, ctx, msg.Creator, campaign.Promoter, msg, types.ErrAuthorizationNotFound, types.ErrAuthorizationNotAccepted); err !=nil {returnnil, err } }if!msg.TopupFunds.IsNil() && msg.TopupFunds.GT(sdkmath.ZeroInt()) {// transfer the pool amount to the reward pool module accountif err := k.modFunder.Fund(types.RewardPoolFunder{}, ctx, sdk.MustAccAddressFromBech32(campaign.Promoter), msg.TopupFunds, ); err !=nil {returnnil, sdkerrors.Wrapf(types.ErrInFundingCampaignPool, "%s", err) } campaign.Pool.Total = campaign.Pool.Total.Add(msg.TopupFunds) } campaign.EndTS = payload.EndTs campaign.IsActive = payload.IsActive k.SetCampaign(ctx, campaign) msg.EmitEvent(&ctx, msg.Uid)return&types.MsgUpdateCampaignResponse{}, nil}
WithdrawFunds
There are several steps for a campaign funds withdrawal to be made:
Get the campaign from the blockchain state.
Validate authorization if the promoter and the creator are not the same.
Calculate the available amount that can be withdrawn from the campaign pool.
Transfer the withdrawable amount from the pool module account to the promoter.
Update the campaign balance and set in the state of the blockchain.
func (k msgServer) WithdrawFunds(goCtx context.Context, msg *types.MsgWithdrawFunds) (*types.MsgWithdrawFundsResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx)var payload types.WithdrawFundsPayloadif err := k.ovmKeeper.VerifyTicketUnmarshal(goCtx, msg.Ticket, &payload); err !=nil {returnnil, sdkerrors.Wrapf(types.ErrInTicketVerification, "%s", err) }// Validate ticket payloadif err := payload.Validate(); err !=nil {returnnil, err }// Check if the campaign exists valFound, isFound := k.GetCampaign(ctx, msg.Uid)if!isFound {returnnil, sdkerrors.Wrap(sdkerrtypes.ErrKeyNotFound, "campaign not found") }if payload.Promoter != valFound.Promoter {returnnil, sdkerrors.Wrap(sdkerrtypes.ErrKeyNotFound, "promoter should be the same as stored campaign promoter") }// Checks if the msg creator is the same as the current ownerif msg.Creator != valFound.Promoter {if err := utils.ValidateMsgAuthorization(k.authzKeeper, ctx, msg.Creator, valFound.Promoter, msg, types.ErrAuthorizationNotFound, types.ErrAuthorizationNotAccepted); err !=nil {returnnil, err } } availableAmount := valFound.Pool.Total.Sub(valFound.Pool.Spent)// check if the pool amount is positiveif availableAmount.IsNil() ||!availableAmount.GT(sdkmath.ZeroInt()) {returnnil, sdkerrors.Wrapf(types.ErrWithdrawFromCampaignPool, "pool amount should be positive") }// transfer the funds present in campaign to the promoterif err := k.modFunder.Refund(types.RewardPoolFunder{}, ctx, sdk.MustAccAddressFromBech32(payload.Promoter), availableAmount, ); err !=nil {returnnil, sdkerrors.Wrapf(types.ErrWithdrawFromCampaignPool, "%s", err) }// set the pool amount to zero valFound.Pool.Total = sdkmath.ZeroInt()// deactivate the campaign valFound.IsActive =false// store the campaign k.SetCampaign(ctx, valFound)// emit withdraw event msg.EmitEvent(&ctx, msg.Uid)return&types.MsgWithdrawFundsResponse{}, nil}
GrantReward
There are several steps for a reward to be granted:
Check for existing rewards with the identifier.
Retrieve the campaign information from the blockchain state.
Check the campaign validity period according to the current block time.
Calculate the reward amount according to the campaign reward type and category.
Check the claims per category for the reward.
Check the campaign pool balance to have enough funds.
Distribute the reward to the corresponding receiver account's subaccount.
Update the campaign's pool spent amount.
Store the reward, reward by campaign and reward by category into the blockchain state.