Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show JIT channel fee in wallet history #1103

Merged
merged 1 commit into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions coordinator/src/node/channel_opening_fee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,20 @@ use bitcoin::hashes::hex::ToHex;
use bitcoin::secp256k1::ThirtyTwoByteHash;
use lightning::ln::PaymentHash;
use lightning_invoice::Invoice;
use ln_dlc_node::channel::JIT_FEE_INVOICE_DESCRIPTION_PREFIX;
use ln_dlc_node::PaymentInfo;

impl Node {
pub async fn channel_opening_fee_invoice(
&self,
amount: u64,
funding_txid: String,
description: Option<String>,
expiry: Option<u32>,
) -> Result<Invoice> {
let invoice = self.inner.create_invoice(
amount,
description.unwrap_or_default(),
expiry.unwrap_or(180),
)?;
let description = format!("{JIT_FEE_INVOICE_DESCRIPTION_PREFIX}{funding_txid}");
let invoice = self
.inner
.create_invoice(amount, description, expiry.unwrap_or(180))?;
let payment_hash = invoice.payment_hash().into_32();
let payment_hash_hex = payment_hash.to_hex();

Expand Down
8 changes: 1 addition & 7 deletions coordinator/src/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,6 @@ pub struct InvoiceParams {
pub struct OpenChannelFeeInvoiceParams {
pub amount: u64,
pub channel_funding_txid: String,
pub description: Option<String>,
pub expiry: Option<u32>,
}

Expand Down Expand Up @@ -237,12 +236,7 @@ pub async fn get_open_channel_fee_invoice(
) -> Result<String, AppError> {
let invoice = state
.node
.channel_opening_fee_invoice(
params.amount,
params.channel_funding_txid,
params.description,
params.expiry,
)
.channel_opening_fee_invoice(params.amount, params.channel_funding_txid, params.expiry)
.await
.map_err(|e| AppError::InternalServerError(format!("Failed to create invoice: {e:#}")))?;

Expand Down
4 changes: 4 additions & 0 deletions crates/ln-dlc-node/src/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ use std::str::FromStr;
use time::OffsetDateTime;
use uuid::Uuid;

/// The prefix used in the description field of an JIT channel opening invoice to be paid by the
/// client.
pub const JIT_FEE_INVOICE_DESCRIPTION_PREFIX: &str = "jit-channel-fee-";

/// We introduce a shadow copy of the Lightning channel as LDK deletes channels from its
/// [`ChannelManager`] as soon as they are closed.
///
Expand Down
20 changes: 17 additions & 3 deletions mobile/lib/features/wallet/domain/wallet_history.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'package:get_10101/common/domain/model.dart';
import 'payment_flow.dart';
import 'package:get_10101/bridge_generated/bridge_definitions.dart' as rust;

enum WalletHistoryItemDataType { lightning, onChain, trade, orderMatchingFee }
enum WalletHistoryItemDataType { lightning, onChain, trade, orderMatchingFee, jitChannelFee }

enum WalletHistoryStatus { pending, confirmed }

Expand All @@ -13,10 +13,10 @@ class WalletHistoryItemData {
final WalletHistoryStatus status;
final DateTime timestamp;

// on-chain
// on-chain (payment txid) and jit fee (funding txid)
final String? txid;

// lightning
// lightning and jit fee
final String? paymentHash;

// trade
Expand Down Expand Up @@ -78,6 +78,20 @@ class WalletHistoryItemData {
orderId: type.orderId);
}

if (item.walletType is rust.WalletType_JitChannelFee) {
rust.WalletType_JitChannelFee type = item.walletType as rust.WalletType_JitChannelFee;

return WalletHistoryItemData(
flow: flow,
amount: amount,
type: WalletHistoryItemDataType.jitChannelFee,
status: status,
timestamp: timestamp,
paymentHash: type.paymentHash,
txid: type.fundingTxid,
);
}

return WalletHistoryItemData(
flow: flow,
amount: amount,
Expand Down
21 changes: 15 additions & 6 deletions mobile/lib/features/wallet/wallet_history_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ class WalletHistoryItem extends StatelessWidget {
Icons.bar_chart,
size: flowIconSize,
);
} else if (data.type == WalletHistoryItemDataType.orderMatchingFee) {
} else if (data.type == WalletHistoryItemDataType.orderMatchingFee ||
data.type == WalletHistoryItemDataType.jitChannelFee) {
return const Icon(
Icons.toll,
size: flowIconSize,
Expand Down Expand Up @@ -66,6 +67,8 @@ class WalletHistoryItem extends StatelessWidget {
}
case WalletHistoryItemDataType.orderMatchingFee:
return "Matching fee";
case WalletHistoryItemDataType.jitChannelFee:
return "Channel opening fee";
}
}();

Expand All @@ -74,6 +77,7 @@ class WalletHistoryItem extends StatelessWidget {
case WalletHistoryItemDataType.lightning:
case WalletHistoryItemDataType.trade:
case WalletHistoryItemDataType.orderMatchingFee:
case WalletHistoryItemDataType.jitChannelFee:
return "off-chain";
case WalletHistoryItemDataType.onChain:
return "on-chain";
Expand Down Expand Up @@ -158,16 +162,21 @@ class WalletHistoryItem extends StatelessWidget {
}

Widget showItemDetails(String title, BuildContext context) {
var [label, id] = () {
List<HistoryDetail> details = () {
switch (data.type) {
case WalletHistoryItemDataType.lightning:
return ["Payment hash", data.paymentHash ?? ""];
return [HistoryDetail(label: "Payment hash", value: data.paymentHash ?? "")];
case WalletHistoryItemDataType.onChain:
return ["Transaction id", data.txid ?? ""];
return [HistoryDetail(label: "Transaction id", value: data.txid ?? "")];
case WalletHistoryItemDataType.trade:
case WalletHistoryItemDataType.orderMatchingFee:
final orderId = data.orderId!.substring(0, 8);
return ["Order", orderId];
return [HistoryDetail(label: "Order", value: orderId)];
case WalletHistoryItemDataType.jitChannelFee:
return [
HistoryDetail(label: "Payment hash", value: data.paymentHash ?? ""),
HistoryDetail(label: "Funding transaction id", value: data.txid ?? "")
];
}
}();

Expand All @@ -185,7 +194,7 @@ class WalletHistoryItem extends StatelessWidget {
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
HistoryDetail(label: label, value: id),
...details,
HistoryDetail(
label: "Amount", value: formatSats(Amount(data.amount.sats * directionMultiplier))),
HistoryDetail(label: "Date and time", value: dateFormat.format(data.timestamp)),
Expand Down
20 changes: 16 additions & 4 deletions mobile/native/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,22 @@ pub struct WalletHistoryItem {

#[derive(Clone, Debug)]
pub enum WalletType {
OnChain { txid: String },
Lightning { payment_hash: String },
Trade { order_id: String },
OrderMatchingFee { order_id: String },
OnChain {
txid: String,
},
Lightning {
payment_hash: String,
},
Trade {
order_id: String,
},
OrderMatchingFee {
order_id: String,
},
JitChannelFee {
funding_txid: String,
payment_hash: String,
},
}

#[derive(Clone, Debug, Default)]
Expand Down
19 changes: 15 additions & 4 deletions mobile/native/src/ln_dlc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use itertools::Itertools;
use lightning::ln::channelmanager::ChannelDetails;
use lightning::util::events::Event;
use lightning_invoice::Invoice;
use ln_dlc_node::channel::JIT_FEE_INVOICE_DESCRIPTION_PREFIX;
use ln_dlc_node::config::app_config;
use ln_dlc_node::node::rust_dlc_manager::subchannel::LNChannelManager;
use ln_dlc_node::node::rust_dlc_manager::ChannelId;
Expand Down Expand Up @@ -348,11 +349,21 @@ fn keep_wallet_balance_and_history_up_to_date(node: &Node) -> Result<()> {
let payment_hash = hex::encode(details.payment_hash.0);

let description = &details.description;
let wallet_type = match description.strip_prefix(FEE_INVOICE_DESCRIPTION_PREFIX_TAKER) {
Some(order_id) => api::WalletType::OrderMatchingFee {
let wallet_type = if let Some(order_id) =
description.strip_prefix(FEE_INVOICE_DESCRIPTION_PREFIX_TAKER)
{
api::WalletType::OrderMatchingFee {
order_id: order_id.to_string(),
},
None => api::WalletType::Lightning { payment_hash },
}
} else if let Some(funding_txid) =
description.strip_prefix(JIT_FEE_INVOICE_DESCRIPTION_PREFIX)
{
api::WalletType::JitChannelFee {
funding_txid: funding_txid.to_string(),
payment_hash,
}
} else {
api::WalletType::Lightning { payment_hash }
};

Some(api::WalletHistoryItem {
Expand Down