Skip to content

Migrate from lnurl-rs to fedimint-lnurl#426

Draft
joschisan wants to merge 2 commits intofedimint:masterfrom
joschisan:lnurl
Draft

Migrate from lnurl-rs to fedimint-lnurl#426
joschisan wants to merge 2 commits intofedimint:masterfrom
joschisan:lnurl

Conversation

@joschisan
Copy link
Copy Markdown

@joschisan joschisan commented Apr 3, 2026

Summary

  • Replace lnurl-rs crate with fedimint-lnurl (pinned to conduit's git rev), aligning with the conduit app's approach to LNURL handling
  • Add new lnurl.rs module with conduit-style FRB-exposed wrapper types: LnurlWrapper, PayResponseWrapper, parse_lnurl, lnurl_fetch_limits, lnurl_resolve
  • Rewrite get_invoice_from_lnaddress_or_lnurl() internals to use fedimint_lnurl while keeping the same signature/behavior so the Flutter-side flow is unchanged
  • Remove dead code: send_lnaddress() (Rust + Dart wrapper), unused lnAddress field on SendPayment widget

🤖 Generated with Claude Code

@m1sterc001guy
Copy link
Copy Markdown
Collaborator

Is the main benefit of doing this to just eliminate a dependency?

@joschisan joschisan force-pushed the lnurl branch 2 times, most recently from 0e06836 to 69b53fb Compare April 6, 2026 08:53
Replace the lnurl-rs crate with fedimint-lnurl, following the pattern
used in the conduit app. Adds a new lnurl.rs module with conduit-style
wrapper types (LnurlWrapper, PayResponseWrapper) exposed via FRB.

Rewrites get_invoice_from_lnaddress_or_lnurl() internals to use
fedimint_lnurl while keeping the same signature. Removes dead code:
send_lnaddress() in Rust, the sendLnaddress Dart wrapper, and the
unused lnAddress field on SendPayment.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@joschisan
Copy link
Copy Markdown
Author

joschisan commented Apr 6, 2026

Is the main benefit of doing this to just eliminate a dependency?

This and of course having this tested with our own recurring payment infra. We then also have the opportunity for lnv2 to enable fedimint-lnurl to bypass the recurringd, so a payment between two fedimint clients via lnurl will be like a silent payment.

@joschisan joschisan marked this pull request as draft April 7, 2026 13:12
Copy link
Copy Markdown
Collaborator

@m1sterc001guy m1sterc001guy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK. Tested and it works. I updated the dependency to use v0.11.0-beta.1 and left a few comments. Let's address the comments then merge

Comment on lines +28 to +43
const MERCHANT_PATTERNS: &[&str] = &[
r"(?i)za\.co\.electrum\.picknpay",
r"(?i)za\.co\.ecentric",
r"(wigroup\.co|yoyogroup\.co)",
r"(zapper\.com|\d+\.zap\.pe)",
r"payat\.io",
r"paynow\.netcash\.co\.za",
r"paynow\.sagepay\.co\.za",
r"^SK-\d{1,}-\d{23}$",
r"transactionjunction\.co\.za",
r"^CRSTPC-\d+-\d+-\d+-\d+-\d+$",
r"scantopay\.io",
r"snapscan",
r"^\d{10}$",
r"^.{2}/.{4}/.{20}$",
];
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vaguely familiar with MoneyBadger and would love to support it, but I'm not sure what these are. Could you explain?

r"^.{2}/.{4}/.{20}$",
];

#[frb(sync)]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I can tell, parse_lnurl is only called on the rust side. Do we need this frb annotation here?

Comment on lines +74 to +81
// Check if input matches MoneyBadger merchant pattern
if MERCHANT_PATTERNS
.iter()
.any(|pattern| Regex::new(pattern).unwrap().is_match(request))
{
let address = format!("{}@cryptoqr.net", strict_uri_encode(request));

return fedimint_lnurl::parse_address(&address).map(LnurlWrapper);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gonna need a little more context on this part too :)

Comment on lines +87 to +122
#[frb(opaque)]
pub struct PayResponseWrapper(fedimint_lnurl::PayResponse);

impl PayResponseWrapper {
#[frb(sync, getter)]
pub fn min_sats(&self) -> i64 {
self.0.min_sendable as i64 / 1000
}

#[frb(sync, getter)]
pub fn max_sats(&self) -> i64 {
self.0.max_sendable as i64 / 1000
}

#[frb(sync)]
pub fn is_fixed_amount(&self) -> bool {
self.0.min_sendable == self.0.max_sendable
}
}

#[frb]
pub async fn lnurl_fetch_limits(lnurl: &LnurlWrapper) -> Result<PayResponseWrapper, String> {
fedimint_lnurl::request(&lnurl.0)
.await
.map(PayResponseWrapper)
}

#[frb]
pub async fn lnurl_resolve(
pay_response: &PayResponseWrapper,
amount_sats: i64,
) -> Result<String, String> {
fedimint_lnurl::get_invoice(&pay_response.0, amount_sats as u64 * 1000)
.await
.map(|response| response.pr.to_string())
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to be used anywhere? Is it necessary?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants