From b7228bcb163a5faf7bb90b2e843c69ca4ba26c47 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Thu, 15 Aug 2024 12:49:55 -0400 Subject: [PATCH 1/2] Reworks the Buy/Sell order api to support creating multiple identical positions. This is especially useful for limit orders because it allows them to be filled piece wise. --- crates/bin/pcli/src/command/tx.rs | 22 +++++--- .../pcli/src/command/tx/liquidity_position.rs | 50 ++++++++++++++----- 2 files changed, 52 insertions(+), 20 deletions(-) diff --git a/crates/bin/pcli/src/command/tx.rs b/crates/bin/pcli/src/command/tx.rs index 8582e7faf1..49606e7ea9 100644 --- a/crates/bin/pcli/src/command/tx.rs +++ b/crates/bin/pcli/src/command/tx.rs @@ -954,15 +954,22 @@ impl TxCmd { tracing::info!(?order); let source = AddressIndex::new(order.source()); - let position = order.as_position(&asset_cache, OsRng)?; - tracing::info!(?position); - - println!("Position id: {}", position.id()); + let positions = order.as_position(&asset_cache)?; + tracing::info!(?positions); + for position in &positions { + println!("Position id: {}", position.id()); + } - let plan = Planner::new(OsRng) + let mut planner = Planner::new(OsRng); + planner .set_gas_prices(gas_prices) - .set_fee_tier(order.fee_tier().into()) - .position_open(position) + .set_fee_tier(order.fee_tier().into()); + + for position in positions { + planner.position_open(position); + } + + let plan = planner .plan( app.view .as_mut() @@ -970,6 +977,7 @@ impl TxCmd { source, ) .await?; + app.build_and_submit_transaction(plan).await?; } TxCmd::Withdraw { diff --git a/crates/bin/pcli/src/command/tx/liquidity_position.rs b/crates/bin/pcli/src/command/tx/liquidity_position.rs index ef2daa52fc..c6a3fcb594 100644 --- a/crates/bin/pcli/src/command/tx/liquidity_position.rs +++ b/crates/bin/pcli/src/command/tx/liquidity_position.rs @@ -8,7 +8,7 @@ use penumbra_dex::{ }, TradingPair, }; -use rand_core::CryptoRngCore; +use rand_core::OsRng; use super::{replicate::ReplicateCmd, FeeTier}; @@ -104,6 +104,9 @@ pub enum OrderCmd { /// The selected fee tier to multiply the fee amount by. #[clap(short, long, default_value_t)] fee_tier: FeeTier, + /// Duplicate the order for the given number of times. + #[clap(short, long, default_value = "1")] + duplicate: u32, }, Sell { /// The desired sale, formatted as a string, e.g. `100penumbra@1.2gm` would attempt @@ -121,6 +124,9 @@ pub enum OrderCmd { /// The selected fee tier to multiply the fee amount by. #[clap(short, long, default_value_t)] fee_tier: FeeTier, + /// Duplicate the order for the given number of times. + #[clap(short, long, default_value = "1")] + duplicate: u32, }, } @@ -146,30 +152,48 @@ impl OrderCmd { } } - pub fn as_position( + pub fn duplicate(&self) -> u32 { + match self { + OrderCmd::Buy { duplicate, .. } => *duplicate, + OrderCmd::Sell { duplicate, .. } => *duplicate, + } + } + + pub fn as_position( &self, // Preserved since we'll need it after denom metadata refactor _asset_cache: &asset::Cache, - rng: R, - ) -> Result { - let mut position = match self { + ) -> Result> { + let positions = match self { OrderCmd::Buy { buy_order, .. } => { tracing::info!(?buy_order, "parsing buy order"); let order = BuyOrder::parse_str(buy_order)?; - order.into_position(rng) + let mut positions = Vec::new(); + for _ in 0..self.duplicate() { + let mut position = order.into_position(OsRng); + if self.is_auto_closing() { + position.close_on_fill = true; + } + positions.push(position); + } + positions } OrderCmd::Sell { sell_order, .. } => { tracing::info!(?sell_order, "parsing sell order"); let order = SellOrder::parse_str(sell_order)?; - order.into_position(rng) + let mut positions = Vec::new(); + + for _ in 0..self.duplicate() { + let mut position = order.into_position(OsRng); + if self.is_auto_closing() { + position.close_on_fill = true; + } + positions.push(position); + } + positions } }; - tracing::info!(?position); - - if self.is_auto_closing() { - position.close_on_fill = true; - } - Ok(position) + Ok(positions) } } From 78cda191f0a72b5b7b3e24c830517408011ad137 Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Thu, 15 Aug 2024 11:42:19 -0700 Subject: [PATCH 2/2] pcli: duplicate positions: use a -n short flag to match auctions --- crates/bin/pcli/src/command/tx.rs | 2 +- .../pcli/src/command/tx/liquidity_position.rs | 21 ++++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/crates/bin/pcli/src/command/tx.rs b/crates/bin/pcli/src/command/tx.rs index 49606e7ea9..90c49d523d 100644 --- a/crates/bin/pcli/src/command/tx.rs +++ b/crates/bin/pcli/src/command/tx.rs @@ -954,7 +954,7 @@ impl TxCmd { tracing::info!(?order); let source = AddressIndex::new(order.source()); - let positions = order.as_position(&asset_cache)?; + let positions = order.as_position(&asset_cache, OsRng)?; tracing::info!(?positions); for position in &positions { println!("Position id: {}", position.id()); diff --git a/crates/bin/pcli/src/command/tx/liquidity_position.rs b/crates/bin/pcli/src/command/tx/liquidity_position.rs index c6a3fcb594..cf2cbb97ef 100644 --- a/crates/bin/pcli/src/command/tx/liquidity_position.rs +++ b/crates/bin/pcli/src/command/tx/liquidity_position.rs @@ -8,7 +8,7 @@ use penumbra_dex::{ }, TradingPair, }; -use rand_core::OsRng; +use rand_core::CryptoRngCore; use super::{replicate::ReplicateCmd, FeeTier}; @@ -106,7 +106,7 @@ pub enum OrderCmd { fee_tier: FeeTier, /// Duplicate the order for the given number of times. #[clap(short, long, default_value = "1")] - duplicate: u32, + num_copies: u32, }, Sell { /// The desired sale, formatted as a string, e.g. `100penumbra@1.2gm` would attempt @@ -126,7 +126,7 @@ pub enum OrderCmd { fee_tier: FeeTier, /// Duplicate the order for the given number of times. #[clap(short, long, default_value = "1")] - duplicate: u32, + num_copies: u32, }, } @@ -152,10 +152,10 @@ impl OrderCmd { } } - pub fn duplicate(&self) -> u32 { + pub fn num_copies(&self) -> u32 { match self { - OrderCmd::Buy { duplicate, .. } => *duplicate, - OrderCmd::Sell { duplicate, .. } => *duplicate, + OrderCmd::Buy { num_copies, .. } => *num_copies, + OrderCmd::Sell { num_copies, .. } => *num_copies, } } @@ -163,14 +163,15 @@ impl OrderCmd { &self, // Preserved since we'll need it after denom metadata refactor _asset_cache: &asset::Cache, + mut rng: impl CryptoRngCore, ) -> Result> { let positions = match self { OrderCmd::Buy { buy_order, .. } => { tracing::info!(?buy_order, "parsing buy order"); let order = BuyOrder::parse_str(buy_order)?; let mut positions = Vec::new(); - for _ in 0..self.duplicate() { - let mut position = order.into_position(OsRng); + for _ in 0..self.num_copies() { + let mut position = order.into_position(&mut rng); if self.is_auto_closing() { position.close_on_fill = true; } @@ -183,8 +184,8 @@ impl OrderCmd { let order = SellOrder::parse_str(sell_order)?; let mut positions = Vec::new(); - for _ in 0..self.duplicate() { - let mut position = order.into_position(OsRng); + for _ in 0..self.num_copies() { + let mut position = order.into_position(&mut rng); if self.is_auto_closing() { position.close_on_fill = true; }