diff --git a/packages/shared/lib/Cargo.lock b/packages/shared/lib/Cargo.lock index d89a92784..9d1830683 100644 --- a/packages/shared/lib/Cargo.lock +++ b/packages/shared/lib/Cargo.lock @@ -2917,7 +2917,7 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "namada" version = "0.20.0" -source = "git+https://github.com/anoma/namada#b6714b5eca577c520b2b42b5f7f8048d46bb9d8b" +source = "git+https://github.com/anoma/namada?branch=bat/generic-io#c5a2ce2215f464ede671889b580a00d1ffdaa5a3" dependencies = [ "async-trait", "bimap", @@ -2966,7 +2966,7 @@ dependencies = [ [[package]] name = "namada_core" version = "0.20.0" -source = "git+https://github.com/anoma/namada#b6714b5eca577c520b2b42b5f7f8048d46bb9d8b" +source = "git+https://github.com/anoma/namada?branch=bat/generic-io#c5a2ce2215f464ede671889b580a00d1ffdaa5a3" dependencies = [ "ark-bls12-381", "ark-ec", @@ -3017,7 +3017,7 @@ dependencies = [ [[package]] name = "namada_ethereum_bridge" version = "0.20.0" -source = "git+https://github.com/anoma/namada#b6714b5eca577c520b2b42b5f7f8048d46bb9d8b" +source = "git+https://github.com/anoma/namada?branch=bat/generic-io#c5a2ce2215f464ede671889b580a00d1ffdaa5a3" dependencies = [ "borsh", "ethers", @@ -3038,7 +3038,7 @@ dependencies = [ [[package]] name = "namada_macros" version = "0.20.0" -source = "git+https://github.com/anoma/namada#b6714b5eca577c520b2b42b5f7f8048d46bb9d8b" +source = "git+https://github.com/anoma/namada?branch=bat/generic-io#c5a2ce2215f464ede671889b580a00d1ffdaa5a3" dependencies = [ "proc-macro2", "quote", @@ -3048,7 +3048,7 @@ dependencies = [ [[package]] name = "namada_proof_of_stake" version = "0.20.0" -source = "git+https://github.com/anoma/namada#b6714b5eca577c520b2b42b5f7f8048d46bb9d8b" +source = "git+https://github.com/anoma/namada?branch=bat/generic-io#c5a2ce2215f464ede671889b580a00d1ffdaa5a3" dependencies = [ "borsh", "data-encoding", diff --git a/packages/shared/lib/Cargo.toml b/packages/shared/lib/Cargo.toml index c888e1674..534f8ca49 100644 --- a/packages/shared/lib/Cargo.toml +++ b/packages/shared/lib/Cargo.toml @@ -23,7 +23,7 @@ gloo-utils = { version = "0.1.5", features = ["serde"] } js-sys = "0.3.60" masp_primitives = { git = "https://github.com/anoma/masp", rev = "252a6059565b125c1444e9e7d0b7c8da0fba8f8f" } masp_proofs = { git = "https://github.com/anoma/masp", rev = "252a6059565b125c1444e9e7d0b7c8da0fba8f8f", default-features = false, features = ["local-prover"] } -namada = { git = "https://github.com/anoma/namada", version = "0.20.0", default-features = false, features = ["abciplus", "namada-sdk"] } +namada = { git = "https://github.com/anoma/namada", branch = "bat/generic-io", default-features = false, features = ["abciplus", "namada-sdk"] } prost = "0.9.0" prost-types = "0.9.0" rand = "0.8.5" diff --git a/packages/shared/lib/src/query.rs b/packages/shared/lib/src/query.rs index 133bd2b5f..f90926f18 100644 --- a/packages/shared/lib/src/query.rs +++ b/packages/shared/lib/src/query.rs @@ -7,15 +7,19 @@ use namada::types::{ masp::ExtendedViewingKey, token::{self}, uint::I256, + io::Io }; use std::collections::{HashMap, HashSet}; use std::str::FromStr; use wasm_bindgen::prelude::*; use crate::rpc_client::HttpClient; +use crate::sdk::io; use crate::sdk::masp; use crate::utils::{set_panic_hook, to_js_result}; +type IO = io::BrowserIo; + #[wasm_bindgen] /// Represents an API for querying the ledger pub struct Query { @@ -188,7 +192,7 @@ impl Query { let epoch = namada::ledger::rpc::query_epoch(&self.client).await; let balance = shielded - .compute_exchanged_balance(&self.client, &viewing_key, epoch) + .compute_exchanged_balance::<_, IO>(&self.client, &viewing_key, epoch) .await .expect("context should contain viewing key"); let balance = Amount::from(balance); diff --git a/packages/shared/lib/src/sdk/io.rs b/packages/shared/lib/src/sdk/io.rs new file mode 100644 index 000000000..ab5a8e96c --- /dev/null +++ b/packages/shared/lib/src/sdk/io.rs @@ -0,0 +1,66 @@ +use namada::types::io::Io; +use wasm_bindgen::JsValue; + +pub struct BrowserIo; + +fn read(question: Option<&str>) -> std::io::Result { + match web_sys::window() { + Some(w) => { + let question = question.unwrap_or("Input: "); + let input = w + .prompt_with_message(question) + .expect("Prompt to be deifned"); + + input.ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + "Input is null", + )) + } + None => Err(std::io::Error::new(std::io::ErrorKind::Other, "No window")), + } +} + +impl Io for BrowserIo { + /// Print to the console.log + /// + /// # Arguments + /// + /// * `output` - The output to print + fn print(output: impl AsRef) { + web_sys::console::log_1(&output.as_ref().into()); + } + + /// Print to the console.log with newline + /// + /// # Arguments + /// + /// * `output` - The output to print + fn println(output: impl AsRef) { + let js_output: JsValue = format!("{}\n", output.as_ref()).into(); + web_sys::console::log_1(&js_output); + } + + /// Print to the console.error with newline + /// + /// # Arguments + /// + /// * `output` - The output to print + fn eprintln(output: impl AsRef) { + let js_output: JsValue = format!("{}\n", output.as_ref()).into(); + web_sys::console::error_1(&js_output); + } + + /// Read from the prompt + /// + /// **Note**: Works only in the context of a document(WebWorkers and ServiceWorkers are not supported) + fn read() -> std::io::Result { + read(None) + } + + /// Read from the prompt with a question + /// + /// **Note**: Works only in the context of a document(WebWorkers and ServiceWorkers are not supported) + fn prompt(question: impl AsRef) -> String { + read(Some(question.as_ref())).unwrap_or(String::from("")) + } +} diff --git a/packages/shared/lib/src/sdk/mod.rs b/packages/shared/lib/src/sdk/mod.rs index 888fd0c81..b23c33d9a 100644 --- a/packages/shared/lib/src/sdk/mod.rs +++ b/packages/shared/lib/src/sdk/mod.rs @@ -21,6 +21,7 @@ pub mod masp; mod signature; mod tx; mod wallet; +pub mod io; // Require that a public key is present fn validate_pk(pk: Option) -> Result { @@ -38,6 +39,8 @@ pub struct Sdk { shielded_ctx: ShieldedContext, } +type IO = io::BrowserIo; + #[wasm_bindgen] /// Sdk mostly wraps the logic of the Sdk struct members, making it a part of public API. /// For more details, navigate to the corresponding modules. @@ -110,7 +113,7 @@ impl Sdk { pk: &PublicKey, ) -> Result<(), JsError> { // Build a transaction to reveal the signer of this transaction - let reveal_pk = namada::ledger::tx::build_reveal_pk( + let reveal_pk = namada::ledger::tx::build_reveal_pk::<_, _, IO>( &self.client, &mut self.wallet, args::RevealPk { @@ -125,10 +128,17 @@ impl Sdk { // Sign the reveal public key transaction with the fee payer signing::sign_tx(&mut self.wallet, &mut rtx, &args, &pk).await?; // Submit the reveal public key transaction first - namada::ledger::tx::process_tx(&self.client, &mut self.wallet, &args, rtx).await?; + namada::ledger::tx::process_tx::<_, _, IO>( + &self.client, + &mut self.wallet, + &args, + rtx, + ) + .await?; // Update the stateful PoW challenge of the outer transaction #[cfg(not(feature = "mainnet"))] - signing::update_pow_challenge(&self.client, &args, &mut tx, &pk, false).await; + signing::update_pow_challenge::<_, IO>(&self.client, &args, &mut tx, &pk, false) + .await; } Ok(()) @@ -150,7 +160,7 @@ impl Sdk { .map_err(JsError::from)?; // Submit tx - namada::ledger::tx::process_tx(&self.client, &mut self.wallet, &args, tx) + namada::ledger::tx::process_tx::<_, _, IO>(&self.client, &mut self.wallet, &args, tx) .await .map_err(JsError::from)?; @@ -161,7 +171,7 @@ impl Sdk { pub async fn build_reveal_pk(&mut self, tx_msg: &[u8]) -> Result { let args = tx::reveal_pk_tx_args(tx_msg)?; - let reveal_pk = namada::ledger::tx::build_reveal_pk( + let reveal_pk = namada::ledger::tx::build_reveal_pk::<_, _, IO>( &self.client, &mut self.wallet, args::RevealPk { @@ -190,9 +200,14 @@ impl Sdk { let reveal_pk_tx = self.sign_tx(tx_bytes, raw_sig_bytes, wrapper_sig_bytes)?; let args = tx::reveal_pk_tx_args(tx_msg).map_err(JsError::from)?; - namada::ledger::tx::process_tx(&self.client, &mut self.wallet, &args.tx, reveal_pk_tx) - .await - .map_err(JsError::from)?; + namada::ledger::tx::process_tx::<_, _, IO>( + &self.client, + &mut self.wallet, + &args.tx, + reveal_pk_tx, + ) + .await + .map_err(JsError::from)?; Ok(()) } @@ -201,7 +216,7 @@ impl Sdk { pub async fn build_transfer(&mut self, tx_msg: &[u8]) -> Result { let args = tx::transfer_tx_args(tx_msg, None, None)?; - let transfer = namada::ledger::tx::build_transfer( + let transfer = namada::ledger::tx::build_transfer::<_, _, _, IO>( &self.client, &mut self.wallet, &mut self.shielded_ctx, @@ -219,9 +234,13 @@ impl Sdk { pub async fn build_bond(&mut self, tx_msg: &[u8]) -> Result { let args = tx::bond_tx_args(tx_msg, None)?; - let bond = namada::ledger::tx::build_bond(&self.client, &mut self.wallet, args.clone()) - .await - .map_err(JsError::from)?; + let bond = namada::ledger::tx::build_bond::<_, _, IO>( + &self.client, + &mut self.wallet, + args.clone(), + ) + .await + .map_err(JsError::from)?; let bytes = bond.0.try_to_vec().map_err(JsError::from)?; @@ -232,9 +251,13 @@ impl Sdk { pub async fn build_unbond(&mut self, tx_msg: &[u8]) -> Result { let args = tx::unbond_tx_args(tx_msg, None)?; - let unbond = namada::ledger::tx::build_unbond(&self.client, &mut self.wallet, args.clone()) - .await - .map_err(JsError::from)?; + let unbond = namada::ledger::tx::build_unbond::<_, _, IO>( + &self.client, + &mut self.wallet, + args.clone(), + ) + .await + .map_err(JsError::from)?; let bytes = unbond.0.try_to_vec().map_err(JsError::from)?; @@ -277,9 +300,14 @@ impl Sdk { self.submit_reveal_pk(&args.tx, transfer_tx.clone(), &pk) .await?; - namada::ledger::tx::process_tx(&self.client, &mut self.wallet, &args.tx, transfer_tx) - .await - .map_err(JsError::from)?; + namada::ledger::tx::process_tx::<_, _, IO>( + &self.client, + &mut self.wallet, + &args.tx, + transfer_tx, + ) + .await + .map_err(JsError::from)?; Ok(()) } @@ -291,7 +319,7 @@ impl Sdk { xsk: Option, ) -> Result<(), JsError> { let args = tx::transfer_tx_args(tx_msg, password, xsk)?; - let (tx, _, pk, _, _) = namada::ledger::tx::build_transfer( + let (tx, _, pk, _, _) = namada::ledger::tx::build_transfer::<_, _, _, IO>( &self.client, &mut self.wallet, &mut self.shielded_ctx, @@ -313,7 +341,7 @@ impl Sdk { let args = tx::ibc_transfer_tx_args(tx_msg, password)?; let (tx, _, pk) = - namada::ledger::tx::build_ibc_transfer(&self.client, &mut self.wallet, args.clone()) + namada::ledger::tx::build_ibc_transfer::<_, _, IO>(&self.client, &mut self.wallet, args.clone()) .await .map_err(JsError::from)?; @@ -330,7 +358,7 @@ impl Sdk { let args = tx::bond_tx_args(tx_msg, password)?; let (tx, _, pk) = - namada::ledger::tx::build_bond(&mut self.client, &mut self.wallet, args.clone()) + namada::ledger::tx::build_bond::<_, _, IO>(&mut self.client, &mut self.wallet, args.clone()) .await .map_err(JsError::from)?; @@ -350,7 +378,7 @@ impl Sdk { let bond_tx = self.sign_tx(tx_bytes, raw_sig_bytes, wrapper_sig_bytes)?; let args = tx::bond_tx_args(tx_msg, None).map_err(JsError::from)?; - namada::ledger::tx::process_tx(&self.client, &mut self.wallet, &args.tx, bond_tx) + namada::ledger::tx::process_tx::<_, _, IO>(&self.client, &mut self.wallet, &args.tx, bond_tx) .await .map_err(JsError::from)?; @@ -366,7 +394,7 @@ impl Sdk { let args = tx::unbond_tx_args(tx_msg, password)?; let (tx, _, pk, _) = - namada::ledger::tx::build_unbond(&mut self.client, &mut self.wallet, args.clone()) + namada::ledger::tx::build_unbond::<_, _, IO>(&mut self.client, &mut self.wallet, args.clone()) .await .map_err(JsError::from)?; @@ -391,7 +419,7 @@ impl Sdk { self.submit_reveal_pk(&args.tx, bond_tx.clone(), &pk) .await?; - namada::ledger::tx::process_tx(&self.client, &mut self.wallet, &args.tx, bond_tx) + namada::ledger::tx::process_tx::<_, _, IO>(&self.client, &mut self.wallet, &args.tx, bond_tx) .await .map_err(JsError::from)?;