Skip to content

Commit

Permalink
Merge pull request #1 from mitsosf/irc2
Browse files Browse the repository at this point in the history
IRC2 support
  • Loading branch information
mitsosf authored Mar 20, 2024
2 parents 57ed01a + 2ebb6b8 commit a394219
Show file tree
Hide file tree
Showing 9 changed files with 334 additions and 46 deletions.
25 changes: 24 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "icon-sdk"
version = "1.1.0"
version = "1.2.0"
edition = "2021"
description = "ICON(ICX) SDK for Rust"
authors = ["Dimitris Frangiadakis <[email protected]>"]
Expand Down
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ Features

- Wallet management
- Read data from the blockchain
- Send transactions
- Send ICX transactions
- Full IRC2 token support
- Perform SCORE calls
- Transaction builder

Expand All @@ -30,7 +31,7 @@ To use the SDK in your Rust project, add the following to your `Cargo.toml`:

```toml
[dependencies]
icon-sdk = "1.1.0"
icon-sdk = "1.2.0"
```

Testing
Expand Down Expand Up @@ -121,6 +122,3 @@ let icon_service = icon_service::IconService::new(Some("https://lisbon.net.solid
### Use the transaction builder
See `icon_service.rs` to see how to use the transaction builder.

Coming soon
--------
- IRC2 token support
146 changes: 146 additions & 0 deletions src/irc2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
use std::error::Error;
use std::str::FromStr;
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use crate::icon_service::IconService;
use crate::transaction_builder::TransactionBuilder;
use crate::utils::helpers::icx_to_hex;
use crate::wallet::Wallet;

#[derive(Default, Serialize, Deserialize)]
pub struct IRC2 {
icon_service: IconService,
contract_address: String,
}

impl IRC2 {
pub fn new(icon_service: IconService, contract_address: String) -> Self {
Self {
icon_service,
contract_address,
}
}

pub async fn name(&self) -> Result<Value, Box<dyn Error>> {
let transaction = TransactionBuilder::new(&self.icon_service)
.method("icx_call")
.to(&self.contract_address)
.call(
json!({
"method": "name",
})
)
.build();

let response: Value = transaction.send().await.map_err(|e| Box::new(e) as Box<dyn Error>)?;

Ok(response)
}

pub async fn symbol(&self) -> Result<Value, Box<dyn Error>> {
let transaction = TransactionBuilder::new(&self.icon_service)
.method("icx_call")
.to(&self.contract_address)
.call(
json!({
"method": "symbol",
})
)
.build();

let response: Value = transaction.send().await.map_err(|e| Box::new(e) as Box<dyn Error>)?;

Ok(response)
}

pub async fn decimals(&self) -> Result<Value, Box<dyn Error>> {
let transaction = TransactionBuilder::new(&self.icon_service)
.method("icx_call")
.to(&self.contract_address)
.call(
json!({
"method": "decimals",
})
)
.build();

let response: Value = transaction.send().await.map_err(|e| Box::new(e) as Box<dyn Error>)?;

Ok(response)
}

pub async fn total_supply(&self) -> Result<Value, Box<dyn Error>> {
let transaction = TransactionBuilder::new(&self.icon_service)
.method("icx_call")
.to(&self.contract_address)
.call(
json!({
"method": "totalSupply",
})
)
.build();

let response: Value = transaction.send().await.map_err(|e| Box::new(e) as Box<dyn Error>)?;

Ok(response)
}

pub async fn balance_of(&self, account: String) -> Result<Value, Box<dyn Error>> {
let transaction = TransactionBuilder::new(&self.icon_service)
.method("icx_call")
.to(&self.contract_address)
.call(
json!({
"method": "balanceOf",
"params": {
"_owner": account,
}
})
)
.build();

let response: Value = transaction.send().await.map_err(|e| Box::new(e) as Box<dyn Error>)?;

Ok(response)
}

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>> {
let mut parsed_value = value.to_string();

if !parsed_value.starts_with("0x") {
match icx_to_hex(Decimal::from_str(value).expect("Invalid value")) {
Some(v) => {
parsed_value = v;
}
None => panic!("Failed to convert value to hex"),
}
}

let transaction = TransactionBuilder::new(&self.icon_service)
.method("icx_sendTransaction")
.from(wallet.get_public_address().as_str())
.to(&self.contract_address)
.version(version)
.nid(nid)
.timestamp()
.nonce(nonce)
.step_limit(step_limit)
.call(
json!({
"method": "transfer",
"params": {
"_to": to,
"_value": parsed_value,
}
})
)
.sign(wallet.get_private_key().as_str())
.build();

let response: Value = transaction.send().await.map_err(|e| Box::new(e) as Box<dyn Error>)?;

Ok(response)
}

}
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ pub mod utils;
pub mod icon_service;
pub mod transaction;
pub mod wallet;
mod transaction_builder;
pub mod transaction_builder;
pub mod irc2;
30 changes: 30 additions & 0 deletions tests/test_helpers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use std::str::FromStr;
use rust_decimal::Decimal;
use icon_sdk::utils::helpers;

#[tokio::test]
async fn test_hex_to_icx() -> Result<(), ()> {
let res = helpers::hex_to_icx("0x63b5429420c741b16a10f");
match res {
Some(response) => {
assert_eq!(response.to_string(), "7533727.039631672546337039");
},
None => panic!("Error"),
}

Ok(())
}

#[tokio::test]
async fn test_icx_to_hex() -> Result<(), ()> {
let res = helpers::icx_to_hex(Decimal::from_str("7533727.039631672546337039").unwrap());
match res {
Some(response) => {
assert_eq!(response, "0x63b5429420c741b16a10f");
println!("{:?}", response);
},
None => panic!("Error"),
}

Ok(())
}
38 changes: 0 additions & 38 deletions tests/test.rs → tests/test_iconservice.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use std::str::FromStr;
use rust_decimal::Decimal;
use serde_json::json;
use icon_sdk::icon_service;
use icon_sdk::utils::helpers;
use icon_sdk::wallet::Wallet;

#[tokio::test]
Expand Down Expand Up @@ -124,33 +121,6 @@ async fn test_call() -> Result<(), ()> {
Ok(())
}

#[tokio::test]
async fn test_hex_to_icx() -> Result<(), ()> {
let res = helpers::hex_to_icx("0x63b5429420c741b16a10f");
match res {
Some(response) => {
assert_eq!(response.to_string(), "7533727.039631672546337039");
},
None => panic!("Error"),
}

Ok(())
}

#[tokio::test]
async fn test_icx_to_hex() -> Result<(), ()> {
let res = helpers::icx_to_hex(Decimal::from_str("7533727.039631672546337039").unwrap());
match res {
Some(response) => {
assert_eq!(response, "0x63b5429420c741b16a10f");
println!("{:?}", response);
},
None => panic!("Error"),
}

Ok(())
}

#[tokio::test]
async fn test_send_transaction() -> Result<(), ()> {
let wallet = Wallet::new(Some("f4ade1ff528c9e0bf10d35909e3486ef6ce88df8a183fc1cc2c65bfa9a53d3fd".to_string()));
Expand Down Expand Up @@ -205,11 +175,3 @@ async fn test_send_transaction_with_message() -> Result<(), ()> {

Ok(())
}

#[tokio::test]
async fn test_wallet() -> Result<(), ()> {
let wallet = Wallet::new(Some("f4ade1ff528c9e0bf10d35909e3486ef6ce88df8a183fc1cc2c65bfa9a53d3fd".to_string()));
assert_eq!(wallet.get_public_address(), "hxb14e0c751899676a1a4e655a34063b42260f844b");

Ok(())
}
Loading

0 comments on commit a394219

Please sign in to comment.