code.vegaprotocol.io/vega@v0.79.0/commands/errors.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 commands
    17  
    18  import (
    19  	"encoding/json"
    20  	"errors"
    21  	"fmt"
    22  	"sort"
    23  	"strings"
    24  
    25  	"golang.org/x/exp/maps"
    26  )
    27  
    28  var (
    29  	ErrIsRequired                                      = errors.New("is required")
    30  	ErrMustBePositive                                  = errors.New("must be positive")
    31  	ErrMustBePositiveOrZero                            = errors.New("must be positive or zero")
    32  	ErrMustBeNegativeOrZero                            = errors.New("must be negative or zero")
    33  	ErrMustBeLessThan150                               = errors.New("must be less than 150")
    34  	ErrMustBeAtMost1M                                  = errors.New("must be at most 1000000")
    35  	ErrMustBeAtMost100                                 = errors.New("must be at most 100")
    36  	ErrMustBeAtMost200                                 = errors.New("must be at most 200")
    37  	ErrMustBeAtMost2048                                = errors.New("must be at most 2048")
    38  	ErrMustBeWithinRange7                              = errors.New("must be between -7 and 7")
    39  	ErrIsNotValid                                      = errors.New("is not a valid value")
    40  	ErrIsNotValidWithOCO                               = errors.New("is not a valid with one cancel other")
    41  	ErrIsNotValidNumber                                = errors.New("is not a valid number")
    42  	ErrIsNotSupported                                  = errors.New("is not supported")
    43  	ErrIsUnauthorised                                  = errors.New("is unauthorised")
    44  	ErrCannotAmendToGFA                                = errors.New("cannot amend to time in force GFA")
    45  	ErrCannotAmendToGFN                                = errors.New("cannot amend to time in force GFN")
    46  	ErrNonGTTOrderWithExpiry                           = errors.New("non GTT order with expiry")
    47  	ErrGTTOrderWithNoExpiry                            = errors.New("GTT order without expiry")
    48  	ErrIsMismatching                                   = errors.New("is mismatching")
    49  	ErrReferenceTooLong                                = errors.New("reference is too long")
    50  	ErrNotAValidInteger                                = errors.New("not a valid integer")
    51  	ErrNotAValidFloat                                  = errors.New("not a valid float")
    52  	ErrMustBeLessThan100Chars                          = errors.New("must be less than 100 characters")
    53  	ErrMustBeLessThan200Chars                          = errors.New("must be less than 200 characters")
    54  	ErrMustNotExceed20000Chars                         = errors.New("must not exceed 20000 characters")
    55  	ErrShouldBeHexEncoded                              = errors.New("should be hex encoded")
    56  	ErrSignatureNotVerifiable                          = errors.New("signature is not verifiable")
    57  	ErrInvalidSignature                                = errors.New("invalid signature")
    58  	ErrUnsupportedAlgorithm                            = errors.New("unsupported algorithm")
    59  	ErrEmptyBatchMarketInstructions                    = errors.New("empty batch market instructions")
    60  	ErrIsNotValidVegaPubkey                            = errors.New("is not a valid vega public key")
    61  	ErrIsNotValidEthereumAddress                       = errors.New("is not a valid ethereum address")
    62  	ErrEmptyEthereumCallSpec                           = errors.New("ethereum call spec is required")
    63  	ErrInvalidEthereumAbi                              = errors.New("is not a valid ethereum abi definition")
    64  	ErrInvalidEthereumCallTrigger                      = errors.New("ethereum call trigger not valid")
    65  	ErrInvalidEthereumCallArgs                         = errors.New("ethereum call arguments not valid")
    66  	ErrInvalidEthereumFilters                          = errors.New("ethereum call filters not valid")
    67  	ErrInvalidEthereumCallSpec                         = errors.New("ethereum call spec is not valid")
    68  	ErrMustBeWithinRange01                             = errors.New("must be between 0 and 1")
    69  	ErrMustBeWithinRange11                             = errors.New("must be between -1 and 1")
    70  	ErrMustBeLTE1                                      = errors.New("must be less than or equal to 1")
    71  	ErrMustBeGTE1                                      = errors.New("must be greater than or equal to 1")
    72  	ErrMustBeReduceOnly                                = errors.New("must be reduce only")
    73  	ErrExpiryStrategyRequiredWhenExpiresAtSet          = errors.New("expiry strategy required when expires_at set")
    74  	ErrMustHaveAtLeastOneOfRisesAboveOrFallsBelow      = errors.New("must have at least one of rises above or falls below")
    75  	ErrMustHaveAStopOrderTrigger                       = errors.New("must have a stop order trigger")
    76  	ErrFallsBelowAndRiseAboveMarketIDMustBeTheSame     = errors.New("market ID for falls below and rises above must be the same")
    77  	ErrTrailingPercentOffsetMinimalIncrementNotReached = errors.New("trailing percent offset minimal increment must be >= 0.001")
    78  	ErrMustBeEmpty                                     = errors.New("must be empty")
    79  	ErrMustBeGTEClampLowerBound                        = errors.New("must be greater than or equal to clamp lower bound")
    80  	ErrOneTimeTriggerAllowedMax                        = errors.New("maximum one time trigger allowed")
    81  	ErrMustBeBetween01                                 = errors.New("must be between 0 (excluded) and 1 (included)")
    82  	ErrMustBeGreaterThanEnactmentTimestamp             = errors.New("must be greater than proposal_submission.terms.enactment_timestamp")
    83  	ErrMustBeLessThen366                               = errors.New("must be less then 366")
    84  	ErrMustBeAtMost500                                 = errors.New("must be at most 500")
    85  	ErrMustBeSetTo0IfSizeSet                           = errors.New("must be set to 0 if the property \"order_amendment.size\" is set")
    86  	ErrMustBeAtMost3600                                = errors.New("must be at most 3600")
    87  	ErrMustBeWithinRangeGT0LT20                        = errors.New("price range must be strictly greater than 0 and less than or equal to 20")
    88  	ErrSizeIsTooLarge                                  = errors.New("size is too large")
    89  	ErrCannotSetAllowListWhenTeamIsOpened              = errors.New("cannot set allow list when team is opened")
    90  	ErrSettingAllowListRequireSettingClosedState       = errors.New("setting an allow list requires setting the closed state")
    91  	ErrIsLimitedTo32Characters                         = errors.New("is limited to 32 characters")
    92  	ErrIsLimitedTo10Entries                            = errors.New("is limited to 10 entries")
    93  	ErrIsLimitedTo255Characters                        = errors.New("is limited to 255 characters")
    94  	ErrCannotBeBlank                                   = errors.New("cannot be blank")
    95  	ErrIsDuplicated                                    = errors.New("is duplicated")
    96  	ErrIsDisabled                                      = errors.New("is disabled")
    97  	ErrMustBeAtMost250                                 = errors.New("must be at most 250")
    98  	ErrNoUpdatesProvided                               = errors.New("no updates provided")
    99  	ErrMaxPriceMustRespectTickSize                     = errors.New("must respect tick size")
   100  )
   101  
   102  type Errors map[string][]error
   103  
   104  func NewErrors() Errors {
   105  	return Errors{}
   106  }
   107  
   108  func (e Errors) Error() string {
   109  	if len(e) <= 0 {
   110  		return ""
   111  	}
   112  
   113  	propMessages := []string{}
   114  	for prop, errs := range e {
   115  		errMessages := make([]string, 0, len(errs))
   116  		for _, err := range errs {
   117  			errMessages = append(errMessages, err.Error())
   118  		}
   119  		propMessageFmt := fmt.Sprintf("%v (%v)", prop, strings.Join(errMessages, ", "))
   120  		propMessages = append(propMessages, propMessageFmt)
   121  	}
   122  
   123  	sort.Strings(propMessages)
   124  	return strings.Join(propMessages, ", ")
   125  }
   126  
   127  func (e Errors) Empty() bool {
   128  	return len(e) == 0
   129  }
   130  
   131  // AddForProperty adds an error for a given property.
   132  func (e Errors) AddForProperty(prop string, err error) {
   133  	errs, ok := e[prop]
   134  	if !ok {
   135  		errs = []error{}
   136  	}
   137  
   138  	e[prop] = append(errs, err)
   139  }
   140  
   141  // AddPrefix adds prefix to each property.
   142  func (e Errors) AddPrefix(prefix string) Errors {
   143  	keys := maps.Keys(e)
   144  	for _, key := range keys {
   145  		// Skip general error
   146  		if key == "*" {
   147  			continue
   148  		}
   149  		e[fmt.Sprintf("%s%s", prefix, key)] = e[key]
   150  		delete(e, key)
   151  	}
   152  	return e
   153  }
   154  
   155  // FinalAddForProperty behaves like AddForProperty, but is meant to be called in
   156  // a "return" statement. This helper is usually used for terminal errors.
   157  func (e Errors) FinalAddForProperty(prop string, err error) Errors {
   158  	e.AddForProperty(prop, err)
   159  	return e
   160  }
   161  
   162  // Add adds a general error that is not related to a specific property.
   163  func (e Errors) Add(err error) {
   164  	e.AddForProperty("*", err)
   165  }
   166  
   167  // FinalAdd behaves like Add, but is meant to be called in a "return" statement.
   168  // This helper is usually used for terminal errors.
   169  func (e Errors) FinalAdd(err error) Errors {
   170  	e.Add(err)
   171  	return e
   172  }
   173  
   174  func (e Errors) Merge(oth Errors) {
   175  	if oth == nil {
   176  		return
   177  	}
   178  
   179  	for prop, errs := range oth {
   180  		for _, err := range errs {
   181  			e.AddForProperty(prop, err)
   182  		}
   183  	}
   184  }
   185  
   186  func (e Errors) Get(prop string) []error {
   187  	messages, ok := e[prop]
   188  	if !ok {
   189  		return nil
   190  	}
   191  	return messages
   192  }
   193  
   194  func (e Errors) ErrorOrNil() error {
   195  	if len(e) <= 0 {
   196  		return nil
   197  	}
   198  	return e
   199  }
   200  
   201  func (e Errors) MarshalJSON() ([]byte, error) {
   202  	out := map[string][]string{}
   203  	for prop, errs := range e {
   204  		messages := []string{}
   205  		for _, err := range errs {
   206  			messages = append(messages, err.Error())
   207  		}
   208  		out[prop] = messages
   209  	}
   210  	return json.Marshal(out)
   211  }