code.vegaprotocol.io/vega@v0.79.0/datanode/entities/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 entities
    17  
    18  import (
    19  	"encoding/json"
    20  	"fmt"
    21  	"time"
    22  
    23  	v2 "code.vegaprotocol.io/vega/protos/data-node/api/v2"
    24  	"code.vegaprotocol.io/vega/protos/vega"
    25  
    26  	"github.com/jackc/pgtype"
    27  	"github.com/shopspring/decimal"
    28  	"google.golang.org/protobuf/encoding/protojson"
    29  )
    30  
    31  type _LiquidityProvision struct{}
    32  
    33  type LiquidityProvisionID = ID[_LiquidityProvision]
    34  
    35  type LiquidityOrderReference struct {
    36  	*vega.LiquidityOrderReference
    37  }
    38  
    39  func (l LiquidityOrderReference) EncodeBinary(_ *pgtype.ConnInfo, buf []byte) ([]byte, error) {
    40  	protoBytes, err := protojson.Marshal(l.LiquidityOrderReference)
    41  	if err != nil {
    42  		return buf, fmt.Errorf("failed to marshal LiquidityOrderReference: %w", err)
    43  	}
    44  	return append(buf, protoBytes...), nil
    45  }
    46  
    47  func (l *LiquidityOrderReference) DecodeBinary(_ *pgtype.ConnInfo, src []byte) error {
    48  	return protojson.Unmarshal(src, l)
    49  }
    50  
    51  type LiquidityProvision struct {
    52  	ID               LiquidityProvisionID
    53  	PartyID          PartyID
    54  	CreatedAt        time.Time
    55  	UpdatedAt        time.Time
    56  	MarketID         MarketID
    57  	CommitmentAmount decimal.Decimal
    58  	Fee              decimal.Decimal
    59  	Sells            []LiquidityOrderReference
    60  	Buys             []LiquidityOrderReference
    61  	Version          int64
    62  	Status           LiquidityProvisionStatus
    63  	Reference        string
    64  	TxHash           TxHash
    65  	VegaTime         time.Time
    66  }
    67  
    68  type CurrentAndPreviousLiquidityProvisions struct {
    69  	ID                       LiquidityProvisionID
    70  	PartyID                  PartyID
    71  	CreatedAt                time.Time
    72  	UpdatedAt                time.Time
    73  	MarketID                 MarketID
    74  	CommitmentAmount         decimal.Decimal
    75  	Fee                      decimal.Decimal
    76  	Sells                    []LiquidityOrderReference
    77  	Buys                     []LiquidityOrderReference
    78  	Version                  int64
    79  	Status                   LiquidityProvisionStatus
    80  	Reference                string
    81  	TxHash                   TxHash
    82  	VegaTime                 time.Time
    83  	PreviousID               LiquidityProvisionID
    84  	PreviousPartyID          PartyID
    85  	PreviousCreatedAt        *time.Time
    86  	PreviousUpdatedAt        *time.Time
    87  	PreviousMarketID         MarketID
    88  	PreviousCommitmentAmount *decimal.Decimal
    89  	PreviousFee              *decimal.Decimal
    90  	PreviousSells            []LiquidityOrderReference
    91  	PreviousBuys             []LiquidityOrderReference
    92  	PreviousVersion          *int64
    93  	PreviousStatus           *LiquidityProvisionStatus
    94  	PreviousReference        *string
    95  	PreviousTxHash           TxHash
    96  	PreviousVegaTime         *time.Time
    97  }
    98  
    99  func LiquidityProvisionFromProto(lpProto *vega.LiquidityProvision, txHash TxHash, vegaTime time.Time) (LiquidityProvision, error) {
   100  	lpID := LiquidityProvisionID(lpProto.Id)
   101  	partyID := PartyID(lpProto.PartyId)
   102  	marketID := MarketID(lpProto.MarketId)
   103  
   104  	commitmentAmount, err := decimal.NewFromString(lpProto.CommitmentAmount)
   105  	if err != nil {
   106  		return LiquidityProvision{}, fmt.Errorf("liquidity provision has invalid commitement amount: %w", err)
   107  	}
   108  
   109  	fee, err := decimal.NewFromString(lpProto.Fee)
   110  	if err != nil {
   111  		return LiquidityProvision{}, fmt.Errorf("liquidity provision has invalid fee amount: %w", err)
   112  	}
   113  
   114  	sells := make([]LiquidityOrderReference, 0, len(lpProto.Sells))
   115  	buys := make([]LiquidityOrderReference, 0, len(lpProto.Buys))
   116  
   117  	for _, sell := range lpProto.Sells {
   118  		sells = append(sells, LiquidityOrderReference{sell})
   119  	}
   120  
   121  	for _, buy := range lpProto.Buys {
   122  		buys = append(buys, LiquidityOrderReference{buy})
   123  	}
   124  
   125  	return LiquidityProvision{
   126  		ID:               lpID,
   127  		PartyID:          partyID,
   128  		CreatedAt:        NanosToPostgresTimestamp(lpProto.CreatedAt),
   129  		UpdatedAt:        NanosToPostgresTimestamp(lpProto.UpdatedAt),
   130  		MarketID:         marketID,
   131  		CommitmentAmount: commitmentAmount,
   132  		Fee:              fee,
   133  		Sells:            sells,
   134  		Buys:             buys,
   135  		Version:          int64(lpProto.Version),
   136  		Status:           LiquidityProvisionStatus(lpProto.Status),
   137  		Reference:        lpProto.Reference,
   138  		TxHash:           txHash,
   139  		VegaTime:         vegaTime,
   140  	}, nil
   141  }
   142  
   143  func (lp LiquidityProvision) ToProto() *vega.LiquidityProvision {
   144  	sells := make([]*vega.LiquidityOrderReference, 0, len(lp.Sells))
   145  	buys := make([]*vega.LiquidityOrderReference, 0, len(lp.Buys))
   146  
   147  	for _, sell := range lp.Sells {
   148  		sells = append(sells, sell.LiquidityOrderReference)
   149  	}
   150  	for _, buy := range lp.Buys {
   151  		buys = append(buys, buy.LiquidityOrderReference)
   152  	}
   153  
   154  	return &vega.LiquidityProvision{
   155  		Id:               lp.ID.String(),
   156  		PartyId:          lp.PartyID.String(),
   157  		CreatedAt:        lp.CreatedAt.UnixNano(),
   158  		UpdatedAt:        lp.UpdatedAt.UnixNano(),
   159  		MarketId:         lp.MarketID.String(),
   160  		CommitmentAmount: lp.CommitmentAmount.String(),
   161  		Fee:              lp.Fee.String(),
   162  		Sells:            sells,
   163  		Buys:             buys,
   164  		Version:          uint64(lp.Version),
   165  		Status:           vega.LiquidityProvision_Status(lp.Status),
   166  		Reference:        lp.Reference,
   167  	}
   168  }
   169  
   170  func (lp CurrentAndPreviousLiquidityProvisions) ToProto() *v2.LiquidityProvision {
   171  	sells := make([]*vega.LiquidityOrderReference, 0)
   172  	buys := make([]*vega.LiquidityOrderReference, 0)
   173  
   174  	for _, sell := range lp.Sells {
   175  		sells = append(sells, sell.LiquidityOrderReference)
   176  	}
   177  	for _, buy := range lp.Buys {
   178  		buys = append(buys, buy.LiquidityOrderReference)
   179  	}
   180  
   181  	if lp.Status == LiquidityProvisionStatusPending && (lp.PreviousStatus != nil && *lp.PreviousStatus == LiquidityProvisionStatusActive) {
   182  		// check to see if the previous state is active, if so, then that is still the active state,
   183  		// and the current state is pending
   184  		return lp.currentWithPendingLP(sells, buys)
   185  	}
   186  
   187  	return &v2.LiquidityProvision{
   188  		Current: &vega.LiquidityProvision{
   189  			Id:               lp.ID.String(),
   190  			PartyId:          lp.PartyID.String(),
   191  			CreatedAt:        lp.CreatedAt.UnixNano(),
   192  			UpdatedAt:        lp.UpdatedAt.UnixNano(),
   193  			MarketId:         lp.MarketID.String(),
   194  			CommitmentAmount: lp.CommitmentAmount.String(),
   195  			Fee:              lp.Fee.String(),
   196  			Sells:            sells,
   197  			Buys:             buys,
   198  			Version:          uint64(lp.Version),
   199  			Status:           vega.LiquidityProvision_Status(lp.Status),
   200  			Reference:        lp.Reference,
   201  		},
   202  	}
   203  }
   204  
   205  func (lp CurrentAndPreviousLiquidityProvisions) currentWithPendingLP(sells, buys []*vega.LiquidityOrderReference) *v2.LiquidityProvision {
   206  	previousSells := make([]*vega.LiquidityOrderReference, 0)
   207  	previousBuys := make([]*vega.LiquidityOrderReference, 0)
   208  
   209  	if lp.PreviousSells != nil {
   210  		for _, sell := range lp.PreviousSells {
   211  			previousSells = append(previousSells, sell.LiquidityOrderReference)
   212  		}
   213  	}
   214  	if lp.PreviousBuys != nil {
   215  		for _, buy := range lp.PreviousBuys {
   216  			previousBuys = append(previousBuys, buy.LiquidityOrderReference)
   217  		}
   218  	}
   219  	pending := vega.LiquidityProvision{
   220  		Id:               lp.ID.String(),
   221  		PartyId:          lp.PartyID.String(),
   222  		CreatedAt:        lp.CreatedAt.UnixNano(),
   223  		UpdatedAt:        lp.UpdatedAt.UnixNano(),
   224  		MarketId:         lp.MarketID.String(),
   225  		CommitmentAmount: lp.CommitmentAmount.String(),
   226  		Fee:              lp.Fee.String(),
   227  		Sells:            sells,
   228  		Buys:             buys,
   229  		Version:          uint64(lp.Version),
   230  		Status:           vega.LiquidityProvision_Status(lp.Status),
   231  		Reference:        lp.Reference,
   232  	}
   233  
   234  	return &v2.LiquidityProvision{
   235  		Current: &vega.LiquidityProvision{
   236  			Id:               (lp.PreviousID).String(),
   237  			PartyId:          (lp.PreviousPartyID).String(),
   238  			CreatedAt:        (lp.PreviousCreatedAt).UnixNano(),
   239  			UpdatedAt:        (lp.PreviousUpdatedAt).UnixNano(),
   240  			MarketId:         (lp.PreviousMarketID).String(),
   241  			CommitmentAmount: (lp.PreviousCommitmentAmount).String(),
   242  			Fee:              (lp.PreviousFee).String(),
   243  			Sells:            previousSells,
   244  			Buys:             previousBuys,
   245  			Version:          uint64(*lp.PreviousVersion),
   246  			Status:           vega.LiquidityProvision_Status(*lp.PreviousStatus),
   247  			Reference:        *lp.PreviousReference,
   248  		},
   249  		Pending: &pending,
   250  	}
   251  }
   252  
   253  type LiquidityProvisionKey struct {
   254  	ID       LiquidityProvisionID
   255  	VegaTime time.Time
   256  }
   257  
   258  func (lp LiquidityProvision) Key() LiquidityProvisionKey {
   259  	return LiquidityProvisionKey{lp.ID, lp.VegaTime}
   260  }
   261  
   262  var LiquidityProvisionColumns = []string{
   263  	"id", "party_id", "created_at", "updated_at", "market_id",
   264  	"commitment_amount", "fee", "sells", "buys", "version",
   265  	"status", "reference", "tx_hash", "vega_time",
   266  }
   267  
   268  func (lp LiquidityProvision) ToRow() []interface{} {
   269  	return []interface{}{
   270  		lp.ID, lp.PartyID, lp.CreatedAt, lp.UpdatedAt, lp.MarketID,
   271  		lp.CommitmentAmount, lp.Fee, lp.Sells, lp.Buys, lp.Version,
   272  		lp.Status, lp.Reference, lp.TxHash, lp.VegaTime,
   273  	}
   274  }
   275  
   276  func (lp LiquidityProvision) Cursor() *Cursor {
   277  	lc := LiquidityProvisionCursor{
   278  		VegaTime: lp.VegaTime,
   279  		ID:       lp.ID,
   280  	}
   281  	return NewCursor(lc.String())
   282  }
   283  
   284  func (lp CurrentAndPreviousLiquidityProvisions) Cursor() *Cursor {
   285  	lc := LiquidityProvisionCursor{
   286  		VegaTime: lp.VegaTime,
   287  		ID:       lp.ID,
   288  	}
   289  	return NewCursor(lc.String())
   290  }
   291  
   292  func (lp LiquidityProvision) ToProtoEdge(_ ...any) (*v2.LiquidityProvisionsEdge, error) {
   293  	return &v2.LiquidityProvisionsEdge{
   294  		Node:   lp.ToProto(),
   295  		Cursor: lp.Cursor().Encode(),
   296  	}, nil
   297  }
   298  
   299  func (lp CurrentAndPreviousLiquidityProvisions) ToProtoEdge(_ ...any) (*v2.LiquidityProvisionWithPendingEdge, error) {
   300  	return &v2.LiquidityProvisionWithPendingEdge{
   301  		Node:   lp.ToProto(),
   302  		Cursor: lp.Cursor().Encode(),
   303  	}, nil
   304  }
   305  
   306  type LiquidityProvisionCursor struct {
   307  	VegaTime time.Time            `json:"vegaTime"`
   308  	ID       LiquidityProvisionID `json:"id"`
   309  }
   310  
   311  func (lc LiquidityProvisionCursor) String() string {
   312  	bs, err := json.Marshal(lc)
   313  	if err != nil {
   314  		panic(fmt.Errorf("could not marshal liquidity provision cursor: %w", err))
   315  	}
   316  	return string(bs)
   317  }
   318  
   319  func (lc *LiquidityProvisionCursor) Parse(cursorString string) error {
   320  	if cursorString == "" {
   321  		return nil
   322  	}
   323  	return json.Unmarshal([]byte(cursorString), lc)
   324  }