icon_sdk/
irc2.rs

1use std::error::Error;
2use std::str::FromStr;
3use rust_decimal::Decimal;
4use serde::{Deserialize, Serialize};
5use serde_json::{json, Value};
6use crate::icon_service::IconService;
7use crate::transaction_builder::TransactionBuilder;
8use crate::utils::helpers::icx_to_hex;
9use crate::wallet::Wallet;
10
11#[derive(Default, Serialize, Deserialize)]
12pub struct IRC2 {
13    icon_service: IconService,
14    contract_address: String,
15}
16
17impl IRC2 {
18    pub fn new(icon_service: IconService, contract_address: String) -> Self {
19        Self {
20            icon_service,
21            contract_address,
22        }
23    }
24
25    pub async fn name(&self) -> Result<Value, Box<dyn Error>> {
26        let transaction = TransactionBuilder::new(&self.icon_service)
27            .method("icx_call")
28            .to(&self.contract_address)
29            .call(
30                json!({
31                    "method": "name",
32                })
33            )
34            .build();
35
36        let response: Value = transaction.send().await.map_err(|e| Box::new(e) as Box<dyn Error>)?;
37
38        Ok(response)
39    }
40
41    pub async fn symbol(&self) -> Result<Value, Box<dyn Error>> {
42        let transaction = TransactionBuilder::new(&self.icon_service)
43            .method("icx_call")
44            .to(&self.contract_address)
45            .call(
46                json!({
47                    "method": "symbol",
48                })
49            )
50            .build();
51
52        let response: Value = transaction.send().await.map_err(|e| Box::new(e) as Box<dyn Error>)?;
53
54        Ok(response)
55    }
56
57    pub async fn decimals(&self) -> Result<Value, Box<dyn Error>> {
58        let transaction = TransactionBuilder::new(&self.icon_service)
59            .method("icx_call")
60            .to(&self.contract_address)
61            .call(
62                json!({
63                    "method": "decimals",
64                })
65            )
66            .build();
67
68        let response: Value = transaction.send().await.map_err(|e| Box::new(e) as Box<dyn Error>)?;
69
70        Ok(response)
71    }
72
73    pub async fn total_supply(&self) -> Result<Value, Box<dyn Error>> {
74        let transaction = TransactionBuilder::new(&self.icon_service)
75            .method("icx_call")
76            .to(&self.contract_address)
77            .call(
78                json!({
79                    "method": "totalSupply",
80                })
81            )
82            .build();
83
84        let response: Value = transaction.send().await.map_err(|e| Box::new(e) as Box<dyn Error>)?;
85
86        Ok(response)
87    }
88
89    pub async fn balance_of(&self, account: String) -> Result<Value, Box<dyn Error>> {
90        let transaction = TransactionBuilder::new(&self.icon_service)
91            .method("icx_call")
92            .to(&self.contract_address)
93            .call(
94                json!({
95                    "method": "balanceOf",
96                    "params": {
97                        "_owner": account,
98                    }
99                })
100            )
101            .build();
102
103        let response: Value = transaction.send().await.map_err(|e| Box::new(e) as Box<dyn Error>)?;
104
105        Ok(response)
106    }
107
108    pub async fn transfer(&self, wallet: Wallet, to: &str, value: &str, version: &str, nid: &str, nonce: &str, step_limit: &str) -> Result<Value, Box<dyn Error>> {
109        let mut parsed_value = value.to_string();
110
111        if !parsed_value.starts_with("0x") {
112            match icx_to_hex(Decimal::from_str(value).expect("Invalid value")) {
113                Some(v) => {
114                    parsed_value = v;
115                }
116                None => panic!("Failed to convert value to hex"),
117            }
118        }
119
120        let transaction = TransactionBuilder::new(&self.icon_service)
121            .method("icx_sendTransaction")
122            .from(wallet.get_public_address().as_str())
123            .to(&self.contract_address)
124            .version(version)
125            .nid(nid)
126            .timestamp()
127            .nonce(nonce)
128            .step_limit(step_limit)
129            .call(
130                json!({
131                    "method": "transfer",
132                    "params": {
133                        "_to": to,
134                        "_value": parsed_value,
135                    }
136                })
137            )
138            .sign(wallet.get_private_key().as_str())
139            .build();
140
141        let response: Value = transaction.send().await.map_err(|e| Box::new(e) as Box<dyn Error>)?;
142
143        Ok(response)
144    }
145
146}