-
Notifications
You must be signed in to change notification settings - Fork 0
/
place_bet.go
112 lines (89 loc) · 2.94 KB
/
place_bet.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/furynet/furynetwork/x/bet/types"
markettypes "github.com/furynet/furynetwork/x/market/types"
"github.com/spf13/cast"
)
// PlaceBet stores a new bet in KVStore
func (k Keeper) PlaceBet(ctx sdk.Context, bet *types.Bet) error {
bettorAddress, err := sdk.AccAddressFromBech32(bet.Creator)
if err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "%s", err)
}
market, err := k.getMarket(ctx, bet.MarketUID)
if err != nil {
return err
}
// check if selected odds is valid
if !oddsExists(bet.OddsUID, market.Odds) {
return types.ErrOddsUIDNotExist
}
// check minimum bet amount allowed
betConstraints := market.GetBetConstraints()
if betConstraints == nil {
market.BetConstraints = k.marketKeeper.GetDefaultBetConstraints(ctx)
}
if bet.Amount.LT(market.BetConstraints.MinAmount) {
return types.ErrBetAmountIsLow
}
// modify the bet fee and subtracted amount
setBetFee(bet, market.BetConstraints.BetFee)
// calculate payoutProfit
payoutProfit, err := types.CalculatePayoutProfit(bet.OddsType, bet.OddsValue, bet.Amount)
if err != nil {
return err
}
stats := k.GetBetStats(ctx)
stats.Count++
betID := stats.Count
betFulfillment, err := k.srKeeper.ProcessBetPlacement(
ctx, bet.UID, bet.MarketUID, bet.OddsUID, bet.MaxLossMultiplier, bet.Amount, payoutProfit,
bettorAddress, bet.BetFee, bet.OddsType, bet.OddsValue, betID,
)
if err != nil {
return sdkerrors.Wrapf(types.ErrInSRPlacementProcessing, "%s", err)
}
// set bet as placed
bet.Status = types.Bet_STATUS_PLACED
// put bet in the result pending status
bet.Result = types.Bet_RESULT_PENDING
bet.CreatedAt = ctx.BlockTime().Unix()
bet.BetFulfillment = betFulfillment
// store bet in the module state
k.SetBet(ctx, *bet, betID)
// set bet as a pending bet
k.SetPendingBet(ctx, types.NewPendingBet(bet.UID, bet.Creator), betID, bet.MarketUID)
// set bet stats
k.SetBetStats(ctx, stats)
return nil
}
// getMarket returns market with id
func (k Keeper) getMarket(ctx sdk.Context, marketID string) (markettypes.Market, error) {
market, found := k.marketKeeper.GetMarket(ctx, marketID)
if !found {
return markettypes.Market{}, types.ErrNoMatchingMarket
}
if market.Status != markettypes.MarketStatus_MARKET_STATUS_ACTIVE {
return markettypes.Market{}, types.ErrInactiveMarket
}
if market.EndTS < cast.ToUint64(ctx.BlockTime().Unix()) {
return markettypes.Market{}, types.ErrEndTSIsPassed
}
return market, nil
}
// oddsExists checks if bet odds id is present in the market list of odds uids
func oddsExists(betOddsUID string, odds []*markettypes.Odds) bool {
for _, o := range odds {
if betOddsUID == o.UID {
return true
}
}
return false
}
// setBetFee sets the bet fee and subtracted amount of bet object pointer
func setBetFee(bet *types.Bet, betFee sdk.Int) {
bet.Amount = bet.Amount.Sub(betFee)
bet.BetFee = betFee
}