astro4nit/xastro_token.rs
1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4use cosmwasm_std::{StdError, StdResult, Uint128};
5use cw20::{Cw20Coin, MinterResponse};
6
7/// ## Description
8/// This structure describes the parameters used for creating a xASTRO token contract.
9/// TokenContract InstantiateMsg
10#[derive(Serialize, Deserialize, JsonSchema)]
11pub struct InstantiateMsg {
12 /// Token name
13 pub name: String,
14 /// Token symbol
15 pub symbol: String,
16 /// The number of decimals the token has
17 pub decimals: u8,
18 /// Initial token balances
19 pub initial_balances: Vec<Cw20Coin>,
20 /// Token minting permissions
21 pub mint: Option<MinterResponse>,
22}
23
24/// ## Description
25/// This enum describes the query messages available in the contract.
26#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
27#[serde(rename_all = "snake_case")]
28pub enum QueryMsg {
29 /// Balance returns the current balance of a given address, 0 if unset.
30 Balance { address: String },
31 /// BalanceAt returns balance of the given address at the given block, 0 if unset.
32 BalanceAt { address: String, block: u64 },
33 /// TotalSupplyAt returns the total token supply at the given block.
34 TotalSupplyAt { block: u64 },
35 /// TokenInfo returns the contract's metadata - name, decimals, supply, etc.
36 TokenInfo {},
37 /// Returns who can mint and the hard cap on maximum tokens after minting.
38 Minter {},
39 /// Allowance returns an amount of tokens the spender can spend from the owner account, 0 if unset.
40 Allowance { owner: String, spender: String },
41 /// AllAllowances returns all allowances this owner has approved. Supports pagination.
42 AllAllowances {
43 owner: String,
44 start_after: Option<String>,
45 limit: Option<u32>,
46 },
47 /// AllAccounts returns all accounts that have balances. Supports pagination.
48 AllAccounts {
49 start_after: Option<String>,
50 limit: Option<u32>,
51 },
52 /// Returns marketing related contract metadata:
53 /// - description, logo, project url, etc.
54 MarketingInfo {},
55 /// Downloads embeded logo data (if stored on chain). Errors if no logo data was stored for this contract.
56 DownloadLogo {},
57}
58
59/// ## Description
60/// This structure describes a migration message.
61/// We currently take no arguments for migrations.
62#[derive(Serialize, Deserialize, JsonSchema)]
63pub struct MigrateMsg {}
64
65impl InstantiateMsg {
66 pub fn get_cap(&self) -> Option<Uint128> {
67 self.mint.as_ref().and_then(|v| v.cap)
68 }
69
70 pub fn validate(&self) -> StdResult<()> {
71 // Check name, symbol, decimals
72 if !is_valid_name(&self.name) {
73 return Err(StdError::generic_err(
74 "Name is not in the expected format (3-50 UTF-8 bytes)",
75 ));
76 }
77 if !is_valid_symbol(&self.symbol) {
78 return Err(StdError::generic_err(
79 "Ticker symbol is not in expected format [a-zA-Z\\-]{3,12}",
80 ));
81 }
82 if self.decimals > 18 {
83 return Err(StdError::generic_err("Decimals must not exceed 18"));
84 }
85 Ok(())
86 }
87}
88
89/// ## Description
90/// Checks the validity of a token's name
91/// ## Params
92/// * **name** is an object of type [`str`]. It is the token name to check
93fn is_valid_name(name: &str) -> bool {
94 let bytes = name.as_bytes();
95 if bytes.len() < 3 || bytes.len() > 50 {
96 return false;
97 }
98 true
99}
100
101/// ## Description
102/// Checks the validity of a token's symbol
103/// ## Params
104/// * **symbol** is an object of type [`str`]. It is the token symbol to check
105fn is_valid_symbol(symbol: &str) -> bool {
106 let bytes = symbol.as_bytes();
107 if bytes.len() < 3 || bytes.len() > 12 {
108 return false;
109 }
110 for byte in bytes.iter() {
111 if (*byte != 45) && (*byte < 65 || *byte > 90) && (*byte < 97 || *byte > 122) {
112 return false;
113 }
114 }
115 true
116}