code.vegaprotocol.io/vega@v0.79.0/core/liquidity/v2/amendments.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 liquidity 17 18 import ( 19 "context" 20 "errors" 21 22 "code.vegaprotocol.io/vega/core/events" 23 "code.vegaprotocol.io/vega/core/types" 24 ) 25 26 var ErrPartyHaveNoLiquidityProvision = errors.New("party have no liquidity provision") 27 28 func (e *Engine) AmendLiquidityProvision( 29 ctx context.Context, 30 lpa *types.LiquidityProvisionAmendment, 31 party string, 32 isCancel bool, 33 ) (bool, error) { 34 if err := e.CanAmend(lpa, party, !isCancel); err != nil { 35 return false, err 36 } 37 38 // LP exists, checked in the previous func. 39 lp, _ := e.provisions.Get(party) 40 if lp == nil { 41 lp, _ = e.pendingProvisions.Get(party) 42 } 43 44 // If we are cancelling the LP, preserve the reference field 45 if lpa.CommitmentAmount.IsZero() { 46 lpa.Reference = lp.Reference 47 } 48 49 updatedLp := e.createAmendedProvision(lp, lpa) 50 51 // add to pending provision since the change in CommitmentAmount should be reflected at the beginning of next epoch 52 // if it's not opening auction. 53 if lp.CommitmentAmount.NEQ(lpa.CommitmentAmount) && !e.auctionState.IsOpeningAuction() { 54 e.pendingProvisions.Set(updatedLp) 55 e.broker.Send(events.NewLiquidityProvisionEvent(ctx, updatedLp)) 56 return false, nil 57 } 58 59 // cancel immediately during opening auction. 60 if e.auctionState.IsOpeningAuction() && isCancel { 61 if err := e.CancelLiquidityProvision(ctx, party); err != nil { 62 return false, err 63 } 64 65 return true, nil 66 } 67 68 // update immediately since either the commitment amount has not changed. 69 updatedLp.Status = types.LiquidityProvisionStatusActive 70 e.broker.Send(events.NewLiquidityProvisionEvent(ctx, updatedLp)) 71 e.provisions.Set(party, updatedLp) 72 return true, nil 73 } 74 75 func (e *Engine) createAmendedProvision( 76 currentProvision *types.LiquidityProvision, 77 amendment *types.LiquidityProvisionAmendment, 78 ) *types.LiquidityProvision { 79 return &types.LiquidityProvision{ 80 ID: currentProvision.ID, 81 MarketID: currentProvision.MarketID, 82 Party: currentProvision.Party, 83 CreatedAt: currentProvision.CreatedAt, 84 Status: types.LiquidityProvisionStatusPending, 85 Fee: amendment.Fee, 86 Reference: amendment.Reference, 87 Version: currentProvision.Version + 1, 88 CommitmentAmount: amendment.CommitmentAmount.Clone(), 89 UpdatedAt: e.timeService.GetTimeNow().UnixNano(), 90 } 91 } 92 93 func (e *Engine) CanAmend(lps *types.LiquidityProvisionAmendment, party string, shouldValidate bool) error { 94 if !e.IsLiquidityProvider(party) { 95 return ErrPartyHaveNoLiquidityProvision 96 } 97 98 if !shouldValidate { 99 return nil 100 } 101 102 if err := e.ValidateLiquidityProvisionAmendment(lps); err != nil { 103 return err 104 } 105 106 return nil 107 } 108 109 func (e *Engine) ValidateLiquidityProvisionAmendment(lp *types.LiquidityProvisionAmendment) error { 110 if lp.Fee.IsZero() && (lp.CommitmentAmount == nil || lp.CommitmentAmount.IsZero()) { 111 return errors.New("empty liquidity provision amendment content") 112 } 113 114 // If orders fee is provided, we need it to be valid 115 if lp.Fee.IsNegative() || lp.Fee.GreaterThan(e.maxFee) { 116 return errors.New("invalid liquidity provision fee") 117 } 118 119 return nil 120 }