Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement colony chain #42

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions colony-chain/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ rust_decimal = "1.25.0"
rust_decimal_macros = "1.25.0"
pdao-colony-common = { version = "0.0.0" }
pdao-colony-contract-common = { version = "0.0.0" }
pdao-cosmos-interact = { path = "../interact"}
pdao-cosmos-light-client = {path = "../contracts/light-client"}
serde-tc = "0.3.3"
serde_json = { version = "1.0" }
anyhow = { version = "1.0" }
cosmwasm-std = "1.0.0"
base64 = "0.13.0"
96 changes: 86 additions & 10 deletions colony-chain/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
use async_trait::async_trait;
use pdao_colony_common::*;
use pdao_colony_contract_common::*;
use pdao_cosmos_interact::{execute, query};
use rust_decimal::prelude::*;
use rust_decimal_macros::dec;

use serde_json::json;
use std::collections::HashMap;

pub struct Juno {}
pub struct Juno {
pub full_node_url: String,
pub rpc_url: String,
pub treasury_address: String,
pub lightclient_address: String,
pub relayer_account: String,

pub chain_id: String,
pub denom: String,
pub mnemonic: String,
pub password: String,
pub account_prefix: String,
}

#[async_trait]
impl ColonyChain for Juno {
Expand All @@ -14,37 +29,72 @@ impl ColonyChain for Juno {
}

async fn get_last_block(&self) -> Result<Block, Error> {
Ok(Block {
height: 0,
timestamp: 0,
})
let height = query::get_latest_block_height(&self.rpc_url)
.await
.map_err(|_| Error::ConnectionError("test".to_string()))?; //TODO: error message

let timestamp = query::get_latest_block_timestamp(&self.rpc_url)
.await
.map_err(|_| Error::ConnectionError("test".to_string()))?; //TODO: error message

Ok(Block { height, timestamp })
}

async fn check_connection(&self) -> Result<(), Error> {
let _height = query::get_latest_block_height(&self.rpc_url)
.await
.map_err(|_| Error::ConnectionError("test".to_string()))?; //TODO: error message

Ok(())
}

async fn get_contract_list(&self) -> Result<Vec<ContractInfo>, Error> {
Ok(vec![
ContractInfo {
address: "0xabcd".to_owned(),
address: self.lightclient_address.clone(),
contract_type: ContractType::LightClient,
sequence: 0,
},
ContractInfo {
address: "0x1234".to_owned(),
address: self.treasury_address.clone(),
contract_type: ContractType::Treasury,
sequence: 0,
},
])
}

async fn get_relayer_account_info(&self) -> Result<(String, Decimal), Error> {
Ok(("0x12341234".to_owned(), dec!(12.34)))
let res = query::get_balance_amount(&self.full_node_url, &self.relayer_account)
.await
.map_err(|_| Error::ConnectionError("test".to_string()))?; //TODO: error message

let balance = Decimal::from_str(res.as_ref())
.map_err(|_| Error::ConnectionError("test".to_string()))?; //TODO: error message

Ok((self.relayer_account.to_owned(), balance))
}

async fn get_light_client_header(&self) -> Result<Header, Error> {
Ok("Hmm".to_owned())
let msg = json!({
"get_header": {}
});

let encode_msg = base64::encode(
&serde_json::to_vec(&msg)
.map_err(|_| Error::InvalidMessageArgument("test".to_string()))?,
); //TODO: error message

let response = query::send_query(
&self.full_node_url,
&self.lightclient_address,
encode_msg.as_str(),
)
.await
.map_err(|_| Error::ConnectionError("test".to_string()))?; //TODO: error message

let header = response["data"]["header"].to_string(); //TODO: current type of header is string

Ok(header)
}

async fn get_treasury_fungible_token_balance(&self) -> Result<HashMap<String, Decimal>, Error> {
Expand All @@ -66,7 +116,33 @@ impl ColonyChain for Juno {
}

async fn update_light_client(&self, _message: LightClientUpdateMessage) -> Result<(), Error> {
Ok(())
let msg = json!({
"update": {
"header": _message.header,
"proof": _message.proof
}
});

let execute_msg =
serde_json::to_vec(&msg).map_err(|_| Error::ConnectionError("test".to_string()))?; //TODO: error type and message

execute::send_execute(
self.mnemonic.clone(),
&self.password,
&self.chain_id,
&self.rpc_url,
&self.full_node_url,
&self.denom,
&self.account_prefix,
10000, //TODO: fix
&self.lightclient_address,
execute_msg,
2000000, //TODO: fix
2000000, //TODO: fix
None,
)
.await
.map_err(|_| pdao_colony_common::Error::TransactionRejected("test".to_string()))
}

async fn transfer_treasury_fungible_token(
Expand Down
13 changes: 12 additions & 1 deletion colony-chain/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,18 @@ async fn main() {
port,
vec![(
"juno".to_owned(),
serde_tc::http::create_http_object(Arc::new(Juno {}) as Arc<dyn ColonyChain>),
serde_tc::http::create_http_object(Arc::new(Juno {
full_node_url: "https://lcd.uni.juno.deuslabs.fi".to_string(),
rpc_url: "https://rpc.uni.juno.deuslabs.fi".to_string(),
treasury_address: "".to_string(),
lightclient_address: "".to_string(),
relayer_account: "".to_string(),
chain_id: "".to_string(),
denom: "".to_string(),
mnemonic: "".to_string(),
password: "".to_string(),
account_prefix: "".to_string(),
}) as Arc<dyn ColonyChain>),
)]
.into_iter()
.collect(),
Expand Down
21 changes: 15 additions & 6 deletions interact/src/execute.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use cosmrs::{
crypto, dev, rpc,
dev, rpc,
tx::{self, Fee, Msg, SignDoc, SignerInfo},
Coin,
};

use super::query::{get_account_number, get_sequence_number};
use super::utils::private_to_pub_and_account;
use super::utils::{mnemonic_to_private_key, private_to_pub_and_account};
use std::error::Error;

#[allow(clippy::too_many_arguments)]
pub async fn send_execute(
sender_private_key: &crypto::secp256k1::SigningKey,
mnemonic: String,
password: &str,
chain_id: &str,
rpc_address: &str,
api_address: &str,
Expand All @@ -23,8 +24,12 @@ pub async fn send_execute(
gas_limit: u64,
tx_memo: Option<&str>,
) -> Result<(), Box<dyn Error>> {
let (sender_public_key, sender_account_id) =
private_to_pub_and_account(sender_private_key, account_id)?;
let (sender_public_key, sender_account_id) = {
let sender_private_key = mnemonic_to_private_key(mnemonic.clone(), password)
.unwrap()
.into();
private_to_pub_and_account(&sender_private_key, account_id)?
};

let funds = Coin {
amount: funds.into(),
Expand Down Expand Up @@ -54,7 +59,11 @@ pub async fn send_execute(
SignerInfo::single_direct(Some(sender_public_key), sequence_number).auth_info(fee);
let account_number = get_account_number(api_address, sender_account_id.as_ref()).await?;
let sign_doc = SignDoc::new(&tx_body, &auth_info, &chain_id, account_number)?;
let tx_raw = sign_doc.sign(sender_private_key)?;

let tx_raw = {
let sender_private_key = mnemonic_to_private_key(mnemonic, password).unwrap().into();
sign_doc.sign(&sender_private_key)?
};

let rpc_address = rpc_address.to_owned();
let rpc_client = rpc::HttpClient::new(rpc_address.as_str())?;
Expand Down
49 changes: 49 additions & 0 deletions interact/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,55 @@ pub async fn send_query(
Ok(result)
}

pub async fn get_balance_amount(
rest_api_endpoint: &str,
account_address: &str,
) -> Result<String, Box<dyn Error>> {
let client = reqwest::Client::new();
let response = request(
&client,
&format!(
"{}/cosmos/bank/v1beta1/balances/{}",
rest_api_endpoint, account_address
),
None,
)
.await?;

let current_balance = response["balances"]
.as_array()
.ok_or("Failed to convert balance to array")?[0]["amount"]
.to_string();

Ok(current_balance)
}

pub async fn get_latest_block_height(rest_api_endpoint: &str) -> Result<u64, Box<dyn Error>> {
let client = reqwest::Client::new();

let response = request(&client, &format!("{}/status?", rest_api_endpoint), None).await?;

let latest_block_height = response["result"]["sync_info"]["latest_block_height"]
.as_str()
.ok_or("Failed to convert code id to &str")?
.parse::<u64>()?;

Ok(latest_block_height)
}

pub async fn get_latest_block_timestamp(rest_api_endpoint: &str) -> Result<u64, Box<dyn Error>> {
let client = reqwest::Client::new();

let response = request(&client, &format!("{}/status?", rest_api_endpoint), None).await?;

let latest_block_timestamp = response["result"]["sync_info"]["latest_block_time"]
.as_str()
.ok_or("Failed to convert code id to &str")?
.parse::<u64>()?;

Ok(latest_block_timestamp)
}

pub async fn get_code_id(
rest_api_endpoint: &str,
contract_address: &str,
Expand Down
21 changes: 6 additions & 15 deletions interact/tests/suite1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,17 +178,14 @@ async fn test_execute_increment_fail() {
);
let _config = Config::read_from_path(full_path);

let sender_private_key = mnemonic_to_private_key(_config.mnemonic, &_config.password)
.unwrap()
.into();

// This should be failed since the count is above 10
let msg = json!({
"increment": {"count": 20u64}
});

let _result = execute::send_execute(
&sender_private_key,
_config.mnemonic.clone(),
&_config.password,
&_config.chain_id,
&_config.rpc,
&_config.full_node_url,
Expand All @@ -215,16 +212,13 @@ async fn test_execute_increment() {
);
let _config = Config::read_from_path(full_path);

let sender_private_key = mnemonic_to_private_key(_config.mnemonic, &_config.password)
.unwrap()
.into();

let msg = json!({
"increment": {"count": 5u64}
});

let _result = execute::send_execute(
&sender_private_key,
_config.mnemonic.clone(),
&_config.password,
&_config.chain_id,
&_config.rpc,
&_config.full_node_url,
Expand All @@ -251,16 +245,13 @@ async fn test_execute_reset() {
);
let _config = Config::read_from_path(full_path);

let sender_private_key = mnemonic_to_private_key(_config.mnemonic, &_config.password)
.unwrap()
.into();

let msg = json!({
"reset": {"count": 50u64}
});

let _result = execute::send_execute(
&sender_private_key,
_config.mnemonic.clone(),
&_config.password,
&_config.chain_id,
&_config.rpc,
&_config.full_node_url,
Expand Down