Skip to content

Commit

Permalink
Add osmosis swap CLI command
Browse files Browse the repository at this point in the history
  • Loading branch information
sug0 committed Dec 2, 2024
1 parent a404896 commit 59b6d2b
Show file tree
Hide file tree
Showing 4 changed files with 280 additions and 1 deletion.
1 change: 1 addition & 0 deletions crates/apps/src/bin/namada/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ fn handle_command(cmd: cli::cmds::Namada, raw_sub_cmd: String) -> Result<()> {
| cli::cmds::Namada::TxShieldingTransfer(_)
| cli::cmds::Namada::TxUnshieldingTransfer(_)
| cli::cmds::Namada::TxIbcTransfer(_)
| cli::cmds::Namada::TxOsmosisSwap(_)
| cli::cmds::Namada::TxUpdateAccount(_)
| cli::cmds::Namada::TxRevealPk(_)
| cli::cmds::Namada::TxInitProposal(_)
Expand Down
113 changes: 113 additions & 0 deletions crates/apps_lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pub mod cmds {
TxShieldingTransfer(TxShieldingTransfer),
TxUnshieldingTransfer(TxUnshieldingTransfer),
TxIbcTransfer(TxIbcTransfer),
TxOsmosisSwap(TxOsmosisSwap),
TxUpdateAccount(TxUpdateAccount),
TxInitProposal(TxInitProposal),
TxVoteProposal(TxVoteProposal),
Expand All @@ -84,6 +85,7 @@ pub mod cmds {
.subcommand(TxShieldingTransfer::def().display_order(2))
.subcommand(TxUnshieldingTransfer::def().display_order(2))
.subcommand(TxIbcTransfer::def().display_order(2))
.subcommand(TxOsmosisSwap::def().display_order(2))
.subcommand(TxUpdateAccount::def().display_order(2))
.subcommand(TxInitProposal::def().display_order(2))
.subcommand(TxVoteProposal::def().display_order(2))
Expand All @@ -107,6 +109,8 @@ pub mod cmds {
SubCmd::parse(matches).map(Self::TxUnshieldingTransfer);
let tx_ibc_transfer =
SubCmd::parse(matches).map(Self::TxIbcTransfer);
let tx_osmosis_swap =
SubCmd::parse(matches).map(Self::TxOsmosisSwap);
let tx_update_account =
SubCmd::parse(matches).map(Self::TxUpdateAccount);
let tx_init_proposal =
Expand All @@ -124,6 +128,7 @@ pub mod cmds {
.or(tx_shielding_transfer)
.or(tx_unshielding_transfer)
.or(tx_ibc_transfer)
.or(tx_osmosis_swap)
.or(tx_update_account)
.or(tx_init_proposal)
.or(tx_vote_proposal)
Expand Down Expand Up @@ -239,6 +244,7 @@ pub mod cmds {
.subcommand(TxShieldingTransfer::def().display_order(1))
.subcommand(TxUnshieldingTransfer::def().display_order(1))
.subcommand(TxIbcTransfer::def().display_order(1))
.subcommand(TxOsmosisSwap::def().display_order(1))
.subcommand(TxUpdateAccount::def().display_order(1))
.subcommand(TxInitAccount::def().display_order(1))
.subcommand(TxRevealPk::def().display_order(1))
Expand Down Expand Up @@ -313,6 +319,7 @@ pub mod cmds {
let tx_unshielding_transfer =
Self::parse_with_ctx(matches, TxUnshieldingTransfer);
let tx_ibc_transfer = Self::parse_with_ctx(matches, TxIbcTransfer);
let tx_osmosis_swap = Self::parse_with_ctx(matches, TxOsmosisSwap);
let tx_update_account =
Self::parse_with_ctx(matches, TxUpdateAccount);
let tx_init_account = Self::parse_with_ctx(matches, TxInitAccount);
Expand Down Expand Up @@ -402,6 +409,7 @@ pub mod cmds {
.or(tx_shielding_transfer)
.or(tx_unshielding_transfer)
.or(tx_ibc_transfer)
.or(tx_osmosis_swap)
.or(tx_update_account)
.or(tx_init_account)
.or(tx_reveal_pk)
Expand Down Expand Up @@ -497,6 +505,7 @@ pub mod cmds {
TxShieldingTransfer(TxShieldingTransfer),
TxUnshieldingTransfer(TxUnshieldingTransfer),
TxIbcTransfer(TxIbcTransfer),
TxOsmosisSwap(TxOsmosisSwap),
QueryResult(QueryResult),
TxUpdateAccount(TxUpdateAccount),
TxInitAccount(TxInitAccount),
Expand Down Expand Up @@ -1436,6 +1445,25 @@ pub mod cmds {
}
}

#[derive(Clone, Debug)]
pub struct TxOsmosisSwap(pub args::TxOsmosisSwap<args::CliTypes>);

impl SubCmd for TxOsmosisSwap {
const CMD: &'static str = "osmosis-swap";

fn parse(matches: &ArgMatches) -> Option<Self> {
matches.subcommand_matches(Self::CMD).map(|matches| {
TxOsmosisSwap(args::TxOsmosisSwap::parse(matches))
})
}

fn def() -> App {
App::new(Self::CMD)
.about(wrap!("Swap two asset kinds using Osmosis."))
.add_args::<args::TxOsmosisSwap<args::CliTypes>>()
}
}

#[derive(Clone, Debug)]
pub struct TxUpdateAccount(pub args::TxUpdateAccount<args::CliTypes>);

Expand Down Expand Up @@ -3569,8 +3597,11 @@ pub mod args {
pub const NUT: ArgFlag = flag("nut");
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");
pub const OUTPUT_FOLDER_PATH: ArgOpt<PathBuf> =
arg_opt("output-folder-path");
pub const OSMOSIS_POOL_HOP: ArgMulti<OsmosisPoolHop, GlobStar> =
arg_multi("pool-hop");
pub const OWNER: Arg<WalletAddress> = arg("owner");
pub const OWNER_OPT: ArgOpt<WalletAddress> = OWNER.opt();
pub const PATH: Arg<PathBuf> = arg("path");
Expand Down Expand Up @@ -3623,6 +3654,7 @@ pub mod args {
pub const SHIELDED: ArgFlag = flag("shielded");
pub const SHOW_IBC_TOKENS: ArgFlag = flag("show-ibc-tokens");
pub const SIGNER: ArgOpt<WalletAddress> = arg_opt("signer");
pub const SLIPPAGE: Arg<u64> = arg("slippage-percentage");
pub const SIGNING_KEYS: ArgMulti<WalletPublicKey, GlobStar> =
arg_multi("signing-keys");
pub const SIGNATURES: ArgMulti<PathBuf, GlobStar> = arg_multi("signatures");
Expand Down Expand Up @@ -3679,6 +3711,7 @@ pub mod args {
pub const WASM_CHECKSUMS_PATH: Arg<PathBuf> = arg("wasm-checksums-path");
pub const WASM_DIR: ArgOpt<PathBuf> = arg_opt("wasm-dir");
pub const WEBSITE_OPT: ArgOpt<String> = arg_opt("website");
pub const WINDOW_SECONDS: Arg<u64> = arg("window-seconds");
pub const WITH_INDEXER: ArgOpt<String> = arg_opt("with-indexer");
pub const WRAPPER_SIGNATURE_OPT: ArgOpt<PathBuf> = arg_opt("gas-signature");
pub const TX_PATH: Arg<PathBuf> = arg("tx-path");
Expand Down Expand Up @@ -5108,6 +5141,86 @@ pub mod args {
}
}

impl CliToSdk<TxOsmosisSwap<SdkTypes>> for TxOsmosisSwap<CliTypes> {
type Error = std::io::Error;

fn to_sdk(
self,
ctx: &mut Context,
) -> Result<TxOsmosisSwap<SdkTypes>, Self::Error> {
let chain_ctx = ctx.borrow_mut_chain_or_exit();
let recipient = chain_ctx.get(&self.recipient);
Ok(TxOsmosisSwap {
transfer: self.transfer.to_sdk(ctx)?,
output_denom: self.output_denom,
recipient,
slippage_percent: self.slippage_percent,
window_seconds: self.window_seconds,
route: self.route,
})
}
}

impl Args for TxOsmosisSwap<CliTypes> {
fn parse(matches: &ArgMatches) -> Self {
let transfer = TxIbcTransfer::parse(matches);
let output_denom = OUTPUT_DENOM.parse(matches);
let recipient = TARGET.parse(matches);
let slippage_percent = SLIPPAGE.parse(matches);
if slippage_percent > 100 {
panic!(
"The slippage percent must be an integer between 0 and \
100."
)
}
let window_seconds = WINDOW_SECONDS.parse(matches);
let route = match OSMOSIS_POOL_HOP.parse(matches) {
r if r.is_empty() => None,
r => Some(r),
};
Self {
transfer,
output_denom,
recipient,
slippage_percent,
window_seconds,
route,
}
}

// TODO:
// - fix window_seconds help str
// - add osmo1... address to recover funds in case of ibc failures
// during packet forwarding
fn def(app: App) -> App {
app.add_args::<TxIbcTransfer<CliTypes>>()
.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."
)))
.arg(TARGET.def().help(wrap!(
"The address that shall receive the swapped tokens."
)))
.arg(SLIPPAGE.def().help(wrap!(
"The slippage percentage as an integer between 0 and 100."
)))
.arg(WINDOW_SECONDS.def().help(wrap!(
"A mysterious thing that should be set to 10s."
)))
.mut_arg(RECEIVER.name, |arg| {
arg.long("swap-contract").help(wrap!(
"The address of the Osmosis contract performing the \
swap. It will be the receiver of the IBC transfer."
))
})
}
}

impl CliToSdk<TxInitAccount<SdkTypes>> for TxInitAccount<CliTypes> {
type Error = std::io::Error;

Expand Down
12 changes: 12 additions & 0 deletions crates/apps_lib/src/cli/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,18 @@ impl CliApi {
let namada = ctx.to_sdk(client, io);
tx::submit_ibc_transfer(&namada, args).await?;
}
Sub::TxOsmosisSwap(TxOsmosisSwap(args)) => {
let chain_ctx = ctx.borrow_mut_chain_or_exit();
let ledger_address =
chain_ctx.get(&args.transfer.tx.ledger_address);
let client = client.unwrap_or_else(|| {
C::from_tendermint_address(&ledger_address)
});
client.wait_until_node_is_synced(&io).await?;
let args = args.to_sdk(&mut ctx)?.assemble();
let namada = ctx.to_sdk(client, io);
tx::submit_ibc_transfer(&namada, args).await?;
}
Sub::TxUpdateAccount(TxUpdateAccount(args)) => {
let chain_ctx = ctx.borrow_mut_chain_or_exit();
let ledger_address =
Expand Down
Loading

0 comments on commit 59b6d2b

Please sign in to comment.