code.vegaprotocol.io/vega@v0.79.0/core/integration/steps/table_wrapper.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  	"errors"
    20  	"fmt"
    21  	"strconv"
    22  	"strings"
    23  	"time"
    24  
    25  	"code.vegaprotocol.io/vega/core/events"
    26  	"code.vegaprotocol.io/vega/core/types"
    27  	"code.vegaprotocol.io/vega/libs/num"
    28  	"code.vegaprotocol.io/vega/libs/ptr"
    29  	proto "code.vegaprotocol.io/vega/protos/vega"
    30  	commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
    31  	datav1 "code.vegaprotocol.io/vega/protos/vega/data/v1"
    32  	eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1"
    33  
    34  	"github.com/cucumber/godog"
    35  	"github.com/cucumber/messages-go/v16"
    36  )
    37  
    38  // StrictParseFirstRow parses and verifies, table integrity and returns only the
    39  // first row. This is suitable of table that act more as object than actual
    40  // table.
    41  func StrictParseFirstRow(table *godog.Table, required, optional []string) RowWrapper {
    42  	rows := StrictParseTable(table, required, optional)
    43  
    44  	if len(rows) > 1 {
    45  		panic("this table supports only one row")
    46  	}
    47  
    48  	return rows[0]
    49  }
    50  
    51  // StrictParseTable parses and verifies the table integrity.
    52  func StrictParseTable(dt *godog.Table, required, optional []string) []RowWrapper {
    53  	tableLen := len(dt.Rows)
    54  	if tableLen < 1 {
    55  		panic("A table is required.")
    56  	}
    57  
    58  	if len(required)+len(optional) != 0 {
    59  		err := verifyTableIntegrity(required, optional, dt.Rows[0])
    60  		if err != nil {
    61  			panic(err)
    62  		}
    63  	}
    64  
    65  	tableWithoutHeaderLen := tableLen - 1
    66  	if tableWithoutHeaderLen == 0 {
    67  		panic("Did you forget the table header?")
    68  	}
    69  
    70  	out := make([]RowWrapper, 0, tableWithoutHeaderLen)
    71  	for _, row := range dt.Rows[1:] {
    72  		wrapper := RowWrapper{values: map[string]string{}}
    73  		for i := range row.Cells {
    74  			wrapper.values[dt.Rows[0].Cells[i].Value] = row.Cells[i].Value
    75  		}
    76  		out = append(out, wrapper)
    77  	}
    78  
    79  	return out
    80  }
    81  
    82  // ParseTable parses the table without verifying its integrity.
    83  // Prefer the use of StrictParseTable().
    84  func ParseTable(dt *godog.Table) []RowWrapper {
    85  	return StrictParseTable(dt, []string{}, []string{})
    86  }
    87  
    88  func verifyTableIntegrity(required, optional []string, header *messages.PickleTableRow) error {
    89  	cols, err := newColumns(required, optional)
    90  	if err != nil {
    91  		return err
    92  	}
    93  
    94  	headerNames := make([]string, 0, len(header.Cells))
    95  	for _, cell := range header.Cells {
    96  		headerNames = append(headerNames, cell.Value)
    97  	}
    98  
    99  	return cols.Verify(headerNames)
   100  }
   101  
   102  type columns struct {
   103  	// config maps a column name to it required state.
   104  	// true == required
   105  	// false == optional
   106  	config map[string]bool
   107  }
   108  
   109  func newColumns(required []string, optional []string) (*columns, error) {
   110  	config := map[string]bool{}
   111  
   112  	for _, column := range required {
   113  		config[column] = true
   114  	}
   115  
   116  	for _, optColumn := range optional {
   117  		_, ok := config[optColumn]
   118  		if ok {
   119  			return nil, fmt.Errorf("column \"%s\" can't be required and optional at the same time", optColumn)
   120  		}
   121  		config[optColumn] = false
   122  	}
   123  
   124  	return &columns{
   125  		config: config,
   126  	}, nil
   127  }
   128  
   129  // Verify ensures the table declares the expected columns and does
   130  // not declared any unexpected columns.
   131  func (c *columns) Verify(header []string) error {
   132  	declaredColumnsSet := map[string]interface{}{}
   133  
   134  	for _, column := range header {
   135  		_, ok := c.config[column]
   136  		if !ok {
   137  			return fmt.Errorf("the column \"%s\" is not expected by this table", column)
   138  		}
   139  		declaredColumnsSet[column] = nil
   140  	}
   141  
   142  	for column, isRequired := range c.config {
   143  		_, ok := declaredColumnsSet[column]
   144  		if !ok && isRequired {
   145  			return fmt.Errorf("the column \"%s\" is required by this table", column)
   146  		}
   147  	}
   148  
   149  	return nil
   150  }
   151  
   152  type RowWrapper struct {
   153  	values map[string]string
   154  }
   155  
   156  func (r RowWrapper) mustColumn(name string) string {
   157  	s, ok := r.values[name]
   158  	if !ok {
   159  		panic(fmt.Errorf("column \"%s\" not found", name))
   160  	}
   161  	return s
   162  }
   163  
   164  func (r RowWrapper) HasColumn(name string) bool {
   165  	if v, ok := r.values[name]; !ok || v == "" {
   166  		return false
   167  	}
   168  	return true
   169  }
   170  
   171  func (r RowWrapper) MustStr(name string) string {
   172  	return r.mustColumn(name)
   173  }
   174  
   175  // StrB does the same as Str, but returns a bool indicating whether or not the
   176  // column was set.
   177  func (r RowWrapper) StrB(name string) (string, bool) {
   178  	return r.Str(name), r.HasColumn(name)
   179  }
   180  
   181  func (r RowWrapper) Str(name string) string {
   182  	return r.values[name]
   183  }
   184  
   185  func (r RowWrapper) MustStrSlice(name, sep string) []string {
   186  	return StrSlice(r.mustColumn(name), sep)
   187  }
   188  
   189  func (r RowWrapper) StrSlice(name, sep string) []string {
   190  	return StrSlice(r.values[name], sep)
   191  }
   192  
   193  func StrSlice(value string, sep string) []string {
   194  	if len(value) == 0 {
   195  		return nil
   196  	}
   197  	return strings.Split(value, sep)
   198  }
   199  
   200  func (r RowWrapper) MustDecimal(name string) num.Decimal {
   201  	value, err := Decimal(r.mustColumn(name))
   202  	panicW(name, err)
   203  	return value
   204  }
   205  
   206  func (r RowWrapper) Decimal(name string) num.Decimal {
   207  	value, err := Decimal(r.values[name])
   208  	panicW(name, err)
   209  	return value
   210  }
   211  
   212  func (r RowWrapper) DecimalB(name string) (num.Decimal, bool) {
   213  	if !r.HasColumn(name) {
   214  		return num.DecimalZero(), false
   215  	}
   216  	return r.Decimal(name), true
   217  }
   218  
   219  func Decimal(rawValue string) (num.Decimal, error) {
   220  	return num.DecimalFromString(rawValue)
   221  }
   222  
   223  func (r RowWrapper) MustU64(name string) uint64 {
   224  	value, err := U64(r.mustColumn(name))
   225  	panicW(name, err)
   226  	return value
   227  }
   228  
   229  func (r RowWrapper) MustInt(name string) *num.Int {
   230  	val, ok := num.IntFromString(r.MustStr(name), 10)
   231  	if ok {
   232  		panicW(name, fmt.Errorf("failed to parse int"))
   233  	}
   234  	return val
   235  }
   236  
   237  func (r RowWrapper) MustUint(name string) *num.Uint {
   238  	value, err := Uint(r.mustColumn(name))
   239  	panicW(name, err)
   240  	return value
   241  }
   242  
   243  func (r RowWrapper) MaybeUint(name string) *num.Uint {
   244  	if !r.HasColumn(name) {
   245  		return nil
   246  	}
   247  	u := r.MustUint(name)
   248  	if u.IsZero() {
   249  		return nil
   250  	}
   251  	return u
   252  }
   253  
   254  func (r RowWrapper) MaybeU64(name string) *uint64 {
   255  	if !r.HasColumn(name) {
   256  		return nil
   257  	}
   258  	return ptr.From(r.MustU64(name))
   259  }
   260  
   261  func (r RowWrapper) Uint(name string) *num.Uint {
   262  	value, err := Uint(r.values[name])
   263  	panicW(name, err)
   264  	return value
   265  }
   266  
   267  func Uint(value string) (*num.Uint, error) {
   268  	retVal, overflow := num.UintFromString(value, 10)
   269  	if overflow {
   270  		return nil, fmt.Errorf("invalid uint value: %v", value)
   271  	}
   272  	return retVal, nil
   273  }
   274  
   275  // U64B does the same as U64, but returns a bool indicating whether or not the
   276  // column was set.
   277  func (r RowWrapper) U64B(name string) (uint64, bool) {
   278  	if !r.HasColumn(name) {
   279  		return 0, false
   280  	}
   281  	return r.U64(name), true
   282  }
   283  
   284  func (r RowWrapper) U64(name string) uint64 {
   285  	value, err := U64(r.values[name])
   286  	panicW(name, err)
   287  	return value
   288  }
   289  
   290  func U64(value string) (uint64, error) {
   291  	return strconv.ParseUint(value, 10, 64)
   292  }
   293  
   294  func (r RowWrapper) MustU32(name string) uint32 {
   295  	return r.U32(name)
   296  }
   297  
   298  func (r RowWrapper) U32(name string) uint32 {
   299  	value, err := strconv.ParseUint(r.values[name], 10, 32)
   300  	panicW(name, err)
   301  	return uint32(value)
   302  }
   303  
   304  func (r RowWrapper) I32(name string) int32 {
   305  	value, err := strconv.ParseInt(r.values[name], 10, 32)
   306  	panicW(name, err)
   307  	return int32(value)
   308  }
   309  
   310  func (r RowWrapper) MustU64Slice(name, sep string) []uint64 {
   311  	value, err := U64Slice(r.mustColumn(name), sep)
   312  	panicW(name, err)
   313  	return value
   314  }
   315  
   316  func (r RowWrapper) U64Slice(name, sep string) []uint64 {
   317  	value, err := U64Slice(r.values[name], sep)
   318  	panicW(name, err)
   319  	return value
   320  }
   321  
   322  func U64Slice(rawValue, sep string) ([]uint64, error) {
   323  	if len(rawValue) == 0 {
   324  		return []uint64{}, nil
   325  	}
   326  	rawValues := strings.Split(rawValue, sep)
   327  	valuesCount := len(rawValues)
   328  	array := make([]uint64, 0, valuesCount)
   329  	for i := 0; i < valuesCount; i++ {
   330  		item, err := strconv.ParseUint(rawValues[i], 10, 0)
   331  		if err != nil {
   332  			return nil, err
   333  		}
   334  		array = append(array, item)
   335  	}
   336  	return array, nil
   337  }
   338  
   339  func (r RowWrapper) MustI64(name string) int64 {
   340  	value, err := I64(r.mustColumn(name))
   341  	panicW(name, err)
   342  	return value
   343  }
   344  
   345  // I64B does the same as U64B, but returns a bool indicating whether or not the
   346  // column was set.
   347  func (r RowWrapper) I64B(name string) (int64, bool) {
   348  	if !r.HasColumn(name) {
   349  		return 0, false
   350  	}
   351  	return r.I64(name), true
   352  }
   353  
   354  func (r RowWrapper) I64(name string) int64 {
   355  	value, err := I64(r.values[name])
   356  	panicW(name, err)
   357  	return value
   358  }
   359  
   360  func I64(rawValue string) (int64, error) {
   361  	return strconv.ParseInt(rawValue, 10, 0)
   362  }
   363  
   364  func (r RowWrapper) MustI64Slice(name, sep string) []int64 {
   365  	value, err := I64Slice(r.mustColumn(name), sep)
   366  	panicW(name, err)
   367  	return value
   368  }
   369  
   370  func (r RowWrapper) I64Slice(name, sep string) []int64 {
   371  	value, err := I64Slice(r.values[name], sep)
   372  	panicW(name, err)
   373  	return value
   374  }
   375  
   376  func I64Slice(rawValue string, sep string) ([]int64, error) {
   377  	if len(rawValue) == 0 {
   378  		return []int64{}, nil
   379  	}
   380  	rawValues := strings.Split(rawValue, sep)
   381  	valuesCount := len(rawValues)
   382  	array := make([]int64, 0, valuesCount)
   383  	for i := 0; i < valuesCount; i++ {
   384  		item, err := strconv.ParseInt(rawValues[i], 10, 0)
   385  		if err != nil {
   386  			return nil, err
   387  		}
   388  		array = append(array, item)
   389  	}
   390  	return array, nil
   391  }
   392  
   393  func (r RowWrapper) MustF64(name string) float64 {
   394  	value, err := F64(r.mustColumn(name))
   395  	panicW(name, err)
   396  	return value
   397  }
   398  
   399  func (r RowWrapper) F64(name string) float64 {
   400  	value, err := F64(r.values[name])
   401  	panicW(name, err)
   402  	return value
   403  }
   404  
   405  func F64(rawValue string) (float64, error) {
   406  	return strconv.ParseFloat(rawValue, 64)
   407  }
   408  
   409  func (r RowWrapper) MustF64Slice(name, sep string) []float64 {
   410  	value, err := F64Slice(r.mustColumn(name), sep)
   411  	panicW(name, err)
   412  	return value
   413  }
   414  
   415  func (r RowWrapper) F64Slice(name, sep string) []float64 {
   416  	value, err := F64Slice(r.values[name], sep)
   417  	panicW(name, err)
   418  	return value
   419  }
   420  
   421  func F64Slice(rawValue string, sep string) ([]float64, error) {
   422  	if len(rawValue) == 0 {
   423  		return nil, nil
   424  	}
   425  	rawValues := strings.Split(rawValue, sep)
   426  	valuesCount := len(rawValues)
   427  	array := make([]float64, 0, valuesCount)
   428  	for i := 0; i < valuesCount; i++ {
   429  		item, err := strconv.ParseFloat(rawValues[i], 64)
   430  		if err != nil {
   431  			return nil, err
   432  		}
   433  		array = append(array, item)
   434  	}
   435  	return array, nil
   436  }
   437  
   438  func (r RowWrapper) MustBool(name string) bool {
   439  	b, err := Bool(r.mustColumn(name))
   440  	panicW(name, err)
   441  	return b
   442  }
   443  
   444  func (r RowWrapper) Bool(name string) bool {
   445  	v, ok := r.values[name]
   446  	if !ok {
   447  		return false
   448  	}
   449  	b, err := Bool(v)
   450  	panicW(name, err)
   451  	return b
   452  }
   453  
   454  func Bool(rawValue string) (bool, error) {
   455  	if rawValue == "true" {
   456  		return true, nil
   457  	} else if rawValue == "false" {
   458  		return false, nil
   459  	}
   460  	return false, fmt.Errorf("invalid bool value: %v", rawValue)
   461  }
   462  
   463  func (r RowWrapper) MustTime(name string) time.Time {
   464  	t, err := Time(r.mustColumn(name))
   465  	panicW(name, err)
   466  	return t
   467  }
   468  
   469  func (r RowWrapper) Time(name string) time.Time {
   470  	t, err := Time(r.values[name])
   471  	panicW(name, err)
   472  	return t
   473  }
   474  
   475  func Time(rawTime string) (time.Time, error) {
   476  	parsedTime, err := time.Parse("2006-01-02T15:04:05Z", rawTime)
   477  	if err != nil {
   478  		return parsedTime, fmt.Errorf("invalid date value: %v", err)
   479  	}
   480  	return parsedTime, nil
   481  }
   482  
   483  func (r RowWrapper) MustEventType(name string) events.Type {
   484  	eventType, err := EventType(r.MustStr(name))
   485  	panicW(name, err)
   486  	return eventType
   487  }
   488  
   489  func EventType(rawValue string) (events.Type, error) {
   490  	ty, ok := events.TryFromString(rawValue)
   491  	if !ok {
   492  		return 0, fmt.Errorf("invalid event type: %v", rawValue)
   493  	}
   494  	return *ty, nil
   495  }
   496  
   497  func (r RowWrapper) LossType(name string) types.LossType {
   498  	lt, err := LossType(r.Str(name))
   499  	if err != nil {
   500  		return types.LossTypeUnspecified
   501  	}
   502  	return lt
   503  }
   504  
   505  func (r RowWrapper) MustLossType(name string) types.LossType {
   506  	lt, err := LossType(r.MustStr(name))
   507  	panicW(name, err)
   508  	return lt
   509  }
   510  
   511  func (r RowWrapper) MustOrderType(name string) types.OrderType {
   512  	orderType, err := OrderType(r.MustStr(name))
   513  	panicW(name, err)
   514  	return orderType
   515  }
   516  
   517  func LossType(rawValue string) (types.LossType, error) {
   518  	lt, ok := eventspb.LossSocialization_Type_value[rawValue]
   519  	if !ok {
   520  		return types.LossType(lt), fmt.Errorf("invalid loss socialisation type: %v", rawValue)
   521  	}
   522  	return types.LossType(lt), nil
   523  }
   524  
   525  func OrderType(rawValue string) (types.OrderType, error) {
   526  	ty, ok := proto.Order_Type_value[rawValue]
   527  	if !ok {
   528  		return types.OrderType(ty), fmt.Errorf("invalid order type: %v", rawValue)
   529  	}
   530  	return types.OrderType(ty), nil
   531  }
   532  
   533  func (r RowWrapper) MustOrderStatus(name string) types.OrderStatus {
   534  	s, err := OrderStatus(r.MustStr(name))
   535  	panicW(name, err)
   536  	return s
   537  }
   538  
   539  func (r RowWrapper) MustStopOrderStatus(name string) types.StopOrderStatus {
   540  	s, err := StopOrderStatus(r.MustStr(name))
   541  	panicW(name, err)
   542  	return s
   543  }
   544  
   545  func OrderStatus(rawValue string) (types.OrderStatus, error) {
   546  	ty, ok := proto.Order_Status_value[rawValue]
   547  	if !ok {
   548  		return types.OrderStatus(ty), fmt.Errorf("invalid order status: %v", rawValue)
   549  	}
   550  	return types.OrderStatus(ty), nil
   551  }
   552  
   553  func StopOrderStatus(rawValue string) (types.StopOrderStatus, error) {
   554  	ty, ok := proto.StopOrder_Status_value[rawValue]
   555  	if !ok {
   556  		return types.StopOrderStatus(ty), fmt.Errorf("invalid stop order status: %v", rawValue)
   557  	}
   558  	return types.StopOrderStatus(ty), nil
   559  }
   560  
   561  func (r RowWrapper) MustPositionStatus(name string) proto.PositionStatus {
   562  	// account for empty values
   563  	if v := r.Str(name); len(v) == 0 {
   564  		return proto.PositionStatus_POSITION_STATUS_UNSPECIFIED
   565  	}
   566  	p, err := PositionStatus(r.MustStr(name))
   567  	panicW(name, err)
   568  	return p
   569  }
   570  
   571  func PositionStatus(rawValue string) (proto.PositionStatus, error) {
   572  	ty, ok := proto.PositionStatus_value[rawValue]
   573  	if !ok {
   574  		return proto.PositionStatus(ty), fmt.Errorf("invalid position status: %v", rawValue)
   575  	}
   576  	return proto.PositionStatus(ty), nil
   577  }
   578  
   579  func (r RowWrapper) MustLiquidityStatus(name string) types.LiquidityProvisionStatus {
   580  	s, err := LiquidityStatus(r.MustStr(name))
   581  	panicW(name, err)
   582  	return s
   583  }
   584  
   585  func LiquidityStatus(rawValue string) (types.LiquidityProvisionStatus, error) {
   586  	ty, ok := proto.LiquidityProvision_Status_value[rawValue]
   587  	if !ok {
   588  		return types.LiquidityProvisionStatus(ty), fmt.Errorf("invalid liquidity provision status: %v", rawValue)
   589  	}
   590  	return types.LiquidityProvisionStatus(ty), nil
   591  }
   592  
   593  func (r RowWrapper) MustTIF(name string) types.OrderTimeInForce {
   594  	tif, err := TIF(r.MustStr(name))
   595  	panicW(name, err)
   596  	return tif
   597  }
   598  
   599  func (r RowWrapper) MustExpiryStrategy(name string) types.StopOrderExpiryStrategy {
   600  	expiryS, err := ExpiryStrategy(r.MustStr(name))
   601  	panicW(name, err)
   602  	return expiryS
   603  }
   604  
   605  func TIF(rawValue string) (types.OrderTimeInForce, error) {
   606  	tif, ok := proto.Order_TimeInForce_value[strings.ReplaceAll(rawValue, "TIF_", "TIME_IN_FORCE_")]
   607  	if !ok {
   608  		return types.OrderTimeInForce(tif), fmt.Errorf("invalid time in force: %v", rawValue)
   609  	}
   610  	return types.OrderTimeInForce(tif), nil
   611  }
   612  
   613  func ExpiryStrategy(rawValue string) (types.StopOrderExpiryStrategy, error) {
   614  	es, ok := proto.StopOrder_ExpiryStrategy_value[rawValue]
   615  	if !ok {
   616  		return types.StopOrderExpiryStrategy(es), fmt.Errorf("invalid expiry strategy: %v", rawValue)
   617  	}
   618  	return types.StopOrderExpiryStrategy(es), nil
   619  }
   620  
   621  func (r RowWrapper) MustSide(name string) types.Side {
   622  	side, err := Side(r.MustStr(name))
   623  	panicW(name, err)
   624  	return side
   625  }
   626  
   627  func Side(rawValue string) (types.Side, error) {
   628  	switch rawValue {
   629  	case "sell":
   630  		return types.SideSell, nil
   631  	case "buy":
   632  		return types.SideBuy, nil
   633  	default:
   634  		return types.SideUnspecified, errors.New("invalid side")
   635  	}
   636  }
   637  
   638  func (r RowWrapper) MustPeggedReference(name string) types.PeggedReference {
   639  	return peggedReference(r.MustStr(name))
   640  }
   641  
   642  func peggedReference(rawValue string) types.PeggedReference {
   643  	switch rawValue {
   644  	case "MID":
   645  		return types.PeggedReferenceMid
   646  	case "ASK":
   647  		return types.PeggedReferenceBestAsk
   648  	case "BID":
   649  		return types.PeggedReferenceBestBid
   650  	}
   651  	return types.PeggedReferenceUnspecified
   652  }
   653  
   654  func (r RowWrapper) MustSizeOverrideSetting(name string) types.StopOrderSizeOverrideSetting {
   655  	return sizeOverrideSetting(r.MustStr(name))
   656  }
   657  
   658  func sizeOverrideSetting(rawValue string) types.StopOrderSizeOverrideSetting {
   659  	switch rawValue {
   660  	case "NONE":
   661  		return types.StopOrderSizeOverrideSettingNone
   662  	case "POSITION":
   663  		return types.StopOrderSizeOverrideSettingPosition
   664  	}
   665  	return types.StopOrderSizeOverrideSettingUnspecified
   666  }
   667  
   668  func (r RowWrapper) MustOracleSpecPropertyType(name string) datav1.PropertyKey_Type {
   669  	ty, err := OracleSpecPropertyType(r.MustStr(name))
   670  	panicW(name, err)
   671  	return ty
   672  }
   673  
   674  func OracleSpecPropertyType(name string) (datav1.PropertyKey_Type, error) {
   675  	ty, ok := datav1.PropertyKey_Type_value[name]
   676  
   677  	if !ok {
   678  		return datav1.PropertyKey_TYPE_UNSPECIFIED, fmt.Errorf("couldn't find %s as property type", name)
   679  	}
   680  	return datav1.PropertyKey_Type(ty), nil
   681  }
   682  
   683  func (r RowWrapper) MustOracleSpecConditionOperator(name string) datav1.Condition_Operator {
   684  	ty, err := OracleSpecConditionOperator(r.MustStr(name))
   685  	panicW(name, err)
   686  	return ty
   687  }
   688  
   689  func OracleSpecConditionOperator(name string) (datav1.Condition_Operator, error) {
   690  	ty, ok := datav1.Condition_Operator_value[name]
   691  
   692  	if !ok {
   693  		return datav1.Condition_OPERATOR_UNSPECIFIED, fmt.Errorf("couldn't find %s as operator condition", name)
   694  	}
   695  	return datav1.Condition_Operator(ty), nil
   696  }
   697  
   698  func (r RowWrapper) MustAuctionTrigger(name string) types.AuctionTrigger {
   699  	at, err := AuctionTrigger(r.MustStr(name))
   700  	panicW(name, err)
   701  	return at
   702  }
   703  
   704  func AuctionTrigger(name string) (types.AuctionTrigger, error) {
   705  	at, ok := proto.AuctionTrigger_value[name]
   706  	if !ok {
   707  		return types.AuctionTriggerUnspecified, fmt.Errorf("couldn't find %s as auction trigger", name)
   708  	}
   709  	return types.AuctionTrigger(at), nil
   710  }
   711  
   712  func (r RowWrapper) MustMarketUpdateState(name string) types.MarketStateUpdateType {
   713  	msu, err := MarketStateUpdate(r.MustStr(name))
   714  	panicW(name, err)
   715  	return msu
   716  }
   717  
   718  func MarketStateUpdate(name string) (types.MarketStateUpdateType, error) {
   719  	msu, ok := proto.MarketStateUpdateType_value[name]
   720  	if !ok {
   721  		return types.MarketStateUpdateTypeUnspecified, fmt.Errorf("couldn't find %s as market state update type", name)
   722  	}
   723  	return types.MarketStateUpdateType(msu), nil
   724  }
   725  
   726  func (r RowWrapper) MustTradingMode(name string) types.MarketTradingMode {
   727  	ty, err := TradingMode(r.MustStr(name))
   728  	panicW(name, err)
   729  	return ty
   730  }
   731  
   732  func (r RowWrapper) MarkPriceType() types.CompositePriceType {
   733  	if !r.HasColumn("price type") {
   734  		return types.CompositePriceTypeByLastTrade
   735  	}
   736  	if r.mustColumn("price type") == "last trade" {
   737  		return types.CompositePriceTypeByLastTrade
   738  	} else if r.mustColumn("price type") == "median" {
   739  		return types.CompositePriceTypeByMedian
   740  	} else if r.mustColumn("price type") == "weight" {
   741  		return types.CompositePriceTypeByWeight
   742  	} else {
   743  		panic("invalid price type")
   744  	}
   745  }
   746  
   747  func TradingMode(name string) (types.MarketTradingMode, error) {
   748  	ty, ok := proto.Market_TradingMode_value[name]
   749  
   750  	if !ok {
   751  		return types.MarketTradingModeUnspecified, fmt.Errorf("couldn't find %s as trading_mode", name)
   752  	}
   753  	return types.MarketTradingMode(ty), nil
   754  }
   755  
   756  func MarketState(name string) (types.MarketState, error) {
   757  	ty, ok := proto.Market_State_value[name]
   758  
   759  	if !ok {
   760  		return types.MarketStateUnspecified, fmt.Errorf("couldn't find %s as market state", name)
   761  	}
   762  	return types.MarketState(ty), nil
   763  }
   764  
   765  func (r RowWrapper) MustAccount(name string) types.AccountType {
   766  	acc, err := Account(r.MustStr(name))
   767  	panicW(name, err)
   768  	return acc
   769  }
   770  
   771  func Account(name string) (types.AccountType, error) {
   772  	value := types.AccountType(proto.AccountType_value[name])
   773  
   774  	if value == types.AccountTypeUnspecified {
   775  		return types.AccountTypeUnspecified, fmt.Errorf("invalid account type %s", name)
   776  	}
   777  	return value, nil
   778  }
   779  
   780  func AccountID(marketID, partyID, asset string, ty types.AccountType) string {
   781  	idBuf := make([]byte, 256)
   782  
   783  	if ty == types.AccountTypeGeneral || ty == types.AccountTypeFeesInfrastructure {
   784  		marketID = ""
   785  	}
   786  
   787  	if partyID == "market" {
   788  		partyID = ""
   789  	}
   790  
   791  	if len(marketID) == 0 {
   792  		marketID = "!"
   793  	}
   794  
   795  	if len(partyID) == 0 {
   796  		partyID = "*"
   797  	}
   798  
   799  	copy(idBuf, marketID)
   800  	ln := len(marketID)
   801  	copy(idBuf[ln:], partyID)
   802  	ln += len(partyID)
   803  	copy(idBuf[ln:], asset)
   804  	ln += len(asset)
   805  	idBuf[ln] = byte(ty + 48)
   806  	return string(idBuf[:ln+1])
   807  }
   808  
   809  func (r RowWrapper) MustDuration(name string) time.Duration {
   810  	return time.Duration(r.MustI64(name))
   811  }
   812  
   813  func (r RowWrapper) Duration(name string) time.Duration {
   814  	return time.Duration(r.I64(name))
   815  }
   816  
   817  func (r RowWrapper) MustDurationStr(name string) time.Duration {
   818  	s := r.MustStr(name)
   819  	d, err := time.ParseDuration(s)
   820  	panicW(name, err)
   821  	return d
   822  }
   823  
   824  func (r RowWrapper) MustDurationSec(name string) time.Duration {
   825  	n := r.MustI64(name)
   826  	if n == 0 {
   827  		return 0
   828  	}
   829  	return time.Duration(n) * time.Second
   830  }
   831  
   832  func (r RowWrapper) MustDurationSec2(name string) time.Duration {
   833  	n := r.MustI64(name)
   834  	if n == 0 {
   835  		return 0
   836  	}
   837  	return time.Duration(n) * time.Second
   838  }
   839  
   840  func (r RowWrapper) DurationSec(name string) time.Duration {
   841  	n := r.I64(name)
   842  	if n == 0 {
   843  		return 0
   844  	}
   845  	return time.Duration(n) * time.Second
   846  }
   847  
   848  func (r RowWrapper) MustAMMCancelationMethod(name string) types.AMMCancellationMethod {
   849  	cancelMethod, err := AMMCancelMethod(r.MustStr(name))
   850  	panicW(name, err)
   851  	return cancelMethod
   852  }
   853  
   854  func (r RowWrapper) MustAMMPoolStatus(name string) types.AMMPoolStatus {
   855  	ps, err := AMMPoolStatus(r.MustStr(name))
   856  	panicW(name, err)
   857  	return ps
   858  }
   859  
   860  func (r RowWrapper) MustPoolStatusReason(name string) types.AMMStatusReason {
   861  	pr, err := AMMPoolStatusReason(r.MustStr(name))
   862  	panicW(name, err)
   863  	return pr
   864  }
   865  
   866  func AMMCancelMethod(rawValue string) (types.AMMCancellationMethod, error) {
   867  	ty, ok := commandspb.CancelAMM_Method_value[rawValue]
   868  	if !ok {
   869  		return types.AMMCancellationMethod(ty), fmt.Errorf("invalid cancelation method: %v", rawValue)
   870  	}
   871  	return types.AMMCancellationMethod(ty), nil
   872  }
   873  
   874  func AMMPoolStatus(rawValue string) (types.AMMPoolStatus, error) {
   875  	ps, ok := eventspb.AMM_Status_value[rawValue]
   876  	if !ok {
   877  		return types.AMMPoolStatusUnspecified, fmt.Errorf("invalid AMM pool status: %s", rawValue)
   878  	}
   879  	return types.AMMPoolStatus(ps), nil
   880  }
   881  
   882  func AMMPoolStatusReason(rawValue string) (types.AMMStatusReason, error) {
   883  	pr, ok := eventspb.AMM_StatusReason_value[rawValue]
   884  	if !ok {
   885  		return types.AMMStatusReasonUnspecified, fmt.Errorf("invalid AMM pool status reason: %s", rawValue)
   886  	}
   887  	return types.AMMStatusReason(pr), nil
   888  }
   889  
   890  func panicW(field string, err error) {
   891  	if err != nil {
   892  		panic(fmt.Sprintf("couldn't parse %s: %v", field, err))
   893  	}
   894  }
   895  
   896  func stringToU64(s string) uint64 {
   897  	i, _ := strconv.ParseUint(s, 10, 64)
   898  	return i
   899  }