code.vegaprotocol.io/vega@v0.79.0/core/integration/steps/the_oracle_spec.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  	"time"
    22  
    23  	dstypes "code.vegaprotocol.io/vega/core/datasource/common"
    24  	"code.vegaprotocol.io/vega/core/integration/steps/market"
    25  	"code.vegaprotocol.io/vega/libs/ptr"
    26  	vgrand "code.vegaprotocol.io/vega/libs/rand"
    27  	protoTypes "code.vegaprotocol.io/vega/protos/vega"
    28  	datav1 "code.vegaprotocol.io/vega/protos/vega/data/v1"
    29  
    30  	"github.com/cucumber/godog"
    31  )
    32  
    33  func TheOracleSpec(config *market.Config, name string, specType string, rawPubKeys string, table *godog.Table) error {
    34  	pubKeys := StrSlice(rawPubKeys, ",")
    35  	pubKeysSigners := make([]*datav1.Signer, len(pubKeys))
    36  	for i, s := range pubKeys {
    37  		pks := dstypes.CreateSignerFromString(s, dstypes.SignerTypePubKey)
    38  		pubKeysSigners[i] = pks.IntoProto()
    39  	}
    40  
    41  	binding := &protoTypes.DataSourceSpecToFutureBinding{}
    42  
    43  	rows := parseOracleSpecTable(table)
    44  	filters := make([]*datav1.Filter, 0, len(rows))
    45  	for _, r := range rows {
    46  		row := oracleSpecRow{row: r}
    47  		var numDec *uint64
    48  		decimals, ok := row.propertyDecimals()
    49  		if ok {
    50  			numDec = ptr.From(decimals)
    51  		}
    52  		filter := &datav1.Filter{
    53  			Key: &datav1.PropertyKey{
    54  				Name:                row.propertyName(),
    55  				Type:                row.propertyType(),
    56  				NumberDecimalPlaces: numDec,
    57  			},
    58  			Conditions: []*datav1.Condition{},
    59  		}
    60  
    61  		if r.HasColumn("condition") != r.HasColumn("value") {
    62  			return errors.New("condition and value columns require each other")
    63  		}
    64  
    65  		if r.HasColumn("condition") {
    66  			value := row.value()
    67  
    68  			if row.propertyType() == datav1.PropertyKey_TYPE_TIMESTAMP {
    69  				expiry, err := time.Parse(time.RFC3339, value)
    70  				if err != nil {
    71  					panic(fmt.Errorf("cannot parse expiry condition: %w", err))
    72  				}
    73  				value = fmt.Sprintf("%d", expiry.Unix())
    74  			}
    75  
    76  			filter.Conditions = append(filter.Conditions,
    77  				&datav1.Condition{
    78  					Operator: row.condition(),
    79  					Value:    value,
    80  				},
    81  			)
    82  		}
    83  
    84  		filters = append(filters, filter)
    85  
    86  		if row.destination() == "settlement data" {
    87  			binding.SettlementDataProperty = row.propertyName()
    88  		}
    89  		if row.destination() == "trading termination" {
    90  			binding.TradingTerminationProperty = row.propertyName()
    91  		}
    92  	}
    93  
    94  	return config.OracleConfigs.Add(
    95  		name,
    96  		specType,
    97  		&protoTypes.DataSourceSpec{
    98  			Id: vgrand.RandomStr(10),
    99  			Data: protoTypes.NewDataSourceDefinition(
   100  				protoTypes.DataSourceContentTypeOracle,
   101  			).SetOracleConfig(
   102  				&protoTypes.DataSourceDefinitionExternal_Oracle{
   103  					Oracle: &protoTypes.DataSourceSpecConfiguration{
   104  						Signers: pubKeysSigners,
   105  						Filters: filters,
   106  					},
   107  				},
   108  			),
   109  		},
   110  		binding,
   111  	)
   112  }
   113  
   114  func parseOracleSpecTable(table *godog.Table) []RowWrapper {
   115  	return StrictParseTable(table, []string{
   116  		"property",
   117  		"type",
   118  		"binding",
   119  	}, []string{
   120  		"decimals",
   121  		"condition",
   122  		"value",
   123  	})
   124  }
   125  
   126  type oracleSpecRow struct {
   127  	row RowWrapper
   128  }
   129  
   130  func (r oracleSpecRow) propertyName() string {
   131  	return r.row.MustStr("property")
   132  }
   133  
   134  func (r oracleSpecRow) propertyType() datav1.PropertyKey_Type {
   135  	return r.row.MustOracleSpecPropertyType("type")
   136  }
   137  
   138  func (r oracleSpecRow) propertyDecimals() (uint64, bool) {
   139  	return r.row.U64B("decimals")
   140  }
   141  
   142  func (r oracleSpecRow) destination() string {
   143  	return r.row.MustStr("binding")
   144  }
   145  
   146  func (r oracleSpecRow) condition() datav1.Condition_Operator {
   147  	return r.row.MustOracleSpecConditionOperator("condition")
   148  }
   149  
   150  func (r oracleSpecRow) value() string {
   151  	return r.row.MustStr("value")
   152  }