1use cosmwasm_schema::{cw_serde, QueryResponses};
2use cosmwasm_std::{Addr, Binary, StdError, StdResult, Uint128};
3use cw20::{Cw20Coin, Expiration, Logo, MinterResponse};
4use gate_pkg::GateMsg;
5
6#[cw_serde]
7pub enum Cw20GateMsgType {
8 Bridge {
9 sender: String,
10 receiver: String,
11 amount: Uint128,
12 },
13
14 BridgeAndExecute {
15 sender: String,
16 receiver: String,
17 amount: Uint128,
18 to_contract: String,
19 msg: Binary,
20 },
21}
22
23#[cw_serde]
24pub enum ExecuteMsg {
25 Transfer {
26 recipient: String,
27 amount: Uint128,
28 },
29 Burn {
30 amount: Uint128,
31 },
32 Send {
33 contract: String,
34 amount: Uint128,
35 msg: Binary,
36 },
37 IncreaseAllowance {
38 spender: String,
39 amount: Uint128,
40 expires: Option<Expiration>,
41 },
42 DecreaseAllowance {
43 spender: String,
44 amount: Uint128,
45 expires: Option<Expiration>,
46 },
47 TransferFrom {
48 owner: String,
49 recipient: String,
50 amount: Uint128,
51 },
52 SendFrom {
53 owner: String,
54 contract: String,
55 amount: Uint128,
56 msg: Binary,
57 },
58 BurnFrom {
59 owner: String,
60 amount: Uint128,
61 },
62 Mint {
63 recipient: String,
64 amount: Uint128,
65 },
66 UpdateMinter {
67 new_minter: Option<String>,
68 },
69 UpdateMarketing {
70 project: Option<String>,
71 description: Option<String>,
72 marketing: Option<String>,
73 },
74 UploadLogo(Logo),
75 RegisterGate {
77 contract: Addr,
78 },
79 GateSetPermission {
80 contract: String,
81 chain: String,
82 },
83 GateBridge {
84 chain: String,
85 remote_receiver: String,
86 amount: Uint128,
87 },
88 GateBridgeAndExecute {
89 chain: String,
90 remote_receiver: String,
91 amount: Uint128,
92 remote_contract: String,
93 msg: Binary,
94 },
95 ReceiveGateMsg(GateMsg),
97}
98
99#[cw_serde]
100#[derive(QueryResponses)]
101pub enum QueryMsg {
102 #[returns(cw20::BalanceResponse)]
104 Balance { address: String },
105 #[returns(cw20::TokenInfoResponse)]
107 TokenInfo {},
108 #[returns(cw20::MinterResponse)]
111 Minter {},
112 #[returns(cw20::AllowanceResponse)]
115 Allowance { owner: String, spender: String },
116 #[returns(cw20::AllAllowancesResponse)]
119 AllAllowances {
120 owner: String,
121 start_after: Option<String>,
122 limit: Option<u32>,
123 },
124 #[returns(cw20::AllSpenderAllowancesResponse)]
127 AllSpenderAllowances {
128 spender: String,
129 start_after: Option<String>,
130 limit: Option<u32>,
131 },
132 #[returns(cw20::AllAccountsResponse)]
135 AllAccounts {
136 start_after: Option<String>,
137 limit: Option<u32>,
138 },
139 #[returns(cw20::MarketingInfoResponse)]
143 MarketingInfo {},
144 #[returns(cw20::DownloadLogoResponse)]
148 DownloadLogo {},
149
150 #[returns(String)]
152 RemoteContract { chain: String },
153 #[returns(String)]
155 Gate {},
156}
157
158#[cw_serde]
159pub struct InstantiateMsg {
160 pub name: String,
161 pub symbol: String,
162 pub decimals: u8,
163 pub initial_balances: Vec<Cw20Coin>,
164 pub mint: Option<MinterResponse>,
165}
166
167impl InstantiateMsg {
168 pub fn get_cap(&self) -> Option<Uint128> {
169 self.mint.as_ref().and_then(|v| v.cap)
170 }
171
172 pub fn validate(&self) -> StdResult<()> {
173 if !is_valid_name(&self.name) {
175 return Err(StdError::generic_err(
176 "Name is not in the expected format (3-50 UTF-8 bytes)",
177 ));
178 }
179 if !is_valid_symbol(&self.symbol) {
180 return Err(StdError::generic_err(
181 "Ticker symbol is not in expected format [a-zA-Z\\-]{3,12}",
182 ));
183 }
184 if self.decimals > 18 {
185 return Err(StdError::generic_err("Decimals must not exceed 18"));
186 }
187 Ok(())
188 }
189}
190
191fn is_valid_name(name: &str) -> bool {
192 let bytes = name.as_bytes();
193 if bytes.len() < 3 || bytes.len() > 50 {
194 return false;
195 }
196 true
197}
198
199fn is_valid_symbol(symbol: &str) -> bool {
200 let bytes = symbol.as_bytes();
201 if bytes.len() < 3 || bytes.len() > 12 {
202 return false;
203 }
204 for byte in bytes.iter() {
205 if (*byte != 45) && (*byte < 65 || *byte > 90) && (*byte < 97 || *byte > 122) {
206 return false;
207 }
208 }
209 true
210}