Skip to content

Commit 6ef701f

Browse files
committed
Rework swap table display logic to use the comfy-table crate
1 parent fb51967 commit 6ef701f

File tree

2 files changed

+182
-82
lines changed

2 files changed

+182
-82
lines changed

crates/cli-client/src/cli/swap.rs

Lines changed: 115 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
use crate::cli::interactive::{
2-
SWAP_COLLATERAL_TAG, current_timestamp, extract_entries_from_result, format_relative_time,
2+
SWAP_COLLATERAL_TAG, current_timestamp, extract_entries_from_result, format_relative_time, format_settlement_asset,
33
get_grantor_tokens_from_wallet, parse_expiry, prompt_amount, select_enriched_token_interactive,
4+
truncate_with_ellipsis,
5+
};
6+
use crate::cli::tables::{
7+
display_active_swaps_table, display_cancellable_swaps_table, display_withdrawable_swaps_table,
48
};
59
use crate::cli::{Cli, SwapCommand};
610
use crate::config::Config;
@@ -22,6 +26,51 @@ use simplicityhl::elements::pset::serialize::Serialize;
2226
use simplicityhl::simplicity::hex::DisplayHex;
2327
use simplicityhl_core::{LIQUID_TESTNET_BITCOIN_ASSET, LIQUID_TESTNET_GENESIS};
2428

29+
pub(crate) struct LocalSwapData {
30+
pub(crate) swap_args: SwapWithChangeArguments,
31+
pub(crate) taproot_pubkey_gen: contracts::sdk::taproot_pubkey_gen::TaprootPubkeyGen,
32+
pub(crate) metadata: ContractMetadata,
33+
pub(crate) current_outpoint: simplicityhl::elements::OutPoint,
34+
pub(crate) current_value: u64,
35+
}
36+
37+
pub(crate) struct LocalCancellableSwap {
38+
pub(crate) swap_args: SwapWithChangeArguments,
39+
pub(crate) taproot_pubkey_gen: contracts::sdk::taproot_pubkey_gen::TaprootPubkeyGen,
40+
pub(crate) metadata: ContractMetadata,
41+
}
42+
43+
pub(crate) struct LocalWithdrawableSwap {
44+
pub(crate) swap_args: SwapWithChangeArguments,
45+
pub(crate) taproot_pubkey_gen: contracts::sdk::taproot_pubkey_gen::TaprootPubkeyGen,
46+
pub(crate) metadata: ContractMetadata,
47+
pub(crate) settlement_amount: u64,
48+
}
49+
50+
pub(crate) struct ActiveSwapDisplay {
51+
pub(crate) index: usize,
52+
pub(crate) offering: String,
53+
pub(crate) price: String,
54+
pub(crate) wants: String,
55+
pub(crate) expires: String,
56+
pub(crate) seller: String,
57+
}
58+
59+
pub(crate) struct CancellableSwapDisplay {
60+
pub(crate) index: usize,
61+
pub(crate) collateral: String,
62+
pub(crate) asset: String,
63+
pub(crate) expired: String,
64+
pub(crate) contract: String,
65+
}
66+
67+
pub(crate) struct WithdrawableSwapDisplay {
68+
pub(crate) index: usize,
69+
pub(crate) settlement: String,
70+
pub(crate) asset: String,
71+
pub(crate) contract: String,
72+
}
73+
2574
impl Cli {
2675
#[allow(clippy::too_many_lines)]
2776
pub(crate) async fn run_swap(&self, config: Config, command: &SwapCommand) -> Result<(), Error> {
@@ -197,14 +246,6 @@ impl Cli {
197246
fee,
198247
broadcast,
199248
} => {
200-
struct LocalSwapData {
201-
swap_args: SwapWithChangeArguments,
202-
taproot_pubkey_gen: contracts::sdk::taproot_pubkey_gen::TaprootPubkeyGen,
203-
metadata: ContractMetadata,
204-
current_outpoint: simplicityhl::elements::OutPoint,
205-
current_value: u64,
206-
}
207-
208249
println!("Taking swap offer...");
209250

210251
let swap_contracts =
@@ -280,24 +321,8 @@ impl Cli {
280321
));
281322
}
282323

283-
println!(
284-
" {:<3} | {:<12} | {:<10} | {:<14} | {:<15} | Seller",
285-
"#", "Offering", "Price", "Wants", "Expires"
286-
);
287-
println!("{}", "-".repeat(90));
288-
for (idx, swap) in active_swaps.iter().enumerate() {
289-
let seller = swap.metadata.nostr_author.as_deref().unwrap_or("unknown");
290-
let price = swap.swap_args.collateral_per_contract();
291-
println!(
292-
" {:<3} | {:<12} | {:<10} | {:<14} | {:<15} | {}",
293-
idx + 1,
294-
swap.current_value,
295-
price,
296-
crate::cli::interactive::format_settlement_asset(&swap.swap_args.get_settlement_asset_id()),
297-
format_relative_time(i64::from(swap.swap_args.expiry_time())),
298-
crate::cli::interactive::truncate_with_ellipsis(seller, 12)
299-
);
300-
}
324+
let active_swap_displays = build_active_swaps_displays(&active_swaps);
325+
display_active_swaps_table(&active_swap_displays);
301326
println!();
302327

303328
let selection =
@@ -500,12 +525,6 @@ impl Cli {
500525
fee,
501526
broadcast,
502527
} => {
503-
struct LocalCancellableSwap {
504-
swap_args: SwapWithChangeArguments,
505-
taproot_pubkey_gen: contracts::sdk::taproot_pubkey_gen::TaprootPubkeyGen,
506-
metadata: ContractMetadata,
507-
}
508-
509528
println!("Cancelling swap offer (reclaiming collateral after expiry)...");
510529

511530
let swap_contracts =
@@ -578,28 +597,8 @@ impl Cli {
578597
));
579598
}
580599

581-
println!(
582-
" {:<3} | {:<12} | {:<14} | {:<20} | Contract",
583-
"#", "Collateral", "Asset", "Expired"
584-
);
585-
println!("{}", "-".repeat(80));
586-
for (idx, cs) in cancellable_swaps.iter().enumerate() {
587-
let asset_display =
588-
crate::cli::interactive::format_settlement_asset(&cs.swap_args.get_collateral_asset_id());
589-
let expiry_time = cs.swap_args.expiry_time();
590-
let contract_short = cs.metadata.nostr_event_id.as_ref().map_or_else(
591-
|| crate::cli::interactive::truncate_with_ellipsis(&cs.taproot_pubkey_gen.to_string(), 16),
592-
|id| crate::cli::interactive::truncate_with_ellipsis(id, 16),
593-
);
594-
println!(
595-
" {:<3} | {:<12} | {:<14} | {:<20} | {}",
596-
idx + 1,
597-
"available",
598-
asset_display,
599-
format!("expired ({})", expiry_time),
600-
contract_short
601-
);
602-
}
600+
let cancellable_swap_displays = build_cancellable_swaps_displays(&cancellable_swaps);
601+
display_cancellable_swaps_table(&cancellable_swap_displays);
603602
println!();
604603

605604
let selected = if let Some(event_id_str) = swap_event {
@@ -800,13 +799,6 @@ impl Cli {
800799
fee,
801800
broadcast,
802801
} => {
803-
struct LocalWithdrawableSwap {
804-
swap_args: SwapWithChangeArguments,
805-
taproot_pubkey_gen: contracts::sdk::taproot_pubkey_gen::TaprootPubkeyGen,
806-
metadata: ContractMetadata,
807-
settlement_amount: u64,
808-
}
809-
810802
println!("Withdrawing settlement from swap (claiming payment after swap was taken)...");
811803

812804
let swap_contracts =
@@ -879,26 +871,8 @@ impl Cli {
879871
));
880872
}
881873

882-
println!(
883-
" {:<3} | {:<20} | {:<14} | Contract",
884-
"#", "Settlement Available", "Asset"
885-
);
886-
println!("{}", "-".repeat(70));
887-
for (idx, ws) in withdrawable_swaps.iter().enumerate() {
888-
let asset_display =
889-
crate::cli::interactive::format_settlement_asset(&ws.swap_args.get_settlement_asset_id());
890-
let contract_short = ws.metadata.nostr_event_id.as_ref().map_or_else(
891-
|| crate::cli::interactive::truncate_with_ellipsis(&ws.taproot_pubkey_gen.to_string(), 16),
892-
|id| crate::cli::interactive::truncate_with_ellipsis(id, 16),
893-
);
894-
println!(
895-
" {:<3} | {:<20} | {:<14} | {}",
896-
idx + 1,
897-
ws.settlement_amount,
898-
asset_display,
899-
contract_short
900-
);
901-
}
874+
let withdrawable_swap_displays = build_withdrawable_swaps_displays(&withdrawable_swaps);
875+
display_withdrawable_swaps_table(&withdrawable_swap_displays);
902876
println!();
903877

