package keeper import ( "context" "errors" "fmt" "math/big" "time" colinearmath "colinear/x/colinearcore/math" "colinear/x/colinearcore/types" sdk "github.com/cosmos/cosmos-sdk/types" ) func (k msgServer) ClaimFunds(goCtx context.Context, msg *types.MsgClaimFunds) (*types.MsgClaimFundsResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) // check that auction exists auction, found := k.Keeper.GetAuction(ctx, msg.AuctionId) if !found { return nil, fmt.Errorf("auction %s not found", msg.AuctionId) } // check that auction is finalized if auction.Best == nil { return nil, fmt.Errorf("auction %s is not finalized", msg.AuctionId) } // check that auction has remaining funds to pay out if auction.Remaining == "0" { return nil, fmt.Errorf("auction %s has no payable %s remaining", msg.AuctionId, auction.Denom) } // check that sender is the selected provider for the auction if auction.Best.Owner != msg.Creator { return nil, fmt.Errorf("lease reward is only claimable by selected provider (%s) (got %s)", auction.Best.Owner, msg.Creator) } // parse address to send to sendTo, err := sdk.AccAddressFromBech32(auction.Best.Owner) if err != nil { return nil, fmt.Errorf("failed to parse address %s: %s", auction.Best.Owner, err) } // calculate payable amount total := new(big.Int) total.SetString(auction.Best.Amount, 10) remaining := new(big.Int) remaining.SetString(auction.Remaining, 10) leaseBegin := time.Unix(int64(auction.LeaseStart), 0) leaseEnd := time.Unix(int64(auction.LeaseEnd), 0) now := ctx.BlockTime() subAmt, err := colinearmath.CalcAmountVestableLinear(total, remaining, now, leaseBegin, leaseEnd) if err != nil { return nil, errors.New("unable to calculate vestable amount") } // pay from module to user account coins := sdk.NewCoins(sdk.NewCoin(auction.Denom, sdk.NewIntFromBigInt(subAmt))) if err := k.bank.SendCoinsFromModuleToAccount(ctx, types.ModuleName, sendTo, coins); err != nil { return nil, fmt.Errorf("failed to send %s %s from module %s", subAmt.String(), auction.Denom, types.ModuleName) } // subtract paid amount off of remaining payout tally & commit to chain state newRemaining := new(big.Int) newRemaining.Sub(remaining, subAmt) auction.Remaining = subAmt.String() k.Keeper.SetAuction(ctx, auction) return &types.MsgClaimFundsResponse{}, nil }