Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
batconjurer committed Jan 9, 2025
1 parent 9b502ec commit f39c5c8
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 9 deletions.
13 changes: 10 additions & 3 deletions crates/apps_lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3597,6 +3597,7 @@ pub mod args {
pub const NO_CONVERSIONS: ArgFlag = flag("no-conversions");
pub const NO_EXPIRATION: ArgFlag = flag("no-expiration");
pub const NUT: ArgFlag = flag("nut");
pub const OSMOSIS_RPC: Arg<String> = arg("osmosis-rpc");
pub const OUT_FILE_PATH_OPT: ArgOpt<PathBuf> = arg_opt("out-file-path");
pub const OUTPUT: ArgOpt<PathBuf> = arg_opt("output");
pub const OUTPUT_DENOM: Arg<String> = arg("output-denom");
Expand Down Expand Up @@ -5168,15 +5169,17 @@ pub mod args {
slippage: self.slippage,
local_recovery_addr: self.local_recovery_addr,
route: self.route,
osmosis_rpc: self.osmosis_rpc,
})
}
}

impl Args for TxOsmosisSwap<CliTypes> {
fn parse(matches: &ArgMatches) -> Self {
let transfer = TxIbcTransfer::parse(matches);
let osmosis_rpc = OSMOSIS_RPC.parse(matches);
let output_denom = OUTPUT_DENOM.parse(matches);
let maybe_traans_recipient = TARGET_OPT.parse(matches);
let maybe_trans_recipient = TARGET_OPT.parse(matches);
let maybe_shielded_recipient =
PAYMENT_ADDRESS_TARGET_OPT.parse(matches);
let maybe_overflow = OVERFLOW_OPT.parse(matches);
Expand Down Expand Up @@ -5218,7 +5221,7 @@ pub mod args {
Self {
transfer,
output_denom,
recipient: if let Some(target) = maybe_traans_recipient {
recipient: if let Some(target) = maybe_trans_recipient {
Either::Left(target)
} else {
Either::Right(maybe_shielded_recipient.unwrap())
Expand All @@ -5227,19 +5230,23 @@ pub mod args {
slippage,
local_recovery_addr,
route,
osmosis_rpc,
}
}

fn def(app: App) -> App {
app.add_args::<TxIbcTransfer<CliTypes>>()
.arg(OSMOSIS_RPC.def().help(wrap!(
"A url pointing to an Osmosis rpc."
)))
.arg(OSMOSIS_POOL_HOP.def().help(wrap!(
"Individual hop of the route to take through Osmosis \
pools. This value takes the form \
<osmosis-pool-id>:<pool-output-denom>. When unspecified, \
the optimal route is queried on the fly."
)))
.arg(OUTPUT_DENOM.def().help(wrap!(
"The IBC denomination (on Osmosis) of the desired asset."
"The IBC denomination (on Namada) of the desired asset."
)))
.arg(TARGET_OPT.def().help(wrap!(
"The transparent Namada address that shall receive the \
Expand Down
12 changes: 9 additions & 3 deletions crates/sdk/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ use namada_tx::data::GasLimit;
use namada_tx::Memo;
use serde::{Deserialize, Serialize};
use zeroize::Zeroizing;

use namada_ibc::apps::transfer::types::TracePath;
use crate::error::Error;
use crate::eth_bridge::bridge_pool;
use crate::ibc::core::host::types::identifiers::{ChannelId, PortId};
use crate::ibc::{NamadaMemo, NamadaMemoData};
use crate::rpc::query_osmosis_pool_routes;
use crate::rpc::{calc_osmosis_denom_from_namada_denom, query_osmosis_pool_routes};
use crate::signing::SigningTxData;
use crate::wallet::{DatedSpendingKey, DatedViewingKey};
use crate::{rpc, tx, Namada};
Expand Down Expand Up @@ -524,7 +524,7 @@ pub enum Slippage {
pub struct TxOsmosisSwap<C: NamadaTypes = SdkTypes> {
/// The IBC transfer data
pub transfer: TxIbcTransfer<C>,
/// The token we wish to receive (on Osmosis)
/// The token we wish to receive (on Namada)
pub output_denom: String,
/// Address of the recipient on Namada
pub recipient: Either<C::Address, C::PaymentAddress>,
Expand All @@ -536,6 +536,8 @@ pub struct TxOsmosisSwap<C: NamadaTypes = SdkTypes> {
pub local_recovery_addr: String,
/// The route to take through Osmosis pools
pub route: Option<Vec<OsmosisPoolHop>>,
/// An rpc endpoint to Osmosis
pub osmosis_rpc: String,
}

impl TxOsmosisSwap<SdkTypes> {
Expand Down Expand Up @@ -596,6 +598,7 @@ impl TxOsmosisSwap<SdkTypes> {
local_recovery_addr,
route,
overflow,
osmosis_rpc,
} = self;

let recipient = recipient
Expand Down Expand Up @@ -649,6 +652,9 @@ impl TxOsmosisSwap<SdkTypes> {
})?
};


let osmosis_output_denom = calc_osmosis_denom_from_namada_denom(&output_denom, )

let (receiver, slippage, final_memo) = match recipient {
Either::Left(transparent_recipient) => {
(transparent_recipient.to_string(), slippage, None)
Expand Down
94 changes: 93 additions & 1 deletion crates/sdk/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ use namada_token::masp::MaspTokenRewardData;
use namada_tx::data::{BatchedTxResult, DryRunResult, ResultCode, TxResult};
use namada_tx::event::{Batch as BatchAttr, Code as CodeAttr};
use serde::{Deserialize, Serialize};

use namada_ibc::apps::transfer::types::TracePath;
use crate::args::{InputAmount, OsmosisPoolHop};
use crate::control_flow::time;
use crate::error::{EncodingError, Error, QueryError, TxSubmitError};
Expand Down Expand Up @@ -1496,6 +1496,98 @@ pub async fn query_ibc_denom<N: Namada>(
token.as_ref().to_string()
}

/// Given a Namada ibc asset returned from an Osmosis swap,
/// find the corresponding asset denom on Osmosis. This is done
/// by querying the crosschain swap contracts.
pub async fn calc_osmosis_denom_from_namada_denom(
namada_denom: &str,
contract_addr: &str,
rpc_addr: &str,
) -> Result<String, Error> {
#[derive(Serialize, Deserialize)]
struct RespData {
data: String
}

let nam_denom = PrefixedDenom::from_str(namada_denom)
.map_err(|e| Error::Other(format!("Could not parse {namada_denom} as a trace path {e}")))?;


let form_req = |query: &str| {
format!("{rpc_addr}/cosmwasm/wasm/v1/contract/{contract_addr}/smart/{query}")
};
let chain_name_req = |prefix| {
data_encoding::BASE64.encode(format!(r#"'{{"get_chain_name_from_bech32_prefix":{{"prefix":"{prefix}"}}'"#).as_bytes())
};
let channel_pair_req = |src: &str, dest: &str| {
data_encoding::BASE64.encode(
format!(r#"{{"get_channel_from_chain_pair": {{"source_chain": "{src}", "destinataion_chain": "{dest}" }} }}'"#).as_bytes()
)
};

let RespData{data: namada_chain_name } = reqwest::get(form_req(&chain_name_req("tnam")))
.await
.map_err(|e| Error::Other(e.to_string()))?
.json()
.await
.map_err(|e| Error::Other(e.to_string()))?;
let RespData{ data: osmosis_chain_name} = reqwest::get(form_req(&chain_name_req("osmo")))
.await
.map_err(|e| Error::Other(e.to_string()))?
.json()
.await
.map_err(|e| Error::Other(e.to_string()))?;

// Namada native asset
if nam_denom.trace_path.is_empty() {
// validate that the base denom is an address
if Address::from_str(nam_denom.base_denom.as_str()).is_err() {
return Err(Error::Encode(EncodingError::Decoding(format!("Could not parse {} as a token address", nam_denom.base_denom))));
}
// we get the channel-id from Osmosis to Namada
let RespData{ data: channel_id} = reqwest::get(form_req(
&channel_pair_req(&osmosis_chain_name, &namada_chain_name),
))
.await
.map_err(|e| Error::Other(e.to_string()))?
.json()
.await
.map_err(|e| Error::Other(e.to_string()))?;
Ok(format!("transfer/{channel_id}/{}", nam_denom.base_denom))
} else {
let nam_channel_id = nam_denom.trace_path.to_string().strip_prefix("transfer/")
.ok_or_else(|| Error::Other("Expected the output denom to originate from the transfer port".to_string()))?;

// we get chain name from which the base denom originated
let RespData{ data: src_chain_name} = reqwest::get(form_req(
&data_encoding::BASE64.encode(
format!(
r#"'{{"get_destination_chain_from_source_chain_via_channel":{{"on_chain": "{namada_chain_name}", "via_channel": "{nam_channel_id}"}} }}'"#
).as_bytes()
)
))
.await
.map_err(|e| Error::Other(e.to_string()))?
.json()
.await
.map_err(|e| Error::Other(e.to_string()))?;

if src_chain_name == osmosis_chain_name {
Ok(nam_denom.base_denom.to_string())
} else {
let RespData{ data: channel_id} = reqwest::get(form_req(
&channel_pair_req(&osmosis_chain_name, &src_chain_name)
))
.await
.map_err(|e| Error::Other(e.to_string()))?
.json()
.await
.map_err(|e| Error::Other(e.to_string()))?;
Ok(format!("transfer/{channel_id}/{}", nam_denom.base_denom))
}
}
}

/// Query a route of Osmosis liquidity pools
/// for swapping betwixt token and output_denom
/// assets.
Expand Down
6 changes: 4 additions & 2 deletions crates/tests/src/e2e/ibc_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3970,7 +3970,7 @@ fn osmosis_bingbong() -> Result<()> {
"--channel-id",
&channel_from_namada_to_osmosis.to_string(),
"--output-denom",
&format!("transfer/{channel_from_namada_to_gaia}/samoleans"),
&output_denom,
"--local-recovery-addr",
&osmosis_jones,
"--swap-contract",
Expand Down Expand Up @@ -4058,7 +4058,7 @@ fn osmosis_bingbong() -> Result<()> {
"--channel-id",
&channel_from_namada_to_osmosis.to_string(),
"--output-denom",
&format!("transfer/{channel_from_osmosis_to_gaia}/samoleans"),
&output_denom,
"--local-recovery-addr",
&osmosis_jones,
"--swap-contract",
Expand All @@ -4075,6 +4075,8 @@ fn osmosis_bingbong() -> Result<()> {
ALBERT_KEY,
"--node",
&rpc_namada,
"--gas-limit",
"500000",
],
Some(40),
)?.assert_success();
Expand Down

0 comments on commit f39c5c8

Please sign in to comment.