Skip to content

Commit bcb1421

Browse files
maltekliemannChralt98sea212
authored
Add ID to Market struct (#1310)
* Add market ID to `Market` struct (#1248) * Add market ID to `Market` struct * Add market builder struct * Use `PredictionMarketBuilder` * Fix issues * Fix copyright * Make `build` return a `Result` * Let `build` raise an error on incomplete data. * Fix formatting * Refactor `MarketBuilder` * Add missing files * AMM-CDA-1: Switch to AmmCdaHybrid enum field (#1274) * switch to AmmCdaHybrid enum field * Update zrml/parimutuel/src/tests/buy.rs Co-authored-by: Malte Kliemann <mail@maltekliemann.com> * Update zrml/parimutuel/src/tests/claim.rs Co-authored-by: Malte Kliemann <mail@maltekliemann.com> * Update zrml/parimutuel/src/tests/refund.rs Co-authored-by: Malte Kliemann <mail@maltekliemann.com> * Update storage version to 11 and add MigrateScoringRuleAmmCdaHybrid * Update primitives/src/market.rs * update migration --------- Co-authored-by: Malte Kliemann <mail@maltekliemann.com> * merge amm-cda-3 changes * merge amm-cda-2 changes * merge amm-cda-4 changes * correct clippy * merge amm-cda-5 changes * merge amm-cda-6 changes * Fix Hybrid Router clippy and tests (#1291) * glue everything together * add hybrid router to configuration * fix tests * fix conditional tests * AMM-CDA-8 Add event information for fees and aggregated amount_out (#1293) * add event info * use slice as function parameter * update test amm amount out of event * fix order book tests * update documentation * removed dependency * Merge `main` into `mkl-market-id-feature` (#1302) * Merge `main` into `mkl-mkl-market-id-feature` * Remove unused `outcomes` * Remove old migrations (#1301) * AMM-CDA-9 Adds soft and hard failure distinction for AMM and order book errors (#1294) * add event info * use slice as function parameter * update test amm amount out of event * wip * handle soft and hard failure * add order book soft failure * fix clippy * fix CI * remove swaps pallet dependency * add compact to order book struct * fix recursion overflow * Migration: Add Market ID to Market (#1257) * Add market ID to `Market` struct * Add market builder struct * Use `PredictionMarketBuilder` * Fix issues * Fix copyright * Make `build` return a `Result` * Let `build` raise an error on incomplete data. * Fix formatting * Refactor `MarketBuilder` * Add missing files * Add migration to new market * Fix migration * Fix missing import * Fix duplicate import * Fix formatting * Remove unused `types/` * Fix of Hybrid Router after asset system merge (#1309) * wip * use asset conversions * adapt hybrid router to new asset system * apply review suggestions * fmt * rename Asset to Assets * update copyrights * Make minor fixes after merge * update hybrid router crate version * correct orderbook spelling * add amount is zero tests * add price limit too high test * add max order exceeded test * use saturated conversion * use saturated conversion again * remove unused code * Update changelog * add tests for soft failures * add skip order test * add changelog for devs description * add amm soft failure test * add numerical soft failure test for sell * Remove ZeitgeistAssetManager trait * correct failing test for parachain feature * cover remaining is zero execution path * Fix try-runtime test --------- Co-authored-by: Chralt <chralt.developer@gmail.com> Co-authored-by: Chralt98 <chralt98@gmail.com> Co-authored-by: Harald Heckmann <mail@haraldheckmann.de>
1 parent 32eedc9 commit bcb1421

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+771
-402
lines changed

docs/changelog_for_devs.md

+9
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,15 @@ APIs/RPC interface.
1414

1515
## v0.5.2
1616

17+
[#1310]: https://github.com/zeitgeistpm/zeitgeist/pull/1310
1718
[#1307]: https://github.com/zeitgeistpm/zeitgeist/pull/1307
1819

1920
### Added
2021

22+
- ⚠️ [#1310] Add `market_id` field to `Market` struct.
23+
- [#1310] Add `MarketBuilderTrait`, which is used to define
24+
`MarketCommonsPalletApi::build_market`, which should be used for creating
25+
markets in the future.
2126
- [#1307] New hybrid router for managing the trade execution using the
2227
`neo-swaps` automated market maker and order book
2328

@@ -33,6 +38,10 @@ APIs/RPC interface.
3338

3439
For details, please refer to the `README.md` and the in-file documentation.
3540

41+
### Deprectaed
42+
43+
- [#1310] `MarketCommonsPalletApi::push_market` is now deprecated.
44+
3645
## v0.5.1
3746

3847
[#1295]: https://github.com/zeitgeistpm/zeitgeist/pull/1295

primitives/src/market.rs

+36-33
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ use sp_runtime::RuntimeDebug;
3131
/// * `BN`: Block number
3232
/// * `M`: Moment (time moment)
3333
/// * `A`: Asset
34+
/// * `MI`: Market ID
3435
#[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
35-
pub struct Market<AI, BA, BN, M, A> {
36+
pub struct Market<AI, BA, BN, M, A, MI> {
37+
pub market_id: MI,
3638
/// Base asset of the market.
3739
pub base_asset: A,
3840
/// Creator of this market.
@@ -68,7 +70,10 @@ pub struct Market<AI, BA, BN, M, A> {
6870
pub early_close: Option<EarlyClose<BN, M>>,
6971
}
7072

71-
impl<AI, BA, BN, M, A> Market<AI, BA, BN, M, A> {
73+
impl<AI, BA, BN, M, A, MI> Market<AI, BA, BN, M, A, MI>
74+
where
75+
MI: Copy + HasCompact + MaxEncodedLen,
76+
{
7277
/// Returns the `ResolutionMechanism` of market, currently either:
7378
/// - `RedeemTokens`, which implies that the module that handles the state transitions of
7479
/// a market is also responsible to provide means for redeeming rewards
@@ -111,21 +116,17 @@ impl<AI, BA, BN, M, A> Market<AI, BA, BN, M, A> {
111116
}
112117

113118
/// Returns a `Vec` of all outcomes for `market_id`.
114-
pub fn outcome_assets<MI: Copy + HasCompact + MaxEncodedLen>(
115-
&self,
116-
market_id: MI,
117-
) -> Vec<MarketAssetClass<MI>> {
119+
pub fn outcome_assets(&self) -> Vec<MarketAssetClass<MI>> {
118120
match self.market_type {
119121
MarketType::Categorical(categories) => {
120122
let mut assets = Vec::new();
121123

122124
for i in 0..categories {
123125
match self.scoring_rule {
124-
ScoringRule::AmmCdaHybrid => {
125-
assets.push(MarketAssetClass::<MI>::CategoricalOutcome(market_id, i))
126-
}
126+
ScoringRule::AmmCdaHybrid => assets
127+
.push(MarketAssetClass::<MI>::CategoricalOutcome(self.market_id, i)),
127128
ScoringRule::Parimutuel => {
128-
assets.push(MarketAssetClass::<MI>::ParimutuelShare(market_id, i))
129+
assets.push(MarketAssetClass::<MI>::ParimutuelShare(self.market_id, i))
129130
}
130131
};
131132
}
@@ -134,8 +135,8 @@ impl<AI, BA, BN, M, A> Market<AI, BA, BN, M, A> {
134135
}
135136
MarketType::Scalar(_) => {
136137
vec![
137-
MarketAssetClass::<MI>::ScalarOutcome(market_id, ScalarPosition::Long),
138-
MarketAssetClass::<MI>::ScalarOutcome(market_id, ScalarPosition::Short),
138+
MarketAssetClass::<MI>::ScalarOutcome(self.market_id, ScalarPosition::Long),
139+
MarketAssetClass::<MI>::ScalarOutcome(self.market_id, ScalarPosition::Short),
139140
]
140141
}
141142
}
@@ -145,45 +146,38 @@ impl<AI, BA, BN, M, A> Market<AI, BA, BN, M, A> {
145146
/// returns `None` if not possible. Cases where `None` is returned are:
146147
/// - The reported outcome does not exist
147148
/// - The reported outcome does not have a corresponding asset type
148-
pub fn report_into_asset<MI: HasCompact + MaxEncodedLen>(
149-
&self,
150-
market_id: MI,
151-
) -> Option<MarketAssetClass<MI>> {
149+
pub fn report_into_asset(&self) -> Option<MarketAssetClass<MI>> {
152150
let outcome = if let Some(ref report) = self.report {
153151
&report.outcome
154152
} else {
155153
return None;
156154
};
157155

158-
self.outcome_report_into_asset(market_id, outcome)
156+
self.outcome_report_into_asset(outcome)
159157
}
160158

161159
/// Tries to convert the resolved outcome for `market_id` into an asset,
162160
/// returns `None` if not possible. Cases where `None` is returned are:
163161
/// - The resolved outcome does not exist
164162
/// - The resolved outcome does not have a corresponding asset type
165-
pub fn resolved_outcome_into_asset<MI: HasCompact + MaxEncodedLen>(
166-
&self,
167-
market_id: MI,
168-
) -> Option<MarketAssetClass<MI>> {
163+
pub fn resolved_outcome_into_asset(&self) -> Option<MarketAssetClass<MI>> {
169164
let outcome = self.resolved_outcome.as_ref()?;
170-
self.outcome_report_into_asset(market_id, outcome)
165+
self.outcome_report_into_asset(outcome)
171166
}
172167

173168
/// Tries to convert a `outcome_report` for `market_id` into an asset,
174169
/// returns `None` if not possible.
175-
fn outcome_report_into_asset<MI: HasCompact + MaxEncodedLen>(
170+
fn outcome_report_into_asset(
176171
&self,
177-
market_id: MI,
178172
outcome_report: &OutcomeReport,
179173
) -> Option<MarketAssetClass<MI>> {
180174
match outcome_report {
181175
OutcomeReport::Categorical(idx) => match self.scoring_rule {
182176
ScoringRule::AmmCdaHybrid => {
183-
Some(MarketAssetClass::<MI>::CategoricalOutcome(market_id, *idx))
177+
Some(MarketAssetClass::<MI>::CategoricalOutcome(self.market_id, *idx))
184178
}
185179
ScoringRule::Parimutuel => {
186-
Some(MarketAssetClass::<MI>::ParimutuelShare(market_id, *idx))
180+
Some(MarketAssetClass::<MI>::ParimutuelShare(self.market_id, *idx))
187181
}
188182
},
189183
OutcomeReport::Scalar(_) => None,
@@ -249,16 +243,18 @@ impl<AI, BA> Default for MarketBonds<AI, BA> {
249243
}
250244
}
251245

252-
impl<AI, BA, BN, M, A> MaxEncodedLen for Market<AI, BA, BN, M, A>
246+
impl<AI, BA, BN, M, A, MI> MaxEncodedLen for Market<AI, BA, BN, M, A, MI>
253247
where
254248
AI: MaxEncodedLen,
255249
BA: MaxEncodedLen,
256250
BN: MaxEncodedLen,
257251
M: MaxEncodedLen,
258252
A: MaxEncodedLen,
253+
MI: MaxEncodedLen,
259254
{
260255
fn max_encoded_len() -> usize {
261256
AI::max_encoded_len()
257+
.saturating_add(MI::max_encoded_len())
262258
.saturating_add(A::max_encoded_len())
263259
.saturating_add(MarketCreation::max_encoded_len())
264260
.saturating_add(Perbill::max_encoded_len())
@@ -433,7 +429,8 @@ mod tests {
433429
types::{Asset, MarketAsset},
434430
};
435431
use test_case::test_case;
436-
type Market = crate::market::Market<u32, u32, u32, u32, Asset<u32>>;
432+
type MarketId = u128;
433+
type Market = crate::market::Market<u32, u32, u32, u32, Asset<MarketId>, MarketId>;
437434

438435
#[test_case(
439436
MarketType::Categorical(6),
@@ -489,13 +486,14 @@ mod tests {
489486
expected: bool,
490487
) {
491488
let market = Market {
489+
market_id: 9,
492490
base_asset: Asset::Ztg,
493491
creator: 1,
494492
creation: MarketCreation::Permissionless,
495493
creator_fee: Default::default(),
496494
oracle: 3,
497495
metadata: vec![4u8; 5],
498-
market_type, // : MarketType::Categorical(6),
496+
market_type,
499497
period: MarketPeriod::Block(7..8),
500498
deadlines: Deadlines {
501499
grace_period: 1_u32,
@@ -528,7 +526,10 @@ mod tests {
528526
#[test_case(
529527
MarketType::Scalar(12..=34),
530528
ScoringRule::AmmCdaHybrid,
531-
vec![MarketAsset::ScalarOutcome(0, ScalarPosition::Long), MarketAsset::ScalarOutcome(0, ScalarPosition::Short)];
529+
vec![
530+
MarketAsset::ScalarOutcome(0, ScalarPosition::Long),
531+
MarketAsset::ScalarOutcome(0, ScalarPosition::Short),
532+
];
532533
"scalar_market"
533534
)]
534535
fn provides_correct_list_of_assets(
@@ -537,6 +538,7 @@ mod tests {
537538
expected: Vec<MarketAsset>,
538539
) {
539540
let market = Market {
541+
market_id: 0,
540542
base_asset: Asset::Ztg,
541543
creator: 1,
542544
creation: MarketCreation::Permissionless,
@@ -558,7 +560,7 @@ mod tests {
558560
bonds: MarketBonds::default(),
559561
early_close: None,
560562
};
561-
assert_eq!(market.outcome_assets(0), expected);
563+
assert_eq!(market.outcome_assets(), expected);
562564
}
563565

564566
#[test_case(
@@ -595,6 +597,7 @@ mod tests {
595597
});
596598

597599
let market = Market {
600+
market_id: 0,
598601
base_asset: Asset::Ztg,
599602
creator: 1,
600603
creation: MarketCreation::Permissionless,
@@ -616,8 +619,8 @@ mod tests {
616619
bonds: MarketBonds::default(),
617620
early_close: None,
618621
};
619-
assert_eq!(market.resolved_outcome_into_asset(0), expected);
620-
assert_eq!(market.report_into_asset(0), expected);
622+
assert_eq!(market.resolved_outcome_into_asset(), expected);
623+
assert_eq!(market.report_into_asset(), expected);
621624
}
622625

623626
#[test]

primitives/src/traits.rs

+13-11
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,24 @@ mod dispute_api;
2222
mod distribute_fees;
2323
mod hybrid_router_amm_api;
2424
mod hybrid_router_orderbook_api;
25+
mod market_builder;
2526
mod market_commons_pallet_api;
2627
mod market_id;
2728
mod market_transition_api;
2829
mod swaps;
2930
mod weights;
3031
mod zeitgeist_asset;
3132

32-
pub use complete_set_operations_api::CompleteSetOperationsApi;
33-
pub use deploy_pool_api::DeployPoolApi;
34-
pub use dispute_api::{DisputeApi, DisputeMaxWeightApi, DisputeResolutionApi};
35-
pub use distribute_fees::DistributeFees;
36-
pub use hybrid_router_amm_api::HybridRouterAmmApi;
37-
pub use hybrid_router_orderbook_api::HybridRouterOrderbookApi;
38-
pub use market_commons_pallet_api::MarketCommonsPalletApi;
39-
pub use market_id::MarketId;
40-
pub use market_transition_api::MarketTransitionApi;
41-
pub use swaps::Swaps;
42-
pub use weights::CheckedDivPerComponent;
33+
pub use complete_set_operations_api::*;
34+
pub use deploy_pool_api::*;
35+
pub use dispute_api::*;
36+
pub use distribute_fees::*;
37+
pub use hybrid_router_amm_api::*;
38+
pub use hybrid_router_orderbook_api::*;
39+
pub use market_builder::*;
40+
pub use market_commons_pallet_api::*;
41+
pub use market_id::*;
42+
pub use market_transition_api::*;
43+
pub use swaps::*;
44+
pub use weights::*;
4345
pub use zeitgeist_asset::*;

primitives/src/traits/dispute_api.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,13 @@ use sp_runtime::DispatchError;
2929

3030
// Abstraction of the market type, which is not a part of `DisputeApi` because Rust doesn't support
3131
// type aliases in traits.
32-
type MarketOfDisputeApi<T> = Market<
32+
pub type MarketOfDisputeApi<T> = Market<
3333
<T as DisputeApi>::AccountId,
3434
<T as DisputeApi>::Balance,
3535
<T as DisputeApi>::BlockNumber,
3636
<T as DisputeApi>::Moment,
3737
BaseAsset,
38+
<T as DisputeApi>::MarketId,
3839
>;
3940

4041
type GlobalDisputeItemOfDisputeApi<T> =
@@ -145,12 +146,13 @@ pub trait DisputeMaxWeightApi {
145146
fn clear_max_weight() -> Weight;
146147
}
147148

148-
type MarketOfDisputeResolutionApi<T> = Market<
149+
pub type MarketOfDisputeResolutionApi<T> = Market<
149150
<T as DisputeResolutionApi>::AccountId,
150151
<T as DisputeResolutionApi>::Balance,
151152
<T as DisputeResolutionApi>::BlockNumber,
152153
<T as DisputeResolutionApi>::Moment,
153154
BaseAsset,
155+
<T as DisputeResolutionApi>::MarketId,
154156
>;
155157

156158
pub trait DisputeResolutionApi {

primitives/src/traits/hybrid_router_amm_api.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ use crate::hybrid_router_api_types::{AmmSoftFail, AmmTrade, ApiError};
1919
use frame_support::dispatch::DispatchError;
2020

2121
/// A type alias for the return struct of AMM buy and sell.
22-
pub type AmmTradeOf<T> = AmmTrade<<T as HybridRouterAmmApi>::Balance>;
22+
type AmmTradeOf<T> = AmmTrade<<T as HybridRouterAmmApi>::Balance>;
2323

2424
/// A type alias for the error type of the AMM part of the hybrid router.
25-
pub type ApiErrorOf = ApiError<AmmSoftFail>;
25+
type ApiErrorOf = ApiError<AmmSoftFail>;
2626

2727
/// Trait for handling the AMM part of the hybrid router.
2828
pub trait HybridRouterAmmApi {

primitives/src/traits/hybrid_router_orderbook_api.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ use frame_support::dispatch::DispatchError;
2020
use crate::hybrid_router_api_types::{ApiError, OrderbookSoftFail, OrderbookTrade};
2121

2222
/// A type alias for the return struct of orderbook trades.
23-
pub type OrderbookTradeOf<T> = OrderbookTrade<
23+
type OrderbookTradeOf<T> = OrderbookTrade<
2424
<T as HybridRouterOrderbookApi>::AccountId,
2525
<T as HybridRouterOrderbookApi>::Balance,
2626
>;
2727

2828
/// A type alias for the error type of the orderbook part of the hybrid router.
29-
pub type ApiErrorOf = ApiError<OrderbookSoftFail>;
29+
type ApiErrorOf = ApiError<OrderbookSoftFail>;
3030

3131
/// Trait for handling the order book part of the hybrid router.
3232
pub trait HybridRouterOrderbookApi {
+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2024 Forecasting Technologies LTD.
2+
//
3+
// This file is part of Zeitgeist.
4+
//
5+
// Zeitgeist is free software: you can redistribute it and/or modify it
6+
// under the terms of the GNU General Public License as published by the
7+
// Free Software Foundation, either version 3 of the License, or (at
8+
// your option) any later version.
9+
//
10+
// Zeitgeist is distributed in the hope that it will be useful, but
11+
// WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
// General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU General Public License
16+
// along with Zeitgeist. If not, see <https://www.gnu.org/licenses/>.
17+
18+
use crate::types::{
19+
Deadlines, EarlyClose, Market, MarketBonds, MarketCreation, MarketDisputeMechanism,
20+
MarketPeriod, MarketStatus, MarketType, OutcomeReport, Report, ScoringRule,
21+
};
22+
use alloc::vec::Vec;
23+
use sp_runtime::{DispatchError, Perbill};
24+
25+
macro_rules! builder_methods {
26+
($($field:ident: $type:ty),* $(,)?) => {
27+
$(fn $field(&mut self, $field: $type) -> &mut Self;)*
28+
}
29+
}
30+
31+
/// Mutably referenced builder struct for the `Market` object. The `build` call is pass-by-value, so
32+
/// the usual calling pattern is:
33+
///
34+
/// ```ignore
35+
/// let builder = MarketBuilderImpl::new();
36+
/// builder.field1(value1).field2(value2);
37+
/// builder.clone().build()
38+
/// ```
39+
pub trait MarketBuilderTrait<AI, BA, BN, M, A, MI> {
40+
fn build(self) -> Result<Market<AI, BA, BN, M, A, MI>, DispatchError>;
41+
42+
builder_methods! {
43+
market_id: MI,
44+
base_asset: A,
45+
creator: AI,
46+
creation: MarketCreation,
47+
creator_fee: Perbill,
48+
oracle: AI,
49+
metadata: Vec<u8>,
50+
market_type: MarketType,
51+
period: MarketPeriod<BN, M>,
52+
deadlines: Deadlines<BN>,
53+
scoring_rule: ScoringRule,
54+
status: MarketStatus,
55+
report: Option<Report<AI, BN>>,
56+
resolved_outcome: Option<OutcomeReport>,
57+
dispute_mechanism: Option<MarketDisputeMechanism>,
58+
bonds: MarketBonds<AI, BA>,
59+
early_close: Option<EarlyClose<BN, M>>,
60+
}
61+
}

0 commit comments

Comments
 (0)