1use crate::Result;
4use crate::client::Client;
5use crate::client::config::api_path;
6use crate::client::config::endpoints::tokens::{
7 BURN, GRANT_AUTHORITY, MANAGE_BLACKLIST, MANAGE_WHITELIST, MINT, PAUSE, TOKEN_METADATA,
8 UPDATE_METADATA,
9};
10use crate::crypto::sign_transaction_payload;
11use crate::requests::{
12 BlacklistTokenRequest, BurnTokenRequest, MintTokenRequest, PauseTokenRequest,
13 TokenAuthorityPayload, TokenAuthorityRequest, TokenBlacklistPayload, TokenBurnPayload,
14 TokenMetadataUpdatePayload, TokenMintPayload, TokenPausePayload, TokenWhitelistPayload,
15 UpdateMetadataRequest, WhitelistTokenRequest,
16};
17use crate::responses::MintInfo;
18use crate::responses::TransactionResponse;
19use alloy_primitives::Address;
20
21impl Client {
22 pub async fn mint_token(
33 &self,
34 payload: TokenMintPayload,
35 private_key: &str,
36 ) -> Result<TransactionResponse> {
37 let signature = sign_transaction_payload(&payload, private_key)?;
38 let request = MintTokenRequest { payload, signature };
39
40 self.post(&api_path(MINT), &request).await
41 }
42
43 pub async fn burn_token(
54 &self,
55 payload: TokenBurnPayload,
56 private_key: &str,
57 ) -> Result<TransactionResponse> {
58 let signature = sign_transaction_payload(&payload, private_key)?;
59 let request = BurnTokenRequest { payload, signature };
60
61 self.post(&api_path(BURN), &request).await
62 }
63
64 pub async fn grant_authority(
75 &self,
76 payload: TokenAuthorityPayload,
77 private_key: &str,
78 ) -> Result<TransactionResponse> {
79 let signature = sign_transaction_payload(&payload, private_key)?;
80 let request = TokenAuthorityRequest { payload, signature };
81
82 self.post(&api_path(GRANT_AUTHORITY), &request).await
83 }
84
85 pub async fn revoke_authority(
99 &self,
100 payload: TokenAuthorityPayload,
101 private_key: &str,
102 ) -> Result<TransactionResponse> {
103 let signature = sign_transaction_payload(&payload, private_key)?;
104 let request = TokenAuthorityRequest { payload, signature };
105
106 self.post(&api_path(GRANT_AUTHORITY), &request).await
107 }
108
109 pub async fn get_token_metadata(&self, mint_address: Address) -> Result<MintInfo> {
138 let path = api_path(&format!("{}?token={}", TOKEN_METADATA, mint_address));
139 let response: MintInfo = self.get(&path).await?;
140 Ok(response)
141 }
142
143 pub async fn pause_token(
154 &self,
155 payload: TokenPausePayload,
156 private_key: &str,
157 ) -> Result<TransactionResponse> {
158 let signature = sign_transaction_payload(&payload, private_key)?;
159 let request = PauseTokenRequest { payload, signature };
160
161 self.post(&api_path(PAUSE), &request).await
162 }
163
164 pub async fn manage_blacklist(
175 &self,
176 payload: TokenBlacklistPayload,
177 private_key: &str,
178 ) -> Result<TransactionResponse> {
179 let signature = sign_transaction_payload(&payload, private_key)?;
180 let request = BlacklistTokenRequest { payload, signature };
181
182 self.post(&api_path(MANAGE_BLACKLIST), &request).await
183 }
184
185 pub async fn manage_whitelist(
196 &self,
197 payload: TokenWhitelistPayload,
198 private_key: &str,
199 ) -> Result<TransactionResponse> {
200 let signature = sign_transaction_payload(&payload, private_key)?;
201 let request = WhitelistTokenRequest { payload, signature };
202
203 self.post(&api_path(MANAGE_WHITELIST), &request).await
204 }
205
206 pub async fn update_token_metadata(
217 &self,
218 payload: TokenMetadataUpdatePayload,
219 private_key: &str,
220 ) -> Result<TransactionResponse> {
221 let signature = sign_transaction_payload(&payload, private_key)?;
222 let request = UpdateMetadataRequest { payload, signature };
223
224 self.post(&api_path(UPDATE_METADATA), &request).await
225 }
226}
227
228#[cfg(test)]
229mod tests {
230 use super::*;
231 use crate::{Authority, AuthorityAction, BlacklistAction, PauseAction, WhitelistAction};
232 use alloy_primitives::{Address, U256};
233 use std::str::FromStr;
234
235 #[test]
236 fn test_authority_values() {
237 assert_eq!(
238 serde_json::to_string(&Authority::MasterMintBurn).expect("Test data should be valid"),
239 "\"MasterMintBurn\""
240 );
241 assert_eq!(
242 serde_json::to_string(&Authority::MintBurnTokens).expect("Test data should be valid"),
243 "\"MintBurnTokens\""
244 );
245 assert_eq!(
246 serde_json::to_string(&Authority::Pause).expect("Test data should be valid"),
247 "\"Pause\""
248 );
249 assert_eq!(
250 serde_json::to_string(&Authority::ManageList).expect("Test data should be valid"),
251 "\"ManageList\""
252 );
253 assert_eq!(
254 serde_json::to_string(&Authority::UpdateMetadata).expect("Test data should be valid"),
255 "\"UpdateMetadata\""
256 );
257 }
258
259 #[test]
260 fn test_token_mint_payload_structure() {
261 let address = Address::from_str("0x742d35Cc6634C0532925a3b8D91D6F4A81B8Cbc0")
262 .expect("Test data should be valid");
263 let token = Address::from_str("0x1234567890abcdef1234567890abcdef12345678")
264 .expect("Test data should be valid");
265
266 let payload = TokenMintPayload {
267 recent_epoch: 100,
268 recent_checkpoint: 200,
269 chain_id: 1212101,
270 nonce: 5,
271 recipient: address,
272 value: U256::from(1000000000000000000u64),
273 token,
274 };
275
276 assert_eq!(payload.recent_epoch, 100);
277 assert_eq!(payload.recent_checkpoint, 200);
278 assert_eq!(payload.chain_id, 1212101);
279 assert_eq!(payload.nonce, 5);
280 assert_eq!(payload.recipient, address);
281 assert_eq!(payload.value, U256::from(1000000000000000000u64));
282 assert_eq!(payload.token, token);
283 }
284
285 #[test]
286 fn test_token_burn_payload_structure() {
287 let address = Address::from_str("0x742d35Cc6634C0532925a3b8D91D6F4A81B8Cbc0")
288 .expect("Test data should be valid");
289 let token = Address::from_str("0x1234567890abcdef1234567890abcdef12345678")
290 .expect("Test data should be valid");
291
292 let payload = TokenBurnPayload {
293 recent_epoch: 100,
294 recent_checkpoint: 200,
295 chain_id: 1212101,
296 nonce: 5,
297 recipient: address,
298 value: U256::from(500000000000000000u64),
299 token,
300 };
301
302 assert_eq!(payload.recent_epoch, 100);
303 assert_eq!(payload.recipient, address);
304 assert_eq!(payload.value, U256::from(500000000000000000u64));
305 }
306
307 #[test]
308 fn test_authority_action_serialization() {
309 assert_eq!(
310 serde_json::to_string(&AuthorityAction::Grant).expect("Test data should be valid"),
311 "\"Grant\""
312 );
313 assert_eq!(
314 serde_json::to_string(&AuthorityAction::Revoke).expect("Test data should be valid"),
315 "\"Revoke\""
316 );
317 }
318
319 #[test]
320 fn test_pause_action_serialization() {
321 assert_eq!(
322 serde_json::to_string(&PauseAction::Pause).expect("Test data should be valid"),
323 "\"Pause\""
324 );
325 assert_eq!(
326 serde_json::to_string(&PauseAction::Unpause).expect("Test data should be valid"),
327 "\"Unpause\""
328 );
329 }
330
331 #[test]
332 fn test_blacklist_action_serialization() {
333 assert_eq!(
334 serde_json::to_string(&BlacklistAction::Add).expect("Test data should be valid"),
335 "\"Add\""
336 );
337 assert_eq!(
338 serde_json::to_string(&BlacklistAction::Remove).expect("Test data should be valid"),
339 "\"Remove\""
340 );
341 }
342
343 #[test]
344 fn test_whitelist_action_serialization() {
345 assert_eq!(
346 serde_json::to_string(&WhitelistAction::Add).expect("Test data should be valid"),
347 "\"Add\""
348 );
349 assert_eq!(
350 serde_json::to_string(&WhitelistAction::Remove).expect("Test data should be valid"),
351 "\"Remove\""
352 );
353 }
354
355 #[test]
356 fn test_token_authority_payload_structure() {
357 let authority_address = Address::from_str("0x742d35Cc6634C0532925a3b8D91D6F4A81B8Cbc0")
358 .expect("Test data should be valid");
359 let token = Address::from_str("0x1234567890abcdef1234567890abcdef12345678")
360 .expect("Test data should be valid");
361
362 let payload = TokenAuthorityPayload {
363 recent_epoch: 100,
364 recent_checkpoint: 200,
365 chain_id: 1212101,
366 nonce: 5,
367 action: AuthorityAction::Grant,
368 authority_type: Authority::MintBurnTokens,
369 authority_address,
370 token,
371 value: U256::from(1000000000000000000u64),
372 };
373
374 assert_eq!(payload.action, AuthorityAction::Grant);
375 assert_eq!(payload.authority_type, Authority::MintBurnTokens);
376 assert_eq!(payload.authority_address, authority_address);
377 }
378
379 #[test]
380 fn test_token_pause_payload_structure() {
381 let token = Address::from_str("0x1234567890abcdef1234567890abcdef12345678")
382 .expect("Test data should be valid");
383
384 let payload = TokenPausePayload {
385 recent_epoch: 100,
386 recent_checkpoint: 200,
387 chain_id: 1212101,
388 nonce: 5,
389 action: PauseAction::Pause,
390 token,
391 };
392
393 assert_eq!(payload.action, PauseAction::Pause);
394 assert_eq!(payload.token, token);
395 }
396
397 #[test]
398 fn test_token_blacklist_payload_structure() {
399 let address = Address::from_str("0x742d35Cc6634C0532925a3b8D91D6F4A81B8Cbc0")
400 .expect("Test data should be valid");
401 let token = Address::from_str("0x1234567890abcdef1234567890abcdef12345678")
402 .expect("Test data should be valid");
403
404 let payload = TokenBlacklistPayload {
405 recent_epoch: 100,
406 recent_checkpoint: 200,
407 chain_id: 1212101,
408 nonce: 5,
409 action: BlacklistAction::Add,
410 address,
411 token,
412 };
413
414 assert_eq!(payload.action, BlacklistAction::Add);
415 assert_eq!(payload.address, address);
416 assert_eq!(payload.token, token);
417 }
418
419 #[test]
420 fn test_token_whitelist_payload_structure() {
421 let address = Address::from_str("0x742d35Cc6634C0532925a3b8D91D6F4A81B8Cbc0")
422 .expect("Test data should be valid");
423 let token = Address::from_str("0x1234567890abcdef1234567890abcdef12345678")
424 .expect("Test data should be valid");
425
426 let payload = TokenWhitelistPayload {
427 recent_epoch: 100,
428 recent_checkpoint: 200,
429 chain_id: 1212101,
430 nonce: 5,
431 action: WhitelistAction::Add,
432 address,
433 token,
434 };
435
436 assert_eq!(payload.action, WhitelistAction::Add);
437 assert_eq!(payload.address, address);
438 assert_eq!(payload.token, token);
439 }
440}