Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds BankQuery::Supply support #51

Merged
merged 3 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ homepage = "https://cosmwasm.com"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default = ["iterator", "staking"]
default = ["iterator", "staking", "cosmwasm_1_1"]
iterator = ["cosmwasm-std/iterator"]
stargate = ["cosmwasm-std/stargate"]
staking = ["cosmwasm-std/staking"]
backtrace = ["anyhow/backtrace"]
cosmwasm_1_1 = ["cosmwasm-std/cosmwasm_1_1"]

[dependencies]
cw-utils = "1.0"
Expand Down
63 changes: 59 additions & 4 deletions src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use schemars::JsonSchema;

use cosmwasm_std::{
coin, to_binary, Addr, AllBalanceResponse, Api, BalanceResponse, BankMsg, BankQuery, Binary,
BlockInfo, Coin, Event, Querier, Storage,
BlockInfo, Coin, Event, Order, Querier, StdResult, Storage, SupplyResponse, Uint128,
};
use cw_storage_plus::Map;
use cw_utils::NativeBalance;
Expand All @@ -18,7 +18,6 @@ const BALANCES: Map<&Addr, NativeBalance> = Map::new("balances");

pub const NAMESPACE_BANK: &[u8] = b"bank";

// WIP
#[derive(Clone, std::fmt::Debug, PartialEq, Eq, JsonSchema)]
pub enum BankSudo {
Mint {
Expand Down Expand Up @@ -48,6 +47,7 @@ impl BankKeeper {
self.set_balance(&mut bank_storage, account, amount)
}

// this is an "admin" function to let us adjust bank accounts
fn set_balance(
&self,
bank_storage: &mut dyn Storage,
Expand All @@ -61,12 +61,29 @@ impl BankKeeper {
.map_err(Into::into)
}

// this is an "admin" function to let us adjust bank accounts
fn get_balance(&self, bank_storage: &dyn Storage, account: &Addr) -> AnyResult<Vec<Coin>> {
let val = BALANCES.may_load(bank_storage, account)?;
Ok(val.unwrap_or_default().into_vec())
}

fn get_supply(&self, bank_storage: &dyn Storage, denom: String) -> AnyResult<Coin> {
let supply: Uint128 = BALANCES
.range(bank_storage, None, None, Order::Ascending)
.collect::<StdResult<Vec<_>>>()?
.into_iter()
.map(|a| a.1)
.fold(Uint128::zero(), |accum, item| {
let mut subtotal = Uint128::zero();
for coin in item.into_vec() {
if coin.denom == denom {
subtotal += coin.amount;
}
}
accum + subtotal
});
Ok(coin(supply.into(), denom))
}

fn send(
&self,
bank_storage: &mut dyn Storage,
Expand Down Expand Up @@ -205,6 +222,12 @@ impl Module for BankKeeper {
let res = BalanceResponse { amount };
Ok(to_binary(&res)?)
}
BankQuery::Supply { denom } => {
let amount = self.get_supply(&bank_storage, denom)?;
let mut res = SupplyResponse::default();
res.amount = amount;
Ok(to_binary(&res)?)
}
q => bail!("Unsupported bank query: {:?}", q),
}
}
Expand Down Expand Up @@ -241,6 +264,7 @@ mod test {
let mut store = MockStorage::new();
let block = mock_env().block;
let querier: MockQuerier<Empty> = MockQuerier::new(&[]);
let router = MockRouter::default();

let owner = Addr::unchecked("owner");
let rcpt = Addr::unchecked("receiver");
Expand Down Expand Up @@ -290,12 +314,43 @@ mod test {
assert_eq!(res.amount, coin(0, "foobar"));

let req = BankQuery::Balance {
address: rcpt.into(),
address: rcpt.clone().into(),
denom: "eth".into(),
};
let raw = bank.query(&api, &store, &querier, &block, req).unwrap();
let res: BalanceResponse = from_slice(&raw).unwrap();
assert_eq!(res.amount, coin(0, "eth"));

// Query total supply of a denom
let req = BankQuery::Supply {
denom: "eth".into(),
};
let raw = bank.query(&api, &store, &querier, &block, req).unwrap();
let res: SupplyResponse = from_slice(&raw).unwrap();
assert_eq!(res.amount, coin(100, "eth"));
JakeHartnell marked this conversation as resolved.
Show resolved Hide resolved

// Mint tokens for recipient account
let msg = BankSudo::Mint {
to_address: rcpt.to_string(),
amount: norm.clone(),
};
bank.sudo(&api, &mut store, &router, &block, msg).unwrap();

// Check that the recipient account has the expected balance
let req = BankQuery::AllBalances {
address: rcpt.into(),
};
let raw = bank.query(&api, &store, &querier, &block, req).unwrap();
let res: AllBalanceResponse = from_slice(&raw).unwrap();
assert_eq!(res.amount, norm);

// Check that the total supply of a denom is updated
let req = BankQuery::Supply {
denom: "eth".into(),
};
let raw = bank.query(&api, &store, &querier, &block, req).unwrap();
let res: SupplyResponse = from_slice(&raw).unwrap();
assert_eq!(res.amount, coin(200, "eth"));
}

#[test]
Expand Down