1use crate::{
3 Aptos,
4 global::mainnet::{
5 sys_address::X_3,
6 sys_module::{
7 self,
8 token::{
9 collections, create_collection_script, create_token_script, token_store,
10 transfer_script,
11 },
12 },
13 },
14 types::ContractCall,
15 wallet::Wallet,
16};
17use serde_json::{Value, json};
18use std::sync::Arc;
19
20pub struct NFTManager;
21
22impl NFTManager {
23 pub async fn create_nft_collection(
25 client: Arc<Aptos>,
26 wallet: Arc<Wallet>,
27 name: &str,
28 description: &str,
29 uri: &str,
30 max_amount: Option<u64>,
31 ) -> Result<Value, String> {
32 let contract_call = ContractCall {
33 module_address: X_3.to_string(),
34 module_name: sys_module::token::name.to_string(),
35 function_name: create_collection_script.to_string(),
36 type_arguments: vec![],
37 arguments: vec![
38 json!(name),
39 json!(description),
40 json!(uri),
41 json!(max_amount.unwrap_or(u64::MAX).to_string()),
42 json!(false), ],
44 };
45 crate::contract::Contract::write(client, wallet, contract_call)
46 .await
47 .map(|result| json!(result))
48 }
49
50 pub async fn create_nft(
52 client: Arc<Aptos>,
53 wallet: Arc<Wallet>,
54 collection: &str,
55 name: &str,
56 description: &str,
57 supply: u64,
58 uri: &str,
59 royalty_points_per_million: u64,
60 ) -> Result<Value, String> {
61 let contract_call = ContractCall {
62 module_address: X_3.to_string(),
63 module_name: sys_module::token::name.to_string(),
64 function_name: create_token_script.to_string(),
65 type_arguments: vec![],
66 arguments: vec![
67 json!(collection),
68 json!(name),
69 json!(description),
70 json!(supply.to_string()),
71 json!(supply.to_string()), json!(uri),
73 json!(wallet.address().map_err(|e| e.to_string())?), json!(royalty_points_per_million.to_string()),
75 json!(0u64.to_string()), json!(vec![] as Vec<Value>), json!(vec![] as Vec<Value>), json!(vec![] as Vec<Value>), ],
80 };
81 crate::contract::Contract::write(client, wallet, contract_call)
82 .await
83 .map(|result| json!(result))
84 }
85
86 pub async fn transfer_nft(
88 client: Arc<Aptos>,
89 wallet: Arc<Wallet>,
90 token_id: &str,
91 recipient: &str,
92 ) -> Result<Value, String> {
93 let contract_call = ContractCall {
94 module_address: X_3.to_string(),
95 module_name: sys_module::token::name.to_string(),
96 function_name: transfer_script.to_string(),
97 type_arguments: vec![],
98 arguments: vec![
99 json!(recipient),
100 json!(token_id),
101 json!(1u64.to_string()), ],
103 };
104 crate::contract::Contract::write(client, wallet, contract_call)
105 .await
106 .map(|result| json!(result))
107 }
108
109 pub async fn get_nft_balance(
111 client: Arc<Aptos>,
112 address: &str,
113 token_id: &str,
114 ) -> Result<u64, String> {
115 let resource_type = format!("{}", token_store);
116 if let Some(resource) = client.get_account_resource(address, &resource_type).await? {
117 Ok(resource
118 .data
119 .get("tokens")
120 .and_then(|t| t.as_object())
121 .and_then(|t| t.get(token_id))
122 .and_then(|t| t.get("amount"))
123 .and_then(|a| a.as_str())
124 .and_then(|a| a.parse().ok())
125 .unwrap_or(0))
126 } else {
127 Ok(0)
128 }
129 }
130
131 pub async fn get_nft_metedata(
133 client: Arc<Aptos>,
134 creator: &str,
135 collection: &str,
136 name: &str,
137 ) -> Result<Value, String> {
138 let resource_type = format!("{}", collections);
139 if let Some(resource) = client.get_account_resource(creator, &resource_type).await? {
140 Ok(resource
141 .data
142 .get("token_data")
143 .cloned()
144 .unwrap_or(Value::Null))
145 } else {
146 Ok(Value::Null)
147 }
148 }
149}