code.vegaprotocol.io/vega@v0.79.0/core/markets/instrument_test.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 markets_test 17 18 import ( 19 "context" 20 "testing" 21 22 "code.vegaprotocol.io/vega/core/broker/mocks" 23 "code.vegaprotocol.io/vega/core/datasource" 24 dstypes "code.vegaprotocol.io/vega/core/datasource/common" 25 "code.vegaprotocol.io/vega/core/datasource/external/signedoracle" 26 "code.vegaprotocol.io/vega/core/datasource/spec" 27 emock "code.vegaprotocol.io/vega/core/execution/common/mocks" 28 "code.vegaprotocol.io/vega/core/markets" 29 "code.vegaprotocol.io/vega/core/products" 30 "code.vegaprotocol.io/vega/core/types" 31 tmocks "code.vegaprotocol.io/vega/core/vegatime/mocks" 32 "code.vegaprotocol.io/vega/logging" 33 datapb "code.vegaprotocol.io/vega/protos/vega/data/v1" 34 35 "github.com/golang/mock/gomock" 36 "github.com/stretchr/testify/assert" 37 "github.com/stretchr/testify/require" 38 ) 39 40 func TestInstrument(t *testing.T) { 41 t.Run("Create a valid new instrument", func(t *testing.T) { 42 ctrl := gomock.NewController(t) 43 pinst := getValidInstrumentProto() 44 inst, err := markets.NewInstrument(context.Background(), logging.NewTestLogger(), pinst, "", tmocks.NewMockTimeService(ctrl), newOracleEngine(t), mocks.NewMockBroker(ctrl), 1) 45 assert.NotNil(t, inst) 46 assert.Nil(t, err) 47 }) 48 49 t.Run("nil product", func(t *testing.T) { 50 ctrl := gomock.NewController(t) 51 pinst := getValidInstrumentProto() 52 pinst.Product = nil 53 inst, err := markets.NewInstrument(context.Background(), logging.NewTestLogger(), pinst, "", tmocks.NewMockTimeService(ctrl), newOracleEngine(t), mocks.NewMockBroker(ctrl), 1) 54 assert.Nil(t, inst) 55 assert.NotNil(t, err) 56 assert.Equal(t, err.Error(), "unable to instantiate product from instrument configuration: nil product") 57 }) 58 59 t.Run("nil oracle spec", func(t *testing.T) { 60 ctrl := gomock.NewController(t) 61 pinst := getValidInstrumentProto() 62 pinst.Product = &types.InstrumentFuture{ 63 Future: &types.Future{ 64 SettlementAsset: "Ethereum/Ether", 65 DataSourceSpecForSettlementData: nil, 66 DataSourceSpecForTradingTermination: nil, 67 DataSourceSpecBinding: &datasource.SpecBindingForFuture{ 68 SettlementDataProperty: "prices.ETH.value", 69 TradingTerminationProperty: "trading.terminated", 70 }, 71 }, 72 } 73 inst, err := markets.NewInstrument(context.Background(), logging.NewTestLogger(), pinst, "", tmocks.NewMockTimeService(ctrl), newOracleEngine(t), mocks.NewMockBroker(ctrl), 1) 74 require.NotNil(t, err) 75 assert.Nil(t, inst) 76 assert.Equal(t, "unable to instantiate product from instrument configuration: a data source spec and spec binding are required", err.Error()) 77 }) 78 79 t.Run("nil oracle spec binding", func(t *testing.T) { 80 ctrl := gomock.NewController(t) 81 pinst := getValidInstrumentProto() 82 pinst.Product = &types.InstrumentFuture{ 83 Future: &types.Future{ 84 SettlementAsset: "Ethereum/Ether", 85 DataSourceSpecForSettlementData: &datasource.Spec{ 86 Data: datasource.NewDefinition( 87 datasource.ContentTypeOracle, 88 ).SetOracleConfig( 89 &signedoracle.SpecConfiguration{ 90 Signers: []*dstypes.Signer{dstypes.CreateSignerFromString("0xDEADBEEF", dstypes.SignerTypePubKey)}, 91 Filters: []*dstypes.SpecFilter{ 92 { 93 Key: &dstypes.SpecPropertyKey{ 94 Name: "prices.ETH.value", 95 Type: datapb.PropertyKey_TYPE_INTEGER, 96 }, 97 Conditions: []*dstypes.SpecCondition{}, 98 }, 99 }, 100 }, 101 ), 102 }, 103 DataSourceSpecForTradingTermination: &datasource.Spec{ 104 Data: datasource.NewDefinition( 105 datasource.ContentTypeOracle, 106 ).SetOracleConfig( 107 &signedoracle.SpecConfiguration{ 108 Signers: []*dstypes.Signer{dstypes.CreateSignerFromString("0xDEADBEEF", dstypes.SignerTypePubKey)}, 109 Filters: []*dstypes.SpecFilter{ 110 { 111 Key: &dstypes.SpecPropertyKey{ 112 Name: "trading.terminated", 113 Type: datapb.PropertyKey_TYPE_BOOLEAN, 114 }, 115 Conditions: []*dstypes.SpecCondition{}, 116 }, 117 }, 118 }, 119 ), 120 }, 121 DataSourceSpecBinding: nil, 122 }, 123 } 124 inst, err := markets.NewInstrument(context.Background(), logging.NewTestLogger(), pinst, "", tmocks.NewMockTimeService(ctrl), newOracleEngine(t), mocks.NewMockBroker(ctrl), 1) 125 require.NotNil(t, err) 126 assert.Nil(t, inst) 127 assert.Equal(t, "unable to instantiate product from instrument configuration: a data source spec and spec binding are required", err.Error()) 128 }) 129 } 130 131 func newOracleEngine(t *testing.T) products.OracleEngine { 132 t.Helper() 133 ctrl := gomock.NewController(t) 134 broker := mocks.NewMockBroker(ctrl) 135 broker.EXPECT().Send(gomock.Any()).AnyTimes() 136 137 ts := emock.NewMockTimeService(ctrl) 138 ts.EXPECT().GetTimeNow().AnyTimes() 139 140 return spec.NewEngine( 141 logging.NewTestLogger(), 142 spec.NewDefaultConfig(), 143 ts, 144 broker, 145 ) 146 } 147 148 func getValidInstrumentProto() *types.Instrument { 149 return &types.Instrument{ 150 ID: "Crypto/BTCUSD/Futures/Dec19", 151 Code: "FX:BTCUSD/DEC19", 152 Name: "December 2019 BTC vs USD future", 153 Metadata: &types.InstrumentMetadata{ 154 Tags: []string{ 155 "asset_class:fx/crypto", 156 "product:futures", 157 }, 158 }, 159 Product: &types.InstrumentFuture{ 160 Future: &types.Future{ 161 QuoteName: "USD", 162 SettlementAsset: "Ethereum/Ether", 163 DataSourceSpecForSettlementData: &datasource.Spec{ 164 Data: datasource.NewDefinition( 165 datasource.ContentTypeOracle, 166 ).SetOracleConfig( 167 &signedoracle.SpecConfiguration{ 168 Signers: []*dstypes.Signer{dstypes.CreateSignerFromString("0xDEADBEEF", dstypes.SignerTypePubKey)}, 169 Filters: []*dstypes.SpecFilter{ 170 { 171 Key: &dstypes.SpecPropertyKey{ 172 Name: "prices.ETH.value", 173 Type: datapb.PropertyKey_TYPE_INTEGER, 174 }, 175 Conditions: []*dstypes.SpecCondition{}, 176 }, 177 }, 178 }, 179 ), 180 }, 181 DataSourceSpecForTradingTermination: &datasource.Spec{ 182 Data: datasource.NewDefinition( 183 datasource.ContentTypeOracle, 184 ).SetOracleConfig( 185 &signedoracle.SpecConfiguration{ 186 Signers: []*dstypes.Signer{dstypes.CreateSignerFromString("0xDEADBEEF", dstypes.SignerTypePubKey)}, 187 Filters: []*dstypes.SpecFilter{ 188 { 189 Key: &dstypes.SpecPropertyKey{ 190 Name: "trading.terminated", 191 Type: datapb.PropertyKey_TYPE_BOOLEAN, 192 }, 193 Conditions: []*dstypes.SpecCondition{}, 194 }, 195 }, 196 }, 197 ), 198 }, 199 DataSourceSpecBinding: &datasource.SpecBindingForFuture{ 200 SettlementDataProperty: "prices.ETH.value", 201 TradingTerminationProperty: "trading.terminated", 202 }, 203 }, 204 }, 205 } 206 }