-
Notifications
You must be signed in to change notification settings - Fork 0
/
orderbook_settle.go
130 lines (114 loc) · 4.18 KB
/
orderbook_settle.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package keeper
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/spf13/cast"
"github.com/furynet/xfury/x/strategicreserve/types"
)
// BatchOrderBookSettlements settles order books
func (k Keeper) BatchOrderBookSettlements(ctx sdk.Context) error {
toFetch := k.GetParams(ctx).BatchSettlementCount
// get the first resolved strategicreserve to process corresponding active deposits.
orderBookUID, found := k.GetFirstUnsettledResolvedOrderBook(ctx)
// return if there is no resolved strategicreserve.
if !found {
return nil
}
book, found := k.GetOrderBook(ctx, orderBookUID)
if !found {
return fmt.Errorf("strategicreserve not found %s", orderBookUID)
}
if book.Status != types.OrderBookStatus_ORDER_BOOK_STATUS_STATUS_RESOLVED {
return fmt.Errorf("strategicreserve status not resolved %s", orderBookUID)
}
// settle order book active deposits.
allSettled, err := k.batchSettlementOfDeposit(ctx, orderBookUID, toFetch)
if err != nil {
return fmt.Errorf("could not settle strategicreserve %s %s", orderBookUID, err)
}
// if there is not any active deposit for strategicreserve
// we need to remove its uid from the list of unsettled resolved orderbooks.
if allSettled {
k.RemoveUnsettledResolvedOrderBook(ctx, orderBookUID)
}
return nil
}
// batchSettlementOfDeposit settles active deposits of a strategicreserve
func (k Keeper) batchSettlementOfDeposit(ctx sdk.Context, orderBookUID string, countToBeSettled uint64) (allSettled bool, err error) {
// initialize iterator for the certain number of active deposits
// equal to countToBeSettled
allSettled, settled := true, 0
bookParticipations, err := k.GetParticipationsOfOrderBook(ctx, orderBookUID)
if err != nil {
return false, fmt.Errorf("batch settlement of book %s failed: %s", orderBookUID, err)
}
for _, bookParticipation := range bookParticipations {
if !bookParticipation.IsSettled {
err = k.settleDeposit(ctx, bookParticipation)
if err != nil {
return allSettled, fmt.Errorf("failed to settle deposit of batch settlement for participation %#v: %s",
bookParticipation, err)
}
settled++
allSettled = false
}
if cast.ToUint64(settled) >= countToBeSettled {
break
}
}
return allSettled, nil
}
func (k Keeper) settleDeposit(ctx sdk.Context, bp types.OrderBookParticipation) error {
if bp.IsSettled {
return sdkerrors.Wrapf(types.ErrBookParticipationAlreadySettled, "%s %d", bp.OrderBookUID, bp.Index)
}
if bp.IsModuleAccount {
depositPlusProfit := bp.Liquidity.Add(bp.ActualProfit)
if depositPlusProfit.LTE(bp.Liquidity) {
// transfer amount to `sr_pool` module account
err := k.transferFundsFromModuleToModule(ctx, types.OrderBookLiquidityName, types.SRPoolName, depositPlusProfit)
if err != nil {
return err
}
} else {
// transfer initial amount to `sr_pool` module account
err := k.transferFundsFromModuleToModule(ctx, types.OrderBookLiquidityName, types.SRPoolName, bp.Liquidity)
if err != nil {
return err
}
// transfer profit to `sr_profit_pool` module account
err = k.transferFundsFromModuleToModule(ctx, types.OrderBookLiquidityName, types.SRProfitName, bp.ActualProfit)
if err != nil {
return err
}
}
} else {
depositPlusProfit := bp.Liquidity.Add(bp.ActualProfit)
depositorAddress, err := sdk.AccAddressFromBech32(bp.ParticipantAddress)
if err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, types.ErrTextInvalidDesositor, err)
}
if depositPlusProfit.LTE(bp.Liquidity) {
// transfer amount to depositor address
err := k.transferFundsFromModuleToAccount(ctx, types.OrderBookLiquidityName, depositorAddress, depositPlusProfit)
if err != nil {
return err
}
} else {
// transfer initial amount to depositor address
err := k.transferFundsFromModuleToAccount(ctx, types.OrderBookLiquidityName, depositorAddress, bp.Liquidity)
if err != nil {
return err
}
// transfer profit to depositor address
err = k.transferFundsFromModuleToAccount(ctx, types.OrderBookLiquidityName, depositorAddress, bp.ActualProfit)
if err != nil {
return err
}
}
}
bp.IsSettled = true
k.SetOrderBookParticipation(ctx, bp)
return nil
}