Skip to content

Commit e196a91

Browse files
Multi-asset send/receive (#645)
* Multi-asset send/receive * Apply suggestions from code review Co-authored-by: Daniel Granhão <32176319+danielgranhao@users.noreply.github.com> * Log the prepare asset_id --------- Co-authored-by: Daniel Granhão <32176319+danielgranhao@users.noreply.github.com>
1 parent 7841939 commit e196a91

File tree

26 files changed

+2754
-963
lines changed

26 files changed

+2754
-963
lines changed

cli/src/commands.rs

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,16 @@ pub(crate) enum Command {
3333
#[arg(long)]
3434
address: Option<String>,
3535

36-
/// The amount in satoshi to pay, in case of a direct Liquid address
37-
/// or amount-less BIP21
36+
/// The amount to pay, in case of a direct Liquid address or amount-less BIP21.
37+
/// If an asset id is provided, it is the base unit of that asset depending on its
38+
/// precision, otherwise in satoshi.
3839
#[arg(short, long)]
39-
amount_sat: Option<u64>,
40+
receiver_amount: Option<u64>,
41+
42+
/// Optional id of the asset, in case of a direct Liquid address
43+
/// or amount-less BIP21
44+
#[clap(long = "asset")]
45+
asset_id: Option<String>,
4046

4147
/// Whether or not this is a drain operation. If true, all available funds will be used.
4248
#[arg(short, long)]
@@ -72,10 +78,15 @@ pub(crate) enum Command {
7278
#[arg(short = 'm', long = "method")]
7379
payment_method: Option<PaymentMethod>,
7480

75-
/// Amount the payer will send, in satoshi
76-
/// If not specified, it will generate a BIP21 URI/Liquid address with no amount
81+
/// The amount the payer should send. If an asset id is provided, it is the base
82+
/// unit of that asset depending on its precision, otherwise in satoshi.
83+
/// If not specified, it will generate a BIP21 URI/address with no amount.
7784
#[arg(short, long)]
78-
payer_amount_sat: Option<u64>,
85+
payer_amount: Option<u64>,
86+
87+
/// Optional id of the asset to receive when the 'payment_method' is "liquid"
88+
#[clap(long = "asset")]
89+
asset_id: Option<String>,
7990

8091
/// Optional description for the invoice
8192
#[clap(short = 'd', long = "description")]
@@ -118,6 +129,10 @@ pub(crate) enum Command {
118129
#[clap(short = 'o', long = "offset")]
119130
offset: Option<u32>,
120131

132+
/// Optional id of the asset for Liquid payment method
133+
#[clap(long = "asset")]
134+
asset_id: Option<String>,
135+
121136
/// Optional Liquid BIP21 URI/address for Liquid payment method
122137
#[clap(short = 'd', long = "destination")]
123138
destination: Option<String>,
@@ -270,19 +285,29 @@ pub(crate) async fn handle_command(
270285
Ok(match command {
271286
Command::ReceivePayment {
272287
payment_method,
273-
payer_amount_sat,
288+
payer_amount,
289+
asset_id,
274290
description,
275291
use_description_hash,
276292
} => {
293+
let amount = match asset_id {
294+
Some(asset_id) => Some(ReceiveAmount::Asset {
295+
asset_id,
296+
payer_amount,
297+
}),
298+
None => {
299+
payer_amount.map(|payer_amount_sat| ReceiveAmount::Bitcoin { payer_amount_sat })
300+
}
301+
};
277302
let prepare_response = sdk
278303
.prepare_receive_payment(&PrepareReceiveRequest {
279-
payer_amount_sat,
280304
payment_method: payment_method.unwrap_or(PaymentMethod::Lightning),
305+
amount: amount.clone(),
281306
})
282307
.await?;
283308

284309
let fees = prepare_response.fees_sat;
285-
let confirmation_msg = match payer_amount_sat {
310+
let confirmation_msg = match amount {
286311
Some(_) => format!("Fees: {fees} sat. Are the fees acceptable? (y/N)"),
287312
None => {
288313
let min = prepare_response.min_payer_amount_sat;
@@ -336,13 +361,14 @@ pub(crate) async fn handle_command(
336361
invoice,
337362
offer,
338363
address,
339-
amount_sat,
364+
receiver_amount,
365+
asset_id,
340366
drain,
341367
delay,
342368
} => {
343369
let destination = match (invoice, offer, address) {
344370
(Some(invoice), None, None) => Ok(invoice),
345-
(None, Some(offer), None) => match amount_sat {
371+
(None, Some(offer), None) => match receiver_amount {
346372
Some(_) => Ok(offer),
347373
None => Err(anyhow!(
348374
"Must specify an amount for a BOLT12 offer."
@@ -358,10 +384,16 @@ pub(crate) async fn handle_command(
358384
"Must specify either a BOLT11 invoice, a BOLT12 offer or a direct/BIP21 address."
359385
))
360386
}?;
361-
let amount = match (amount_sat, drain.unwrap_or(false)) {
362-
(Some(amount_sat), _) => Some(PayAmount::Receiver { amount_sat }),
363-
(_, true) => Some(PayAmount::Drain),
364-
(_, _) => None,
387+
let amount = match (asset_id, receiver_amount, drain.unwrap_or(false)) {
388+
(Some(asset_id), Some(receiver_amount), _) => Some(PayAmount::Asset {
389+
asset_id,
390+
receiver_amount,
391+
}),
392+
(None, Some(receiver_amount_sat), _) => Some(PayAmount::Bitcoin {
393+
receiver_amount_sat,
394+
}),
395+
(_, _, true) => Some(PayAmount::Drain),
396+
_ => None,
365397
};
366398

367399
let prepare_response = sdk
@@ -404,8 +436,8 @@ pub(crate) async fn handle_command(
404436
} => {
405437
let amount = match drain.unwrap_or(false) {
406438
true => PayAmount::Drain,
407-
false => PayAmount::Receiver {
408-
amount_sat: receiver_amount_sat.ok_or(anyhow::anyhow!(
439+
false => PayAmount::Bitcoin {
440+
receiver_amount_sat: receiver_amount_sat.ok_or(anyhow::anyhow!(
409441
"Must specify `receiver_amount_sat` if not draining"
410442
))?,
411443
},
@@ -492,13 +524,21 @@ pub(crate) async fn handle_command(
492524
to_timestamp,
493525
limit,
494526
offset,
527+
asset_id,
495528
destination,
496529
address,
497530
sort_ascending,
498531
} => {
499-
let details = match (destination, address) {
500-
(Some(destination), None) => Some(ListPaymentDetails::Liquid { destination }),
501-
(None, Some(address)) => Some(ListPaymentDetails::Bitcoin { address }),
532+
let details = match (asset_id.clone(), destination.clone(), address) {
533+
(None, Some(_), None) | (Some(_), None, None) | (Some(_), Some(_), None) => {
534+
Some(ListPaymentDetails::Liquid {
535+
asset_id,
536+
destination,
537+
})
538+
}
539+
(None, None, Some(address)) => Some(ListPaymentDetails::Bitcoin {
540+
address: Some(address),
541+
}),
502542
_ => None,
503543
};
504544

0 commit comments

Comments
 (0)