Skip to content

Commit

Permalink
Separate tx send fees from amount
Browse files Browse the repository at this point in the history
  • Loading branch information
dangeross committed Jan 8, 2025
1 parent 7f338e7 commit dafa38d
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 46 deletions.
7 changes: 3 additions & 4 deletions lib/core/src/chain_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,9 +531,8 @@ impl ChainSwapHandler {
tx_id: lockup_tx_id.clone(),
timestamp: Some(utils::now()),
asset_id: LIQUID_BTC_ASSET_ID.to_string(),
amount_sat: swap.receiver_amount_sat,
// This should be: boltz fee + lockup fee + claim fee
fees_sat: lockup_tx_fees_sat + swap.claim_fees_sat,
amount: create_response.lockup_details.amount,
fees_sat: lockup_tx_fees_sat,
payment_type: PaymentType::Send,
is_confirmed: false,
unblinding_data: None,
Expand Down Expand Up @@ -867,7 +866,7 @@ impl ChainSwapHandler {
tx_id: claim_tx_id.clone(),
timestamp: Some(utils::now()),
asset_id: LIQUID_BTC_ASSET_ID.to_string(),
amount_sat: swap.receiver_amount_sat,
amount: swap.receiver_amount_sat,
fees_sat: 0,
payment_type: PaymentType::Receive,
is_confirmed: false,
Expand Down
34 changes: 19 additions & 15 deletions lib/core/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1352,7 +1352,7 @@ pub struct PaymentTxData {
/// The onchain tx amount.
///
/// In case of an outbound payment (Send), this is the payer amount. Otherwise it's the receiver amount.
pub amount_sat: u64,
pub amount: u64,

/// The onchain fees of this tx
pub fees_sat: u64,
Expand Down Expand Up @@ -1617,6 +1617,22 @@ impl Payment {
swap: Option<PaymentSwapData>,
details: PaymentDetails,
) -> Payment {
let (amount_sat, fees_sat) = match swap.as_ref() {
Some(s) => match tx.payment_type {
// For receive swaps, to avoid some edge case issues related to potential past
// overpayments, we use the actual claim value as the final received amount
// for fee calculation.
PaymentType::Receive => (tx.amount, s.payer_amount_sat - tx.amount),
PaymentType::Send => (
s.receiver_amount_sat,
s.payer_amount_sat - s.receiver_amount_sat,
),
},
None => match tx.payment_type {
PaymentType::Receive => (tx.amount, 0),
PaymentType::Send => (tx.amount, tx.fees_sat),
},
};
Payment {
tx_id: Some(tx.tx_id),
unblinding_data: tx.unblinding_data,
Expand Down Expand Up @@ -1649,20 +1665,8 @@ impl Payment {
.timestamp
.or(swap.as_ref().map(|s| s.created_at))
.unwrap_or(utils::now()),
amount_sat: tx.amount_sat,
fees_sat: match swap.as_ref() {
Some(s) => match tx.payment_type {
// For receive swaps, to avoid some edge case issues related to potential past
// overpayments, we use the actual claim value as the final received amount
// for fee calculation.
PaymentType::Receive => s.payer_amount_sat - tx.amount_sat,
PaymentType::Send => s.payer_amount_sat - s.receiver_amount_sat,
},
None => match tx.payment_type {
PaymentType::Receive => 0,
PaymentType::Send => tx.fees_sat,
},
},
amount_sat,
fees_sat,
swapper_fees_sat: swap.as_ref().map(|s| s.swapper_fees_sat),
payment_type: tx.payment_type,
status: match &swap {
Expand Down
6 changes: 5 additions & 1 deletion lib/core/src/persist/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ pub(crate) fn current_migrations() -> Vec<&'static str> {
ALTER TABLE receive_swaps ADD COLUMN timeout_block_height INTEGER NOT NULL DEFAULT 0;
ALTER TABLE send_swaps ADD COLUMN timeout_block_height INTEGER NOT NULL DEFAULT 0;
",
"ALTER TABLE payment_tx_data ADD COLUMN asset_id TEXT NOT NULL DEFAULT '6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d';",
"
ALTER TABLE payment_tx_data ADD COLUMN asset_id TEXT NOT NULL DEFAULT '6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d';
ALTER TABLE payment_tx_data RENAME COLUMN amount_sat TO amount;
UPDATE payment_tx_data SET amount = amount - fees_sat WHERE payment_type = 1;
",
]
}
42 changes: 26 additions & 16 deletions lib/core/src/persist/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,22 @@ impl Persister {
.pop_first()
.map(|(asset_id, balance)| (asset_id.to_hex(), balance));
}
let Some((asset_id, amount_sat)) = balance else {
log::warn!("Attempted to persist a payment with no balance: tx_id {tx_id}");
return Ok(());
let (asset_id, payment_type, amount) = match balance {
Some((asset_id, asset_amount)) => {
let payment_type = match asset_amount >= 0 {
true => PaymentType::Receive,
false => PaymentType::Send,
};
let mut amount = asset_amount.unsigned_abs();
if payment_type == PaymentType::Send && asset_id.eq(LIQUID_BTC_ASSET_ID.as_str()) {
amount = amount.saturating_sub(tx.fee);
}
(asset_id, payment_type, amount)
}
None => {
log::warn!("Attempted to persist a payment with no balance: tx_id {tx_id}");
return Ok(());
}
};
let maybe_script_pubkey = tx
.outputs
Expand All @@ -134,12 +147,9 @@ impl Persister {
tx_id: tx_id.clone(),
timestamp: tx.timestamp,
asset_id,
amount_sat: amount_sat.unsigned_abs(),
amount,
fees_sat: tx.fee,
payment_type: match amount_sat >= 0 {
true => PaymentType::Receive,
false => PaymentType::Send,
},
payment_type,
is_confirmed: is_tx_confirmed,
unblinding_data: Some(unblinding_data),
},
Expand All @@ -158,7 +168,7 @@ impl Persister {
"SELECT tx_id,
timestamp,
asset_id,
amount_sat,
amount,
fees_sat,
payment_type,
is_confirmed,
Expand All @@ -172,7 +182,7 @@ impl Persister {
tx_id: row.get(0)?,
timestamp: row.get(1)?,
asset_id: row.get(2)?,
amount_sat: row.get(3)?,
amount: row.get(3)?,
fees_sat: row.get(4)?,
payment_type: row.get(5)?,
is_confirmed: row.get(6)?,
Expand All @@ -197,7 +207,7 @@ impl Persister {
tx_id,
timestamp,
asset_id,
amount_sat,
amount,
fees_sat,
payment_type,
is_confirmed,
Expand All @@ -207,7 +217,7 @@ impl Persister {
ON CONFLICT (tx_id)
DO UPDATE SET timestamp = CASE WHEN excluded.is_confirmed = 1 THEN excluded.timestamp ELSE timestamp END,
asset_id = excluded.asset_id,
amount_sat = excluded.amount_sat,
amount = excluded.amount,
fees_sat = excluded.fees_sat,
payment_type = excluded.payment_type,
is_confirmed = excluded.is_confirmed,
Expand All @@ -217,7 +227,7 @@ impl Persister {
&ptx.tx_id,
ptx.timestamp.or(Some(utils::now())),
ptx.asset_id,
ptx.amount_sat,
ptx.amount,
ptx.fees_sat,
ptx.payment_type,
ptx.is_confirmed,
Expand Down Expand Up @@ -372,7 +382,7 @@ impl Persister {
ptx.tx_id,
ptx.timestamp,
ptx.asset_id,
ptx.amount_sat,
ptx.amount,
ptx.fees_sat,
ptx.payment_type,
ptx.is_confirmed,
Expand Down Expand Up @@ -415,7 +425,7 @@ impl Persister {
cs.pair_fees_json,
cs.actual_payer_amount_sat,
cs.accepted_receiver_amount_sat,
rtx.amount_sat,
rtx.amount,
pd.destination,
pd.description,
pd.lnurl_info_json
Expand Down Expand Up @@ -463,7 +473,7 @@ impl Persister {
tx_id: tx_id.to_string(),
timestamp: row.get(1)?,
asset_id: row.get(2)?,
amount_sat: row.get(3)?,
amount: row.get(3)?,
fees_sat: row.get(4)?,
payment_type: row.get(5)?,
is_confirmed: row.get(6)?,
Expand Down
2 changes: 1 addition & 1 deletion lib/core/src/receive_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ impl ReceiveSwapHandler {
tx_id: claim_tx_id.clone(),
timestamp: Some(utils::now()),
asset_id: LIQUID_BTC_ASSET_ID.to_string(),
amount_sat: swap.receiver_amount_sat,
amount: swap.receiver_amount_sat,
fees_sat: 0,
payment_type: PaymentType::Receive,
is_confirmed: false,
Expand Down
9 changes: 2 additions & 7 deletions lib/core/src/sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1306,15 +1306,10 @@ impl LiquidSdk {
receiver_amount_sat,
)
.await?;
let tx_id = tx.txid().to_string();
let tx_fees_sat = tx.all_fees().values().sum::<u64>();
ensure_sdk!(tx_fees_sat <= fees_sat, PaymentError::InvalidOrExpiredFees);

let tx_id = tx.txid().to_string();
let amount_sat = if asset_id.eq(LIQUID_BTC_ASSET_ID.as_str()) {
receiver_amount_sat + tx_fees_sat
} else {
receiver_amount_sat
};
info!(
"Built onchain L-BTC tx with receiver_amount_sat = {receiver_amount_sat}, fees_sat = {fees_sat} and txid = {tx_id}"
);
Expand All @@ -1327,7 +1322,7 @@ impl LiquidSdk {
let tx_data = PaymentTxData {
tx_id: tx_id.clone(),
timestamp: Some(utils::now()),
amount_sat,
amount: receiver_amount_sat,
fees_sat,
payment_type: PaymentType::Send,
is_confirmed: false,
Expand Down
2 changes: 1 addition & 1 deletion lib/core/src/send_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ impl SendSwapHandler {
tx_id: lockup_tx_id.clone(),
timestamp: Some(utils::now()),
asset_id: LIQUID_BTC_ASSET_ID.to_string(),
amount_sat: swap.payer_amount_sat,
amount: create_response.expected_amount,
fees_sat: lockup_tx_fees_sat,
payment_type: PaymentType::Send,
is_confirmed: false,
Expand Down
2 changes: 1 addition & 1 deletion lib/core/src/test_utils/persist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ pub(crate) fn new_payment_tx_data(payment_type: PaymentType) -> PaymentTxData {
tx_id: generate_random_string(4),
timestamp: None,
asset_id: LIQUID_BTC_ASSET_ID.to_string(),
amount_sat: 0,
amount: 0,
fees_sat: 0,
payment_type,
is_confirmed: false,
Expand Down

0 comments on commit dafa38d

Please sign in to comment.