904878
let selected = if let Some(event_id_str) = swap_event {
@@ -1095,3 +1069,62 @@ impl Cli {
10951069
}
10961070
}
10971071
}
1072+
1073+
fn build_active_swaps_displays(active_swaps: &[LocalSwapData]) -> Vec<ActiveSwapDisplay> {
1074+
active_swaps
1075+
.iter()
1076+
.enumerate()
1077+
.map(|(idx, swap)| {
1078+
let seller = swap.metadata.nostr_author.as_deref().unwrap_or("unknown");
1079+
let price = swap.swap_args.collateral_per_contract();
1080+
ActiveSwapDisplay {
1081+
index: idx + 1,
1082+
offering: swap.current_value.to_string(),
1083+
price: price.to_string(),
1084+
wants: format_settlement_asset(&swap.swap_args.get_settlement_asset_id()),
1085+
expires: format_relative_time(i64::from(swap.swap_args.expiry_time())),
1086+
seller: truncate_with_ellipsis(seller, 12),
1087+
}
1088+
})
1089+
.collect()
1090+
}
1091+
1092+
fn build_cancellable_swaps_displays(cancellable_swaps: &[LocalCancellableSwap]) -> Vec<CancellableSwapDisplay> {
1093+
cancellable_swaps
1094+
.iter()
1095+
.enumerate()
1096+
.map(|(idx, cs)| {
1097+
let expiry_time = cs.swap_args.expiry_time();
1098+
let contract_short = cs.metadata.nostr_event_id.as_ref().map_or_else(
1099+
|| truncate_with_ellipsis(&cs.taproot_pubkey_gen.to_string(), 16),
1100+
|id| truncate_with_ellipsis(id, 16),
1101+
);
1102+
CancellableSwapDisplay {
1103+
index: idx + 1,
1104+
collateral: "available".to_string(),
1105+
asset: format_settlement_asset(&cs.swap_args.get_collateral_asset_id()),
1106+
expired: format!("expired ({expiry_time})"),
1107+
contract: contract_short,
1108+
}
1109+
})
1110+
.collect()
1111+
}
1112+
1113+
fn build_withdrawable_swaps_displays(withdrawable_swaps: &[LocalWithdrawableSwap]) -> Vec<WithdrawableSwapDisplay> {
1114+
withdrawable_swaps
1115+
.iter()
1116+
.enumerate()
1117+
.map(|(idx, ws)| {
1118+
let contract_short = ws.metadata.nostr_event_id.as_ref().map_or_else(
1119+
|| truncate_with_ellipsis(&ws.taproot_pubkey_gen.to_string(), 16),
1120+
|id| truncate_with_ellipsis(id, 16),
1121+
);
1122+
WithdrawableSwapDisplay {
1123+
index: idx + 1,
1124+
settlement: ws.settlement_amount.to_string(),
1125+
asset: format_settlement_asset(&ws.swap_args.get_settlement_asset_id()),
1126+
contract: contract_short,
1127+
}
1128+
})
1129+
.collect()
1130+
}

crates/cli-client/src/cli/tables.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::cli::interactive::{SwapDisplay, TokenDisplay};
22
use crate::cli::positions::{CollateralDisplay, UserTokenDisplay};
3+
use crate::cli::swap::{ActiveSwapDisplay, CancellableSwapDisplay, WithdrawableSwapDisplay};
34
use comfy_table::presets::UTF8_FULL;
45
use comfy_table::{Attribute, Cell, Table};
56

@@ -81,6 +82,60 @@ impl TableData for UserTokenDisplay {
8182
}
8283
}
8384

85+
impl TableData for ActiveSwapDisplay {
86+
fn get_header() -> Vec<String> {
87+
vec!["#", "Offering", "Price", "Wants", "Expires", "Seller"]
88+
.into_iter()
89+
.map(String::from)
90+
.collect()
91+
}
92+
fn to_row(&self) -> Vec<String> {
93+
vec![
94+
self.index.to_string(),
95+
self.offering.clone(),
96+
self.price.clone(),
97+
self.wants.clone(),
98+
self.expires.clone(),
99+
self.seller.clone(),
100+
]
101+
}
102+
}
103+
104+
impl TableData for CancellableSwapDisplay {
105+
fn get_header() -> Vec<String> {
106+
vec!["#", "Collateral", "Asset", "Expired", "Contract"]
107+
.into_iter()
108+
.map(String::from)
109+
.collect()
110+
}
111+
fn to_row(&self) -> Vec<String> {
112+
vec![
113+
self.index.to_string(),
114+
self.collateral.clone(),
115+
self.asset.clone(),
116+
self.expired.clone(),
117+
self.contract.clone(),
118+
]
119+
}
120+
}
121+
122+
impl TableData for WithdrawableSwapDisplay {
123+
fn get_header() -> Vec<String> {
124+
vec!["#", "Settlement Available", "Asset", "Contract"]
125+
.into_iter()
126+
.map(String::from)
127+
.collect()
128+
}
129+
fn to_row(&self) -> Vec<String> {
130+
vec![
131+
self.index.to_string(),
132+
self.settlement.clone(),
133+
self.asset.clone(),
134+
self.contract.clone(),
135+
]
136+
}
137+
}
138+
84139
fn render_table<T: TableData>(items: &[T], empty_msg: &str) {
85140
if items.is_empty() {
86141
println!(" ({empty_msg})");
@@ -121,3 +176,15 @@ pub fn display_collateral_table(displays: &[CollateralDisplay]) {
121176
pub fn display_user_token_table(displays: &[UserTokenDisplay]) {
122177
render_table(displays, "No option/grantor tokens found");
123178
}
179+
180+
pub fn display_active_swaps_table(active_swaps: &[ActiveSwapDisplay]) {
181+
render_table(active_swaps, "No swaps found");
182+
}
183+
184+
pub fn display_cancellable_swaps_table(cancellable_swaps: &[CancellableSwapDisplay]) {
185+
render_table(cancellable_swaps, "No cancellable swaps found");
186+
}
187+
188+
pub fn display_withdrawable_swaps_table(withdrawable_swaps: &[WithdrawableSwapDisplay]) {
189+
render_table(withdrawable_swaps, "No withdrawable swaps found");
190+
}

0 commit comments

Comments
 (0)