code.vegaprotocol.io/vega@v0.79.0/core/integration/steps/parties_submit_liquidity_provision.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 steps
    17  
    18  import (
    19  	"context"
    20  	"encoding/hex"
    21  	"errors"
    22  	"fmt"
    23  	"sort"
    24  
    25  	"code.vegaprotocol.io/vega/core/types"
    26  	"code.vegaprotocol.io/vega/libs/crypto"
    27  	"code.vegaprotocol.io/vega/libs/num"
    28  
    29  	"github.com/cucumber/godog"
    30  )
    31  
    32  type LPUpdate struct {
    33  	MarketID         string
    34  	CommitmentAmount *num.Uint
    35  	Fee              num.Decimal
    36  	Reference        string
    37  	LpType           string
    38  	Err              string
    39  }
    40  
    41  func PartyCancelsTheirLiquidityProvision(exec Execution, marketID, party string) error {
    42  	cancel := types.LiquidityProvisionCancellation{
    43  		MarketID: marketID,
    44  	}
    45  	if err := exec.CancelLiquidityProvision(context.Background(), &cancel, party); err != nil {
    46  		return errCancelLiquidityProvision(party, marketID, err)
    47  	}
    48  	return nil
    49  }
    50  
    51  func PartiesSubmitLiquidityProvision(exec Execution, table *godog.Table) error {
    52  	lps := map[string]*LPUpdate{}
    53  	parties := map[string]string{}
    54  	keys := []string{}
    55  
    56  	var errRow ErroneousRow
    57  	for _, r := range parseSubmitLiquidityProvisionTable(table) {
    58  		row := submitLiquidityProvisionRow{row: r}
    59  		if errRow == nil || row.ExpectError() {
    60  			errRow = row
    61  		}
    62  		id := row.ID()
    63  		ref := id
    64  
    65  		if _, ok := lps[id]; !ok {
    66  			lp := &LPUpdate{
    67  				MarketID:         row.MarketID(),
    68  				CommitmentAmount: row.CommitmentAmount(),
    69  				Fee:              row.Fee(),
    70  				Reference:        ref,
    71  				LpType:           row.LpType(),
    72  				Err:              row.Error(),
    73  			}
    74  			parties[id] = row.Party()
    75  			lps[id] = lp
    76  			keys = append(keys, id)
    77  		}
    78  	}
    79  	// ensure we always submit in the same order
    80  	sort.Strings(keys)
    81  	for _, id := range keys {
    82  		lp, ok := lps[id]
    83  		if !ok {
    84  			return errors.New("LP  not found")
    85  		}
    86  		party, ok := parties[id]
    87  		if !ok {
    88  			return errors.New("party for LP not found")
    89  		}
    90  
    91  		if lp.LpType == "amendment" {
    92  			lpa := &types.LiquidityProvisionAmendment{
    93  				MarketID:         lp.MarketID,
    94  				CommitmentAmount: lp.CommitmentAmount,
    95  				Fee:              lp.Fee,
    96  				Reference:        lp.Reference,
    97  			}
    98  
    99  			err := exec.AmendLiquidityProvision(context.Background(), lpa, party)
   100  			if ceerr := checkExpectedError(errRow, err, errAmendingLiquidityProvision(lpa, party, err)); ceerr != nil {
   101  				return ceerr
   102  			}
   103  		} else if lp.LpType == "submission" {
   104  			sub := &types.LiquidityProvisionSubmission{
   105  				MarketID:         lp.MarketID,
   106  				CommitmentAmount: lp.CommitmentAmount,
   107  				Fee:              lp.Fee,
   108  				Reference:        lp.Reference,
   109  			}
   110  			deterministicID := hex.EncodeToString(crypto.Hash([]byte(id + party + lp.MarketID)))
   111  			err := exec.SubmitLiquidityProvision(context.Background(), sub, party, id, deterministicID)
   112  			if ceerr := checkExpectedError(errRow, err, errSubmittingLiquidityProvision(sub, party, id, err)); ceerr != nil {
   113  				return ceerr
   114  			}
   115  		} else if lp.LpType == "cancellation" {
   116  			cancel := types.LiquidityProvisionCancellation{
   117  				MarketID: lp.MarketID,
   118  			}
   119  			err := exec.CancelLiquidityProvision(context.Background(), &cancel, party)
   120  			if ceerr := checkExpectedError(errRow, err, errCancelLiquidityProvision(party, lp.MarketID, err)); ceerr != nil {
   121  				return ceerr
   122  			}
   123  		}
   124  	}
   125  	return nil
   126  }
   127  
   128  func errSubmittingLiquidityProvision(lp *types.LiquidityProvisionSubmission, party, id string, err error) error {
   129  	return fmt.Errorf("failed to submit [%v] for party %s and id %s: %v", lp, party, id, err)
   130  }
   131  
   132  func errCancelLiquidityProvision(party, market string, err error) error {
   133  	return fmt.Errorf("failed to cancel LP for party %s on market %s: %v", party, market, err)
   134  }
   135  
   136  func errAmendingLiquidityProvision(lp *types.LiquidityProvisionAmendment, party string, err error) error {
   137  	return fmt.Errorf("failed to amend [%v] for party %s : %v", lp, party, err)
   138  }
   139  
   140  func parseSubmitLiquidityProvisionTable(table *godog.Table) []RowWrapper {
   141  	return StrictParseTable(table, []string{
   142  		"id",
   143  		"party",
   144  		"market id",
   145  		"commitment amount",
   146  		"fee",
   147  		"lp type",
   148  	}, []string{
   149  		"reference",
   150  		"error",
   151  	})
   152  }
   153  
   154  type submitLiquidityProvisionRow struct {
   155  	row RowWrapper
   156  }
   157  
   158  func (r submitLiquidityProvisionRow) ID() string {
   159  	return r.row.MustStr("id")
   160  }
   161  
   162  func (r submitLiquidityProvisionRow) Party() string {
   163  	return r.row.MustStr("party")
   164  }
   165  
   166  func (r submitLiquidityProvisionRow) MarketID() string {
   167  	return r.row.MustStr("market id")
   168  }
   169  
   170  func (r submitLiquidityProvisionRow) Side() types.Side {
   171  	if len(r.row.Str("side")) == 0 {
   172  		return types.SideUnspecified
   173  	}
   174  	return r.row.MustSide("side")
   175  }
   176  
   177  func (r submitLiquidityProvisionRow) CommitmentAmount() *num.Uint {
   178  	return r.row.MustUint("commitment amount")
   179  }
   180  
   181  func (r submitLiquidityProvisionRow) Fee() num.Decimal {
   182  	return r.row.MustDecimal("fee")
   183  }
   184  
   185  func (r submitLiquidityProvisionRow) LpType() string {
   186  	return r.row.MustStr("lp type")
   187  }
   188  
   189  func (r submitLiquidityProvisionRow) Reference() string {
   190  	return r.row.Str("reference")
   191  }
   192  
   193  func (r submitLiquidityProvisionRow) Error() string {
   194  	return r.row.Str("error")
   195  }
   196  
   197  func (r submitLiquidityProvisionRow) ExpectError() bool {
   198  	return r.row.HasColumn("error")
   199  }