Skip to content

Commit

Permalink
SDK can now query for the native token address from the network. Also…
Browse files Browse the repository at this point in the history
… added null IO implementation.
  • Loading branch information
murisi committed Oct 9, 2023
1 parent b1bc845 commit 5b148cb
Show file tree
Hide file tree
Showing 14 changed files with 122 additions and 33 deletions.
2 changes: 1 addition & 1 deletion apps/src/bin/namada-client/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ async fn main() -> Result<()> {
let _log_guard = logging::init_from_env_or(LevelFilter::INFO)?;

// run the CLI
CliApi::<CliIo>::handle_client_command::<HttpClient>(
CliApi::handle_client_command::<HttpClient, _>(
None,
cli::namada_client_cli()?,
&CliIo,
Expand Down
3 changes: 1 addition & 2 deletions apps/src/bin/namada-relayer/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,5 @@ async fn main() -> Result<()> {

let cmd = cli::namada_relayer_cli()?;
// run the CLI
CliApi::<CliIo>::handle_relayer_command::<HttpClient>(None, cmd, &CliIo)
.await
CliApi::handle_relayer_command::<HttpClient>(None, cmd, &CliIo).await
}
2 changes: 1 addition & 1 deletion apps/src/bin/namada-wallet/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ pub fn main() -> Result<()> {
color_eyre::install()?;
let (cmd, ctx) = cli::namada_wallet_cli()?;
// run the CLI
CliApi::<CliIo>::handle_wallet_command(cmd, ctx, &CliIo)
CliApi::handle_wallet_command(cmd, ctx, &CliIo)
}
4 changes: 1 addition & 3 deletions apps/src/lib/cli/api.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::marker::PhantomData;

use namada::sdk::queries::Client;
use namada::sdk::rpc::wait_until_node_is_synched;
use namada::tendermint_rpc::HttpClient;
Expand Down Expand Up @@ -32,4 +30,4 @@ pub struct CliIo;
#[async_trait::async_trait(?Send)]
impl Io for CliIo {}

pub struct CliApi<IO: Io = CliIo>(PhantomData<IO>);
pub struct CliApi;
7 changes: 4 additions & 3 deletions apps/src/lib/cli/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ fn error() -> Report {
eyre!("Fatal error")
}

impl<IO: Io> CliApi<IO> {
pub async fn handle_client_command<C>(
impl CliApi {
pub async fn handle_client_command<C, IO: Io>(
client: Option<C>,
cmd: cli::NamadaClient,
io: &IO,
Expand Down Expand Up @@ -139,11 +139,12 @@ impl<IO: Io> CliApi<IO> {
.await
.proceed_or_else(error)?;
let args = args.to_sdk(&mut ctx);
let namada = NamadaImpl::new(
let namada = NamadaImpl::native_new(
&client,
&mut ctx.wallet,
&mut ctx.shielded,
io,
ctx.native_token,
);
tx::submit_init_validator(
&namada,
Expand Down
8 changes: 7 additions & 1 deletion apps/src/lib/cli/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,13 @@ impl Context {
C: namada::ledger::queries::Client + Sync,
IO: Io,
{
NamadaImpl::new(client, &mut self.wallet, &mut self.shielded, io)
NamadaImpl::native_new(
client,
&mut self.wallet,
&mut self.shielded,
io,
self.native_token.clone(),
)
}

/// Parse and/or look-up the value from the context.
Expand Down
4 changes: 2 additions & 2 deletions apps/src/lib/cli/relayer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ fn error() -> Report {
eyre!("Fatal error")
}

impl<IO: Io> CliApi<IO> {
impl CliApi {
pub async fn handle_relayer_command<C>(
client: Option<C>,
cmd: cli::NamadaRelayer,
io: &IO,
io: &impl Io,
) -> Result<()>
where
C: CliClient,
Expand Down
2 changes: 1 addition & 1 deletion apps/src/lib/cli/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::cli::args::CliToSdk;
use crate::cli::{args, cmds, Context};
use crate::wallet::{read_and_confirm_encryption_password, CliWalletUtils};

impl<IO: Io> CliApi<IO> {
impl CliApi {
pub fn handle_wallet_command(
cmd: cmds::NamadaWallet,
mut ctx: Context,
Expand Down
6 changes: 3 additions & 3 deletions apps/src/lib/node/ledger/shell/testing/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub fn run(
NamadaClient::WithoutContext(sub_cmd, global)
}
};
rt.block_on(CliApi::<TestingIo>::handle_client_command(
rt.block_on(CliApi::handle_client_command(
Some(node),
cmd,
&TestingIo,
Expand All @@ -61,7 +61,7 @@ pub fn run(

let cmd = cmds::NamadaWallet::parse(&matches)
.expect("Could not parse wallet command");
CliApi::<TestingIo>::handle_wallet_command(cmd, ctx, &TestingIo)
CliApi::handle_wallet_command(cmd, ctx, &TestingIo)
}
Bin::Relayer => {
args.insert(0, "relayer");
Expand All @@ -83,7 +83,7 @@ pub fn run(
NamadaRelayer::ValidatorSet(sub_cmd)
}
};
rt.block_on(CliApi::<TestingIo>::handle_relayer_command(
rt.block_on(CliApi::handle_relayer_command(
Some(node),
cmd,
&TestingIo,
Expand Down
3 changes: 2 additions & 1 deletion benches/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -810,11 +810,12 @@ impl BenchShieldedCtx {
&[],
))
.unwrap();
let namada = NamadaImpl::new(
let namada = NamadaImpl::native_new(
&self.shell,
&mut self.wallet,
&mut self.shielded,
&StdIo,
self.shell.wl_storage.storage.native_token.clone(),
);
let shielded = async_runtime
.block_on(
Expand Down
35 changes: 27 additions & 8 deletions shared/src/ledger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use crate::ibc::core::ics24_host::identifier::{ChannelId, PortId};
use crate::proto::Tx;
use crate::sdk::args::{self, InputAmount, SdkTypes};
use crate::sdk::masp::{ShieldedContext, ShieldedUtils};
use crate::sdk::rpc::query_native_token;
use crate::sdk::signing::{self, SigningTxData};
use crate::sdk::tx::{
self, ProcessTxResponse, TX_BOND_WASM, TX_BRIDGE_POOL_WASM,
Expand Down Expand Up @@ -405,32 +406,33 @@ where
pub shielded: RwLock<&'a mut ShieldedContext<V>>,
/// Captures the input/output streams used by this object
pub io: &'a I,
/// The address of the native token
native_token: Address,
/// The default builder for a Tx
prototype: args::Tx,
}

/// The Namada token
pub const NAM: &str = "atest1v4ehgw36x3prswzxggunzv6pxqmnvdj9xvcyzvpsggeyvs3cg9qnywf589qnwvfsg5erg3fkl09rg5";

impl<'a, C, U, V, I> NamadaImpl<'a, C, U, V, I>
where
C: crate::ledger::queries::Client + Sync,
U: WalletIo,
V: ShieldedUtils,
I: Io,
{
/// Construct a new Namada context
pub fn new(
/// Construct a new Namada context with the given native token address
pub fn native_new(
client: &'a C,
wallet: &'a mut Wallet<U>,
shielded: &'a mut ShieldedContext<V>,
io: &'a I,
native_token: Address,
) -> Self {
Self {
NamadaImpl {
client,
wallet: RwLock::new(wallet),
shielded: RwLock::new(shielded),
io,
native_token: native_token.clone(),
prototype: args::Tx {
dry_run: false,
dry_run_wrapper: false,
Expand All @@ -443,7 +445,7 @@ where
wallet_alias_force: false,
fee_amount: None,
wrapper_fee_payer: None,
fee_token: Address::from_str(NAM).unwrap(),
fee_token: native_token,
fee_unshield: None,
gas_limit: GasLimit::from(20_000),
expiration: None,
Expand All @@ -457,6 +459,23 @@ where
},
}
}

/// Construct a new Namada context looking up the native token address
pub async fn new(
client: &'a C,
wallet: &'a mut Wallet<U>,
shielded: &'a mut ShieldedContext<V>,
io: &'a I,
) -> crate::sdk::error::Result<NamadaImpl<'a, C, U, V, I>> {
let native_token = query_native_token(client).await?;
Ok(NamadaImpl::native_new(
client,
wallet,
shielded,
io,
native_token,
))
}
}

#[async_trait::async_trait(?Send)]
Expand All @@ -478,7 +497,7 @@ where
}

async fn native_token(&self) -> Address {
Address::from_str(NAM).unwrap()
self.native_token.clone()
}

fn io(&self) -> &'a Self::Io {
Expand Down
12 changes: 12 additions & 0 deletions shared/src/ledger/queries/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ router! {SHELL,
// Epoch of the last committed block
( "epoch" ) -> Epoch = epoch,

// The address of the native token
( "native_token" ) -> Address = native_token,

// Epoch of the input block height
( "epoch_at_height" / [height: BlockHeight]) -> Option<Epoch> = epoch_at_height,

Expand Down Expand Up @@ -288,6 +291,15 @@ where
Ok(data)
}

fn native_token<D, H>(ctx: RequestCtx<'_, D, H>) -> storage_api::Result<Address>
where
D: 'static + DB + for<'iter> DBIter<'iter> + Sync,
H: 'static + StorageHasher + Sync,
{
let data = ctx.wl_storage.storage.native_token.clone();
Ok(data)
}

fn epoch_at_height<D, H>(
ctx: RequestCtx<'_, D, H>,
height: BlockHeight,
Expand Down
7 changes: 7 additions & 0 deletions shared/src/sdk/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ pub async fn query_epoch<C: crate::ledger::queries::Client + Sync>(
convert_response::<C, _>(RPC.shell().epoch(client).await)
}

/// Query the address of the native token
pub async fn query_native_token<C: crate::ledger::queries::Client + Sync>(
client: &C,
) -> Result<Address, error::Error> {
convert_response::<C, _>(RPC.shell().native_token(client).await)
}

/// Query the epoch of the given block height, if it exists.
/// Will return none if the input block height is greater than
/// the latest committed block height.
Expand Down
60 changes: 53 additions & 7 deletions shared/src/types/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,26 @@
//! generic IO. The defaults are the obvious Rust native
//! functions.
/// Rust native I/O handling.
pub struct StdIo;

/// A trait that abstracts out I/O operations
#[async_trait::async_trait(?Send)]
impl Io for StdIo {}

#[async_trait::async_trait(?Send)]
#[allow(missing_docs)]
pub trait Io {
/// Print the given string
fn print(&self, output: impl AsRef<str>) {
print!("{}", output.as_ref());
}

/// Flush the output
fn flush(&self) {
use std::io::Write;
std::io::stdout().flush().unwrap();
}

/// Print the given string with a newline
fn println(&self, output: impl AsRef<str>) {
println!("{}", output.as_ref());
}

/// Print the given string into the given Writer
fn write<W: std::io::Write>(
&self,
mut writer: W,
Expand All @@ -32,6 +30,7 @@ pub trait Io {
write!(writer, "{}", output.as_ref())
}

/// Print the given string into the given Writer and terminate with newline
fn writeln<W: std::io::Write>(
&self,
mut writer: W,
Expand All @@ -40,10 +39,12 @@ pub trait Io {
writeln!(writer, "{}", output.as_ref())
}

/// Print the given error string
fn eprintln(&self, output: impl AsRef<str>) {
eprintln!("{}", output.as_ref());
}

/// Read a string from input
async fn read(&self) -> std::io::Result<String> {
#[cfg(not(target_family = "wasm"))]
{
Expand All @@ -55,6 +56,7 @@ pub trait Io {
}
}

/// Display the given prompt and return the string input
async fn prompt(&self, question: impl AsRef<str>) -> String {
#[cfg(not(target_family = "wasm"))]
{
Expand All @@ -76,6 +78,50 @@ pub trait Io {
}
}

/// Rust native I/O handling.
pub struct StdIo;

#[async_trait::async_trait(?Send)]
impl Io for StdIo {}

/// Ignores all I/O operations.
pub struct NullIo;

#[async_trait::async_trait(?Send)]
impl Io for NullIo {
fn print(&self, _output: impl AsRef<str>) {}

fn flush(&self) {}

fn println(&self, _output: impl AsRef<str>) {}

fn write<W: std::io::Write>(
&self,
mut _writer: W,
_output: impl AsRef<str>,
) -> std::io::Result<()> {
Ok(())
}

fn writeln<W: std::io::Write>(
&self,
mut _writer: W,
_output: impl AsRef<str>,
) -> std::io::Result<()> {
Ok(())
}

fn eprintln(&self, _output: impl AsRef<str>) {}

async fn read(&self) -> std::io::Result<String> {
panic!("Unsupported operation")
}

async fn prompt(&self, _question: impl AsRef<str>) -> String {
panic!("Unsupported operation")
}
}

/// A generic function for displaying a prompt to users and reading
/// in their response.
#[cfg(not(target_family = "wasm"))]
Expand Down

0 comments on commit 5b148cb

Please sign in to comment.