1use crate::adapters::eris::ErisHub;
2use crate::helpers::time::Time;
3use cosmwasm_schema::{cw_serde, QueryResponses};
4use cosmwasm_std::{Addr, Binary, Decimal, Empty, QuerierWrapper, StdResult, Uint128};
5use cw20::{Cw20ReceiveMsg, Expiration};
6#[allow(unused_imports)]
7use cw721::{
8 AllNftInfoResponse, ApprovalResponse, ApprovalsResponse, ContractInfoResponse, NftInfoResponse,
9 NumTokensResponse, OperatorsResponse, OwnerOfResponse, TokensResponse,
10};
11#[allow(unused_imports)]
12use cw721_base::MinterResponse;
13use cw721_base::QueryMsg as CW721QueryMsg;
14use cw721_base::{state::TokenInfo, ExecuteMsg as CW721ExecuteMsg};
15use cw_address_like::AddressLike;
16use cw_asset::{Asset, AssetInfoBase};
17use std::fmt;
18
19#[cw_serde]
21pub struct InstantiateMsg {
22 pub global_config_addr: String,
24 pub deposit_assets: Vec<DepositAsset<String>>,
26}
27
28#[cw_serde]
29pub struct DepositAsset<T: AddressLike> {
30 pub info: AssetInfoBase<T>,
31 pub config: AssetInfoConfig,
32}
33
34#[cw_serde]
36pub enum ExecuteMsg {
37 CreateLock {
40 time: Option<u64>,
41 recipient: Option<String>,
42 },
43 MergeLock {
44 token_id: String,
45 token_id_add: String,
46 },
47 SplitLock {
48 token_id: String,
49 amount: Uint128,
50 recipient: Option<String>,
51 },
52 ExtendLockTime {
54 time: u64,
55 token_id: String,
56 },
57 ExtendLockAmount {
59 token_id: String,
60 },
61
62 LockPermanent {
63 token_id: String,
64 },
65
66 UnlockPermanent {
67 token_id: String,
68 },
69
70 Withdraw {
72 token_id: String,
73 },
74 Receive(Cw20ReceiveMsg),
76
77 UpdateBlacklist {
80 append_addrs: Option<Vec<String>>,
81 remove_addrs: Option<Vec<String>>,
82 },
83 UpdateConfig {
85 append_deposit_assets: Option<Vec<DepositAsset<String>>>,
88
89 push_update_contracts: Option<Vec<String>>,
90 decommissioned: Option<bool>,
92 },
93
94 TransferNft {
97 recipient: String,
98 token_id: String,
99 },
100 SendNft {
103 contract: String,
104 token_id: String,
105 msg: Binary,
106 },
107 Burn {
109 token_id: String,
110 },
111
112 Approve {
115 spender: String,
116 token_id: String,
117 expires: Option<Expiration>,
118 },
119 Revoke {
121 spender: String,
122 token_id: String,
123 },
124 ApproveAll {
127 operator: String,
128 expires: Option<Expiration>,
129 },
130 RevokeAll {
132 operator: String,
133 },
134}
135
136#[cw_serde]
137pub enum ReceiveMsg {
138 ExtendLockAmount {
139 token_id: String,
140 },
141 CreateLock {
142 time: Option<u64>,
143 recipient: Option<String>,
144 },
145}
146
147pub type VeNftCollection<'a> = cw721_base::Cw721Contract<'a, Extension, Empty, Empty, Empty>;
148pub type VeNftInfo = TokenInfo<Metadata>;
149
150#[cw_serde]
151pub struct Trait {
152 pub display_type: Option<String>,
153 pub trait_type: String,
154 pub value: String,
155}
156
157pub type Extension = Metadata;
158
159#[cw_serde]
161pub struct Metadata {
162 pub image: Option<String>,
163 pub description: Option<String>,
166 pub name: Option<String>,
167 pub attributes: Option<Vec<Trait>>,
168 }
172
173impl From<ExecuteMsg> for CW721ExecuteMsg<Metadata, Empty> {
174 fn from(msg: ExecuteMsg) -> CW721ExecuteMsg<Metadata, Empty> {
175 match msg {
176 ExecuteMsg::Approve {
177 spender,
178 token_id,
179 expires,
180 } => CW721ExecuteMsg::Approve {
181 spender,
182 token_id,
183 expires,
184 },
185 ExecuteMsg::Revoke {
186 spender,
187 token_id,
188 } => CW721ExecuteMsg::Revoke {
189 spender,
190 token_id,
191 },
192 ExecuteMsg::ApproveAll {
193 operator,
194 expires,
195 } => CW721ExecuteMsg::ApproveAll {
196 operator,
197 expires,
198 },
199 ExecuteMsg::RevokeAll {
200 operator,
201 } => CW721ExecuteMsg::RevokeAll {
202 operator,
203 },
204 _ => panic!("cannot covert {:?} to CW721ExecuteMsg", msg),
205 }
206 }
207}
208
209#[cw_serde]
211pub enum BlacklistedVotersResponse {
212 VotersBlacklisted {},
214 VotersNotBlacklisted {
216 voter: String,
217 },
218}
219
220impl fmt::Display for BlacklistedVotersResponse {
221 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
222 match self {
223 BlacklistedVotersResponse::VotersBlacklisted {} => write!(f, "Voters are blacklisted!"),
224 BlacklistedVotersResponse::VotersNotBlacklisted {
225 voter,
226 } => {
227 write!(f, "Voter is not blacklisted: {}", voter)
228 },
229 }
230 }
231}
232
233#[cw_serde]
235#[derive(QueryResponses)]
236pub enum QueryMsg {
237 #[returns(Vec<Addr>)]
239 BlacklistedVoters {
240 start_after: Option<String>,
241 limit: Option<u32>,
242 },
243
244 #[returns(VotingPowerResponse)]
246 TotalVamp {
247 time: Option<Time>,
248 },
249
250 #[returns(VotingPowerFixedResponse)]
252 TotalFixed {
253 time: Option<Time>,
254 },
255
256 #[returns(VotingPowerResponse)]
258 LockVamp {
259 token_id: String,
260 time: Option<Time>,
261 },
262
263 #[returns(LockInfoResponse)]
265 LockInfo {
266 token_id: String,
267 time: Option<Time>,
268 },
269 #[returns(Config)]
271 Config {},
272
273 #[returns(NftInfoResponse<Extension>)]
314 NftInfo {
315 token_id: String,
316 },
317
318 #[returns(AllNftInfoResponse<Extension>)]
321 AllNftInfo {
322 token_id: String,
323 include_expired: Option<bool>,
325 },
326
327 #[returns(OwnerOfResponse)]
331 OwnerOf {
332 token_id: String,
333 include_expired: Option<bool>,
335 },
336 #[returns(ApprovalResponse)]
339 Approval {
340 token_id: String,
341 spender: String,
342 include_expired: Option<bool>,
343 },
344 #[returns(ApprovalsResponse)]
346 Approvals {
347 token_id: String,
348 include_expired: Option<bool>,
349 },
350 #[returns(OperatorsResponse)]
352 AllOperators {
353 owner: String,
354 include_expired: Option<bool>,
356 start_after: Option<String>,
357 limit: Option<u32>,
358 },
359 #[returns(NumTokensResponse)]
361 NumTokens {},
362
363 #[returns(ContractInfoResponse)]
365 ContractInfo {},
366
367 #[returns(TokensResponse)]
370 Tokens {
371 owner: String,
372 start_after: Option<String>,
373 limit: Option<u32>,
374 },
375 #[returns(TokensResponse)]
378 AllTokens {
379 start_after: Option<String>,
380 limit: Option<u32>,
381 },
382
383 #[returns(MinterResponse)]
385 Minter {},
386}
387
388impl From<QueryMsg> for CW721QueryMsg<Empty> {
389 fn from(msg: QueryMsg) -> CW721QueryMsg<Empty> {
390 match msg {
391 QueryMsg::OwnerOf {
392 token_id,
393 include_expired,
394 } => CW721QueryMsg::OwnerOf {
395 token_id,
396 include_expired,
397 },
398 QueryMsg::Approval {
399 token_id,
400 spender,
401 include_expired,
402 } => CW721QueryMsg::Approval {
403 token_id,
404 spender,
405 include_expired,
406 },
407 QueryMsg::Approvals {
408 token_id,
409 include_expired,
410 } => CW721QueryMsg::Approvals {
411 token_id,
412 include_expired,
413 },
414 QueryMsg::AllOperators {
415 owner,
416 include_expired,
417 start_after,
418 limit,
419 } => CW721QueryMsg::AllOperators {
420 owner,
421 include_expired,
422 start_after,
423 limit,
424 },
425 QueryMsg::NumTokens {} => CW721QueryMsg::NumTokens {},
426 QueryMsg::ContractInfo {} => CW721QueryMsg::ContractInfo {},
427 QueryMsg::NftInfo {
428 token_id,
429 } => CW721QueryMsg::NftInfo {
430 token_id,
431 },
432 QueryMsg::AllNftInfo {
433 token_id,
434 include_expired,
435 } => CW721QueryMsg::AllNftInfo {
436 token_id,
437 include_expired,
438 },
439 QueryMsg::Tokens {
440 owner,
441 start_after,
442 limit,
443 } => CW721QueryMsg::Tokens {
444 owner,
445 start_after,
446 limit,
447 },
448 QueryMsg::AllTokens {
449 start_after,
450 limit,
451 } => CW721QueryMsg::AllTokens {
452 start_after,
453 limit,
454 },
455 QueryMsg::Minter {} => CW721QueryMsg::Minter {},
456 _ => panic!("cannot covert {:?} to CW721QueryMsg", msg),
457 }
458 }
459}
460
461#[cw_serde]
463pub struct VotingPowerResponse {
464 pub fixed: Uint128,
465 pub voting_power: Uint128,
466 pub vp: Uint128,
468}
469
470#[cw_serde]
471pub struct VotingPowerFixedResponse {
472 pub fixed: Uint128,
473}
474
475#[cw_serde]
477pub struct LockInfoResponse {
478 pub owner: Addr,
479
480 pub from_period: u64,
481
482 pub asset: Asset,
483 pub underlying_amount: Uint128,
485 pub coefficient: Decimal,
487 pub start: u64,
489 pub end: End,
491 pub slope: Uint128,
493
494 pub fixed_amount: Uint128,
496 pub voting_power: Uint128,
498}
499
500impl LockInfoResponse {
501 pub fn has_vp(&self) -> bool {
502 !self.fixed_amount.is_zero() || !self.voting_power.is_zero()
503 }
504
505 pub fn end_string(&self) -> String {
506 self.end.to_string()
507 }
508}
509
510#[cw_serde]
511pub enum End {
512 Permanent,
513 Period(u64),
514}
515
516impl fmt::Display for End {
517 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
518 match self {
519 End::Permanent => fmt.write_str("permanent")?,
520 End::Period(period) => fmt.write_str(&period.to_string())?,
521 }
522
523 Ok(())
524 }
525}
526
527#[cw_serde]
529pub struct Config {
530 pub global_config_addr: Addr,
532 pub deposit_assets: Vec<DepositAsset<Addr>>,
534 pub push_update_contracts: Vec<Addr>,
536 pub decommissioned: Option<bool>,
538}
539
540#[cw_serde]
541pub enum AssetInfoConfig {
542 Default,
543 ExchangeRate {
544 contract: Addr,
545 },
546}
547
548impl AssetInfoConfig {
549 pub fn get_exchange_rate(&self, querier: &QuerierWrapper) -> StdResult<Option<Decimal>> {
550 match self {
551 AssetInfoConfig::Default => Ok(None),
552 AssetInfoConfig::ExchangeRate {
553 contract,
554 } => Ok(Some(ErisHub(contract).query_exchange_rate(querier)?)),
555 }
556 }
557
558 pub fn get_underlying_amount(
559 &self,
560 querier: &QuerierWrapper,
561 amount: Uint128,
562 ) -> StdResult<Uint128> {
563 Ok(self.get_exchange_rate(querier)?.map_or(amount, |e| e * amount))
564 }
565}
566
567#[cw_serde]
569pub struct MigrateMsg {}