code.vegaprotocol.io/vega@v0.79.0/datanode/entities/proposal.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package entities 17 18 import ( 19 "encoding/json" 20 "fmt" 21 "time" 22 23 "code.vegaprotocol.io/vega/libs/num" 24 "code.vegaprotocol.io/vega/libs/ptr" 25 v2 "code.vegaprotocol.io/vega/protos/data-node/api/v2" 26 "code.vegaprotocol.io/vega/protos/vega" 27 28 "google.golang.org/protobuf/encoding/protojson" 29 ) 30 31 type ProposalType v2.ListGovernanceDataRequest_Type 32 33 var ( 34 ProposalTypeAll = ProposalType(v2.ListGovernanceDataRequest_TYPE_ALL) 35 ProposalTypeNewMarket = ProposalType(v2.ListGovernanceDataRequest_TYPE_NEW_MARKET) 36 ProposalTypeNewAsset = ProposalType(v2.ListGovernanceDataRequest_TYPE_NEW_ASSET) 37 ProposalTypeUpdateAsset = ProposalType(v2.ListGovernanceDataRequest_TYPE_UPDATE_ASSET) 38 ProposalTypeUpdateMarket = ProposalType(v2.ListGovernanceDataRequest_TYPE_UPDATE_MARKET) 39 ProposalTypeUpdateNetworkParameter = ProposalType(v2.ListGovernanceDataRequest_TYPE_NETWORK_PARAMETERS) 40 ProposalTypeNewFreeform = ProposalType(v2.ListGovernanceDataRequest_TYPE_NEW_FREE_FORM) 41 ProposalTypeNewSpotMarket = ProposalType(v2.ListGovernanceDataRequest_TYPE_NEW_SPOT_MARKET) 42 ProposalTypeUpdateSpotMarket = ProposalType(v2.ListGovernanceDataRequest_TYPE_UPDATE_SPOT_MARKET) 43 ProposalTypeNewTransfer = ProposalType(v2.ListGovernanceDataRequest_TYPE_NEW_TRANSFER) 44 ProposalTypeCancelTransfer = ProposalType(v2.ListGovernanceDataRequest_TYPE_CANCEL_TRANSFER) 45 ProposalTypeUpdateMarketState = ProposalType(v2.ListGovernanceDataRequest_TYPE_UPDATE_MARKET_STATE) 46 ProposalTypeUpdateReferralProgram = ProposalType(v2.ListGovernanceDataRequest_TYPE_UPDATE_REFERRAL_PROGRAM) 47 ProposalTypeUpdateVolumeDiscountProgram = ProposalType(v2.ListGovernanceDataRequest_TYPE_UPDATE_VOLUME_DISCOUNT_PROGRAM) 48 ProposalTypeAutomatedPurchase = ProposalType(v2.ListGovernanceDataRequest_TYPE_NEW_AUTOMATED_PURCHASE) 49 ) 50 51 func (p *ProposalType) String() string { 52 if p == nil { 53 return "" 54 } 55 switch *p { 56 case ProposalTypeAll: 57 return "all" 58 case ProposalTypeNewMarket: 59 return "newMarket" 60 case ProposalTypeNewAsset: 61 return "newAsset" 62 case ProposalTypeUpdateAsset: 63 return "updateAsset" 64 case ProposalTypeUpdateMarket: 65 return "updateMarket" 66 case ProposalTypeUpdateNetworkParameter: 67 return "updateNetworkParameter" 68 case ProposalTypeNewFreeform: 69 return "newFreeform" 70 case ProposalTypeNewSpotMarket: 71 return "newSpotMarket" 72 case ProposalTypeUpdateSpotMarket: 73 return "updateSpotMarket" 74 case ProposalTypeNewTransfer: 75 return "newTransfer" 76 case ProposalTypeCancelTransfer: 77 return "cancelTransfer" 78 case ProposalTypeUpdateMarketState: 79 return "updateMarketState" 80 case ProposalTypeUpdateReferralProgram: 81 return "updateReferralProgram" 82 case ProposalTypeUpdateVolumeDiscountProgram: 83 return "updateVolumeDiscountProgram" 84 case ProposalTypeAutomatedPurchase: 85 return "NewProtocolAutomatedPurchase" 86 default: 87 return "unknown" 88 } 89 } 90 91 type _Proposal struct{} 92 93 type ProposalID = ID[_Proposal] 94 95 type Proposal struct { 96 ID ProposalID 97 BatchID ProposalID 98 Reference string 99 PartyID PartyID 100 State ProposalState 101 Rationale ProposalRationale 102 Terms ProposalTerms 103 BatchTerms BatchProposalTerms 104 Reason ProposalError 105 ErrorDetails string 106 ProposalTime time.Time 107 VegaTime time.Time 108 RequiredMajority num.Decimal 109 RequiredParticipation num.Decimal 110 RequiredLPMajority *num.Decimal 111 RequiredLPParticipation *num.Decimal 112 TxHash TxHash 113 Proposals []Proposal 114 } 115 116 func (p Proposal) IsBatch() bool { 117 return p.BatchTerms.BatchProposalTerms != nil 118 } 119 120 func (p Proposal) BelongsToBatch() bool { 121 return len(p.BatchID) > 0 122 } 123 124 func (p Proposal) ToProto() *vega.Proposal { 125 var lpMajority *string 126 if !p.RequiredLPMajority.IsZero() { 127 lpMajority = toPtr(p.RequiredLPMajority.String()) 128 } 129 var lpParticipation *string 130 if !p.RequiredLPParticipation.IsZero() { 131 lpParticipation = toPtr(p.RequiredLPParticipation.String()) 132 } 133 134 var reason *vega.ProposalError 135 if p.Reason != ProposalErrorUnspecified { 136 reason = ptr.From(vega.ProposalError(p.Reason)) 137 } 138 139 var errDetails *string 140 if len(p.ErrorDetails) > 0 { 141 errDetails = ptr.From(p.ErrorDetails) 142 } 143 144 var batchID *string 145 if len(p.BatchID) > 0 { 146 batchID = ptr.From(p.BatchID.String()) 147 } 148 149 pp := vega.Proposal{ 150 Id: p.ID.String(), 151 BatchId: batchID, 152 Reference: p.Reference, 153 PartyId: p.PartyID.String(), 154 State: vega.Proposal_State(p.State), 155 Rationale: p.Rationale.ProposalRationale, 156 Timestamp: p.ProposalTime.UnixNano(), 157 Terms: p.Terms.ProposalTerms, 158 BatchTerms: p.BatchTerms.BatchProposalTerms, 159 Reason: reason, 160 ErrorDetails: errDetails, 161 RequiredMajority: p.RequiredMajority.String(), 162 RequiredParticipation: p.RequiredParticipation.String(), 163 RequiredLiquidityProviderMajority: lpMajority, 164 RequiredLiquidityProviderParticipation: lpParticipation, 165 } 166 return &pp 167 } 168 169 func (p Proposal) Cursor() *Cursor { 170 pc := ProposalCursor{ 171 State: p.State, 172 VegaTime: p.VegaTime, 173 ID: p.ID, 174 } 175 return NewCursor(pc.String()) 176 } 177 178 func (p Proposal) ToProtoEdge(_ ...any) (*v2.GovernanceDataEdge, error) { 179 proposalsProto := make([]*vega.Proposal, len(p.Proposals)) 180 181 for i, proposal := range p.Proposals { 182 proposalsProto[i] = proposal.ToProto() 183 } 184 185 return &v2.GovernanceDataEdge{ 186 Node: &vega.GovernanceData{ 187 Proposal: p.ToProto(), 188 Proposals: proposalsProto, 189 }, 190 Cursor: p.Cursor().Encode(), 191 }, nil 192 } 193 194 func ProposalFromProto(pp *vega.Proposal, txHash TxHash) (Proposal, error) { 195 var err error 196 var majority num.Decimal 197 if len(pp.RequiredMajority) <= 0 { 198 majority = num.DecimalZero() 199 } else if majority, err = num.DecimalFromString(pp.RequiredMajority); err != nil { 200 return Proposal{}, err 201 } 202 203 var participation num.Decimal 204 if len(pp.RequiredParticipation) <= 0 { 205 participation = num.DecimalZero() 206 } else if participation, err = num.DecimalFromString(pp.RequiredParticipation); err != nil { 207 return Proposal{}, err 208 } 209 210 lpMajority := num.DecimalZero() 211 if pp.RequiredLiquidityProviderMajority != nil && len(*pp.RequiredLiquidityProviderMajority) > 0 { 212 if lpMajority, err = num.DecimalFromString(*pp.RequiredLiquidityProviderMajority); err != nil { 213 return Proposal{}, err 214 } 215 } 216 lpParticipation := num.DecimalZero() 217 if pp.RequiredLiquidityProviderParticipation != nil && len(*pp.RequiredLiquidityProviderParticipation) > 0 { 218 if lpParticipation, err = num.DecimalFromString(*pp.RequiredLiquidityProviderParticipation); err != nil { 219 return Proposal{}, err 220 } 221 } 222 223 reason := ProposalErrorUnspecified 224 if pp.Reason != nil { 225 reason = ProposalError(*pp.Reason) 226 } 227 228 var errDetails string 229 if pp.ErrorDetails != nil { 230 errDetails = *pp.ErrorDetails 231 } 232 233 var batchID ProposalID 234 if pp.BatchId != nil { 235 batchID = ProposalID(*pp.BatchId) 236 } 237 238 p := Proposal{ 239 ID: ProposalID(pp.Id), 240 BatchID: batchID, 241 Reference: pp.Reference, 242 PartyID: PartyID(pp.PartyId), 243 State: ProposalState(pp.State), 244 Rationale: ProposalRationale{pp.Rationale}, 245 Terms: ProposalTerms{pp.GetTerms()}, 246 BatchTerms: BatchProposalTerms{pp.GetBatchTerms()}, 247 Reason: reason, 248 ErrorDetails: errDetails, 249 ProposalTime: time.Unix(0, pp.Timestamp), 250 RequiredMajority: majority, 251 RequiredParticipation: participation, 252 RequiredLPMajority: &lpMajority, 253 RequiredLPParticipation: &lpParticipation, 254 TxHash: txHash, 255 } 256 return p, nil 257 } 258 259 type ProposalRationale struct { 260 *vega.ProposalRationale 261 } 262 263 func (pt ProposalRationale) MarshalJSON() ([]byte, error) { 264 return protojson.Marshal(pt) 265 } 266 267 func (pt *ProposalRationale) UnmarshalJSON(b []byte) error { 268 pt.ProposalRationale = &vega.ProposalRationale{} 269 return protojson.Unmarshal(b, pt) 270 } 271 272 type ProposalTerms struct { 273 *vega.ProposalTerms 274 } 275 276 func (pt ProposalTerms) MarshalJSON() ([]byte, error) { 277 return protojson.Marshal(pt) 278 } 279 280 func (pt *ProposalTerms) UnmarshalJSON(b []byte) error { 281 pt.ProposalTerms = &vega.ProposalTerms{} 282 if err := protojson.Unmarshal(b, pt); err != nil { 283 return err 284 } 285 286 if pt.ProposalTerms.Change == nil { 287 pt.ProposalTerms = nil 288 } 289 290 return nil 291 } 292 293 type BatchProposalTerms struct { 294 *vega.BatchProposalTerms 295 } 296 297 func (pt BatchProposalTerms) MarshalJSON() ([]byte, error) { 298 return protojson.Marshal(pt) 299 } 300 301 func (pt *BatchProposalTerms) UnmarshalJSON(b []byte) error { 302 pt.BatchProposalTerms = &vega.BatchProposalTerms{} 303 if err := protojson.Unmarshal(b, pt); err != nil { 304 return err 305 } 306 307 if pt.BatchProposalTerms.Changes == nil || len(pt.BatchProposalTerms.Changes) == 0 { 308 pt.BatchProposalTerms = nil 309 } 310 311 return nil 312 } 313 314 type ProposalCursor struct { 315 State ProposalState `json:"state"` 316 VegaTime time.Time `json:"vega_time"` 317 ID ProposalID `json:"id"` 318 } 319 320 func (pc ProposalCursor) String() string { 321 bs, err := json.Marshal(pc) 322 if err != nil { 323 panic(fmt.Errorf("failed to marshal proposal cursor: %w", err)) 324 } 325 return string(bs) 326 } 327 328 func (pc *ProposalCursor) Parse(cursorString string) error { 329 if cursorString == "" { 330 return nil 331 } 332 return json.Unmarshal([]byte(cursorString), pc) 333 } 334 335 func toPtr[T any](t T) *T { 336 return &t 337 }