1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use cosmwasm_bignumber::{Decimal256, Uint256};
use cosmwasm_std::{
from_binary, to_binary, AllBalanceResponse, Api, BalanceResponse, BankQuery, Binary, Coin,
Extern, HumanAddr, Querier, QueryRequest, StdResult, Storage, Uint128, WasmQuery,
};
use cosmwasm_storage::to_length_prefixed;
use cw20::TokenInfoResponse;
use terra_cosmwasm::TerraQuerier;
pub fn query_all_balances<S: Storage, A: Api, Q: Querier>(
deps: &Extern<S, A, Q>,
account_addr: &HumanAddr,
) -> StdResult<Vec<Coin>> {
let all_balances: AllBalanceResponse =
deps.querier
.query(&QueryRequest::Bank(BankQuery::AllBalances {
address: HumanAddr::from(account_addr),
}))?;
Ok(all_balances.amount)
}
pub fn query_balance<S: Storage, A: Api, Q: Querier>(
deps: &Extern<S, A, Q>,
account_addr: &HumanAddr,
denom: String,
) -> StdResult<Uint256> {
let balance: BalanceResponse = deps.querier.query(&QueryRequest::Bank(BankQuery::Balance {
address: HumanAddr::from(account_addr),
denom,
}))?;
Ok(balance.amount.amount.into())
}
pub fn query_token_balance<S: Storage, A: Api, Q: Querier>(
deps: &Extern<S, A, Q>,
contract_addr: &HumanAddr,
account_addr: &HumanAddr,
) -> StdResult<Uint256> {
let res: Binary = deps
.querier
.query(&QueryRequest::Wasm(WasmQuery::Raw {
contract_addr: HumanAddr::from(contract_addr),
key: Binary::from(concat(
&to_length_prefixed(b"balance").to_vec(),
(deps.api.canonical_address(&account_addr)?).as_slice(),
)),
}))
.unwrap_or_else(|_| to_binary(&Uint128::zero()).unwrap());
let balance: Uint128 = from_binary(&res)?;
Ok(balance.into())
}
pub fn query_supply<S: Storage, A: Api, Q: Querier>(
deps: &Extern<S, A, Q>,
contract_addr: &HumanAddr,
) -> StdResult<Uint256> {
let res: Binary = deps.querier.query(&QueryRequest::Wasm(WasmQuery::Raw {
contract_addr: HumanAddr::from(contract_addr),
key: Binary::from(to_length_prefixed(b"token_info")),
}))?;
let token_info: TokenInfoResponse = from_binary(&res)?;
Ok(Uint256::from(token_info.total_supply))
}
pub fn query_tax_rate<S: Storage, A: Api, Q: Querier>(
deps: &Extern<S, A, Q>,
) -> StdResult<Decimal256> {
let terra_querier = TerraQuerier::new(&deps.querier);
Ok(terra_querier.query_tax_rate()?.rate.into())
}
pub fn compute_tax<S: Storage, A: Api, Q: Querier>(
deps: &Extern<S, A, Q>,
coin: &Coin,
) -> StdResult<Uint256> {
let terra_querier = TerraQuerier::new(&deps.querier);
let tax_rate = Decimal256::from((terra_querier.query_tax_rate()?).rate);
let tax_cap = Uint256::from((terra_querier.query_tax_cap(coin.denom.to_string())?).cap);
let amount = Uint256::from(coin.amount);
Ok(std::cmp::min(
amount * (Decimal256::one() - Decimal256::one() / (Decimal256::one() + tax_rate)),
tax_cap,
))
}
pub fn deduct_tax<S: Storage, A: Api, Q: Querier>(
deps: &Extern<S, A, Q>,
coin: Coin,
) -> StdResult<Coin> {
let tax_amount = compute_tax(deps, &coin)?;
Ok(Coin {
denom: coin.denom,
amount: (Uint256::from(coin.amount) - tax_amount).into(),
})
}
#[inline]
fn concat(namespace: &[u8], key: &[u8]) -> Vec<u8> {
let mut k = namespace.to_vec();
k.extend_from_slice(key);
k
}