From 3ec74dc887bb5cfc902f923afa6d3d5dcb106bcd Mon Sep 17 00:00:00 2001 From: Aniket Dixit Date: Fri, 11 Aug 2023 11:06:53 +0530 Subject: [PATCH] modifications for deviations (#147) * modifications for deviations init * test fixes * unit test fixes * contract query import error fix * schema modifications * tc name fix * resolve duration flag * contract version change * updating docs * merge fixes --- .gitignore | 5 +- cosmwasm/Cargo.lock | 4 +- cosmwasm/README.md | 12 +- cosmwasm/contracts/price-feed/Cargo.toml | 2 +- .../contracts/price-feed/examples/schema.rs | 5 +- cosmwasm/contracts/price-feed/src/contract.rs | 78 +++++----- cosmwasm/contracts/price-feed/src/msg.rs | 23 ++- cosmwasm/contracts/price-feed/src/state.rs | 22 ++- cw-relayer/README.md | 6 +- cw-relayer/relayer/messages.go | 40 ++--- cw-relayer/relayer/relayer_test.go | 74 ++++++---- cw-relayer/tests/e2e/e2e_test.go | 138 ++++++++++++++---- 12 files changed, 265 insertions(+), 144 deletions(-) diff --git a/.gitignore b/.gitignore index 6a9604b..0eaac01 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ cosmwasm/artifacts cosmwasm/target -cw-relayer/build \ No newline at end of file +cw-relayer/build + +# ide files +.idea \ No newline at end of file diff --git a/cosmwasm/Cargo.lock b/cosmwasm/Cargo.lock index e0c40cf..215528f 100644 --- a/cosmwasm/Cargo.lock +++ b/cosmwasm/Cargo.lock @@ -646,7 +646,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "std-reference" -version = "0.1.3" +version = "0.1.6" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -735,4 +735,4 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" name = "zeroize" version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" \ No newline at end of file +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" diff --git a/cosmwasm/README.md b/cosmwasm/README.md index b85a26f..27297a2 100644 --- a/cosmwasm/README.md +++ b/cosmwasm/README.md @@ -186,15 +186,15 @@ pub struct RefMedianData { ### DeviationData -`RefData` is the struct that is returned when querying with `GetDeviationRef` or `GetDeviationRefBulk` where the -bulk variant returns `Vec` +`RefDeviationData` is the struct that is returned when querying with `GetDeviationRef` or `GetDeviationRefBulk` where the +bulk variant returns `Vec` -`RefData` is defined as: +`RefDeviationData` is defined as: ```rust -pub struct RefData { - // Rate of an asset relative to USD (deviation of assets when used with deviation queries) - pub rate: Uint64, +pub struct RefDeviationData { + // Deviation Rates of an asset relative to USD + pub rates: Vec, // The resolve time of the request ID pub resolve_time: Uint64, // The request ID where the rate was derived from diff --git a/cosmwasm/contracts/price-feed/Cargo.toml b/cosmwasm/contracts/price-feed/Cargo.toml index 34fcffa..ba7f539 100644 --- a/cosmwasm/contracts/price-feed/Cargo.toml +++ b/cosmwasm/contracts/price-feed/Cargo.toml @@ -2,7 +2,7 @@ authors = ["ojonetwork"] edition = "2021" name = "std-reference" -version = "0.1.3" +version = "0.1.6" exclude = [ "contract.wasm", diff --git a/cosmwasm/contracts/price-feed/examples/schema.rs b/cosmwasm/contracts/price-feed/examples/schema.rs index 2ffc644..02699cc 100644 --- a/cosmwasm/contracts/price-feed/examples/schema.rs +++ b/cosmwasm/contracts/price-feed/examples/schema.rs @@ -4,7 +4,7 @@ use std::fs::create_dir_all; use cosmwasm_schema::{export_schema, remove_schemas, schema_for}; use std_reference::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; -use std_reference::state::{RefData, ReferenceData, RefMedianData}; +use std_reference::state::{RefData, RefMedianData, ReferenceData,RefDeviationData}; fn main() { let mut out_dir = current_dir().unwrap(); @@ -17,6 +17,7 @@ fn main() { export_schema(&schema_for!(ExecuteMsg), &out_dir); export_schema(&schema_for!(QueryMsg), &out_dir); export_schema(&schema_for!(RefData), &out_dir); - export_schema(&schema_for!(ReferenceData), &out_dir); export_schema(&schema_for!(RefMedianData), &out_dir); + export_schema(&schema_for!(RefDeviationData), &out_dir); + export_schema(&schema_for!(ReferenceData), &out_dir); } diff --git a/cosmwasm/contracts/price-feed/src/contract.rs b/cosmwasm/contracts/price-feed/src/contract.rs index 66ac8c2..a35dd56 100644 --- a/cosmwasm/contracts/price-feed/src/contract.rs +++ b/cosmwasm/contracts/price-feed/src/contract.rs @@ -8,8 +8,8 @@ use semver::Version; use crate::errors::ContractError; use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; use crate::state::{ - RefData, RefMedianData, ReferenceData, ADMIN, DEVIATIONDATA, MEDIANREFDATA, MEDIANSTATUS, - REFDATA, RELAYERS, + RefData, RefDeviationData, RefMedianData, ReferenceData, ADMIN, DEVIATIONDATA, MEDIANREFDATA, + MEDIANSTATUS, REFDATA, RELAYERS, }; const E0: Uint64 = Uint64::zero(); @@ -288,7 +288,7 @@ fn execute_force_relay_historical_median( fn execute_relay_historical_deviation( deps: DepsMut, info: MessageInfo, - symbol_rates: Vec<(String, Uint64)>, + symbol_rates: Vec<(String, Vec)>, resolve_time: Uint64, request_id: Uint64, ) -> Result { @@ -301,7 +301,7 @@ fn execute_relay_historical_deviation( } // Saves price data - for (symbol, rate) in symbol_rates { + for (symbol, rates) in symbol_rates { if let Some(existing_refdata) = DEVIATIONDATA.may_load(deps.storage, &symbol)? { if existing_refdata.resolve_time >= resolve_time { continue; @@ -311,7 +311,7 @@ fn execute_relay_historical_deviation( DEVIATIONDATA.save( deps.storage, &symbol, - &RefData::new(rate, resolve_time, request_id), + &RefDeviationData::new(rates, resolve_time, request_id), )? } @@ -321,7 +321,7 @@ fn execute_relay_historical_deviation( fn execute_force_relay_historical_deviation( deps: DepsMut, info: MessageInfo, - symbol_rates: Vec<(String, Uint64)>, + symbol_rates: Vec<(String, Vec)>, resolve_time: Uint64, request_id: Uint64, ) -> Result { @@ -334,11 +334,11 @@ fn execute_force_relay_historical_deviation( } // Saves price data - for (symbol, rate) in symbol_rates { + for (symbol, rates) in symbol_rates { DEVIATIONDATA.save( deps.storage, &symbol, - &RefData::new(rate, resolve_time, request_id), + &RefDeviationData::new(rates, resolve_time, request_id), )? } @@ -409,7 +409,7 @@ fn query_reference_data_bulk( // can only support USD fn query_median_ref(deps: Deps, symbol: &str) -> StdResult { if !MEDIANSTATUS.load(deps.storage)? { - return Err(StdError::generic_err ("MEDIAN DISABLED")); + return Err(StdError::generic_err("MEDIAN DISABLED")); } if symbol == "USD" { @@ -426,15 +426,15 @@ fn query_median_ref_data_bulk(deps: Deps, symbols: &[String]) -> StdResult StdResult { +fn query_deviation_ref(deps: Deps, symbol: &str) -> StdResult { if symbol == "USD" { - Ok(RefData::new(E0, Uint64::MAX, Uint64::zero())) + Ok(RefDeviationData::new(vec![E0], Uint64::MAX, Uint64::zero())) } else { DEVIATIONDATA.load(deps.storage, symbol) } } -fn query_deviation_ref_bulk(deps: Deps, symbols: &[String]) -> StdResult> { +fn query_deviation_ref_bulk(deps: Deps, symbols: &[String]) -> StdResult> { symbols .iter() .map(|symbol| query_deviation_ref(deps, symbol)) @@ -925,10 +925,7 @@ mod tests { // Check if relay was successful let err = query_median_ref_data_bulk(deps.as_ref(), &symbols.clone()).unwrap_err(); - assert_eq!( - err, - StdError::generic_err ("MEDIAN DISABLED") - ); + assert_eq!(err, StdError::generic_err("MEDIAN DISABLED")); } #[test] @@ -1015,9 +1012,14 @@ mod tests { .map(|r| Uint64::new(*r)) .collect::>(); + let symbol_rates: Vec<(String, Vec)> = symbols + .iter() + .zip(std::iter::repeat(rates.clone())) + .map(|(s, r)| (s.to_owned(), r)) + .collect(); + let msg = RelayHistoricalDeviation { - symbol_rates: zip(symbols.clone(), rates.clone()) - .collect::>(), + symbol_rates: symbol_rates.clone(), resolve_time: Uint64::from(10u64), request_id: Uint64::one(), }; @@ -1027,13 +1029,9 @@ mod tests { let reference_datas = query_deviation_ref_bulk(deps.as_ref(), &symbols.clone()).unwrap(); - let retrieved_rates = reference_datas - .clone() - .iter() - .map(|r| r.rate) - .collect::>(); - - assert_eq!(retrieved_rates, rates); + for (expected, actual) in symbol_rates.iter().zip(reference_datas.iter()) { + assert_eq!(expected.1, actual.rates) + } } #[test] @@ -1050,14 +1048,19 @@ mod tests { .into_iter() .map(|s| s.to_string()) .collect::>(); - let deviations = [1000, 2000, 3000] + let rates = [1000, 2000, 3000] .iter() .map(|r| Uint64::new(*r)) .collect::>(); + let symbol_rates: Vec<(String, Vec)> = symbols + .iter() + .zip(std::iter::repeat(rates.clone())) + .map(|(s, r)| (s.to_owned(), r)) + .collect(); + let msg = ForceRelayHistoricalDeviation { - symbol_rates: zip(symbols.clone(), deviations.clone()) - .collect::>(), + symbol_rates: symbol_rates.clone(), resolve_time: Uint64::from(100u64), request_id: Uint64::from(2u64), }; @@ -1071,9 +1074,14 @@ mod tests { .map(|r| Uint64::new(*r)) .collect::>(); + let symbol_rates: Vec<(String, Vec)> = symbols + .iter() + .zip(std::iter::repeat(forced_deviations.clone())) + .map(|(s, r)| (s.to_owned(), r)) + .collect(); + let msg = ForceRelayHistoricalDeviation { - symbol_rates: zip(symbols.clone(), forced_deviations.clone()) - .collect::>(), + symbol_rates: symbol_rates.clone(), resolve_time: Uint64::from(10u64), request_id: Uint64::zero(), }; @@ -1083,13 +1091,9 @@ mod tests { let reference_datas = query_deviation_ref_bulk(deps.as_ref(), &symbols.clone()).unwrap(); - let retrieved_rates = reference_datas - .clone() - .iter() - .map(|r| r.rate) - .collect::>(); - - assert_eq!(retrieved_rates, forced_deviations); + for (expected, actual) in symbol_rates.iter().zip(reference_datas.iter()) { + assert_eq!(expected.1, actual.rates) + } } #[test] diff --git a/cosmwasm/contracts/price-feed/src/msg.rs b/cosmwasm/contracts/price-feed/src/msg.rs index b639829..643a155 100644 --- a/cosmwasm/contracts/price-feed/src/msg.rs +++ b/cosmwasm/contracts/price-feed/src/msg.rs @@ -1,7 +1,6 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::Uint64; - -use crate::state::{RefData, RefMedianData, ReferenceData}; +use crate::state::{RefData,RefDeviationData,RefMedianData,ReferenceData}; #[cw_serde] pub struct InstantiateMsg {} @@ -44,7 +43,7 @@ pub enum ExecuteMsg { // Request ID of the results on Ojo request_id: Uint64, }, - // Relays a vector of symbols and their corresponding rates + // Relays a vector of symbols and their corresponding median rates RelayHistoricalMedian { // A vector of symbols and their corresponding rates where: // symbol_rate := (symbol, rate) @@ -57,9 +56,9 @@ pub enum ExecuteMsg { // Request ID of the results on Ojo request_id: Uint64, }, - // Relays a vector of symbols and their corresponding rates + // Relays a vector of symbols and their corresponding deviation rates RelayHistoricalDeviation { - symbol_rates: Vec<(String, Uint64)>, + symbol_rates: Vec<(String, Vec)>, resolve_time: Uint64, // Request ID of the results on Ojo request_id: Uint64, @@ -70,15 +69,15 @@ pub enum ExecuteMsg { resolve_time: Uint64, request_id: Uint64, }, - // Same as Relay but without the resolve_time guard + // Same as RelayHistoricalMedian but without the resolve_time guard ForceRelayHistoricalMedian { symbol_rates: Vec<(String, Vec)>, resolve_time: Uint64, request_id: Uint64, }, - // Relays a vector of symbols and their corresponding deviations + // Same as RelayHistoricalDeviation but without the resolve_time guard ForceRelayHistoricalDeviation { - symbol_rates: Vec<(String, Uint64)>, + symbol_rates: Vec<(String, Vec)>, resolve_time: Uint64, // Request ID of the results on Ojo request_id: Uint64, @@ -133,15 +132,15 @@ pub enum QueryMsg { // Vector of Symbols to query symbols: Vec, }, - #[returns(RefData)] - // Returns the deviation RefData of a given symbol + #[returns(RefDeviationData)] + // Returns the deviation RefDeviationData of a given symbol GetDeviationRef { // Symbol to query symbol: String, }, - #[returns(Vec < RefData >)] - // Returns the deviation RefData of the given symbols + #[returns(Vec < RefDeviationData >)] + // Returns the deviation RefDeviationData of the given symbols GetDeviationRefBulk { // Vector of Symbols to query symbols: Vec, diff --git a/cosmwasm/contracts/price-feed/src/state.rs b/cosmwasm/contracts/price-feed/src/state.rs index fc23633..b479799 100644 --- a/cosmwasm/contracts/price-feed/src/state.rs +++ b/cosmwasm/contracts/price-feed/src/state.rs @@ -19,7 +19,7 @@ pub const MEDIANREFDATA: Map<&str, RefMedianData> = Map::new("medianrefdata"); pub const MEDIANSTATUS: Item = Item::new("medianstatus"); // Used to store Deviation data -pub const DEVIATIONDATA: Map<&str, RefData> = Map::new("deviationdata"); +pub const DEVIATIONDATA: Map<&str, RefDeviationData> = Map::new("deviationdata"); #[cw_serde] pub struct RefData { @@ -61,6 +61,26 @@ impl RefMedianData { } } +#[cw_serde] +pub struct RefDeviationData { + // Deviation Rates of an asset relative to USD + pub rates: Vec, + // The resolve time of the request ID + pub resolve_time: Uint64, + // The request ID where the rate was derived from + pub request_id: Uint64, +} + +impl RefDeviationData { + pub fn new(rates: Vec, resolve_time: Uint64, request_id: Uint64) -> Self { + RefDeviationData { + rates, + resolve_time, + request_id, + } + } +} + #[cw_serde] pub struct ReferenceData { // Pair rate e.g. rate of BTC/USD diff --git a/cw-relayer/README.md b/cw-relayer/README.md index da1ec17..70bd03d 100644 --- a/cw-relayer/README.md +++ b/cw-relayer/README.md @@ -14,4 +14,8 @@ each msg above has a forced version which ignores the resolve duration present i #### Median Duration - median duration determines how frequently median prices are posted to the contract -- if median duration is set to 0, then median prices are not posted to the contract \ No newline at end of file +- if median duration is set to 0, then median prices are not posted to the contract + +### Links to other supported implementations +- [Secret Network](https://github.com/ojo-network/contracts/tree/secret) +- [Evm](https://github.com/ojo-network/contracts/tree/evm) \ No newline at end of file diff --git a/cw-relayer/relayer/messages.go b/cw-relayer/relayer/messages.go index b2b42d6..cd56ea2 100644 --- a/cw-relayer/relayer/messages.go +++ b/cw-relayer/relayer/messages.go @@ -130,42 +130,42 @@ func genRateMsgData(forceRelay bool, msgType MsgType, requestID uint64, resolveT RequestID: requestID, } - if msgType != RelayHistoricalMedian { + if msgType == RelayRate { for _, rate := range rates { msg.SymbolRates = append(msg.SymbolRates, [2]interface{}{rate.Denom, rate.Amount.Mul(RateFactor).TruncateInt().String()}) } - } - switch msgType { - case RelayRate: if forceRelay { msgData, err = json.Marshal(MsgForceRelay{Relay: msg}) } else { msgData, err = json.Marshal(MsgRelay{Relay: msg}) } - case RelayHistoricalMedian: - // collect denom's medians - medianRates := map[string][]string{} + return + } else { + symbolRates := map[string][]string{} for _, rate := range rates { - medianRates[rate.Denom] = append(medianRates[rate.Denom], rate.Amount.Mul(RateFactor).TruncateInt().String()) + symbolRates[rate.Denom] = append(symbolRates[rate.Denom], rate.Amount.Mul(RateFactor).TruncateInt().String()) } - for denom, medians := range medianRates { + for denom, medians := range symbolRates { msg.SymbolRates = append(msg.SymbolRates, [2]interface{}{denom, medians}) } - if forceRelay { - msgData, err = json.Marshal(MsgForceRelayHistoricalMedian{Relay: msg}) - } else { - msgData, err = json.Marshal(MsgRelayHistoricalMedian{Relay: msg}) - } - - case RelayHistoricalDeviation: - if forceRelay { - msgData, err = json.Marshal(MsgForceRelayHistoricalDeviation{Relay: msg}) - } else { - msgData, err = json.Marshal(MsgRelayHistoricalDeviation{Relay: msg}) + switch msgType { + case RelayHistoricalMedian: + if forceRelay { + msgData, err = json.Marshal(MsgForceRelayHistoricalMedian{Relay: msg}) + } else { + msgData, err = json.Marshal(MsgRelayHistoricalMedian{Relay: msg}) + } + + case RelayHistoricalDeviation: + if forceRelay { + msgData, err = json.Marshal(MsgForceRelayHistoricalDeviation{Relay: msg}) + } else { + msgData, err = json.Marshal(MsgRelayHistoricalDeviation{Relay: msg}) + } } } diff --git a/cw-relayer/relayer/relayer_test.go b/cw-relayer/relayer/relayer_test.go index 1e2ea66..232e622 100644 --- a/cw-relayer/relayer/relayer_test.go +++ b/cw-relayer/relayer/relayer_test.go @@ -82,16 +82,6 @@ func (rts *RelayerTestSuite) Test_generateRelayMsg() { forceRelay: true, msgType: RelayRate, }, - { - tc: "Relay deviations", - forceRelay: false, - msgType: RelayHistoricalDeviation, - }, - { - tc: "Force Relay deviations", - forceRelay: true, - msgType: RelayHistoricalDeviation, - }, } for _, tc := range testCases { @@ -104,11 +94,9 @@ func (rts *RelayerTestSuite) Test_generateRelayMsg() { err = json.Unmarshal(msg, &expectedMsg) rts.Require().NoError(err) - var msgKey string + msgKey := tc.msgType.String() if tc.forceRelay { msgKey = fmt.Sprintf("force_%s", tc.msgType.String()) - } else { - msgKey = tc.msgType.String() } rates := expectedMsg[msgKey].SymbolRates @@ -139,27 +127,53 @@ func (rts *RelayerTestSuite) Test_generateMedianRelayMsg() { } } - relayMsg, err := genRateMsgData(false, RelayHistoricalMedian, 0, 0, exchangeRates) - rts.Require().NoError(err) + testCases := []struct { + tc string + forceRelay bool + msgType MsgType + }{ + { + tc: "Median Relay msg", + forceRelay: false, + msgType: RelayHistoricalMedian, + }, + { + tc: "Median Force Relay msg", + forceRelay: true, + msgType: RelayHistoricalMedian, + }, + { + tc: "Deviation Relay msg", + forceRelay: false, + msgType: RelayHistoricalDeviation, + }, + { + tc: "Deviation Force Relay msg", + forceRelay: false, + msgType: RelayHistoricalDeviation, + }, + } - forceRelayMsg, err := genRateMsgData(true, RelayHistoricalMedian, 0, 0, exchangeRates) - rts.Require().NoError(err) + for _, tc := range testCases { + rts.Run(tc.tc, func() { + msg, err := genRateMsgData(tc.forceRelay, tc.msgType, 0, 0, exchangeRates) + rts.Require().NoError(err) - for i, msg := range [][]byte{relayMsg, forceRelayMsg} { - var expectedMsg map[string]Msg - err = json.Unmarshal(msg, &expectedMsg) - rts.Require().NoError(err) + var expectedMsg map[string]Msg + err = json.Unmarshal(msg, &expectedMsg) + rts.Require().NoError(err) - key := RelayHistoricalMedian.String() - if i/1 == 1 { - key = fmt.Sprintf("force_%s", key) - } + key := tc.msgType.String() + if tc.forceRelay { + key = fmt.Sprintf("force_%s", key) + } - rates := expectedMsg[key].SymbolRates - rts.Require().Len(rates, 3) + rates := expectedMsg[key].SymbolRates + rts.Require().Len(rates, 3) - for _, rate := range rates { - rts.Require().Equal(rate[1], rateMap[rate[0].(string)]) - } + for _, rate := range rates { + rts.Require().Equal(rate[1], rateMap[rate[0].(string)]) + } + }) } } diff --git a/cw-relayer/tests/e2e/e2e_test.go b/cw-relayer/tests/e2e/e2e_test.go index 1a23814..d03fceb 100644 --- a/cw-relayer/tests/e2e/e2e_test.go +++ b/cw-relayer/tests/e2e/e2e_test.go @@ -66,7 +66,7 @@ var ( refDataFactor = types.NewDec(10).Power(18) ) -func (s *IntegrationTestSuite) TestQueryRateAndReferenceData() { +func (s *IntegrationTestSuite) Test_QueryRateAndReferenceData() { grpcConn, err := grpc.Dial( s.orchestrator.QueryRpc, grpc.WithTransportCredentials(insecure.NewCredentials()), @@ -108,19 +108,6 @@ func (s *IntegrationTestSuite) TestQueryRateAndReferenceData() { }, rate: mockPrices[0].Amount.Mul(refDataFactor).TruncateInt().String(), }, - { - tc: "query deviations from contract", - prepare: func() ([]byte, error) { - msg := deviationRateMsg{Ref: symbol{Symbol: mockPrices[0].Denom}} - data, err := json.Marshal(msg) - if err != nil { - return nil, err - } - - return data, err - }, - rate: mockPrices[0].Amount.Mul(relayer.RateFactor).TruncateInt().String(), - }, } for _, tc := range testCases { @@ -164,7 +151,7 @@ func (s *IntegrationTestSuite) TestQueryRateAndReferenceData() { } } -func (s *IntegrationTestSuite) TestQueryReferenceDataBulk() { +func (s *IntegrationTestSuite) Test_QueryReferenceDataBulk() { grpcConn, err := grpc.Dial( s.orchestrator.QueryRpc, grpc.WithTransportCredentials(insecure.NewCredentials()), @@ -198,15 +185,93 @@ func (s *IntegrationTestSuite) TestQueryReferenceDataBulk() { }, factor: refDataFactor, }, + } + + for _, tc := range testCases { + s.Run(tc.tc, func() { + queryClient := wasmtypes.NewQueryClient(grpcConn) + data, err := tc.prepare() + s.Require().NoError(err) + + query := wasmtypes.QuerySmartContractStateRequest{ + Address: s.orchestrator.ContractAddress, + QueryData: data, + } + + ctx, cancel := context.WithTimeout(context.Background(), testConfigTimeout) + defer cancel() + + s.Require().Eventually(func() bool { + queryResponse, err := queryClient.SmartContractState(ctx, &query) + if err != nil { + return false + } + + if queryResponse != nil { + var resp []map[string]string + err = json.Unmarshal(queryResponse.Data, &resp) + if err != nil { + return false + } + + for i, respData := range resp { + s.Require().Equal(respData["rate"], mockPrices[i].Amount.Mul(tc.factor).TruncateInt().String()) + } + + return true + } + + return false + }, + 1*time.Minute, + time.Second*4, + "failed to query prices from contract", + ) + }) + } +} + +func (s *IntegrationTestSuite) Test_QueryMedianRates() { + grpcConn, err := grpc.Dial( + s.orchestrator.QueryRpc, + grpc.WithTransportCredentials(insecure.NewCredentials()), + ) + + s.Require().NoError(err) + defer grpcConn.Close() + + mockPrices := s.priceServer.GetMockPrices() + + testCases := []struct { + tc string + prepare func() ([]byte, error) + factor types.Dec + bulk bool + }{ + { + tc: "query median rate data from contract", + prepare: func() ([]byte, error) { + + msg := medianRateMsg{Ref: symbol{mockPrices[0].Denom}} + data, err := json.Marshal(msg) + if err != nil { + return nil, err + } + + return data, nil + }, + factor: relayer.RateFactor, + bulk: false, + }, { - tc: "query deviation data in bulk", + tc: "query median ref data bulk", prepare: func() ([]byte, error) { var denoms []string for _, mockPrice := range mockPrices { denoms = append(denoms, mockPrice.Denom) } - msg := deviationRateMsgBulk{symbols{Symbols: denoms}} + msg := medianRefMsgBulk{symbols{denoms}} data, err := json.Marshal(msg) if err != nil { return nil, err @@ -215,6 +280,7 @@ func (s *IntegrationTestSuite) TestQueryReferenceDataBulk() { return data, nil }, factor: relayer.RateFactor, + bulk: true, }, } @@ -239,14 +305,24 @@ func (s *IntegrationTestSuite) TestQueryReferenceDataBulk() { } if queryResponse != nil { - var resp []map[string]string - err = json.Unmarshal(queryResponse.Data, &resp) - if err != nil { - return false - } + if tc.bulk { + var resp []map[string]interface{} + err = json.Unmarshal(queryResponse.Data, &resp) + if err != nil { + return false + } - for i, respData := range resp { - s.Require().Equal(respData["rate"], mockPrices[i].Amount.Mul(tc.factor).TruncateInt().String()) + for i, respData := range resp { + s.Require().Equal(respData["rates"].([]interface{})[0], mockPrices[i].Amount.Mul(tc.factor).TruncateInt().String()) + } + } else { + var resp map[string]interface{} + err = json.Unmarshal(queryResponse.Data, &resp) + if err != nil { + return false + } + + s.Require().Equal(resp["rates"].([]interface{})[0], mockPrices[0].Amount.Mul(tc.factor).TruncateInt().String()) } return true @@ -254,7 +330,7 @@ func (s *IntegrationTestSuite) TestQueryReferenceDataBulk() { return false }, - 1*time.Minute, + 2*time.Minute, time.Second*4, "failed to query prices from contract", ) @@ -262,7 +338,7 @@ func (s *IntegrationTestSuite) TestQueryReferenceDataBulk() { } } -func (s *IntegrationTestSuite) TestQueryMedianRates() { +func (s *IntegrationTestSuite) Test_QueryDeviationRates() { grpcConn, err := grpc.Dial( s.orchestrator.QueryRpc, grpc.WithTransportCredentials(insecure.NewCredentials()), @@ -280,10 +356,10 @@ func (s *IntegrationTestSuite) TestQueryMedianRates() { bulk bool }{ { - tc: "query median rate data from contract", + tc: "query deviation rate data from contract", prepare: func() ([]byte, error) { - msg := medianRateMsg{Ref: symbol{mockPrices[0].Denom}} + msg := deviationRateMsg{Ref: symbol{mockPrices[0].Denom}} data, err := json.Marshal(msg) if err != nil { return nil, err @@ -295,14 +371,14 @@ func (s *IntegrationTestSuite) TestQueryMedianRates() { bulk: false, }, { - tc: "query median ref data bulk", + tc: "query deviation ref data bulk", prepare: func() ([]byte, error) { var denoms []string for _, mockPrice := range mockPrices { denoms = append(denoms, mockPrice.Denom) } - msg := medianRefMsgBulk{symbols{denoms}} + msg := deviationRateMsgBulk{symbols{denoms}} data, err := json.Marshal(msg) if err != nil { return nil, err @@ -361,7 +437,7 @@ func (s *IntegrationTestSuite) TestQueryMedianRates() { return false }, - 2*time.Minute, + 3*time.Minute, time.Second*4, "failed to query prices from contract", )