-
Notifications
You must be signed in to change notification settings - Fork 39
/
vesting_account.go
192 lines (161 loc) · 6.54 KB
/
vesting_account.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
package types
import (
fmt "fmt"
"time"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
vestexported "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported"
vesttypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
"gopkg.in/yaml.v2"
)
// for pretty purpose
type vestingAccountYAML struct {
Address sdk.AccAddress `json:"address" yaml:"address"`
PubKey string `json:"public_key" yaml:"public_key"`
AccountNumber uint64 `json:"account_number" yaml:"account_number"`
Sequence uint64 `json:"sequence" yaml:"sequence"`
OriginalVesting sdk.Coins `json:"original_vesting" yaml:"original_vesting"`
DelegatedFree sdk.Coins `json:"delegated_free" yaml:"delegated_free"`
DelegatedVesting sdk.Coins `json:"delegated_vesting" yaml:"delegated_vesting"`
EndTime int64 `json:"end_time" yaml:"end_time"`
// custom fields based on concrete vesting type which can be omitted
VestingSchedules VestingSchedules `json:"vesting_schedules,omitempty" yaml:"vesting_schedules,omitempty"`
}
//-----------------------------------------------------------------------------
// Lazy Graded Vesting Account
// LazyGradedVestingAccount implements the LazyGradedVestingAccount interface. It vests all
// coins according to a predefined schedule.
var (
_ vestexported.VestingAccount = (*LazyGradedVestingAccount)(nil)
_ authtypes.GenesisAccount = (*LazyGradedVestingAccount)(nil)
)
// NewLazyGradedVestingAccountRaw creates a new LazyGradedVestingAccount object from BaseVestingAccount
func NewLazyGradedVestingAccountRaw(baseVestingAcc *vesttypes.BaseVestingAccount, lazyVestingSchedules VestingSchedules) *LazyGradedVestingAccount {
return &LazyGradedVestingAccount{
BaseVestingAccount: baseVestingAcc,
VestingSchedules: lazyVestingSchedules,
}
}
// NewLazyGradedVestingAccount returns a new LazyGradedVestingAccount
func NewLazyGradedVestingAccount(baseAcc *authtypes.BaseAccount, originalVesting sdk.Coins, lazyVestingSchedules VestingSchedules) *LazyGradedVestingAccount {
baseVestingAcc := &vesttypes.BaseVestingAccount{
BaseAccount: baseAcc,
OriginalVesting: originalVesting,
DelegatedFree: sdk.NewCoins(),
DelegatedVesting: sdk.NewCoins(),
EndTime: 0,
}
return &LazyGradedVestingAccount{baseVestingAcc, lazyVestingSchedules}
}
// GetVestingSchedules returns the VestingSchedules of the graded lazy vesting account
func (lgva LazyGradedVestingAccount) GetVestingSchedules() VestingSchedules {
return lgva.VestingSchedules
}
// GetVestingSchedule returns the VestingSchedule of the given denom
func (lgva LazyGradedVestingAccount) GetVestingSchedule(denom string) (VestingSchedule, bool) {
for _, vs := range lgva.VestingSchedules {
if vs.Denom == denom {
return vs, true
}
}
return VestingSchedule{}, false
}
// GetVestedCoins returns the total amount of vested coins for a graded vesting
// account. All coins are vested continuously once the schedule's StartTime has elapsed until EndTime.
func (lgva LazyGradedVestingAccount) GetVestedCoins(blockTime time.Time) sdk.Coins {
var vestedCoins sdk.Coins
for _, ovc := range lgva.OriginalVesting {
if vestingSchedule, exists := lgva.GetVestingSchedule(ovc.Denom); exists {
vestedRatio := vestingSchedule.GetVestedRatio(blockTime.Unix())
vestedAmt := sdk.NewDecFromInt(ovc.Amount).Mul(vestedRatio).RoundInt()
if vestedAmt.Equal(sdk.ZeroInt()) {
continue
}
vestedCoins = append(vestedCoins, sdk.NewCoin(ovc.Denom, vestedAmt))
} else {
vestedCoins = append(vestedCoins, sdk.NewCoin(ovc.Denom, ovc.Amount))
}
}
return vestedCoins
}
// GetVestingCoins returns the total number of vesting coins for a graded
// vesting account.
func (lgva LazyGradedVestingAccount) GetVestingCoins(blockTime time.Time) sdk.Coins {
return lgva.OriginalVesting.Sub(lgva.GetVestedCoins(blockTime)...)
}
// LockedCoins returns the set of coins that are not spendable (i.e. locked).
func (lgva LazyGradedVestingAccount) LockedCoins(blockTime time.Time) sdk.Coins {
return lgva.BaseVestingAccount.LockedCoinsFromVesting(lgva.GetVestingCoins(blockTime))
}
// TrackDelegation tracks a delegation amount for any given vesting account type
// given the amount of coins currently vesting. It returns the resulting base
// coins.
//
// CONTRACT: The account's coins, delegation coins, vesting coins, and delegated
// vesting coins must be sorted.
func (lgva *LazyGradedVestingAccount) TrackDelegation(blockTime time.Time, balance, amount sdk.Coins) {
lgva.BaseVestingAccount.TrackDelegation(balance, lgva.GetVestingCoins(blockTime), amount)
}
// GetStartTime returns zero since a lazy graded vesting account has no start time.
func (lgva LazyGradedVestingAccount) GetStartTime() int64 {
return 0
}
// GetEndTime returns zero since a lazy graded vesting account has no end time.
func (lgva LazyGradedVestingAccount) GetEndTime() int64 {
return 0
}
// Validate checks for errors on the account fields
func (lgva LazyGradedVestingAccount) Validate() error {
denomMap := make(map[string]bool)
for _, vestingSchedule := range lgva.GetVestingSchedules() {
if _, ok := denomMap[vestingSchedule.Denom]; ok {
return fmt.Errorf("cannot have multiple vesting schedules for %s", vestingSchedule.Denom)
}
if err := vestingSchedule.Validate(); err != nil {
return err
}
denomMap[vestingSchedule.Denom] = true
}
return lgva.BaseVestingAccount.Validate()
}
// String implements fmt.Stringer interface
func (lgva LazyGradedVestingAccount) String() string {
out, _ := lgva.MarshalYAML()
return out.(string)
}
// MarshalYAML returns the YAML representation of a LazyGradedVestingAccount.
func (lgva LazyGradedVestingAccount) MarshalYAML() (interface{}, error) {
accAddr, err := sdk.AccAddressFromBech32(lgva.Address)
if err != nil {
return nil, err
}
out := vestingAccountYAML{
Address: accAddr,
AccountNumber: lgva.AccountNumber,
PubKey: getPKString(lgva),
Sequence: lgva.Sequence,
OriginalVesting: lgva.OriginalVesting,
DelegatedFree: lgva.DelegatedFree,
DelegatedVesting: lgva.DelegatedVesting,
EndTime: lgva.EndTime,
VestingSchedules: lgva.VestingSchedules,
}
return marshalYaml(out)
}
type getPK interface {
GetPubKey() cryptotypes.PubKey
}
func getPKString(g getPK) string {
if pk := g.GetPubKey(); pk != nil {
return pk.String()
}
return ""
}
func marshalYaml(i interface{}) (interface{}, error) {
bz, err := yaml.Marshal(i)
if err != nil {
return nil, err
}
return string(bz), nil
}