1use std::{fmt::Display, num::ParseIntError, str::FromStr};
4
5use super::market::{
6 entry::{ExecuteMsg as MarketExecuteMsg, SlippageAssert, StopLoss},
7 order::OrderId,
8 position::PositionId,
9};
10use crate::{
11 number::{Collateral, LpToken, NonZero},
12 price::{PriceBaseInQuote, PricePoint, TakeProfitTrader},
13 storage::{DirectionToBase, LeverageToBase, MarketId, RawAddr},
14 time::Timestamp,
15};
16use anyhow::{anyhow, bail};
17use cosmwasm_std::{Addr, Binary, Decimal256, StdError, StdResult, Uint128, Uint64};
18use cw_storage_plus::{IntKey, Key, KeyDeserialize, Prefixer, PrimaryKey};
19use thiserror::Error;
20
21#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
23#[serde(rename_all = "snake_case")]
24pub struct InstantiateMsg {
25 pub leader: RawAddr,
27 pub config: ConfigUpdate,
29 pub parameters: FactoryConfigUpdate,
31}
32
33#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
35#[serde(rename_all = "snake_case")]
36pub struct Config {
38 pub factory: Addr,
40 pub admin: Addr,
43 pub pending_admin: Option<Addr>,
45 pub leader: Addr,
47 pub name: String,
49 pub description: String,
52 pub commission_rate: Decimal256,
54 pub created_at: Timestamp,
56 pub allowed_rebalance_queries: u32,
58 pub allowed_lp_token_queries: u32,
60}
61
62impl Config {
63 pub fn check(&self) -> anyhow::Result<()> {
65 if self.name.len() > 128 {
66 Err(anyhow!(
67 "Description should not be more than 128 characters"
68 ))
69 } else if self.commission_rate < Decimal256::from_ratio(1u32, 100u32) {
70 Err(anyhow!("Commission rate less than 1 percent"))
71 } else if self.commission_rate > Decimal256::from_ratio(30u32, 100u32) {
72 Err(anyhow!("Commission rate greater than 30 percent"))
73 } else {
74 Ok(())
75 }
76 }
77
78 pub fn ensure_leader(&self, sender: &Addr) -> anyhow::Result<()> {
80 if self.leader != sender {
81 bail!("Unautorized access, only {} allowed", self.leader)
82 }
83 Ok(())
84 }
85
86 pub fn ensure_factory(&self, sender: &Addr) -> anyhow::Result<()> {
88 if self.factory != sender {
89 bail!("Unautorized access, only {} allowed", self.factory)
90 }
91 Ok(())
92 }
93}
94
95#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Default)]
99#[serde(rename_all = "snake_case")]
100#[allow(missing_docs)]
101pub struct ConfigUpdate {
102 pub name: Option<String>,
103 pub description: Option<String>,
104 pub commission_rate: Option<Decimal256>,
105}
106
107#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Default)]
111#[serde(rename_all = "snake_case")]
112#[allow(missing_docs)]
113pub struct FactoryConfigUpdate {
114 pub allowed_rebalance_queries: Option<u32>,
115 pub allowed_lp_token_queries: Option<u32>,
116}
117
118#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
120#[serde(rename_all = "snake_case")]
121pub enum ExecuteMsg {
122 Receive {
124 sender: RawAddr,
126 amount: Uint128,
128 msg: Binary,
130 },
131 Deposit {},
133 Withdraw {
135 shares: NonZero<LpToken>,
137 token: Token,
139 },
140 LeaderUpdateConfig(ConfigUpdate),
142 FactoryUpdateConfig(FactoryConfigUpdate),
144 LeaderMsg {
146 market_id: MarketId,
148 message: Box<MarketExecuteMsg>,
150 collateral: Option<NonZero<Collateral>>,
152 },
153 LeaderWithdrawal {
155 requested_funds: NonZero<Collateral>,
157 token: Token,
159 },
160 DoWork {},
162}
163
164#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
166#[serde(rename_all = "snake_case")]
167pub enum QueryMsg {
168 Config {},
172 QueueStatus {
176 address: RawAddr,
178 start_after: Option<QueuePositionId>,
180 limit: Option<u32>,
182 },
183 Balance {
187 address: RawAddr,
189 start_after: Option<Token>,
191 limit: Option<u32>,
193 },
194 LeaderStatus {
199 start_after: Option<Token>,
201 limit: Option<u32>,
203 },
204 HasWork {},
208}
209
210#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
212#[serde(rename_all = "snake_case")]
213pub struct QueueResp {
214 pub items: Vec<QueueItemStatus>,
216 pub inc_processed_till: Option<IncQueuePositionId>,
218 pub dec_processed_till: Option<DecQueuePositionId>,
220}
221
222#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
224#[serde(rename_all = "snake_case")]
225pub struct QueueItemStatus {
226 pub item: QueueItem,
228 pub status: ProcessingStatus,
230}
231
232#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
234#[serde(rename_all = "snake_case")]
235pub enum ProcessingStatus {
236 NotProcessed,
238 Finished,
240 InProgress,
242 Failed(FailedReason),
244}
245
246impl ProcessingStatus {
247 pub fn failed(&self) -> bool {
249 match self {
250 ProcessingStatus::NotProcessed => false,
251 ProcessingStatus::Finished => false,
252 ProcessingStatus::Failed(_) => true,
253 ProcessingStatus::InProgress => false,
254 }
255 }
256
257 pub fn pending(&self) -> bool {
259 match self {
260 ProcessingStatus::NotProcessed => true,
261 ProcessingStatus::Finished => false,
262 ProcessingStatus::Failed(_) => false,
263 ProcessingStatus::InProgress => true,
264 }
265 }
266
267 pub fn finish(&self) -> bool {
269 match self {
270 ProcessingStatus::NotProcessed => false,
271 ProcessingStatus::Finished => true,
272 ProcessingStatus::Failed(_) => false,
273 ProcessingStatus::InProgress => false,
274 }
275 }
276
277 pub fn in_progress(&self) -> bool {
279 match self {
280 ProcessingStatus::NotProcessed => false,
281 ProcessingStatus::Finished => false,
282 ProcessingStatus::Failed(_) => false,
283 ProcessingStatus::InProgress => true,
284 }
285 }
286}
287
288#[derive(Error, Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq)]
290#[serde(rename_all = "snake_case")]
291pub enum FailedReason {
292 #[error("Collateral not available. Requested {requested}, but only available {available}")]
294 NotEnoughCollateral {
295 available: Collateral,
297 requested: NonZero<Collateral>,
299 },
300 #[error("Crank fee not available. Requested {requested}, but only available {available}")]
302 NotEnoughCrankFee {
303 available: Collateral,
305 requested: Collateral,
307 },
308 #[error("Collateral amount {funds} is less than chain's minimum representation.not available")]
310 FundLessThanMinChain {
311 funds: NonZero<Collateral>,
313 },
314 #[error("Shares not available. Requested {requested}, but only available {available}")]
316 NotEnoughShares {
317 available: LpToken,
319 requested: LpToken,
321 },
322 #[error("{market_id} result in error: {message}")]
324 MarketError {
325 market_id: MarketId,
327 message: String,
329 },
330 #[error("Deferred exec failure at {executed} because of: {reason}")]
332 DeferredExecFailure {
333 reason: String,
335 executed: Timestamp,
337 crank_price: Option<PricePoint>,
339 },
340}
341
342#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
344#[serde(rename_all = "snake_case")]
345pub enum QueueItem {
346 IncCollateral {
348 item: IncQueueItem,
350 id: IncQueuePositionId,
352 },
353 DecCollateral {
355 item: Box<DecQueueItem>,
357 id: DecQueuePositionId,
359 },
360}
361
362#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
364#[serde(rename_all = "snake_case")]
365pub enum IncQueueItem {
366 Deposit {
368 funds: NonZero<Collateral>,
370 token: Token,
372 },
373 MarketItem {
375 id: MarketId,
377 token: Token,
379 item: Box<IncMarketItem>,
381 },
382}
383
384#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
386#[serde(rename_all = "snake_case")]
387pub enum DecQueueItem {
388 Withdrawal {
390 tokens: NonZero<LpToken>,
392 token: Token,
394 },
395 MarketItem {
397 id: MarketId,
399 token: Token,
401 item: Box<DecMarketItem>,
403 },
404}
405
406#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
408#[serde(rename_all = "snake_case")]
409pub enum IncMarketItem {
410 UpdatePositionRemoveCollateralImpactLeverage {
412 id: PositionId,
414 amount: NonZero<Collateral>,
416 },
417 UpdatePositionRemoveCollateralImpactSize {
419 id: PositionId,
421 amount: NonZero<Collateral>,
423 slippage_assert: Option<SlippageAssert>,
425 },
426 CancelLimitOrder {
428 order_id: OrderId,
430 },
431 ClosePosition {
433 id: PositionId,
435 slippage_assert: Option<SlippageAssert>,
437 },
438}
439
440#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
442#[serde(rename_all = "snake_case")]
443pub enum DecMarketItem {
444 OpenPosition {
446 collateral: NonZero<Collateral>,
448 slippage_assert: Option<SlippageAssert>,
450 leverage: LeverageToBase,
452 direction: DirectionToBase,
454 stop_loss_override: Option<PriceBaseInQuote>,
456 #[serde(alias = "take_profit_override")]
458 take_profit: TakeProfitTrader,
459 },
460 UpdatePositionAddCollateralImpactLeverage {
462 collateral: NonZero<Collateral>,
464 id: PositionId,
466 },
467 UpdatePositionAddCollateralImpactSize {
469 collateral: NonZero<Collateral>,
471 id: PositionId,
473 slippage_assert: Option<SlippageAssert>,
475 },
476 UpdatePositionLeverage {
478 id: PositionId,
480 leverage: LeverageToBase,
482 slippage_assert: Option<SlippageAssert>,
484 },
485 UpdatePositionTakeProfitPrice {
487 id: PositionId,
489 price: TakeProfitTrader,
491 },
492 UpdatePositionStopLossPrice {
494 id: PositionId,
496 stop_loss: StopLoss,
498 },
499 PlaceLimitOrder {
502 collateral: NonZero<Collateral>,
504 trigger_price: PriceBaseInQuote,
506 leverage: LeverageToBase,
508 direction: DirectionToBase,
510 stop_loss_override: Option<PriceBaseInQuote>,
512 #[serde(alias = "take_profit_override")]
514 take_profit: TakeProfitTrader,
515 },
516}
517
518pub enum RequiresToken {
520 Token {
522 token: Token,
524 },
525 NoToken {},
527}
528
529impl IncQueueItem {
530 pub fn requires_token(self) -> RequiresToken {
532 match self {
533 IncQueueItem::Deposit { token, .. } => RequiresToken::Token { token },
534 IncQueueItem::MarketItem { .. } => RequiresToken::NoToken {},
535 }
536 }
537}
538
539impl DecQueueItem {
540 pub fn requires_token(self) -> RequiresToken {
542 match self {
543 DecQueueItem::Withdrawal { token, .. } => RequiresToken::Token { token },
544 DecQueueItem::MarketItem { .. } => RequiresToken::NoToken {},
546 }
547 }
548}
549
550#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
552#[serde(rename_all = "snake_case")]
553pub struct LeaderStatusResp {
554 pub tokens: Vec<TokenStatus>,
556}
557
558#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
560#[serde(rename_all = "snake_case")]
561pub struct TokenStatus {
562 pub token: Token,
564 pub collateral: Collateral,
566 pub shares: LpToken,
568 pub unclaimed_commission: Collateral,
570 pub claimed_commission: Collateral,
572}
573
574#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
576#[serde(rename_all = "snake_case")]
577pub struct BalanceResp {
578 pub balance: Vec<BalanceRespItem>,
580 pub start_after: Option<Token>,
582}
583
584#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
586#[serde(rename_all = "snake_case")]
587pub struct BalanceRespItem {
588 pub shares: NonZero<LpToken>,
590 pub token: Token,
592}
593
594#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)]
596#[serde(rename_all = "snake_case")]
597pub enum Token {
598 Native(String),
600 Cw20(Addr),
602}
603
604impl Token {
605 pub fn is_same(&self, token: &crate::token::Token) -> bool {
607 match token {
608 crate::token::Token::Cw20 { addr, .. } => match self {
609 Token::Native(_) => false,
610 Token::Cw20(cw20_addr) => {
611 let cw20_addr: &RawAddr = &cw20_addr.into();
612 cw20_addr == addr
613 }
614 },
615 crate::token::Token::Native { denom, .. } => match self {
616 Token::Native(native_denom) => *native_denom == *denom,
617 Token::Cw20(_) => false,
618 },
619 }
620 }
621}
622
623impl<'a> PrimaryKey<'a> for Token {
624 type Prefix = ();
625 type SubPrefix = ();
626 type Suffix = Self;
627 type SuperSuffix = Self;
628
629 fn key(&self) -> Vec<Key> {
630 let (token_type, bytes) = match self {
631 Token::Native(native) => (0u8, native.as_bytes()),
632 Token::Cw20(cw20) => (1u8, cw20.as_bytes()),
633 };
634 let token_type = Key::Val8([token_type]);
635 let key = Key::Ref(bytes);
636
637 vec![token_type, key]
638 }
639}
640
641impl<'a> Prefixer<'a> for Token {
642 fn prefix(&self) -> Vec<Key> {
643 let (token_type, bytes) = match self {
644 Token::Native(native) => (0u8, native.as_bytes()),
645 Token::Cw20(cw20) => (1u8, cw20.as_bytes()),
646 };
647 let token_type = Key::Val8([token_type]);
648 let key = Key::Ref(bytes);
649 vec![token_type, key]
650 }
651}
652
653impl KeyDeserialize for Token {
654 type Output = Token;
655
656 const KEY_ELEMS: u16 = 2;
657
658 fn from_vec(value: Vec<u8>) -> StdResult<Self::Output> {
659 let (token_type, token) = <(u8, Vec<u8>) as KeyDeserialize>::from_vec(value)?;
660 let token = match token_type {
661 0 => {
662 let native_token = String::from_slice(&token)?;
663 Token::Native(native_token)
664 }
665 1 => {
666 let cw20_token = Addr::from_slice(&token)?;
667 Token::Cw20(cw20_token)
668 }
669 _ => {
670 return Err(StdError::serialize_err(
671 "Token",
672 "Invalid number in token_type",
673 ))
674 }
675 };
676 Ok(token)
677 }
678}
679
680impl KeyDeserialize for &Token {
681 type Output = Token;
682
683 const KEY_ELEMS: u16 = 2;
684
685 fn from_vec(value: Vec<u8>) -> StdResult<Self::Output> {
686 let token = <Token as KeyDeserialize>::from_vec(value)?;
687 Ok(token)
688 }
689}
690
691impl Display for Token {
692 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
693 match self {
694 Token::Native(denom) => f.write_str(denom),
695 Token::Cw20(addr) => f.write_str(addr.as_str()),
696 }
697 }
698}
699
700impl Token {
701 pub fn ensure_matches(&self, token: &crate::token::Token) -> anyhow::Result<()> {
703 match (self, token) {
704 (Token::Native(_), crate::token::Token::Cw20 { addr, .. }) => {
705 anyhow::bail!("Provided native funds, but market requires a CW20 (contract {addr})")
706 }
707 (
708 Token::Native(denom1),
709 crate::token::Token::Native {
710 denom: denom2,
711 decimal_places: _,
712 },
713 ) => {
714 if denom1 == denom2 {
715 Ok(())
716 } else {
717 Err(anyhow::anyhow!("Wrong denom provided. You sent {denom1}, but the contract expects {denom2}"))
718 }
719 }
720 (
721 Token::Cw20(addr1),
722 crate::token::Token::Cw20 {
723 addr: addr2,
724 decimal_places: _,
725 },
726 ) => {
727 if addr1.as_str() == addr2.as_str() {
728 Ok(())
729 } else {
730 Err(anyhow::anyhow!(
731 "Wrong CW20 used. You used {addr1}, but the contract expects {addr2}"
732 ))
733 }
734 }
735 (Token::Cw20(_), crate::token::Token::Native { denom, .. }) => {
736 anyhow::bail!(
737 "Provided CW20 funds, but market requires native funds with denom {denom}"
738 )
739 }
740 }
741 }
742}
743
744#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
746#[serde(rename_all = "snake_case")]
747pub enum WorkResp {
748 NoWork,
750 HasWork {
752 work_description: WorkDescription,
754 },
755}
756
757impl WorkResp {
758 pub fn has_work(&self) -> bool {
760 match self {
761 WorkResp::NoWork => false,
762 WorkResp::HasWork { .. } => true,
763 }
764 }
765
766 pub fn is_deferred_work(&self) -> bool {
768 match self {
769 WorkResp::NoWork => false,
770 WorkResp::HasWork { work_description } => work_description.is_deferred_work(),
771 }
772 }
773
774 pub fn is_rebalance(&self) -> bool {
776 match self {
777 WorkResp::NoWork => false,
778 WorkResp::HasWork { work_description } => work_description.is_rebalance(),
779 }
780 }
781
782 pub fn is_compute_lp_token(&self) -> bool {
784 match self {
785 WorkResp::NoWork => false,
786 WorkResp::HasWork { work_description } => work_description.is_compute_lp_token(),
787 }
788 }
789
790 pub fn is_reset_status(&self) -> bool {
792 match self {
793 WorkResp::NoWork => false,
794 WorkResp::HasWork { work_description } => work_description.is_reset_status(),
795 }
796 }
797}
798
799#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
801#[serde(rename_all = "snake_case")]
802pub enum WorkDescription {
803 LoadMarket {},
805 ComputeLpTokenValue {
807 token: Token,
809 process_start_from: Option<MarketId>,
811 validate_start_from: Option<MarketId>,
813 },
814 ProcessQueueItem {
816 id: QueuePositionId,
818 },
819 ResetStats {
821 token: Token,
823 },
824 HandleDeferredExecId {},
826 Rebalance {
829 token: Token,
831 amount: NonZero<Collateral>,
833 start_from: Option<MarketId>,
835 },
836}
837
838impl WorkDescription {
839 pub fn is_rebalance(&self) -> bool {
841 match self {
842 WorkDescription::LoadMarket {} => false,
843 WorkDescription::ComputeLpTokenValue { .. } => false,
844 WorkDescription::ProcessQueueItem { .. } => false,
845 WorkDescription::ResetStats { .. } => false,
846 WorkDescription::HandleDeferredExecId {} => false,
847 WorkDescription::Rebalance { .. } => true,
848 }
849 }
850
851 pub fn is_compute_lp_token(&self) -> bool {
853 match self {
854 WorkDescription::LoadMarket {} => false,
855 WorkDescription::ComputeLpTokenValue { .. } => true,
856 WorkDescription::ProcessQueueItem { .. } => false,
857 WorkDescription::ResetStats { .. } => false,
858 WorkDescription::HandleDeferredExecId {} => false,
859 WorkDescription::Rebalance { .. } => false,
860 }
861 }
862
863 pub fn is_reset_status(&self) -> bool {
865 match self {
866 WorkDescription::LoadMarket {} => false,
867 WorkDescription::ComputeLpTokenValue { .. } => false,
868 WorkDescription::ProcessQueueItem { .. } => false,
869 WorkDescription::ResetStats { .. } => true,
870 WorkDescription::HandleDeferredExecId {} => false,
871 WorkDescription::Rebalance { .. } => false,
872 }
873 }
874
875 pub fn is_deferred_work(&self) -> bool {
877 match self {
878 WorkDescription::LoadMarket {} => false,
879 WorkDescription::ComputeLpTokenValue { .. } => false,
880 WorkDescription::ProcessQueueItem { .. } => false,
881 WorkDescription::ResetStats { .. } => false,
882 WorkDescription::HandleDeferredExecId {} => true,
883 WorkDescription::Rebalance { .. } => false,
884 }
885 }
886}
887
888#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
890#[serde(rename_all = "snake_case")]
891pub enum QueuePositionId {
892 IncQueuePositionId(IncQueuePositionId),
895 DecQueuePositionId(DecQueuePositionId),
898}
899
900impl<'a> PrimaryKey<'a> for QueuePositionId {
901 type Prefix = ();
902 type SubPrefix = ();
903 type Suffix = Self;
904 type SuperSuffix = Self;
905
906 fn key(&self) -> Vec<Key> {
907 let (queue_type, key) = match self {
908 QueuePositionId::IncQueuePositionId(id) => (0u8, id.key()),
909 QueuePositionId::DecQueuePositionId(id) => (1u8, id.key()),
910 };
911 let mut keys = vec![Key::Val8([queue_type])];
912 keys.extend(key);
913 keys
914 }
915}
916
917impl KeyDeserialize for QueuePositionId {
918 type Output = QueuePositionId;
919
920 const KEY_ELEMS: u16 = 2;
921
922 fn from_vec(value: Vec<u8>) -> StdResult<Self::Output> {
923 let (queue_type, queue_id) = <(u8, u64) as KeyDeserialize>::from_vec(value)?;
924 let position_id = match queue_type {
925 0 => QueuePositionId::IncQueuePositionId(IncQueuePositionId(queue_id.into())),
926 1 => QueuePositionId::DecQueuePositionId(DecQueuePositionId(queue_id.into())),
927 _ => {
928 return Err(StdError::serialize_err(
929 "QueuePositionId",
930 "Invalid number in queue_type",
931 ))
932 }
933 };
934 Ok(position_id)
935 }
936}
937
938impl<'a> Prefixer<'a> for QueuePositionId {
939 fn prefix(&self) -> Vec<Key> {
940 match self {
941 QueuePositionId::IncQueuePositionId(id) => {
942 let mut keys = vec![Key::Val8([0u8])];
943 keys.extend(id.key());
944 keys
945 }
946 QueuePositionId::DecQueuePositionId(id) => {
947 let mut keys = vec![Key::Val8([1u8])];
948 keys.extend(id.key());
949 keys
950 }
951 }
952 }
953}
954
955#[derive(
957 Copy, PartialOrd, Ord, Eq, Clone, PartialEq, serde::Serialize, serde::Deserialize, Debug,
958)]
959#[serde(rename_all = "snake_case")]
960pub struct IncQueuePositionId(Uint64);
961
962impl IncQueuePositionId {
963 pub fn new(x: u64) -> Self {
965 IncQueuePositionId(x.into())
966 }
967
968 pub fn u64(self) -> u64 {
970 self.0.u64()
971 }
972
973 pub fn next(self) -> Self {
977 IncQueuePositionId((self.u64() + 1).into())
978 }
979}
980
981impl<'a> PrimaryKey<'a> for IncQueuePositionId {
982 type Prefix = ();
983 type SubPrefix = ();
984 type Suffix = Self;
985 type SuperSuffix = Self;
986
987 fn key(&self) -> Vec<Key> {
988 vec![Key::Val64(self.0.u64().to_cw_bytes())]
989 }
990}
991
992impl<'a> Prefixer<'a> for IncQueuePositionId {
993 fn prefix(&self) -> Vec<Key> {
994 vec![Key::Val64(self.0.u64().to_cw_bytes())]
995 }
996}
997
998impl KeyDeserialize for IncQueuePositionId {
999 type Output = IncQueuePositionId;
1000
1001 const KEY_ELEMS: u16 = 1;
1002
1003 #[inline(always)]
1004 fn from_vec(value: Vec<u8>) -> StdResult<Self::Output> {
1005 u64::from_vec(value).map(|x| IncQueuePositionId(Uint64::new(x)))
1006 }
1007}
1008
1009impl std::fmt::Display for IncQueuePositionId {
1010 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1011 write!(f, "{}", self.0)
1012 }
1013}
1014
1015impl FromStr for IncQueuePositionId {
1016 type Err = ParseIntError;
1017 fn from_str(src: &str) -> Result<Self, ParseIntError> {
1018 src.parse().map(|x| IncQueuePositionId(Uint64::new(x)))
1019 }
1020}
1021
1022#[derive(
1024 Copy, PartialOrd, Ord, Eq, Clone, PartialEq, serde::Serialize, serde::Deserialize, Debug,
1025)]
1026#[serde(rename_all = "snake_case")]
1027pub struct DecQueuePositionId(Uint64);
1028
1029impl DecQueuePositionId {
1030 pub fn new(x: u64) -> Self {
1032 DecQueuePositionId(x.into())
1033 }
1034
1035 pub fn u64(self) -> u64 {
1037 self.0.u64()
1038 }
1039
1040 pub fn next(self) -> Self {
1044 DecQueuePositionId((self.u64() + 1).into())
1045 }
1046}
1047
1048impl<'a> PrimaryKey<'a> for DecQueuePositionId {
1049 type Prefix = ();
1050 type SubPrefix = ();
1051 type Suffix = Self;
1052 type SuperSuffix = Self;
1053
1054 fn key(&self) -> Vec<Key> {
1055 vec![Key::Val64(self.0.u64().to_cw_bytes())]
1056 }
1057}
1058
1059impl<'a> Prefixer<'a> for DecQueuePositionId {
1060 fn prefix(&self) -> Vec<Key> {
1061 vec![Key::Val64(self.0.u64().to_cw_bytes())]
1062 }
1063}
1064
1065impl KeyDeserialize for DecQueuePositionId {
1066 type Output = DecQueuePositionId;
1067
1068 const KEY_ELEMS: u16 = 1;
1069
1070 #[inline(always)]
1071 fn from_vec(value: Vec<u8>) -> StdResult<Self::Output> {
1072 u64::from_vec(value).map(|x| DecQueuePositionId(Uint64::new(x)))
1073 }
1074}
1075
1076impl std::fmt::Display for DecQueuePositionId {
1077 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1078 write!(f, "{}", self.0)
1079 }
1080}
1081
1082impl FromStr for DecQueuePositionId {
1083 type Err = ParseIntError;
1084 fn from_str(src: &str) -> Result<Self, ParseIntError> {
1085 src.parse().map(|x| DecQueuePositionId(Uint64::new(x)))
1086 }
1087}
1088
1089#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
1091#[serde(rename_all = "snake_case")]
1092pub struct MigrateMsg {}