mirror of
https://github.com/daywalker90/cln-nip47.git
synced 2026-08-13 12:33:43 +02:00
some small payer_note and amount fixes
This commit is contained in:
parent
4e6b1b8341
commit
26fbbb881e
4 changed files with 110 additions and 77 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
|
@ -800,7 +800,7 @@ checksum = "f0efe882e02d206d8d279c20eb40e03baf7cb5136a1476dc084a324fbc3ec42d"
|
|||
[[package]]
|
||||
name = "nostr"
|
||||
version = "0.44.0"
|
||||
source = "git+https://github.com/daywalker90/nostr.git?branch=bolt12#829d51d2594ef14dc1499b8961514b671c27bf05"
|
||||
source = "git+https://github.com/daywalker90/nostr.git?branch=bolt12#f5acfd7b4651608a03712365dfb150855cef663c"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"base64",
|
||||
|
|
@ -824,7 +824,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "nostr-database"
|
||||
version = "0.44.0"
|
||||
source = "git+https://github.com/daywalker90/nostr.git?branch=bolt12#829d51d2594ef14dc1499b8961514b671c27bf05"
|
||||
source = "git+https://github.com/daywalker90/nostr.git?branch=bolt12#f5acfd7b4651608a03712365dfb150855cef663c"
|
||||
dependencies = [
|
||||
"lru",
|
||||
"nostr",
|
||||
|
|
@ -834,7 +834,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "nostr-gossip"
|
||||
version = "0.44.0"
|
||||
source = "git+https://github.com/daywalker90/nostr.git?branch=bolt12#829d51d2594ef14dc1499b8961514b671c27bf05"
|
||||
source = "git+https://github.com/daywalker90/nostr.git?branch=bolt12#f5acfd7b4651608a03712365dfb150855cef663c"
|
||||
dependencies = [
|
||||
"nostr",
|
||||
]
|
||||
|
|
@ -842,7 +842,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "nostr-relay-pool"
|
||||
version = "0.44.0"
|
||||
source = "git+https://github.com/daywalker90/nostr.git?branch=bolt12#829d51d2594ef14dc1499b8961514b671c27bf05"
|
||||
source = "git+https://github.com/daywalker90/nostr.git?branch=bolt12#f5acfd7b4651608a03712365dfb150855cef663c"
|
||||
dependencies = [
|
||||
"async-utility",
|
||||
"async-wsocket",
|
||||
|
|
@ -859,7 +859,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "nostr-sdk"
|
||||
version = "0.44.0"
|
||||
source = "git+https://github.com/daywalker90/nostr.git?branch=bolt12#829d51d2594ef14dc1499b8961514b671c27bf05"
|
||||
source = "git+https://github.com/daywalker90/nostr.git?branch=bolt12#f5acfd7b4651608a03712365dfb150855cef663c"
|
||||
dependencies = [
|
||||
"async-utility",
|
||||
"nostr",
|
||||
|
|
|
|||
|
|
@ -167,6 +167,9 @@ fn make_payment_received_from_listinvoices(
|
|||
settled_at,
|
||||
metadata: None,
|
||||
state: Some(state),
|
||||
offer_issuer: invoice_decoded.offer_issuer,
|
||||
payer_note: invoice_decoded.invreq_payer_note,
|
||||
offer_id: invoice_decoded.offer_id,
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
@ -234,9 +237,6 @@ async fn make_payment_sent_from_listpays(
|
|||
&String::new()
|
||||
};
|
||||
|
||||
let description;
|
||||
let description_hash;
|
||||
let amount;
|
||||
let created_at = Timestamp::from_secs(pay.created_at);
|
||||
let preimage = hex::encode(
|
||||
pay.preimage
|
||||
|
|
@ -245,60 +245,47 @@ async fn make_payment_sent_from_listpays(
|
|||
);
|
||||
let settled_at = Timestamp::from_secs(pay.completed_at.unwrap());
|
||||
|
||||
if invstring.is_empty() {
|
||||
description = pay.description.clone();
|
||||
description_hash = None;
|
||||
amount = if let Some(amt) = pay.amount_msat {
|
||||
amt.msat()
|
||||
} else {
|
||||
// Amount missing but required
|
||||
0
|
||||
}
|
||||
} else {
|
||||
let invoice_decoded = rpc
|
||||
.call_typed(&DecodeRequest {
|
||||
string: invstring.clone(),
|
||||
})
|
||||
.await?;
|
||||
let invoice_decoded = rpc
|
||||
.call_typed(&DecodeRequest {
|
||||
string: invstring.clone(),
|
||||
})
|
||||
.await?;
|
||||
|
||||
let not_invoice_err = Err(anyhow!(NOT_INV_ERR.to_owned()));
|
||||
let not_invoice_err = Err(anyhow!(NOT_INV_ERR.to_owned()));
|
||||
|
||||
if !invoice_decoded.valid {
|
||||
return not_invoice_err;
|
||||
}
|
||||
|
||||
description = match invoice_decoded.item_type {
|
||||
cln_rpc::model::responses::DecodeType::BOLT12_INVOICE => {
|
||||
invoice_decoded.offer_description
|
||||
}
|
||||
cln_rpc::model::responses::DecodeType::BOLT11_INVOICE => invoice_decoded.description,
|
||||
_ => return not_invoice_err,
|
||||
};
|
||||
description_hash = match invoice_decoded.item_type {
|
||||
cln_rpc::model::responses::DecodeType::BOLT12_INVOICE => None,
|
||||
cln_rpc::model::responses::DecodeType::BOLT11_INVOICE => {
|
||||
invoice_decoded.description_hash.map(|h| h.to_string())
|
||||
}
|
||||
_ => return not_invoice_err,
|
||||
};
|
||||
amount = match invoice_decoded.item_type {
|
||||
cln_rpc::model::responses::DecodeType::BOLT12_INVOICE => {
|
||||
invoice_decoded.invoice_amount_msat.unwrap().msat()
|
||||
}
|
||||
cln_rpc::model::responses::DecodeType::BOLT11_INVOICE => {
|
||||
if let Some(amt) = invoice_decoded.amount_msat {
|
||||
amt.msat()
|
||||
} else if let Some(a) = pay.amount_msat {
|
||||
a.msat()
|
||||
} else {
|
||||
// amount: `any` but have to put a value...
|
||||
0
|
||||
}
|
||||
}
|
||||
_ => return not_invoice_err,
|
||||
};
|
||||
if !invoice_decoded.valid {
|
||||
return not_invoice_err;
|
||||
}
|
||||
|
||||
let description = match invoice_decoded.item_type {
|
||||
cln_rpc::model::responses::DecodeType::BOLT12_INVOICE => invoice_decoded.offer_description,
|
||||
cln_rpc::model::responses::DecodeType::BOLT11_INVOICE => invoice_decoded.description,
|
||||
_ => return not_invoice_err,
|
||||
};
|
||||
let description_hash = match invoice_decoded.item_type {
|
||||
cln_rpc::model::responses::DecodeType::BOLT12_INVOICE => None,
|
||||
cln_rpc::model::responses::DecodeType::BOLT11_INVOICE => {
|
||||
invoice_decoded.description_hash.map(|h| h.to_string())
|
||||
}
|
||||
_ => return not_invoice_err,
|
||||
};
|
||||
let amount = match invoice_decoded.item_type {
|
||||
cln_rpc::model::responses::DecodeType::BOLT12_INVOICE => {
|
||||
invoice_decoded.invoice_amount_msat.unwrap().msat()
|
||||
}
|
||||
cln_rpc::model::responses::DecodeType::BOLT11_INVOICE => {
|
||||
if let Some(amt) = invoice_decoded.amount_msat {
|
||||
amt.msat()
|
||||
} else if let Some(a) = pay.amount_msat {
|
||||
a.msat()
|
||||
} else {
|
||||
// amount: `any` but have to put a value...
|
||||
0
|
||||
}
|
||||
}
|
||||
_ => return not_invoice_err,
|
||||
};
|
||||
|
||||
let fees_paid = if let Some(amt_sent) = pay.amount_sent_msat {
|
||||
amt_sent.msat() - amount
|
||||
} else {
|
||||
|
|
@ -327,6 +314,9 @@ async fn make_payment_sent_from_listpays(
|
|||
settled_at,
|
||||
metadata: None,
|
||||
state: Some(state),
|
||||
offer_issuer: invoice_decoded.offer_issuer,
|
||||
payer_note: invoice_decoded.invreq_payer_note,
|
||||
offer_id: invoice_decoded.offer_id,
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use cln_plugin::Plugin;
|
|||
use cln_rpc::{
|
||||
model::{
|
||||
requests::{DecodeRequest, FetchinvoiceRequest, OfferRequest, PayRequest, XpayRequest},
|
||||
responses::DecodeResponse,
|
||||
responses::{DecodeResponse, FetchinvoiceResponse},
|
||||
},
|
||||
primitives::{Amount, Secret},
|
||||
ClnRpc,
|
||||
|
|
@ -196,11 +196,13 @@ async fn pay_offer(
|
|||
) -> Result<(nip47::PayOfferResponse, Option<String>), (nip47::NIP47Error, Option<String>)> {
|
||||
let mut rpc = plugin.state().rpc_lock.lock().await;
|
||||
|
||||
let decoded_invoice = fetch_invoice(&mut rpc, ¶ms).await?;
|
||||
let fetch_invoice_response = fetch_invoice(&mut rpc, ¶ms).await?;
|
||||
|
||||
let id = get_payment_id(¶ms, &decoded_invoice)?;
|
||||
let decoded_bolt12 = decode_bolt12_invoice(&mut rpc, ¶ms, &fetch_invoice_response).await?;
|
||||
|
||||
let invoice_amt_msat = get_invoice_amount_msat(&decoded_invoice, &id)?;
|
||||
let id = get_payment_id(¶ms, &decoded_bolt12)?;
|
||||
|
||||
let invoice_amt_msat = get_invoice_amount_msat(&decoded_bolt12, ¶ms, &id)?;
|
||||
|
||||
let nwc_store =
|
||||
load_nwc_and_check_budget(&mut rpc, label, ¶ms, invoice_amt_msat, &id).await?;
|
||||
|
|
@ -209,22 +211,36 @@ async fn pay_offer(
|
|||
let use_xpay = check_cln_version(&my_version, &id)?;
|
||||
|
||||
if use_xpay {
|
||||
pay_with_xpay_full(&mut rpc, params, label, nwc_store, &id).await
|
||||
pay_with_xpay_full(
|
||||
&mut rpc,
|
||||
fetch_invoice_response.invoice,
|
||||
label,
|
||||
nwc_store,
|
||||
&id,
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
pay_with_legacy_full(&mut rpc, params, label, nwc_store, &id).await
|
||||
pay_with_legacy_full(
|
||||
&mut rpc,
|
||||
fetch_invoice_response.invoice,
|
||||
label,
|
||||
nwc_store,
|
||||
&id,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
async fn fetch_invoice(
|
||||
rpc: &mut ClnRpc,
|
||||
params: &nip47::PayOfferRequest,
|
||||
) -> Result<DecodeResponse, (nip47::NIP47Error, Option<String>)> {
|
||||
) -> Result<FetchinvoiceResponse, (nip47::NIP47Error, Option<String>)> {
|
||||
let bolt12_invoice = rpc
|
||||
.call_typed(&FetchinvoiceRequest {
|
||||
amount_msat: params.amount.map(Amount::from_msat),
|
||||
bip353: None,
|
||||
payer_metadata: None,
|
||||
payer_note: None,
|
||||
payer_note: params.payer_note.clone(),
|
||||
quantity: None,
|
||||
recurrence_counter: None,
|
||||
recurrence_label: None,
|
||||
|
|
@ -242,9 +258,17 @@ async fn fetch_invoice(
|
|||
params.id.clone(),
|
||||
)
|
||||
})?;
|
||||
Ok(bolt12_invoice)
|
||||
}
|
||||
|
||||
async fn decode_bolt12_invoice(
|
||||
rpc: &mut ClnRpc,
|
||||
params: &nip47::PayOfferRequest,
|
||||
fetch_invoice_resp: &FetchinvoiceResponse,
|
||||
) -> Result<DecodeResponse, (nip47::NIP47Error, Option<String>)> {
|
||||
let invoice_decoded = rpc
|
||||
.call_typed(&DecodeRequest {
|
||||
string: bolt12_invoice.invoice.clone(),
|
||||
string: fetch_invoice_resp.invoice.clone(),
|
||||
})
|
||||
.await
|
||||
.map_err(|e| {
|
||||
|
|
@ -256,7 +280,6 @@ async fn fetch_invoice(
|
|||
params.id.clone(),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(invoice_decoded)
|
||||
}
|
||||
|
||||
|
|
@ -286,10 +309,11 @@ fn get_payment_id(
|
|||
}
|
||||
|
||||
fn get_invoice_amount_msat(
|
||||
decoded_invoice: &DecodeResponse,
|
||||
invoice_decoded: &DecodeResponse,
|
||||
params: &nip47::PayOfferRequest,
|
||||
id: &str,
|
||||
) -> Result<u64, (nip47::NIP47Error, Option<String>)> {
|
||||
decoded_invoice
|
||||
let amt = invoice_decoded
|
||||
.invoice_amount_msat
|
||||
.as_ref()
|
||||
.ok_or_else(|| {
|
||||
|
|
@ -301,7 +325,20 @@ fn get_invoice_amount_msat(
|
|||
Some(id.to_owned()),
|
||||
)
|
||||
})
|
||||
.map(Amount::msat)
|
||||
.map(Amount::msat)?;
|
||||
if let Some(a) = params.amount {
|
||||
if amt != a {
|
||||
return Err((
|
||||
nip47::NIP47Error {
|
||||
code: nip47::ErrorCode::Internal,
|
||||
message: "amount in decoded bolt12 invoice does not match amount in request"
|
||||
.to_owned(),
|
||||
},
|
||||
Some(id.to_owned()),
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(amt)
|
||||
}
|
||||
|
||||
async fn load_nwc_and_check_budget(
|
||||
|
|
@ -450,20 +487,20 @@ fn map_cln_error_to_nip47(
|
|||
|
||||
async fn pay_with_xpay_full(
|
||||
rpc: &mut ClnRpc,
|
||||
params: nip47::PayOfferRequest,
|
||||
bolt12_invoice: String,
|
||||
label: &str,
|
||||
mut nwc_store: NwcStore,
|
||||
id: &str,
|
||||
) -> Result<(nip47::PayOfferResponse, Option<String>), (nip47::NIP47Error, Option<String>)> {
|
||||
let payment_result = rpc
|
||||
.call_typed(&XpayRequest {
|
||||
amount_msat: params.amount.map(Amount::from_msat),
|
||||
amount_msat: None,
|
||||
maxdelay: None,
|
||||
maxfee: None,
|
||||
partial_msat: None,
|
||||
retry_for: None,
|
||||
layers: None,
|
||||
invstring: params.offer,
|
||||
invstring: bolt12_invoice,
|
||||
})
|
||||
.await
|
||||
.map_err(|e| map_cln_error_to_nip47(&e, id, true))?;
|
||||
|
|
@ -486,14 +523,14 @@ async fn pay_with_xpay_full(
|
|||
|
||||
async fn pay_with_legacy_full(
|
||||
rpc: &mut ClnRpc,
|
||||
params: nip47::PayOfferRequest,
|
||||
bolt12_invoice: String,
|
||||
label: &str,
|
||||
mut nwc_store: NwcStore,
|
||||
id: &str,
|
||||
) -> Result<(nip47::PayOfferResponse, Option<String>), (nip47::NIP47Error, Option<String>)> {
|
||||
let payment_result = rpc
|
||||
.call_typed(&PayRequest {
|
||||
amount_msat: params.amount.map(Amount::from_msat),
|
||||
amount_msat: None,
|
||||
description: None,
|
||||
exemptfee: None,
|
||||
label: None,
|
||||
|
|
@ -505,7 +542,7 @@ async fn pay_with_legacy_full(
|
|||
retry_for: None,
|
||||
riskfactor: None,
|
||||
exclude: None,
|
||||
bolt11: params.offer,
|
||||
bolt11: bolt12_invoice,
|
||||
})
|
||||
.await
|
||||
.map_err(|e| map_cln_error_to_nip47(&e, id, false))?;
|
||||
|
|
|
|||
|
|
@ -1270,6 +1270,8 @@ async def test_pay_offer(node_factory, get_plugin, nostr_relay): # noqa: F811
|
|||
"method": "pay_offer",
|
||||
"params": {
|
||||
"offer": offer1["bolt12"],
|
||||
"amount": 3000,
|
||||
"payer_note": "for pizza",
|
||||
},
|
||||
}
|
||||
json_content = json.dumps(content)
|
||||
|
|
@ -1279,6 +1281,10 @@ async def test_pay_offer(node_factory, get_plugin, nostr_relay): # noqa: F811
|
|||
assert len(success_events) == 1
|
||||
|
||||
pay = l1.rpc.call("listpays", {})["pays"][0]
|
||||
decoded_pay_inv = l2.rpc.call(
|
||||
"listinvoices", {"payment_hash": pay["payment_hash"]}
|
||||
)["invoices"][0]
|
||||
assert decoded_pay_inv["invreq_payer_note"] == "for pizza"
|
||||
assert success_events[0]["result"]["preimage"] == pay["preimage"]
|
||||
|
||||
offer2 = l2.rpc.call(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue