Files
hash-wallet/lib/core/open_crypto_pay/lnurl.dart
T
c1e9668b1e CW-969-Add-DFX-s-Open-CryptoPay (#2122)
* feat: Add Open CryptoPay for sending

* bug: Fix sending Open CryptoPay for eth

* feat: add transaction dismissal

* style: remove print statements from OCP

* feat: add support for Monero over OCP

* bug: Hide "Add to Address Book" on OCP transactions

* style: revert code style in send_view_model.dart

* style: revert code style in send_view_model.dart

* feat: set failure state if it fails to create an OCP transaction

* Update lib/view_model/send/send_view_model.dart

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
2025-04-10 04:03:06 +02:00

79 lines
2.4 KiB
Dart

import 'dart:convert';
import 'package:bech32/bech32.dart';
Uri decodeLNURL(String encodedUrl) {
Uri decodedUri;
/// The URL doesn't have to be encoded at all as per LUD-17: Protocol schemes and raw (non bech32-encoded) URLs.
/// https://github.com/lnurl/luds/blob/luds/17.md
/// Handle non bech32-encoded LNURL
final lud17prefixes = ['lnurlw', 'lnurlc', 'lnurlp', 'keyauth'];
decodedUri = Uri.parse(encodedUrl);
for (final prefix in lud17prefixes) {
if (decodedUri.scheme.contains(prefix)) {
decodedUri = decodedUri.replace(scheme: prefix);
}
}
if (lud17prefixes.contains(decodedUri.scheme)) {
/// If the non-bech32 LNURL is a Tor address, the port has to be http instead of https for the clearnet LNURL so check if the host ends with '.onion' or '.onion.'
decodedUri = decodedUri.replace(
scheme: decodedUri.host.endsWith('onion') ||
decodedUri.host.endsWith('onion.')
? 'http'
: 'https');
} else {
/// Try to parse the input as a lnUrl. Will throw an error if it fails.
final lnUrl = _findLnUrl(encodedUrl);
/// Decode the lnurl using bech32
final bech32 = const Bech32Codec().decode(lnUrl, lnUrl.length);
decodedUri = Uri.parse(utf8.decode(_convert(bech32.data, 5, 8, false)));
}
return decodedUri;
}
/// Parse and return a given lnurl string if it's valid. Will remove
/// `lightning:` from the beginning of it if present.
String _findLnUrl(String input) {
final res = RegExp(
r',*?((lnurl)([0-9]+[a-z0-9]+))',
).allMatches(input.toLowerCase());
if (res.length == 1) {
return res.first.group(0)!;
} else {
throw ArgumentError('Not a valid lnurl string');
}
}
/// Taken from bech32 (bitcoinjs): https://github.com/bitcoinjs/bech32
List<int> _convert(List<int> data, int inBits, int outBits, bool pad) {
var value = 0;
var bits = 0;
final maxV = (1 << outBits) - 1;
final result = <int>[];
for (final dataValue in data) {
value = (value << inBits) | dataValue;
bits += inBits;
while (bits >= outBits) {
bits -= outBits;
result.add((value >> bits) & maxV);
}
}
if (pad) {
if (bits > 0) result.add((value << (outBits - bits)) & maxV);
} else {
if (bits >= inBits) throw Exception('Excess padding');
if ((value << (outBits - bits)) & maxV > 0) {
throw Exception('Non-zero padding');
}
}
return result;
}