Skip to content

Commit

Permalink
Remove query parameters from address and parse amount
Browse files Browse the repository at this point in the history
Did not modify PaymentUriInfo to avoid issues with segwit variants
  • Loading branch information
takenagain committed Mar 17, 2024
1 parent 3b44149 commit 101ce94
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,10 @@ class _AmountAddressStepState extends State<AmountAddressStep> {
widget.addressController.text = address;
}

set qrAmount(String amount) {
widget.amountController.text = amount;
}

void showWrongCoinDialog(PaymentUriInfo uriInfo) {
dialogBloc.dialog = showDialog<void>(
context: context,
Expand Down Expand Up @@ -301,15 +305,17 @@ class _AmountAddressStepState extends State<AmountAddressStep> {
barcode = 'Error';
});
} else {
final address = removeBlockchainPrefix(result);
final uri = Uri.tryParse(address.trim());
final String address = getAddressFromUri(result.trim());
final String amount = getParameterValue(result.trim(), 'amount');
final Uri uri = Uri.tryParse(result.trim());

setState(() {
final PaymentUriInfo uriInfo = PaymentUriInfo.fromUri(uri);
if (uriInfo != null) {
handlePaymentData(uriInfo);
} else {
handleQrAdress(address);
qrAmount = amount ?? '';
}
});
}
Expand Down
50 changes: 29 additions & 21 deletions lib/utils/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,35 @@ class PaymentUriInfo {
final String amount;
}

/// Returns the value of a [parameter] from the [address].
/// Returns null if the [parameter] is not found.
/// [address] is expected to be a blockchain address or URL with parameters,
/// e.g. '?amount=123'
///
/// Example usage:
/// ```dart
/// getParameterValue('litecoin:NPZcaiggQTy6uxL?amount=0.2', 'amount') == '0.2'
/// ```
String getParameterValue(String address, String parameter) {
final RegExp regExp = RegExp('(?<=$parameter=)(.*?)(?=&|\$)');
final RegExpMatch match = regExp.firstMatch(address);
return match?.group(0);
}

/// Returns the address from the [uri].
/// Returns the [uri] if no address is found.
/// [uri] is expected to be a blockchain address or URL with parameters,
/// e.g. '?amount=123'
/// Example usage:
/// ```dart
/// getAddressFromUri('litecoin:NPZcaiggQTy6uxL?amount=0.2') == 'NPZcaiggQTy6uxL'
/// ```
String getAddressFromUri(String uri) {
final RegExp regExp = RegExp(r'(?<=:)(.*?)(?=\?|$)');
final RegExpMatch match = regExp.firstMatch(uri);
return match?.group(0) ?? uri.split(':').last;
}

void showUriDetailsDialog(
BuildContext context, PaymentUriInfo uriInfo, Function callbackIfAccepted) {
if (uriInfo == null) return;
Expand Down Expand Up @@ -865,27 +894,6 @@ Future<String> scanQr(BuildContext context) async {
);
}

/// Removes the blockchain prefix from [address]
///
/// Returns [address] if either the prefix or address are empty.
///
/// Example usage:
/// ```dart
/// removeBlockchainPrefix(eth:0x123) == '0x123'
/// ```
String removeBlockchainPrefix(String address) {
if (address.contains(':')) {
final List<String> parts = address.split(':');
final bool hasPrefix = parts.length == 2 && parts[0].isNotEmpty;
final bool hasAddress = parts.length == 2 && parts[1].isNotEmpty;
if (hasPrefix && hasAddress) {
return parts[1];
}
}

return address;
}

/// Function to generate password based on some criteria
///
/// Adapted from code at https://blog.albertobonacina.com/password-generator-with-dart.
Expand Down
36 changes: 25 additions & 11 deletions test/utils/utils_test.dart
Original file line number Diff line number Diff line change
@@ -1,36 +1,50 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:komodo_dex/model/coin.dart';
import 'package:komodo_dex/utils/utils.dart';

void main() {
group('removeBlockchainPrefix', () {
test('removes blockchain prefix from address', () {
const String address = 'eth:0x1234567890abcdef';
final String result = removeBlockchainPrefix(address);
final String result = getAddressFromUri(address);
expect(result, '0x1234567890abcdef');
});

test('removes blackcoin prefix from address', () {
const String address = 'blackcoin:B8Q9aZ4Mz1ZwWYaknJdZ8t3Z6z9F3Fz1Zz';
final String result = removeBlockchainPrefix(address);
final String result = getAddressFromUri(address);
expect(result, 'B8Q9aZ4Mz1ZwWYaknJdZ8t3Z6z9F3Fz1Zz');
});

test('returns the same address if no prefix is present', () {
const String address = '0x1234567890abcdef';
final String result = removeBlockchainPrefix(address);
final String result = getAddressFromUri(address);
expect(result, '0x1234567890abcdef');
});
});

test('returns the address after the prefix', () {
const String address = ':0x1234567890abcdef';
final String result = removeBlockchainPrefix(address);
expect(result, ':0x1234567890abcdef');
group('getParameterValue', () {
test('returns the parameter value from the address', () {
const String address =
'eth:0x1234567890abcdef?param1=value1&param2=value2';
const String parameter = 'param1';
final String result = getParameterValue(address, parameter);
expect(result, 'value1');
});

test('returns the same address if no prefix is present', () {
const String address = '0x1234567890abcdef:';
final String result = removeBlockchainPrefix(address);
expect(result, '0x1234567890abcdef:');
test('returns null if the parameter is not present in the address', () {
const String address =
'eth:0x1234567890abcdef?param1=value1&param2=value2';
const String parameter = 'param3';
final String result = getParameterValue(address, parameter);
expect(result, isNull);
});

test('returns null if the address does not contain any parameters', () {
const String address = 'eth:0x1234567890abcdef';
const String parameter = 'param1';
final String result = getParameterValue(address, parameter);
expect(result, isNull);
});
});
}

0 comments on commit 101ce94

Please sign in to comment.