/
redeem.go
114 lines (91 loc) · 3.56 KB
/
redeem.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
package keeper
import (
sdkerrors "cosmossdk.io/errors"
"cosmossdk.io/math"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/celinium-network/celinium/x/liquidstake/types"
)
// UpdateRedeemRate update redeemrate for each source chain
// TODO Record the rate in the last few epochs, and then average?
func (k Keeper) UpdateRedeemRate(ctx sdk.Context, delegations []types.ProxyDelegation) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, types.SouceChainKeyPrefix)
chainProcessingAmts := k.GetDelegaionProcessingAmount(delegations)
for ; iterator.Valid(); iterator.Next() {
sourcechain := &types.SourceChain{}
bz := iterator.Value()
k.cdc.MustUnmarshal(bz, sourcechain)
if !k.sourceChainAvaiable(ctx, sourcechain) {
continue
}
// If the status of a ProxyDelegation is `ProxyDelegationDone`, it maybe remove from the store.
// So the stakingAmount = stakedAmount.
stakingAmount := sourcechain.StakedAmount
processingAmount, found := chainProcessingAmts[sourcechain.ChainID]
if !found {
processingAmount = math.ZeroInt()
}
if stakingAmount.IsNil() {
stakingAmount = math.ZeroInt()
}
stakingAmount = stakingAmount.Add(processingAmount)
derivationAmount := k.bankKeeper.GetSupply(ctx, sourcechain.DerivativeDenom)
if derivationAmount.IsZero() || stakingAmount.IsZero() {
// TODO precise
sourcechain.Redemptionratio = sdk.NewDec(1)
} else {
sourcechain.Redemptionratio = sdk.NewDecFromInt(stakingAmount).Quo(sdk.NewDecFromInt(derivationAmount.Amount))
}
k.SetSourceChain(ctx, sourcechain)
}
}
func (k Keeper) GetDelegaionProcessingAmount(delegations []types.ProxyDelegation) map[string]math.Int {
chainAmts := make(map[string]math.Int)
for _, delegation := range delegations {
if !types.IsProxyDelegationProcessing(delegation.Status) {
continue
}
if delegation.Coin.Amount.IsZero() {
continue
}
amt, found := chainAmts[delegation.ChainID]
userDelegationAmt := delegation.Coin.Amount
if !delegation.ReinvestAmount.IsZero() {
userDelegationAmt = userDelegationAmt.Sub(delegation.ReinvestAmount)
}
if !found {
chainAmts[delegation.ChainID] = userDelegationAmt
} else {
chainAmts[delegation.ChainID] = userDelegationAmt.Add(amt)
}
}
return chainAmts
}
// ClaimUnbonding implement delegator claim reward and stake token.
func (k Keeper) ClaimUnbonding(ctx sdk.Context, deletator sdk.AccAddress, epoch uint64, chainID string) (math.Int, error) {
undelegationRecord, found := k.GetUserUnbonding(ctx, chainID, epoch, deletator.String())
if !found {
return math.ZeroInt(), sdkerrors.Wrapf(types.ErrUserUndelegationNotExist, "chainID %s, epoch %d, address %s",
chainID, epoch, deletator.String())
}
if undelegationRecord.CliamStatus != types.UserUnbondingClaimable {
return math.ZeroInt(), sdkerrors.Wrapf(types.ErrUserUndelegationWatting, "chainID %s, epoch %d, address %s",
chainID, epoch, deletator.String())
}
sourceChain, found := k.GetSourceChain(ctx, chainID)
if !found {
return math.ZeroInt(), sdkerrors.Wrapf(types.ErrUnknownSourceChain, "chainID %s", chainID)
}
chainDelegatorAccAddress, err := sdk.AccAddressFromBech32(sourceChain.DelegateAddress)
if err != nil {
return math.ZeroInt(), err
}
err = k.sendCoinsFromAccountToAccount(ctx, chainDelegatorAccAddress, deletator, sdk.NewCoins(undelegationRecord.RedeemCoin))
if err != nil {
return math.ZeroInt(), err
}
undelegationRecord.CliamStatus = types.UserUnbondingComplete
k.SetUserUnbonding(ctx, undelegationRecord)
return math.ZeroInt(), nil
}