1#![allow(clippy::field_reassign_with_default)] use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5
6use crate::pubkey_to_account;
7use cosmwasm_std::{Binary, CanonicalAddr, HumanAddr, Uint128};
8
9#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
10#[serde(rename_all = "snake_case")]
11pub struct Permit<Permission: Permissions = TokenPermissions> {
12 #[serde(bound = "")]
13 pub params: PermitParams<Permission>,
14 pub signature: PermitSignature,
15}
16
17impl<Permission: Permissions> Permit<Permission> {
18 pub fn check_token(&self, token: &HumanAddr) -> bool {
19 self.params.allowed_tokens.contains(token)
20 }
21
22 pub fn check_permission(&self, permission: &Permission) -> bool {
23 self.params.permissions.contains(permission)
24 }
25}
26
27#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
28#[serde(rename_all = "snake_case")]
29pub struct PermitParams<Permission: Permissions = TokenPermissions> {
30 pub allowed_tokens: Vec<HumanAddr>,
31 pub permit_name: String,
32 pub chain_id: String,
33 #[serde(bound = "")]
34 pub permissions: Vec<Permission>,
35}
36
37#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
38#[serde(rename_all = "snake_case")]
39pub struct PermitSignature {
40 pub pub_key: PubKey,
41 pub signature: Binary,
42}
43
44#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
45#[serde(rename_all = "snake_case")]
46pub struct PubKey {
47 pub r#type: String,
49 pub value: Binary,
51}
52
53impl PubKey {
54 pub fn canonical_address(&self) -> CanonicalAddr {
55 pubkey_to_account(&self.value)
56 }
57}
58
59#[remain::sorted]
61#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
62#[serde(rename_all = "snake_case")]
63pub struct SignedPermit<Permission: Permissions = TokenPermissions> {
64 pub account_number: Uint128,
66 pub chain_id: String,
68 pub fee: Fee,
70 pub memo: String,
72 #[serde(bound = "")]
74 pub msgs: Vec<PermitMsg<Permission>>,
75 pub sequence: Uint128,
77}
78
79impl<Permission: Permissions> SignedPermit<Permission> {
80 pub fn from_params(params: &PermitParams<Permission>) -> Self {
81 Self {
82 account_number: Uint128::zero(),
83 chain_id: params.chain_id.clone(),
84 fee: Fee::new(),
85 memo: String::new(),
86 msgs: vec![PermitMsg::from_content(PermitContent::from_params(params))],
87 sequence: Uint128::zero(),
88 }
89 }
90}
91
92#[remain::sorted]
94#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
95#[serde(rename_all = "snake_case")]
96pub struct Fee {
97 pub amount: Vec<Coin>,
98 pub gas: Uint128,
99}
100
101impl Fee {
102 pub fn new() -> Self {
103 Self {
104 amount: vec![Coin::new()],
105 gas: Uint128(1),
106 }
107 }
108}
109
110impl Default for Fee {
111 fn default() -> Self {
112 Self::new()
113 }
114}
115
116#[remain::sorted]
118#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
119#[serde(rename_all = "snake_case")]
120pub struct Coin {
121 pub amount: Uint128,
122 pub denom: String,
123}
124
125impl Coin {
126 pub fn new() -> Self {
127 Self {
128 amount: Uint128::zero(),
129 denom: "uscrt".to_string(),
130 }
131 }
132}
133
134impl Default for Coin {
135 fn default() -> Self {
136 Self::new()
137 }
138}
139
140#[remain::sorted]
142#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
143#[serde(rename_all = "snake_case")]
144pub struct PermitMsg<Permission: Permissions = TokenPermissions> {
145 pub r#type: String,
146 #[serde(bound = "")]
147 pub value: PermitContent<Permission>,
148}
149
150impl<Permission: Permissions> PermitMsg<Permission> {
151 pub fn from_content(content: PermitContent<Permission>) -> Self {
152 Self {
153 r#type: "query_permit".to_string(),
154 value: content,
155 }
156 }
157}
158
159#[remain::sorted]
161#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
162#[serde(rename_all = "snake_case")]
163pub struct PermitContent<Permission: Permissions = TokenPermissions> {
164 pub allowed_tokens: Vec<HumanAddr>,
165 #[serde(bound = "")]
166 pub permissions: Vec<Permission>,
167 pub permit_name: String,
168}
169
170impl<Permission: Permissions> PermitContent<Permission> {
171 pub fn from_params(params: &PermitParams<Permission>) -> Self {
172 Self {
173 allowed_tokens: params.allowed_tokens.clone(),
174 permit_name: params.permit_name.clone(),
175 permissions: params.permissions.clone(),
176 }
177 }
178}
179
180pub trait Permissions:
184Clone + PartialEq + Serialize + for<'d> Deserialize<'d> + JsonSchema
185{
186}
187
188impl<T> Permissions for T where
189 T: Clone + PartialEq + Serialize + for<'d> Deserialize<'d> + JsonSchema
190{
191}
192
193#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
194#[serde(rename_all = "snake_case")]
195pub enum TokenPermissions {
196 Allowance,
198 Balance,
200 History,
202 Owner,
210}