diff --git a/demos/rust-cosmos-broadcaster-client/Cargo.toml b/demos/rust-cosmos-broadcaster-client/Cargo.toml deleted file mode 100644 index fb3f6d1764..0000000000 --- a/demos/rust-cosmos-broadcaster-client/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "rust-cosmos-broadcaster-client" -version = "0.1.0" -authors.workspace = true -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -clap = { version = "4.0", features = ["derive"] } -nym-bin-common = { path = "../../common/bin-common"} -nym-sphinx-addressing = { path = "../../common/nymsphinx/addressing" } -nym-sdk = { path = "../../sdk/rust/nym-sdk" } -nym-crypto = { path = "../../common/crypto" } -nym-cli-commands = { path = "../../common/commands" } -nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] } -nym-network-defaults = { path = "../../common/network-defaults" } -async-trait = { workspace = true, optional = true } -bip39 = { workspace = true, features = ["rand"] } -cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support", features = ["rpc", "bip32", "cosmwasm"] } -tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] } -ts-rs = "6.1.2" -bs58 = "0.5.0" -serde = { workspace = true, features = ["derive"] } -serde_json = { workspace = true } -anyhow.workspace = true diff --git a/demos/rust-cosmos-broadcaster-client/README.md b/demos/rust-cosmos-broadcaster-client/README.md deleted file mode 100644 index 8429ffe82a..0000000000 --- a/demos/rust-cosmos-broadcaster-client/README.md +++ /dev/null @@ -1,3 +0,0 @@ -cosmos broadcaster client code - sign txs offline and send thru the mixnet! - -heavily pulling from the offline_signing.rs example file in the validator client code (s/o Jon for writing top examples) & the nym-cli tool (:hattip: mr vez) \ No newline at end of file diff --git a/demos/rust-cosmos-broadcaster-client/src/commands/commands.rs b/demos/rust-cosmos-broadcaster-client/src/commands/commands.rs deleted file mode 100644 index 69a841eaa7..0000000000 --- a/demos/rust-cosmos-broadcaster-client/src/commands/commands.rs +++ /dev/null @@ -1,121 +0,0 @@ -use nym_sphinx_addressing::clients::Recipient; -use nym_validator_client::signing::direct_wallet::DirectSecp256k1HdWallet; -use nym_validator_client::signing::tx_signer::TxSigner; -use nym_validator_client::signing::SignerData; -use nym_validator_client::nyxd::cosmwasm_client::types; -use cosmrs::bank::MsgSend; -use cosmrs::tx::Msg; -use cosmrs::{tx, AccountId, Coin, Denom}; -use bip39; -use bs58; -use nym_sdk::mixnet::{self, MixnetClient, ReconstructedMessage}; -use crate::commands::reqres::{SequenceRequest, ResponseTypes, self, BroadcastRequest}; - -pub async fn offline_sign(mnemonic: bip39::Mnemonic, to: AccountId, client: &mut MixnetClient , sp_address: Recipient) -> String { - - // TODO take coin amount from function args, + load network vars from config file. - let prefix = "n"; - let denom: Denom = "unym".parse().unwrap(); - let validator = String::from("https://qwerty-validator.qa.nymte.ch"); - - let signer = DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic.clone()); - let signer_address = signer.try_derive_accounts().unwrap()[0].address().clone(); - - // local 'client' ONLY signing messages - let tx_signer = TxSigner::new(signer); - - let message = SequenceRequest{ - validator, - signer_address, - }; - - // send req to client - client.send_str(sp_address, &serde_json::to_string(&message).unwrap()).await; - - // handle incoming message - we presume its a reply from the SP - let mut message: Vec = Vec::new(); - - // get the actual message - discard the empty vec sent along with the SURB request - while let Some(new_message) = client.wait_for_messages().await { - if new_message.is_empty() { - continue; - } println!("got a response"); - message = new_message; - break - } - - // convert from vec -> JSON String - let mut parsed = String::new(); - for r in message.iter() { - parsed = String::from_utf8(r.message.clone()).unwrap(); - break - }; - let sp_response: ResponseTypes = serde_json::from_str(&parsed).unwrap(); - - let res = match sp_response { - reqres::ResponseTypes::Sequence(request) => { - println!("got a response to the chain sequence request. using this to sign our tx offline"); - - // use the response to create SignerData instance - let sequence_response = types::SequenceResponse { - account_number: request.account_number, - sequence: request.sequence - }; - let signer_data = SignerData::new_from_sequence_response( sequence_response, request.chain_id); - - // create (and sign) the send message - let amount = vec![Coin { - denom: denom.clone(), - amount: 12345u32.into(), - }]; - - // TODO there must be a better way of doing this instead of re-generating the signer address from the mnemonic twice - let signer = DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic.clone()); - let signer_address = signer.try_derive_accounts().unwrap()[0].address().clone(); - - let send_msg = MsgSend { - from_address: signer_address.clone(), - to_address: to.clone(), - amount, - } - .to_any() - .unwrap(); - - let memo = "example memo"; - let fee = tx::Fee::from_amount_and_gas( - Coin { - denom, - amount: 2500u32.into(), - }, - 100000, - ); - - let tx_raw = tx_signer - .sign_direct(&signer_address, vec![send_msg], fee, memo, signer_data) - .unwrap(); - - let tx_bytes = tx_raw.to_bytes().unwrap(); - let base58_tx_bytes = bs58::encode(tx_bytes).into_string(); - base58_tx_bytes - }, - // TODO make this a proper error - _ => { println!("weird response"); String::from("placeholder error") } - }; - - res - -} - -pub async fn send_tx(base58_tx: String, sp_address: Recipient, client: &mut MixnetClient) -> Option> { - - let broadcast_request = BroadcastRequest { - base58_tx_bytes: base58_tx - }; - - client.send_str(sp_address, &serde_json::to_string(&broadcast_request).unwrap()).await; - - println!("\nWaiting for reply\n"); - - let res = client.wait_for_messages().await; - res -} diff --git a/demos/rust-cosmos-broadcaster-client/src/commands/commands/reqres.rs b/demos/rust-cosmos-broadcaster-client/src/commands/commands/reqres.rs deleted file mode 100644 index 31cf148c83..0000000000 --- a/demos/rust-cosmos-broadcaster-client/src/commands/commands/reqres.rs +++ /dev/null @@ -1,39 +0,0 @@ -use serde::{Deserialize, Serialize}; -use cosmrs::{AccountId, tendermint}; - -#[derive(Deserialize, Serialize, Debug)] -pub struct SequenceRequest { - pub validator: String, - pub signer_address: AccountId, -} - -#[derive(Deserialize, Serialize, Debug)] -pub struct SequenceRequestResponse { - pub account_number: u64, - pub sequence: u64, - pub chain_id: tendermint::chain::Id -} -#[derive(Deserialize, Serialize, Debug)] -pub struct BroadcastRequest { - pub base58_tx_bytes: String -} - -#[derive(Deserialize, Serialize, Debug)] -pub struct BroadcastResponse{ - pub tx_hash: String -} - -#[derive(Debug, Deserialize, Serialize)] -#[serde(untagged)] -pub enum RequestTypes { - Sequence(SequenceRequest), - Broadcast(BroadcastRequest) -} - -#[derive(Debug, Deserialize, Serialize)] -#[serde(untagged)] -pub enum ResponseTypes { - Sequence(SequenceRequestResponse), - Broadcast(BroadcastResponse) -} - diff --git a/demos/rust-cosmos-broadcaster-client/src/commands/mod.rs b/demos/rust-cosmos-broadcaster-client/src/commands/mod.rs deleted file mode 100644 index b4eb760edf..0000000000 --- a/demos/rust-cosmos-broadcaster-client/src/commands/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod reqres; -pub mod commands; diff --git a/demos/rust-cosmos-broadcaster-client/src/commands/reqres.rs b/demos/rust-cosmos-broadcaster-client/src/commands/reqres.rs deleted file mode 100644 index 31cf148c83..0000000000 --- a/demos/rust-cosmos-broadcaster-client/src/commands/reqres.rs +++ /dev/null @@ -1,39 +0,0 @@ -use serde::{Deserialize, Serialize}; -use cosmrs::{AccountId, tendermint}; - -#[derive(Deserialize, Serialize, Debug)] -pub struct SequenceRequest { - pub validator: String, - pub signer_address: AccountId, -} - -#[derive(Deserialize, Serialize, Debug)] -pub struct SequenceRequestResponse { - pub account_number: u64, - pub sequence: u64, - pub chain_id: tendermint::chain::Id -} -#[derive(Deserialize, Serialize, Debug)] -pub struct BroadcastRequest { - pub base58_tx_bytes: String -} - -#[derive(Deserialize, Serialize, Debug)] -pub struct BroadcastResponse{ - pub tx_hash: String -} - -#[derive(Debug, Deserialize, Serialize)] -#[serde(untagged)] -pub enum RequestTypes { - Sequence(SequenceRequest), - Broadcast(BroadcastRequest) -} - -#[derive(Debug, Deserialize, Serialize)] -#[serde(untagged)] -pub enum ResponseTypes { - Sequence(SequenceRequestResponse), - Broadcast(BroadcastResponse) -} - diff --git a/demos/rust-cosmos-broadcaster-client/src/main.rs b/demos/rust-cosmos-broadcaster-client/src/main.rs deleted file mode 100644 index 674e50b74b..0000000000 --- a/demos/rust-cosmos-broadcaster-client/src/main.rs +++ /dev/null @@ -1,97 +0,0 @@ -use std::path::PathBuf; -use clap::{ Parser, Subcommand, Args}; -use nym_sdk::mixnet::{Recipient, MixnetClientBuilder, StoragePaths}; -use nym_validator_client::nyxd::AccountId; -use nym_bin_common::logging::setup_logging; -mod commands; - -#[derive(Debug, Parser)] -#[clap(name = "nym cosmos tx signer ")] -#[clap(about = "demo binary with which users can perform offline signing and transmission of signed tx to broadcaster via the mixnet ")] -struct Cli { - // TODO make this import from file & remove from cli args - // #[clap(long, global = true)] - // #[clap( - // help = "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC." - // )] - // mnemonic: Option, - - // TODO add SP address - - #[clap(subcommand)] - command: Option, -} - -#[derive(Debug, Subcommand)] -enum Commands { - /// sign a transaction offline - OfflineSignTx(OfflineSignTx), - /// send signed tx to SP for broadcast - SendTx(SendTx) -} - -#[derive(Debug, Clone, Args)] -struct OfflineSignTx { - /// mnemonic of signing + sending account (you!) - TODO this will be removed and replaced with file - mnemonic: bip39::Mnemonic, - /// recipient nyx chain address for token transfer - nyx_token_receipient: AccountId -} - -#[derive(Debug, Args)] -struct SendTx { - /// the base58 encoded signed payload created in OfflineSign() - base58_payload: String, - /// the nym address of the broadcaster service provider - sp_address: Recipient -} - -#[tokio::main] -async fn main() { - // setup_logging(); - let cli = Cli::parse(); - // TODO look @ arg env setup from NR main.rs - // TODO take from args - let sp_address = Recipient::try_from_base58_string("HfbesQm2pRYCN4BAdYXhkqXBbV1Pp929mtKsESVeWXh8.8AgoUPUQbXNBCPaqAaWd3vnxhc9484qwfgrrQwBngQk2@Ck8zpXTSXMtS9YZ7k7a5BiaoLZfffWuqGWLndujh4Lw4").unwrap(); - let config_dir = PathBuf::from("/tmp/cosmos-broadcaster-mixnet-client-2"); - let storage_paths = StoragePaths::new_from_dir(&config_dir).unwrap(); - let client = MixnetClientBuilder::new_with_default_storage(storage_paths) - .await - .unwrap() - .build() - .await - .unwrap(); - let mut client = client.connect_to_mixnet().await.unwrap(); - let our_address = client.nym_address(); - println!("\nOur client nym address is: {our_address}"); - - match &cli.command { - Some(Commands::OfflineSignTx(OfflineSignTx { mnemonic, nyx_token_receipient} )) => { - println!("sending offline sign info"); - let base58_tx_bytes = commands::commands::offline_sign(mnemonic.clone(), nyx_token_receipient.clone(), &mut client, sp_address.clone()).await; - - println!("base58 encoded signed tx payload: \n\n{}\n\n", &base58_tx_bytes); - println!("do you wish to send the tx? y/n"); - - let mut input = String::new(); - let stdin = std::io::stdin(); - let n = stdin.read_line(&mut input).unwrap(); - - if input.chars().next().unwrap() == 'y' { // TODO add proper parsing for getting y/n - println!("\nsending tx thru the mixnet to broadcaster service"); - let tx_hash = commands::commands::send_tx(base58_tx_bytes, sp_address, &mut client).await; - println!("the response from the broadcaster: {:#?}", tx_hash); - } else if input.chars().next().unwrap() == 'n' { - println!("\nok, you can send the signed tx at a later date by passing the base58 string above as the argument for send-tx") - } else { //TODO make a loop & return to the question if input is not y/n? - println!("\nunrecognised user input"); - } - } - Some(Commands::SendTx(SendTx { base58_payload, sp_address} )) => { - let tx_hash = commands::commands::send_tx(base58_payload.clone(), sp_address.clone(), &mut client).await; - println!("the response from the broadcaster: {:#?}", tx_hash); - } - None => {println!("no command specified - nothing to do")} - } - println!("\nend ~(0.o)~ ") -} diff --git a/demos/rust-cosmos-broadcaster-server/Cargo.toml b/demos/rust-cosmos-broadcaster-server/Cargo.toml deleted file mode 100644 index a93c80f4c4..0000000000 --- a/demos/rust-cosmos-broadcaster-server/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "rust-cosmos-broadcaster-server" -version = "0.1.0" -authors.workspace = true -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -clap = { version = "4.0", features = ["derive"] } -nym-bin-common = { path = "../../common/bin-common"} -nym-sphinx-addressing = { path = "../../common/nymsphinx/addressing" } -nym-sphinx-anonymous-replies = { path = "../../common/nymsphinx/anonymous-replies" } -nym-sdk = { path = "../../sdk/rust/nym-sdk" } -nym-crypto = { path = "../../common/crypto" } -nym-cli-commands = { path = "../../common/commands" } -nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] } -nym-network-defaults = { path = "../../common/network-defaults" } -async-trait = { workspace = true, optional = true } -bip39 = { workspace = true, features = ["rand"] } -cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support", features = ["rpc", "bip32", "cosmwasm"] } -tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] } -ts-rs = "6.1.2" -bs58 = "0.5.0" -serde = { workspace = true, features = ["derive"] } -serde_json = { workspace = true } -cosmwasm-std = { workspace = true, optional = true } -anyhow.workspace = true diff --git a/demos/rust-cosmos-broadcaster-server/src/commands/commands.rs b/demos/rust-cosmos-broadcaster-server/src/commands/commands.rs deleted file mode 100644 index a472ca5836..0000000000 --- a/demos/rust-cosmos-broadcaster-server/src/commands/commands.rs +++ /dev/null @@ -1,61 +0,0 @@ -use nym_validator_client::nyxd::CosmWasmClient; -use cosmrs::rpc::{HttpClient, Client}; -use cosmrs::{AccountId, tendermint}; -use bs58; -use crate::commands::reqres::{SequenceRequestResponse, BroadcastResponse}; - -pub async fn get_sequence(validator: String, signer_address: AccountId) -> SequenceRequestResponse { - - /* - TODO create broadcaster in different fn and build on setup - pass to both fns as arg - */ - let broadcaster = HttpClient::new(validator.as_str()).unwrap(); - - // get signer information - let sequence = broadcaster.get_sequence(&signer_address).await.unwrap(); - let chain_id: tendermint::chain::Id = broadcaster.get_chain_id().await.unwrap(); - let res = SequenceRequestResponse { account_number: sequence.account_number, sequence: sequence.sequence, chain_id }; - res -} - -pub async fn broadcast(base58_tx_bytes: String) -> BroadcastResponse { - // decode the base58 tx to vec - let tx_bytes = bs58::decode(base58_tx_bytes).into_vec().unwrap(); - println!("decoded tx bytes: {:#?}", tx_bytes); - - /* - TODO create broadcaster in different fn and build on setup - pass to both fns as arg - */ - let broadcaster = HttpClient::new("https://qwerty-validator.qa.nymte.ch").unwrap(); - - - let to_address: AccountId = "n1p8ayfmdash352gh6yy8zlxk24dm6yzc9mdq0p6".parse().unwrap(); - - // compare balances from before and after the tx - let before = broadcaster - .get_balance(&to_address, "unym".to_string()) - .await - .unwrap() - .unwrap(); - - // broadcast the tx - let broadcast_res = Client::broadcast_tx_commit(&broadcaster, tx_bytes.into()) - .await - .unwrap(); - - let after = broadcaster - .get_balance(&to_address, "unym".to_string()) - .await - .unwrap() - .unwrap(); - - println!("{:#?}", broadcast_res.hash); - - println!("balance before: {before}"); - println!("balance after: {after}"); - - let res = BroadcastResponse { - tx_hash: serde_json::to_string(&broadcast_res.hash).unwrap() - }; - res -} \ No newline at end of file diff --git a/demos/rust-cosmos-broadcaster-server/src/commands/mod.rs b/demos/rust-cosmos-broadcaster-server/src/commands/mod.rs deleted file mode 100644 index b4eb760edf..0000000000 --- a/demos/rust-cosmos-broadcaster-server/src/commands/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod reqres; -pub mod commands; diff --git a/demos/rust-cosmos-broadcaster-server/src/commands/reqres.rs b/demos/rust-cosmos-broadcaster-server/src/commands/reqres.rs deleted file mode 100644 index b610d9f5bc..0000000000 --- a/demos/rust-cosmos-broadcaster-server/src/commands/reqres.rs +++ /dev/null @@ -1,39 +0,0 @@ -use serde::{Deserialize, Serialize}; -use cosmrs::{AccountId, tendermint}; - -#[derive(Deserialize, Serialize, Debug)] -pub struct SequenceRequest { - pub validator: String, - pub signer_address: AccountId, -} - -#[derive(Deserialize, Serialize, Debug)] -pub struct SequenceRequestResponse { - pub account_number: u64, - pub sequence: u64, - pub chain_id: tendermint::chain::Id -} - -#[derive(Deserialize, Serialize, Debug)] -pub struct BroadcastRequest { - pub base58_tx_bytes: String -} - -#[derive(Deserialize, Serialize, Debug)] -pub struct BroadcastResponse{ - pub tx_hash: String -} - -#[derive(Debug, Deserialize, Serialize)] -#[serde(untagged)] -pub enum RequestTypes { - Sequence(SequenceRequest), - Broadcast(BroadcastRequest) -} - -#[derive(Debug, Deserialize, Serialize)] -#[serde(untagged)] -pub enum ResponseTypes { - Sequence(SequenceRequestResponse), - Broadcast(BroadcastResponse) -} \ No newline at end of file diff --git a/demos/rust-cosmos-broadcaster-server/src/main.rs b/demos/rust-cosmos-broadcaster-server/src/main.rs deleted file mode 100644 index eff5860085..0000000000 --- a/demos/rust-cosmos-broadcaster-server/src/main.rs +++ /dev/null @@ -1,101 +0,0 @@ -use nym_sdk::mixnet::{StoragePaths, MixnetClientBuilder, ReconstructedMessage}; -use nym_bin_common::logging::setup_logging; -use std::path::PathBuf; -mod commands; -use nym_sphinx_anonymous_replies::{self, requests::AnonymousSenderTag}; -use crate::commands::reqres; - -#[tokio::main] -async fn main() { - setup_logging(); - // TODO put client creation in own fn - let config_dir = PathBuf::from("/tmp/cosmos-broadcaster-mixnet-server-2"); - let storage_paths = StoragePaths::new_from_dir(&config_dir).unwrap(); - let client = MixnetClientBuilder::new_with_default_storage(storage_paths) - .await - .unwrap() - .build() - .await - .unwrap(); - let mut client = client.connect_to_mixnet().await.unwrap(); - let our_address = client.nym_address(); - println!("\nOur client nym address is: {our_address}"); - - /* - TODO - * add threads - loop just to check everything works quickly - */ - loop { - println!("\nWaiting for message"); - // TODO rewrite this to parse any empty SURB data and then parse the actual incoming message - // let received = client.wait_for_messages().await; - - // handle incoming message - we presume its a reply from the SP - // check incoming is empty - SURB requests also send data ( empty vec ) along - let mut received: Vec = Vec::new(); - - // get the actual message - discard the empty vec sent along with the SURB request - while let Some(new_message) = client.wait_for_messages().await { - if new_message.is_empty() { - continue; - } - println!("got a response:"); - received = new_message; - println!("{:#?}", &received); - break - } - - for r in received.iter() { - // convert incoming vec -> String - let s = String::from_utf8(r.message.clone()); - println!("{:#?}", &s); - if s.is_ok() { - let p = s.unwrap(); - println!("{:#?}", &p); - // parse JSON string -> request type & match - let request: reqres::RequestTypes = serde_json::from_str(&p).unwrap(); - println!("incoming request: {:#?}", &request); - match request { - reqres::RequestTypes::Sequence(request) => { - println!("\nincoming sequence request details:\nvalidator: {},\nsigner address: {}\n", request.validator, request.signer_address); - let sequence: reqres::SequenceRequestResponse = commands::commands::get_sequence(request.validator, request.signer_address).await; - // print!("debug print -------- {:#?}", sequence); - // println!("debug print SENDER TAG --------- {:#?}", r.sender_tag); - if Some(r.sender_tag).is_some() { - // println!("debug print ---- sending reply "); - let return_recipient: AnonymousSenderTag = r.sender_tag.unwrap(); - println!("return recipient surb bucket: {}", &return_recipient); - // todo actually return sequence serialised as json - client.send_str_reply(return_recipient, &serde_json::to_string(&sequence).unwrap()).await; - // println!("sent reply - sleeping"); - // tokio::time::sleep(Duration::from_secs(25)).await; - // println!("stopped sleep"); - } else { - // TODO replace with actual error type to return - println!("no surbs cannot reply an0n") - } - }, - reqres::RequestTypes::Broadcast(request) => { - println!("\nincoming sequence request details: {}\n", request.base58_tx_bytes); - let tx_hash: reqres::BroadcastResponse = commands::commands::broadcast(request.base58_tx_bytes).await; - if Some(r.sender_tag).is_some() { - // println!("debug print ---- sending reply "); - let return_recipient: AnonymousSenderTag = r.sender_tag.unwrap(); - println!("return recipient surb bucket: {}", &return_recipient); - // todo actually return sequence serialised as json - client.send_str_reply(return_recipient, &serde_json::to_string(&tx_hash).unwrap()).await; - } else { - // TODO replace with actual error type to return - println!("no surbs cannot reply an0n") - } - - } - } - } - } - } - client.disconnect().await; -} - - -