use cosmwasm_schema::cw_serde;
use cw_utils::{must_pay, PaymentError};
use thiserror::Error;
use abstract_cw20::{Denom, UncheckedDenom};
use cosmwasm_std::{
to_json_binary, Addr, BankMsg, Coin, CosmosMsg, Deps, MessageInfo, StdResult, Uint128, WasmMsg,
};
#[cw_serde]
pub struct DepositInfo {
pub amount: Uint128,
pub denom: Denom,
pub refund_failed_proposals: bool,
}
#[cw_serde]
pub struct UncheckedDepositInfo {
pub amount: Uint128,
pub denom: UncheckedDenom,
pub refund_failed_proposals: bool,
}
#[derive(Error, Debug, PartialEq, Eq)]
pub enum DepositError {
#[error("Invalid zero deposit. Set the deposit to None to have no deposit.")]
ZeroDeposit {},
#[error("Invalid cw20")]
InvalidCw20 {},
#[error("{0}")]
Payment(#[from] PaymentError),
#[error("Invalid native deposit amount")]
InvalidDeposit {},
}
impl UncheckedDepositInfo {
pub fn into_checked(self, deps: Deps) -> Result<DepositInfo, DepositError> {
if self.amount.is_zero() {
Err(DepositError::ZeroDeposit {})
} else {
Ok(DepositInfo {
amount: self.amount,
denom: self
.denom
.into_checked(deps)
.map_err(|_| DepositError::InvalidCw20 {})?,
refund_failed_proposals: self.refund_failed_proposals,
})
}
}
}
impl DepositInfo {
pub fn check_native_deposit_paid(&self, info: &MessageInfo) -> Result<(), DepositError> {
if let Self {
amount,
denom: Denom::Native(denom),
..
} = self
{
let paid = must_pay(info, denom)?;
if paid != *amount {
Err(DepositError::InvalidDeposit {})
} else {
Ok(())
}
} else {
Ok(())
}
}
pub fn get_take_deposit_messages(
&self,
depositor: &Addr,
contract: &Addr,
) -> StdResult<Vec<CosmosMsg>> {
let take_deposit_msg: Vec<CosmosMsg> = if let DepositInfo {
amount,
denom: Denom::Cw20(address),
..
} = self
{
if amount.is_zero() {
vec![]
} else {
vec![WasmMsg::Execute {
contract_addr: address.to_string(),
funds: vec![],
msg: to_json_binary(&abstract_cw20::Cw20ExecuteMsg::TransferFrom {
owner: depositor.to_string(),
recipient: contract.to_string(),
amount: *amount,
})?,
}
.into()]
}
} else {
vec![]
};
Ok(take_deposit_msg)
}
pub fn get_return_deposit_message(&self, depositor: &Addr) -> StdResult<CosmosMsg> {
let message = match &self.denom {
Denom::Native(denom) => BankMsg::Send {
to_address: depositor.to_string(),
amount: vec![Coin {
amount: self.amount,
denom: denom.to_string(),
}],
}
.into(),
Denom::Cw20(address) => WasmMsg::Execute {
contract_addr: address.to_string(),
msg: to_json_binary(&abstract_cw20::Cw20ExecuteMsg::Transfer {
recipient: depositor.to_string(),
amount: self.amount,
})?,
funds: vec![],
}
.into(),
};
Ok(message)
}
}