use namada_core::address::{Address, InternalAddress};
use namada_core::storage::{self, DbKeySeg, KeySeg};
pub const BALANCE_STORAGE_KEY: &str = "balance";
pub const DENOM_STORAGE_KEY: &str = "denomination";
pub const MINTER_STORAGE_KEY: &str = "minter";
pub const MINTED_STORAGE_KEY: &str = "minted";
pub const PARAMETERS_STORAGE_KEY: &str = "parameters";
pub fn key_of_token(
token_addr: &Address,
specific_key: &str,
expect_message: &str,
) -> storage::Key {
storage::Key::from(token_addr.to_db_key())
.push(&specific_key.to_owned())
.expect(expect_message)
}
pub fn balance_key(token_addr: &Address, owner: &Address) -> storage::Key {
balance_prefix(token_addr)
.push(&owner.to_db_key())
.expect("Cannot obtain a storage key")
}
pub fn balance_prefix(token_addr: &Address) -> storage::Key {
storage::Key::from(
Address::Internal(InternalAddress::Multitoken).to_db_key(),
)
.push(&token_addr.to_db_key())
.expect("Cannot obtain a storage key")
.push(&BALANCE_STORAGE_KEY.to_owned())
.expect("Cannot obtain a storage key")
}
pub fn parameter_prefix(token_addr: &Address) -> storage::Key {
storage::Key::from(
Address::Internal(InternalAddress::Multitoken).to_db_key(),
)
.push(&token_addr.to_db_key())
.expect("Cannot obtain a storage key")
.push(&PARAMETERS_STORAGE_KEY.to_owned())
.expect("Cannot obtain a storage key")
}
pub fn minter_key(token_addr: &Address) -> storage::Key {
storage::Key::from(
Address::Internal(InternalAddress::Multitoken).to_db_key(),
)
.push(&token_addr.to_db_key())
.expect("Cannot obtain a storage key")
.push(&MINTER_STORAGE_KEY.to_owned())
.expect("Cannot obtain a storage key")
}
pub fn minted_balance_key(token_addr: &Address) -> storage::Key {
balance_prefix(token_addr)
.push(&MINTED_STORAGE_KEY.to_owned())
.expect("Cannot obtain a storage key")
}
pub fn is_multitoken_key(key: &storage::Key) -> bool {
match key.fst_address() {
Some(addr) => addr.eq(&Address::Internal(InternalAddress::Multitoken)),
None => false,
}
}
pub fn is_balance_key<'a>(
token_addr: &Address,
key: &'a storage::Key,
) -> Option<&'a Address> {
match &key.segments[..] {
[
DbKeySeg::AddressSeg(addr),
DbKeySeg::AddressSeg(token),
DbKeySeg::StringSeg(balance),
DbKeySeg::AddressSeg(owner),
] if *addr == Address::Internal(InternalAddress::Multitoken)
&& token == token_addr
&& balance == BALANCE_STORAGE_KEY =>
{
Some(owner)
}
_ => None,
}
}
pub fn is_any_token_parameter_key(key: &storage::Key) -> Option<&Address> {
match &key.segments[..] {
[
DbKeySeg::AddressSeg(addr),
DbKeySeg::AddressSeg(token),
DbKeySeg::StringSeg(parameter),
DbKeySeg::StringSeg(_parameter_name),
] if *addr == Address::Internal(InternalAddress::Multitoken)
&& parameter == PARAMETERS_STORAGE_KEY =>
{
Some(token)
}
_ => None,
}
}
pub fn is_any_token_balance_key(key: &storage::Key) -> Option<[&Address; 2]> {
match &key.segments[..] {
[
DbKeySeg::AddressSeg(addr),
DbKeySeg::AddressSeg(token),
DbKeySeg::StringSeg(balance),
DbKeySeg::AddressSeg(owner),
] if *addr == Address::Internal(InternalAddress::Multitoken)
&& balance == BALANCE_STORAGE_KEY =>
{
Some([token, owner])
}
_ => None,
}
}
pub fn denom_key(token_addr: &Address) -> storage::Key {
storage::Key::from(token_addr.to_db_key())
.push(&DENOM_STORAGE_KEY.to_owned())
.expect("Cannot obtain a storage key")
}
pub fn is_denom_key(token_addr: &Address, key: &storage::Key) -> bool {
matches!(&key.segments[..],
[
DbKeySeg::AddressSeg(addr),
..,
DbKeySeg::StringSeg(key),
] if key == DENOM_STORAGE_KEY && addr == token_addr)
}
pub fn is_any_minter_key(key: &storage::Key) -> Option<&Address> {
match &key.segments[..] {
[
DbKeySeg::AddressSeg(addr),
DbKeySeg::AddressSeg(token),
DbKeySeg::StringSeg(minter),
] if *addr == Address::Internal(InternalAddress::Multitoken)
&& minter == MINTER_STORAGE_KEY =>
{
Some(token)
}
_ => None,
}
}
pub fn is_any_minted_balance_key(key: &storage::Key) -> Option<&Address> {
match &key.segments[..] {
[
DbKeySeg::AddressSeg(addr),
DbKeySeg::AddressSeg(token),
DbKeySeg::StringSeg(balance),
DbKeySeg::StringSeg(owner),
] if *addr == Address::Internal(InternalAddress::Multitoken)
&& balance == BALANCE_STORAGE_KEY
&& owner == MINTED_STORAGE_KEY =>
{
Some(token)
}
_ => None,
}
}