diff --git a/lib/screens/portfolio/coin_detail/steps_withdraw.dart/amount_address_step/amount_address_step.dart b/lib/screens/portfolio/coin_detail/steps_withdraw.dart/amount_address_step/amount_address_step.dart index 74ebc548..91a84327 100644 --- a/lib/screens/portfolio/coin_detail/steps_withdraw.dart/amount_address_step/amount_address_step.dart +++ b/lib/screens/portfolio/coin_detail/steps_withdraw.dart/amount_address_step/amount_address_step.dart @@ -188,6 +188,10 @@ class _AmountAddressStepState extends State { widget.addressController.text = address; } + set qrAmount(String amount) { + widget.amountController.text = amount; + } + void showWrongCoinDialog(PaymentUriInfo uriInfo) { dialogBloc.dialog = showDialog( context: context, @@ -301,8 +305,9 @@ class _AmountAddressStepState extends State { 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); @@ -310,6 +315,7 @@ class _AmountAddressStepState extends State { handlePaymentData(uriInfo); } else { handleQrAdress(address); + qrAmount = amount ?? ''; } }); } diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index d52a096f..4fbe145c 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -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; @@ -865,27 +894,6 @@ Future 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 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. diff --git a/test/utils/utils_test.dart b/test/utils/utils_test.dart index 5fb45f94..796a786d 100644 --- a/test/utils/utils_test.dart +++ b/test/utils/utils_test.dart @@ -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¶m2=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¶m2=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); }); }); }