From eff1f7b9505b9ca987a8cdf522ee314fb4b13cfc Mon Sep 17 00:00:00 2001 From: sajee_techi Date: Mon, 12 Jan 2026 13:45:41 +0530 Subject: [PATCH 1/9] fix(parser): extract nested parameters from malformed sendto/tipTo URLs - Added logic to parse encoded `amount` and `description` inside the `sendto` parameter. - Added logic to parse encoded `tipAmount` and `tipDescription` inside the `tipTo` parameter. - Ensures correct address and alias extraction when query strings are improperly encoded. --- lib/utils/qr.dart | 53 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/lib/utils/qr.dart b/lib/utils/qr.dart index fb0507a7..cce1ee7a 100644 --- a/lib/utils/qr.dart +++ b/lib/utils/qr.dart @@ -133,7 +133,6 @@ ParsedQRData parseSendtoUrl(String raw) { } // Handle malformed query strings (convert ? to & after the first one) - // e.g., "alias=...?sendto=..." becomes "alias=...&sendto=..." if (queryString.contains('?')) { final firstQuestionMark = queryString.indexOf('?'); queryString = queryString.substring(0, firstQuestionMark) + @@ -148,24 +147,54 @@ ParsedQRData parseSendtoUrl(String raw) { uriData = parsedUri; } - final sendToParam = uriData.queryParameters['sendto']; - final amountParam = uriData.queryParameters['amount']; - final descriptionParam = uriData.queryParameters['description']; + // Use 'var' so we can update them if hidden params are found + var sendToParam = uriData.queryParameters['sendto']; + var amountParam = uriData.queryParameters['amount']; + var descriptionParam = uriData.queryParameters['description']; - final tipToParam = uriData.queryParameters['tipTo']; - final tipAmountParam = uriData.queryParameters['tipAmount']; - final tipDescriptionParam = uriData.queryParameters['tipDescription']; + var tipToParam = uriData.queryParameters['tipTo']; + var tipAmountParam = uriData.queryParameters['tipAmount']; + var tipDescriptionParam = uriData.queryParameters['tipDescription']; + + // 1. Handle encoded params inside sendto + if (sendToParam != null && sendToParam.contains('&')) { + final firstAmpIndex = sendToParam.indexOf('&'); + final realSendTo = sendToParam.substring(0, firstAmpIndex); + final hiddenParamsString = sendToParam.substring(firstAmpIndex + 1); + + sendToParam = realSendTo; + + final hiddenParams = Uri.splitQueryString(hiddenParamsString); + amountParam ??= hiddenParams['amount']; + descriptionParam ??= hiddenParams['description']; + } + + // 2. Handle encoded params inside tipTo (NEW LOGIC) + if (tipToParam != null && tipToParam.contains('&')) { + final firstAmpIndex = tipToParam.indexOf('&'); + final realTipTo = tipToParam.substring(0, firstAmpIndex); + final hiddenParamsString = tipToParam.substring(firstAmpIndex + 1); + + // Clean the tipTo param + tipToParam = realTipTo; + + // Parse the hidden string + final hiddenTipParams = Uri.splitQueryString(hiddenParamsString); + + // Populate tipAmount and tipDescription if they are null + tipAmountParam ??= hiddenTipParams['tipAmount']; + tipDescriptionParam ??= hiddenTipParams['tipDescription']; + } if (sendToParam == null) { return ParsedQRData(address: ''); } final address = sendToParam.split('@').first; - // Extract alias from sendto parameter (after @) as fallback - final aliasFromSendto = sendToParam.contains('@') - ? sendToParam.split('@').last - : null; - // Use explicit alias parameter if present, otherwise fallback to alias from sendto + + final aliasFromSendto = + sendToParam.contains('@') ? sendToParam.split('@').last : null; + final alias = uriData.queryParameters['alias'] ?? aliasFromSendto; final tip = tipToParam != null From c6c15702b017395072e0c4ba8020e19f007c1b2c Mon Sep 17 00:00:00 2001 From: sajee_techi Date: Mon, 12 Jan 2026 14:13:56 +0530 Subject: [PATCH 2/9] localise sendTip --- lib/l10n/app_en.arb | 3 +- lib/l10n/app_es.arb | 3 +- lib/l10n/app_fr.arb | 3 +- lib/l10n/app_localizations.dart | 6 + lib/l10n/app_localizations_en.dart | 3 + lib/l10n/app_localizations_es.dart | 3 + lib/l10n/app_localizations_fr.dart | 3 + lib/l10n/app_localizations_nl.dart | 3 + lib/l10n/app_nl.arb | 3 +- lib/screens/send/send_progress.dart | 3 +- pubspec.lock | 164 +++++++++++++++++----------- 11 files changed, 125 insertions(+), 72 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index de8ccc05..b4eeff9d 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -204,5 +204,6 @@ "more": "More", "start": "Start", "connecting": "Connecting", - "accountNotFound": "Account not found" + "accountNotFound": "Account not found", + "sendTip": "Send Tip" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index b62ffab5..0eebd3f8 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -204,5 +204,6 @@ "more": "Más", "start": "Iniciar", "connecting": "Conectando", - "accountNotFound": "Cuenta no encontrada" + "accountNotFound": "Cuenta no encontrada", + "sendTip": "Enviar propina" } \ No newline at end of file diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 9b4bd69e..2a38d8cb 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -203,5 +203,6 @@ "close": "Fermer", "start": "Commencer", "connecting": "Connexion", - "accountNotFound": "Compte non trouvé" + "accountNotFound": "Compte non trouvé", + "sendTip": "Envoyer un pourboire" } \ No newline at end of file diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index 42b9531c..e11dfba2 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -1331,6 +1331,12 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'Account not found'** String get accountNotFound; + + /// No description provided for @sendTip. + /// + /// In en, this message translates to: + /// **'Send Tip'** + String get sendTip; } class _AppLocalizationsDelegate diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index cf7a7b21..5b9620ce 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -667,4 +667,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String get accountNotFound => 'Account not found'; + + @override + String get sendTip => 'Send Tip'; } diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index 7b0cfb8d..9e65bc20 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -671,4 +671,7 @@ class AppLocalizationsEs extends AppLocalizations { @override String get accountNotFound => 'Cuenta no encontrada'; + + @override + String get sendTip => 'Enviar propina'; } diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index f2153012..4cc63ad1 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -672,4 +672,7 @@ class AppLocalizationsFr extends AppLocalizations { @override String get accountNotFound => 'Compte non trouvé'; + + @override + String get sendTip => 'Envoyer un pourboire'; } diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index 7eac1ca0..efd99d1f 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -674,4 +674,7 @@ class AppLocalizationsNl extends AppLocalizations { @override String get accountNotFound => 'Account niet gevonden'; + + @override + String get sendTip => 'Fooi versturen'; } diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb index 171bdea4..0343f6dd 100644 --- a/lib/l10n/app_nl.arb +++ b/lib/l10n/app_nl.arb @@ -203,5 +203,6 @@ "close": "Sluiten", "start": "Start", "connecting": "Verbinding maken", - "accountNotFound": "Account niet gevonden" + "accountNotFound": "Account niet gevonden", + "sendTip": "Fooi versturen" } \ No newline at end of file diff --git a/lib/screens/send/send_progress.dart b/lib/screens/send/send_progress.dart index 136c97f7..b4de216e 100644 --- a/lib/screens/send/send_progress.dart +++ b/lib/screens/send/send_progress.dart @@ -363,8 +363,7 @@ class _SendProgressState extends State { ? Column( children: [ Button( - text: - "${AppLocalizations.of(context)!.send} Tip", + text: AppLocalizations.of(context)!.sendTip, color: Theme.of(context) .colors .primary diff --git a/pubspec.lock b/pubspec.lock index caf39144..82c7b0cb 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -69,10 +69,10 @@ packages: dependency: "direct main" description: name: async - sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 url: "https://pub.dev" source: hosted - version: "2.13.0" + version: "2.12.0" audio_in_app: dependency: "direct main" description: @@ -161,6 +161,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.2" + buffer: + dependency: transitive + description: + name: buffer + sha256: "389da2ec2c16283c8787e0adaede82b1842102f8c8aae2f49003a766c5c6b3d1" + url: "https://pub.dev" + source: hosted + version: "1.2.3" cached_network_image: dependency: "direct main" description: @@ -213,10 +221,10 @@ packages: dependency: transitive description: name: checked_yaml - sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff url: "https://pub.dev" source: hosted - version: "2.0.4" + version: "2.0.3" cli_config: dependency: transitive description: @@ -386,6 +394,22 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.3" + equatable: + dependency: transitive + description: + name: equatable + sha256: "3e0141505477fd8ad55d6eb4e7776d3fe8430be8e497ccb1521370c3f21a3e2b" + url: "https://pub.dev" + source: hosted + version: "2.0.8" + eth_sig_util: + dependency: transitive + description: + name: eth_sig_util + sha256: "20fdc5ce3864e70e5ade1c1cd03cce4ef01018db00adab107303f9055d26b01a" + url: "https://pub.dev" + source: hosted + version: "0.0.9" event: dependency: transitive description: @@ -406,10 +430,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" + sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" url: "https://pub.dev" source: hosted - version: "1.3.3" + version: "1.3.2" ffi: dependency: transitive description: @@ -608,10 +632,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "306f0596590e077338312f38837f595c04f28d6cdeeac392d3d74df2f0003687" + sha256: c2fe1001710127dfa7da89977a08d591398370d099aacdaa6d44da7eb14b8476 url: "https://pub.dev" source: hosted - version: "2.0.32" + version: "2.0.31" flutter_secure_storage: dependency: "direct main" description: @@ -682,10 +706,10 @@ packages: dependency: transitive description: name: freezed_annotation - sha256: "7294967ff0a6d98638e7acb774aac3af2550777accd8149c90af5b014e6d44d8" + sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "2.4.4" frontend_server_client: dependency: transitive description: @@ -850,10 +874,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf url: "https://pub.dev" source: hosted - version: "0.20.2" + version: "0.19.0" io: dependency: transitive description: @@ -890,26 +914,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" + sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec url: "https://pub.dev" source: hosted - version: "11.0.2" + version: "10.0.8" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 url: "https://pub.dev" source: hosted - version: "3.0.10" + version: "3.0.9" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.1" lints: dependency: transitive description: @@ -938,10 +962,10 @@ packages: dependency: "direct main" description: name: lottie - sha256: "8ae0be46dbd9e19641791dc12ee480d34e1fd3f84c749adc05f3ad9342b71b95" + sha256: c5fa04a80a620066c15cf19cc44773e19e9b38e989ff23ea32e5903ef1015950 url: "https://pub.dev" source: hosted - version: "3.3.2" + version: "3.3.1" markdown: dependency: transitive description: @@ -1114,18 +1138,18 @@ packages: dependency: transitive description: name: path_provider_android - sha256: e122c5ea805bb6773bb12ce667611265980940145be920cd09a4b0ec0285cb16 + sha256: "3b4c1fc3aa55ddc9cd4aa6759984330d5c8e66aa7702a6223c61540dc6380c37" url: "https://pub.dev" source: hosted - version: "2.2.20" + version: "2.2.19" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: efaec349ddfc181528345c56f8eda9d6cccd71c177511b132c6a0ddaefaa2738 + sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd" url: "https://pub.dev" source: hosted - version: "2.4.3" + version: "2.4.2" path_provider_linux: dependency: transitive description: @@ -1154,10 +1178,10 @@ packages: dependency: transitive description: name: petitparser - sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1" + sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" url: "https://pub.dev" source: hosted - version: "7.0.1" + version: "6.1.0" platform: dependency: transitive description: @@ -1250,26 +1274,34 @@ packages: dependency: transitive description: name: reown_core - sha256: "8d5d14b4e8d008b09ec9db964ab8913b4fc17000d666eb1fece20a80a4b5e37a" + sha256: "37e8bd16263400856592b58331ec61665bcc8814d4a2a1801a7f12caf3c4673d" url: "https://pub.dev" source: hosted - version: "1.3.6" + version: "1.2.0" reown_sign: dependency: transitive description: name: reown_sign - sha256: c2fec55ed3d0042d0802c80d7fc36f9b1937eac6ef9c2907dae3b8146188cffa + sha256: ae2e171b93ddaae2ce7db18a66647afc9680cf55f49e88d49a3c3df5d1eb2cde url: "https://pub.dev" source: hosted - version: "1.3.7" + version: "1.2.0" reown_walletkit: dependency: "direct main" description: name: reown_walletkit - sha256: f96cc9f6e264138b3411fd1635e06d437d5912d7a21ef28af21974e2680dfd70 + sha256: b779e4914c9299edea80a849773fc08ddd5e44549bf53a2fd26cac4a59f5c99c + url: "https://pub.dev" + source: hosted + version: "1.2.0" + reown_yttrium: + dependency: transitive + description: + name: reown_yttrium + sha256: e59d9e8dbad8e2c420c201719da12bca528c38ecab9571364d5b6d18715ce773 url: "https://pub.dev" source: hosted - version: "1.3.7" + version: "0.0.1" rxdart: dependency: "direct main" description: @@ -1314,18 +1346,18 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: "34266009473bf71d748912da4bf62d439185226c03e01e2d9687bc65bbfcb713" + sha256: bd14436108211b0d4ee5038689a56d4ae3620fd72fd6036e113bf1345bc74d9e url: "https://pub.dev" source: hosted - version: "2.4.15" + version: "2.4.13" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "1c33a907142607c40a7542768ec9badfd16293bac51da3a4482623d15845f88b" + sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" url: "https://pub.dev" source: hosted - version: "2.5.5" + version: "2.5.4" shared_preferences_linux: dependency: transitive description: @@ -1448,18 +1480,18 @@ packages: dependency: transitive description: name: sqflite_android - sha256: ecd684501ebc2ae9a83536e8b15731642b9570dc8623e0073d227d0ee2bfea88 + sha256: "2b3070c5fa881839f8b402ee4a39c1b4d561704d4ebbbcfb808a119bc2a1701b" url: "https://pub.dev" source: hosted - version: "2.4.2+2" + version: "2.4.1" sqflite_common: dependency: "direct main" description: name: sqflite_common - sha256: "6ef422a4525ecc601db6c0a2233ff448c731307906e92cabc9ba292afaae16a6" + sha256: "84731e8bfd8303a3389903e01fb2141b6e59b5973cacbb0929021df08dddbe8b" url: "https://pub.dev" source: hosted - version: "2.5.6" + version: "2.5.5" sqflite_common_ffi: dependency: transitive description: @@ -1472,10 +1504,10 @@ packages: dependency: "direct main" description: name: sqflite_common_ffi_web - sha256: "793c1ff5b0c95ac618e7731e209db99e96abff59ad3432a3c91bd2b1454a00d5" + sha256: "983cf7b33b16e6bc086c8e09f6a1fae69d34cdb167d7acaf64cbd3515942d4e6" url: "https://pub.dev" source: hosted - version: "1.0.1+2" + version: "1.0.0" sqflite_darwin: dependency: transitive description: @@ -1536,10 +1568,10 @@ packages: dependency: transitive description: name: synchronized - sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0 + sha256: "0669c70faae6270521ee4f05bffd2919892d42d1276e6c495be80174b6bc0ef6" url: "https://pub.dev" source: hosted - version: "3.4.0" + version: "3.3.1" term_glyph: dependency: transitive description: @@ -1552,26 +1584,26 @@ packages: dependency: transitive description: name: test - sha256: "65e29d831719be0591f7b3b1a32a3cda258ec98c58c7b25f7b84241bc31215bb" + sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e" url: "https://pub.dev" source: hosted - version: "1.26.2" + version: "1.25.15" test_api: dependency: transitive description: name: test_api - sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd url: "https://pub.dev" source: hosted - version: "0.7.6" + version: "0.7.4" test_core: dependency: transitive description: name: test_core - sha256: "80bf5a02b60af04b09e14f6fe68b921aad119493e26e490deaca5993fef1b05a" + sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa" url: "https://pub.dev" source: hosted - version: "0.6.11" + version: "0.6.8" timeago: dependency: "direct main" description: @@ -1616,18 +1648,18 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "5c8b6c2d89a78f5a1cca70a73d9d5f86c701b36b42f9c9dac7bad592113c28e9" + sha256: "81777b08c498a292d93ff2feead633174c386291e35612f8da438d6e92c4447e" url: "https://pub.dev" source: hosted - version: "6.3.24" + version: "6.3.20" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "6b63f1441e4f653ae799166a72b50b1767321ecc263a57aadf825a7a2a5477d9" + sha256: d80b3f567a617cb923546034cc94bfe44eb15f989fe670b37f26abdb9d939cb7 url: "https://pub.dev" source: hosted - version: "6.3.5" + version: "6.3.4" url_launcher_linux: dependency: transitive description: @@ -1640,10 +1672,10 @@ packages: dependency: transitive description: name: url_launcher_macos - sha256: "8262208506252a3ed4ff5c0dc1e973d2c0e0ef337d0a074d35634da5d44397c9" + sha256: c043a77d6600ac9c38300567f33ef12b0ef4f4783a2c1f00231d2b1941fea13f url: "https://pub.dev" source: hosted - version: "3.2.4" + version: "3.2.3" url_launcher_platform_interface: dependency: transitive description: @@ -1712,18 +1744,18 @@ packages: dependency: transitive description: name: vector_math - sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.1.4" vm_service: dependency: transitive description: name: vm_service - sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" + sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" url: "https://pub.dev" source: hosted - version: "15.0.2" + version: "14.3.1" wallet: dependency: transitive description: @@ -1784,10 +1816,10 @@ packages: dependency: transitive description: name: win32 - sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e + sha256: "329edf97fdd893e0f1e3b9e88d6a0e627128cc17cc316a8d67fda8f1451178ba" url: "https://pub.dev" source: hosted - version: "5.15.0" + version: "5.13.0" x25519: dependency: transitive description: @@ -1808,10 +1840,10 @@ packages: dependency: transitive description: name: xml - sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 url: "https://pub.dev" source: hosted - version: "6.6.1" + version: "6.5.0" yaml: dependency: transitive description: @@ -1821,5 +1853,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.9.0 <4.0.0" - flutter: ">=3.35.0" + dart: ">=3.7.2 <4.0.0" + flutter: ">=3.29.0" From 967554816b66f0bfe2d5436d8f6db95bc89cd191 Mon Sep 17 00:00:00 2001 From: sajee_techi Date: Mon, 12 Jan 2026 17:46:38 +0530 Subject: [PATCH 3/9] initialize sendToURL parameter in WalletScreenState --- lib/screens/wallet/screen.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/screens/wallet/screen.dart b/lib/screens/wallet/screen.dart index 73aaf54f..46859a4f 100644 --- a/lib/screens/wallet/screen.dart +++ b/lib/screens/wallet/screen.dart @@ -142,6 +142,7 @@ class WalletScreenState extends State _receiveParams = widget.receiveParams; _deepLink = widget.deepLink; _deepLinkParams = widget.deepLinkParams; + _sendToURL = widget.sendToURL; WidgetsBinding.instance.addPostFrameCallback((_) { onLoad(); From a8859a13fd0cd512201362b3f5bff65b76969f6d Mon Sep 17 00:00:00 2001 From: sajee_techi Date: Mon, 12 Jan 2026 18:10:23 +0530 Subject: [PATCH 4/9] Add tipAmount and tipDescription parameter parsing to router - Parse tipAmount and tipDescription from URI query parameters in Landing route - Include tipAmount and tipDescription when constructing sendToParams - Parse tipAmount and tipDescription in Wallet route for sendToURL construction - Maintains consistency with existing parameter handling pattern --- lib/router/router.dart | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/router/router.dart b/lib/router/router.dart index a5a5daca..0e12e4e2 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -90,6 +90,14 @@ GoRouter createRouter( sendToParams += '&description=${uri.queryParameters['description']}'; } + if (uri.queryParameters['tipAmount'] != null) { + sendToParams += + '&tipAmount=${uri.queryParameters['tipAmount']}'; + } + if (uri.queryParameters['tipDescription'] != null) { + sendToParams += + '&tipDescription=${uri.queryParameters['tipDescription']}'; + } } else if (eip681 != null) { sendToParams = encodeParams(uri.toString().replaceFirst('/?', '')); @@ -181,6 +189,9 @@ GoRouter createRouter( final tipTo = state.uri.queryParameters['tipTo']; final amount = state.uri.queryParameters['amount']; final description = state.uri.queryParameters['description']; + final tipAmount = state.uri.queryParameters['tipAmount']; + final tipDescription = + state.uri.queryParameters['tipDescription']; if (sendTo != null) { String params = 'sendto=$sendTo'; if (tipTo != null) { @@ -192,6 +203,12 @@ GoRouter createRouter( if (description != null) { params += '&description=$description'; } + if (tipAmount != null) { + params += '&tipAmount=$tipAmount'; + } + if (tipDescription != null) { + params += '&tipDescription=$tipDescription'; + } sendToURL = 'https://app.citizenwallet.xyz/?$params'; } } @@ -544,7 +561,6 @@ GoRouter createWebRouter( } } - return WebLandingScreen( voucher: state.uri.queryParameters['voucher'], voucherParams: state.uri.queryParameters['params'], From 13b02a8067b29a8c42fce39e2dd95a6fa8f74bfb Mon Sep 17 00:00:00 2001 From: sajee_techi Date: Mon, 12 Jan 2026 18:32:00 +0530 Subject: [PATCH 5/9] refactor: remove unused sendTransaction parameter from SendToScreen - Remove sendTransaction property from SendToScreen widget - Remove unused SendTransaction import - Remove sendTransaction from router instantiation - Clean up commented-out dead code The sendTransaction parameter was never used within the SendToScreen widget and was never passed any value during navigation. --- lib/router/router.dart | 1 - lib/screens/send/send_to.dart | 4 ---- lib/screens/wallet/screen.dart | 1 + 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/router/router.dart b/lib/router/router.dart index 0e12e4e2..ac62b029 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -276,7 +276,6 @@ GoRouter createRouter( voucherLogic: extra['voucherLogic'], isMinting: extra['isMinting'] ?? false, sendToURL: extra['sendToURL'], - sendTransaction: extra['sendTransaction'], ); }, ), diff --git a/lib/screens/send/send_to.dart b/lib/screens/send/send_to.dart index 2774855d..75c74cd5 100644 --- a/lib/screens/send/send_to.dart +++ b/lib/screens/send/send_to.dart @@ -1,5 +1,4 @@ // import 'package:citizenwallet/l10n/app_localizations.dart'; -import 'package:citizenwallet/models/send_transaction.dart'; import 'package:citizenwallet/services/wallet/contracts/profile.dart'; import 'package:citizenwallet/services/wallet/utils.dart'; import 'package:citizenwallet/state/profiles/logic.dart'; @@ -34,7 +33,6 @@ class SendToScreen extends StatefulWidget { final ProfilesLogic profilesLogic; final VoucherLogic? voucherLogic; final String? sendToURL; - final SendTransaction? sendTransaction; final bool isMinting; @@ -45,7 +43,6 @@ class SendToScreen extends StatefulWidget { this.voucherLogic, this.isMinting = false, this.sendToURL, - this.sendTransaction, }); @override @@ -57,7 +54,6 @@ class _SendToScreenState extends State { final ScanLogic _scanLogic = ScanLogic(); String? _currentSendToURL; final _scrollController = ScrollController(); - // late SendTransaction _sendTransaction; late void Function() debouncedAddressUpdate; diff --git a/lib/screens/wallet/screen.dart b/lib/screens/wallet/screen.dart index 46859a4f..e0983eef 100644 --- a/lib/screens/wallet/screen.dart +++ b/lib/screens/wallet/screen.dart @@ -586,6 +586,7 @@ class WalletScreenState extends State }); if (result != true && sendToURL != null) { + // TODO: check clear tipping _logic.clearTipTo(); _sendToURL = null; } From 96eef5a0f0a8bdb3a4148f82c6bb23c16a15f20e Mon Sep 17 00:00:00 2001 From: sajee_techi Date: Tue, 13 Jan 2026 09:06:22 +0530 Subject: [PATCH 6/9] tipping with - to - amount - description --- lib/models/send_transaction.dart | 40 -------------- lib/router/router.dart | 2 - lib/screens/send/send_details.dart | 16 ++---- lib/screens/send/send_progress.dart | 28 ++++++---- lib/screens/send/tip_details.dart | 81 ++++++++++++----------------- lib/screens/wallet/receive.dart | 4 +- lib/screens/wallet/screen.dart | 5 +- lib/state/wallet/logic.dart | 33 +++++++----- lib/state/wallet/state.dart | 27 +++++----- 9 files changed, 93 insertions(+), 143 deletions(-) delete mode 100644 lib/models/send_transaction.dart diff --git a/lib/models/send_transaction.dart b/lib/models/send_transaction.dart deleted file mode 100644 index cf278cb0..00000000 --- a/lib/models/send_transaction.dart +++ /dev/null @@ -1,40 +0,0 @@ -class SendTransaction { - String? _to; - String? _amount; - String? _description; - String? _tipTo; - String? _tipAmount; - String? _tipDescription; - - SendTransaction({ - String? to, - String? amount, - String? description, - String? tipTo, - String? tipAmount, - String? tipDescription, - }) : _to = to, - _amount = amount, - _description = description, - _tipTo = tipTo, - _tipAmount = tipAmount, - _tipDescription = tipDescription; - - String? get to => _to; - set to(String? value) => _to = value; - - String? get amount => _amount; - set amount(String? value) => _amount = value; - - String? get description => _description; - set description(String? value) => _description = value; - - String? get tipTo => _tipTo; - set tipTo(String? value) => _tipTo = value; - - String? get tipAmount => _tipAmount; - set tipAmount(String? value) => _tipAmount = value; - - String? get tipDescription => _tipDescription; - set tipDescription(String? value) => _tipDescription = value; -} diff --git a/lib/router/router.dart b/lib/router/router.dart index ac62b029..1e085cf9 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -332,7 +332,6 @@ GoRouter createRouter( walletLogic: extra['walletLogic'], profilesLogic: extra['profilesLogic'], isMinting: extra['isMinting'] ?? false, - sendTransaction: extra['sendTransaction'], ); }, ), @@ -363,7 +362,6 @@ GoRouter createRouter( to: state.pathParameters['to'], isMinting: extra?['isMinting'] ?? false, profilesLogic: extra?['profilesLogic'], - sendTransaction: extra?['sendTransaction'], walletLogic: extra?['walletLogic'], ); }, diff --git a/lib/screens/send/send_details.dart b/lib/screens/send/send_details.dart index ca9d9a2e..b6b6ee45 100644 --- a/lib/screens/send/send_details.dart +++ b/lib/screens/send/send_details.dart @@ -1,5 +1,4 @@ // import 'package:citizenwallet/l10n/app_localizations.dart'; -import 'package:citizenwallet/models/send_transaction.dart'; import 'package:citizenwallet/services/config/config.dart'; import 'package:citizenwallet/services/wallet/utils.dart'; import 'package:citizenwallet/state/profiles/logic.dart'; @@ -230,17 +229,13 @@ class _SendDetailsScreenState extends State { final toAccount = selectedAddress ?? walletLogic.addressController.value.text; - - final sendTransaction = SendTransaction( - amount: walletLogic.amountController.value.text, - to: toAccount, - description: walletLogic.messageController.value.text.trim(), - ); + final amount = walletLogic.amountController.value.text; + final description = walletLogic.messageController.value.text.trim(); walletLogic.sendTransaction( - sendTransaction.amount!, - sendTransaction.to!, - message: sendTransaction.description!, + amount, + toAccount, + message: description, ); await Future.delayed(const Duration(milliseconds: 50)); @@ -253,7 +248,6 @@ class _SendDetailsScreenState extends State { 'isMinting': widget.isMinting, 'walletLogic': walletLogic, 'profilesLogic': widget.profilesLogic, - 'sendTransaction': sendTransaction, }); walletLogic.clearInProgressTransaction(); diff --git a/lib/screens/send/send_progress.dart b/lib/screens/send/send_progress.dart index b4de216e..a9003e5a 100644 --- a/lib/screens/send/send_progress.dart +++ b/lib/screens/send/send_progress.dart @@ -1,6 +1,5 @@ // import 'package:citizenwallet/l10n/app_localizations.dart'; import 'dart:async'; -import 'package:citizenwallet/models/send_transaction.dart'; import 'package:citizenwallet/models/transaction.dart'; import 'package:citizenwallet/services/wallet/utils.dart'; import 'package:citizenwallet/state/profiles/logic.dart'; @@ -8,6 +7,7 @@ import 'package:citizenwallet/state/profiles/state.dart'; import 'package:citizenwallet/state/wallet/logic.dart'; import 'package:citizenwallet/state/wallet/state.dart'; import 'package:citizenwallet/theme/provider.dart'; +import 'package:citizenwallet/utils/send.dart'; import 'package:citizenwallet/widgets/button.dart'; import 'package:citizenwallet/widgets/coin_logo.dart'; import 'package:citizenwallet/widgets/loaders/progress_circle.dart'; @@ -23,7 +23,6 @@ class SendProgress extends StatefulWidget { final bool isMinting; final WalletLogic? walletLogic; final ProfilesLogic? profilesLogic; - final SendTransaction? sendTransaction; const SendProgress({ super.key, @@ -31,7 +30,6 @@ class SendProgress extends StatefulWidget { this.isMinting = false, this.walletLogic, this.profilesLogic, - this.sendTransaction, }); @override @@ -76,15 +74,17 @@ class _SendProgressState extends State { }); } - Future handleSendTip(BuildContext context) async { + Future handleSendTip( + BuildContext context, + SendDestination tipping, + ) async { if (!context.mounted) { return; } final navigator = GoRouter.of(context); - final toAccount = widget.sendTransaction?.to ?? - widget.walletLogic?.addressController.value.text; + final toAccount = tipping.to; await navigator.push( '/wallet/${widget.walletLogic?.account}/send/$toAccount/tip', @@ -92,7 +92,6 @@ class _SendProgressState extends State { 'walletLogic': widget.walletLogic, 'profilesLogic': widget.profilesLogic, 'isMinting': widget.isMinting, - 'sendTransaction': widget.sendTransaction, }, ); } @@ -118,9 +117,12 @@ class _SendProgressState extends State { (WalletState state) => state.inProgressTransactionError, ); + final tipping = context.select((WalletState state) => state.tipping); + if (inProgressTransaction.state == TransactionState.success && _previousState != TransactionState.success) { - final hasTip = context.read().hasTip; + final hasTip = + context.select((WalletState state) => state.tipping) != null; if (!hasTip) { handleStartCloseScreenTimer(context); } @@ -135,7 +137,8 @@ class _SendProgressState extends State { if (inProgressTransaction.state == TransactionState.fail && _previousState != TransactionState.fail && !_isClosing) { - final hasTip = context.read().hasTip; + final hasTip = + context.select((WalletState state) => state.tipping) != null; if (!hasTip) { handleStartCloseScreenTimer(context); } @@ -359,7 +362,7 @@ class _SendProgressState extends State { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - context.select((WalletState state) => state.hasTip) + tipping != null ? Column( children: [ Button( @@ -372,7 +375,8 @@ class _SendProgressState extends State { .colors .white .resolveFrom(context), - onPressed: () => handleSendTip(context), + onPressed: () => + handleSendTip(context, tipping), minWidth: 200, maxWidth: width - 60, ), @@ -383,6 +387,8 @@ class _SendProgressState extends State { onPressed: () { final navigator = GoRouter.of(context); + widget.walletLogic?.clearTipping(); + navigator.go( '/wallet/${widget.walletLogic?.account}'); }, diff --git a/lib/screens/send/tip_details.dart b/lib/screens/send/tip_details.dart index a1feea4f..61f82778 100644 --- a/lib/screens/send/tip_details.dart +++ b/lib/screens/send/tip_details.dart @@ -1,5 +1,4 @@ // import 'package:citizenwallet/l10n/app_localizations.dart'; -import 'package:citizenwallet/models/send_transaction.dart'; import 'package:citizenwallet/services/config/config.dart'; import 'package:citizenwallet/services/wallet/utils.dart'; import 'package:citizenwallet/state/profiles/logic.dart'; @@ -29,7 +28,6 @@ class TipDetailsScreen extends StatefulWidget { final WalletLogic walletLogic; final ProfilesLogic profilesLogic; final VoucherLogic? voucherLogic; - final SendTransaction? sendTransaction; final bool isMinting; final bool isLink; @@ -39,7 +37,6 @@ class TipDetailsScreen extends StatefulWidget { required this.walletLogic, required this.profilesLogic, this.voucherLogic, - this.sendTransaction, this.isMinting = false, this.isLink = false, }); @@ -60,12 +57,10 @@ class _TipDetailsScreenState extends State { late void Function() debouncedAmountUpdate; bool _isSending = false; - late SendTransaction _sendTransaction; @override void initState() { super.initState(); - _sendTransaction = widget.sendTransaction ?? SendTransaction(); // Clear amount controller when tip screen initializes // to ensure hasAmount state is reset @@ -73,10 +68,25 @@ class _TipDetailsScreenState extends State { WidgetsBinding.instance.addPostFrameCallback((_) { final walletLogic = widget.walletLogic; - final tipTo = context.read().tipTo; + final tipping = context.read().tipping; - if (tipTo != null) { - widget.profilesLogic.getProfile(tipTo).then((profile) { + if (tipping != null) { + // Set address state + walletLogic.setHasAddress(true); + + // Pre-fill amount and description if provided + if (tipping.amount != null) { + walletLogic.amountController.text = tipping.amount!; + } + if (tipping.description != null) { + walletLogic.messageController.text = tipping.description!; + } + + // Update amount after setting text + walletLogic.updateAmount(unlimited: widget.isMinting); + + // Load profile for tip recipient + widget.profilesLogic.getProfile(tipping.to).then((profile) { if (profile != null) { widget.profilesLogic.selectProfile(profile); } @@ -92,18 +102,6 @@ class _TipDetailsScreenState extends State { }); } - @override - void didChangeDependencies() { - super.didChangeDependencies(); - final tipTo = context.read().tipTo; - if (tipTo != null) { - widget.walletLogic.setHasTip(true); - widget.walletLogic.setHasAddress(true); - // Reset amount state since tip screen starts with empty amount - widget.walletLogic.updateAmount(unlimited: widget.isMinting); - } - } - @override void dispose() { amountFocusNode.dispose(); @@ -225,15 +223,14 @@ class _TipDetailsScreenState extends State { } } - void handleSend( - BuildContext context, String? selectedAddress, String? tipTo) async { + void handleSend(BuildContext context, String? selectedAddress) async { if (_isSending) { return; } final walletLogic = widget.walletLogic; - if (tipTo == null) { + if (selectedAddress == null) { return; } @@ -249,7 +246,7 @@ class _TipDetailsScreenState extends State { final isValid = walletLogic.validateSendFields( walletLogic.amountController.value.text, - selectedAddress ?? walletLogic.addressController.value.text, + selectedAddress, ); if (!isValid) { @@ -259,41 +256,30 @@ class _TipDetailsScreenState extends State { return; } - final toAccount = - selectedAddress ?? walletLogic.addressController.value.text; - - final sendTip = SendTransaction( - tipAmount: walletLogic.amountController.value.text, - tipTo: tipTo, - tipDescription: walletLogic.messageController.value.text.trim(), - ); - try { walletLogic.sendTransaction( - sendTip.tipAmount!, - sendTip.tipTo!, - message: sendTip.tipDescription!, + walletLogic.amountController.value.text, + selectedAddress, + message: walletLogic.messageController.value.text.trim(), ); } catch (e, stackTrace) { - print('error: $e'); - print('stack: $stackTrace'); + debugPrint('error: $e'); + debugPrint('stack: $stackTrace'); } - widget.walletLogic.setHasTip(false); + widget.walletLogic.clearTipping(); widget.walletLogic.setHasAddress(false); - widget.walletLogic.setTipTo(null); await Future.delayed(const Duration(milliseconds: 50)); HapticFeedback.heavyImpact(); final sent = await navigator.push( - '/wallet/${walletLogic.account}/send/$toAccount/progress', + '/wallet/${walletLogic.account}/send/$selectedAddress/progress', extra: { 'isMinting': widget.isMinting, 'walletLogic': walletLogic, 'profilesLogic': widget.profilesLogic, - 'sendTransaction': sendTip, }); if (sent == true) { @@ -416,10 +402,6 @@ class _TipDetailsScreenState extends State { (WalletState state) => state.wallet, ); - final tipTo = context.select( - (WalletState state) => state.tipTo, - ); - final balance = double.tryParse(wallet != null ? wallet.balance : '0.0') ?? 0.0; @@ -827,7 +809,6 @@ class _TipDetailsScreenState extends State { selectedProfile?.account ?? searchedProfile ?.account, - tipTo, ) : null, enabled: isSendingValid, @@ -836,8 +817,10 @@ class _TipDetailsScreenState extends State { ? AppLocalizations.of(context)! .swipeToMint : isLink - ? "${AppLocalizations.of(context)!.swipeToConfirm} Tip" - : "${AppLocalizations.of(context)!.swipeToSend} Tip", + ? AppLocalizations.of(context)! + .swipeToConfirm + : AppLocalizations.of(context)! + .swipeToSend, completionLabelColor: Theme.of(context) .colors .primary diff --git a/lib/screens/wallet/receive.dart b/lib/screens/wallet/receive.dart index 30afe332..00e6c080 100644 --- a/lib/screens/wallet/receive.dart +++ b/lib/screens/wallet/receive.dart @@ -117,7 +117,7 @@ class ReceiveScreenState extends State { _selectedProfile = context.read().selectedProfile; }); - widget.logic.setTipTo(result); + widget.logic.setTipping(to: result); // Update QR code with new tip information widget.logic.updateReceiveQR(); } @@ -130,7 +130,7 @@ class ReceiveScreenState extends State { }); widget.profilesLogic.deSelectProfile(); widget.logic.clearAddressController(); - widget.logic.setTipTo(null); + widget.logic.clearTipping(); widget.logic.updateReceiveQR(); } diff --git a/lib/screens/wallet/screen.dart b/lib/screens/wallet/screen.dart index e0983eef..57380e2a 100644 --- a/lib/screens/wallet/screen.dart +++ b/lib/screens/wallet/screen.dart @@ -586,8 +586,7 @@ class WalletScreenState extends State }); if (result != true && sendToURL != null) { - // TODO: check clear tipping - _logic.clearTipTo(); + _logic.clearTipping(); _sendToURL = null; } @@ -1125,7 +1124,7 @@ class WalletScreenState extends State _receiveParams = null; _deepLink = deepLink; _deepLinkParams = deepLinkParams; - + if (voucher != null && voucherParams != null) { _sendToURL = null; } else { diff --git a/lib/state/wallet/logic.dart b/lib/state/wallet/logic.dart index 81b1264e..e5ca0126 100644 --- a/lib/state/wallet/logic.dart +++ b/lib/state/wallet/logic.dart @@ -1665,16 +1665,20 @@ class WalletLogic extends WidgetsBindingObserver { _amountController.clear(); } - void clearTipTo() { - _state.clearTipTo(); - } - - void setTipTo(String? tipTo) { - _state.setTipTo(tipTo); + void setTipping({ + required String to, + String? amount, + String? description, + }) { + _state.setTipping( + to: to, + amount: amount, + description: description, + ); } - void setHasTip(bool value) { - _state.setHasTip(value); + void clearTipping() { + _state.clearTipping(); } void setHasAddress(bool value) { @@ -1827,8 +1831,11 @@ class WalletLogic extends WidgetsBindingObserver { // Handle tip information if present if (parsedData.tip != null) { - _state.setTipTo(parsedData.tip!.to); - _state.setHasTip(true); + _state.setTipping( + to: parsedData.tip!.to, + amount: parsedData.tip!.amount, + description: parsedData.tip!.description, + ); } return addressToUse; @@ -1894,9 +1901,9 @@ class WalletLogic extends WidgetsBindingObserver { } // Add tipTo parameter if it exists in the state - final tipTo = _state.tipTo; - if (tipTo != null && tipTo.isNotEmpty) { - params += '&tipTo=$tipTo'; + final tipping = _state.tipping; + if (tipping != null && tipping.to.isNotEmpty) { + params += '&tipTo=${tipping.to}'; } // Check if URL already has query parameters in the fragment diff --git a/lib/state/wallet/state.dart b/lib/state/wallet/state.dart index 4eb75cba..d87d6292 100644 --- a/lib/state/wallet/state.dart +++ b/lib/state/wallet/state.dart @@ -4,6 +4,7 @@ import 'package:citizenwallet/services/config/config.dart'; import 'package:citizenwallet/services/engine/events.dart'; import 'package:citizenwallet/services/preferences/preferences.dart'; import 'package:citizenwallet/state/wallet/utils.dart'; +import 'package:citizenwallet/utils/send.dart'; import 'package:collection/collection.dart'; import 'package:flutter/cupertino.dart'; @@ -80,9 +81,7 @@ class WalletState with ChangeNotifier { bool cwWalletsLoading = false; bool cwWalletsError = false; - String? tipTo; - bool _hasTip = false; - bool get hasTip => _hasTip; + SendDestination? tipping; void setEventServiceState(EventServiceState state) { eventServiceState = state; @@ -701,19 +700,23 @@ class WalletState with ChangeNotifier { notifyListeners(); } - void setTipTo(String? tipTo) { - this.tipTo = tipTo; + void setTipping({ + required String to, + String? amount, + String? description, + }) { + tipping = SendDestination( + to: to, + amount: amount, + description: description, + ); notifyListeners(); } - void setHasTip(bool value) { - _hasTip = value; + void clearTipping() { + tipping = null; notifyListeners(); } - void clearTipTo() { - tipTo = null; - _hasTip = false; - notifyListeners(); - } + bool get hasTip => tipping != null; } From 06bd89d347f33dc748fd7b931a26863e96d8a8d0 Mon Sep 17 00:00:00 2001 From: sajee_techi Date: Tue, 13 Jan 2026 09:21:48 +0530 Subject: [PATCH 7/9] fix: defer controller clearing in tip_details dispose to prevent build phase error Wrap clearAmountController() and resetInputErrorState() in addPostFrameCallback to avoid triggering rebuilds during navigation back to send_progress screen. This fixes the "setState() called during build" error. --- lib/screens/send/tip_details.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/screens/send/tip_details.dart b/lib/screens/send/tip_details.dart index 61f82778..a83ec592 100644 --- a/lib/screens/send/tip_details.dart +++ b/lib/screens/send/tip_details.dart @@ -110,8 +110,12 @@ class _TipDetailsScreenState extends State { final walletLogic = widget.walletLogic; - walletLogic.clearAmountController(); - walletLogic.resetInputErrorState(); + // Schedule controller clearing after the current frame to avoid + // triggering rebuilds during navigation + WidgetsBinding.instance.addPostFrameCallback((_) { + walletLogic.clearAmountController(); + walletLogic.resetInputErrorState(); + }); super.dispose(); } From f3c5580f9136095f7015ccf5fd4e869a22a358c9 Mon Sep 17 00:00:00 2001 From: sajee_techi Date: Tue, 13 Jan 2026 09:38:35 +0530 Subject: [PATCH 8/9] ios pod --- ios/Podfile.lock | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index f1ccaa00..62e61e6b 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -156,6 +156,9 @@ PODS: - Flutter - FlutterMacOS - PromisesObjC (2.4.0) + - reown_yttrium (0.0.1): + - Flutter + - YttriumWrapper (= 0.8.35) - SDWebImage (5.21.2): - SDWebImage/Core (= 5.21.2) - SDWebImage/Core (5.21.2) @@ -170,6 +173,7 @@ PODS: - SwiftyGif (5.4.5) - url_launcher_ios (0.0.1): - Flutter + - YttriumWrapper (0.8.35) DEPENDENCIES: - audioplayers_darwin (from `.symlinks/plugins/audioplayers_darwin/ios`) @@ -187,6 +191,7 @@ DEPENDENCIES: - nfc_manager (from `.symlinks/plugins/nfc_manager/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - reown_yttrium (from `.symlinks/plugins/reown_yttrium/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) @@ -213,6 +218,7 @@ SPEC REPOS: - PromisesObjC - SDWebImage - SwiftyGif + - YttriumWrapper EXTERNAL SOURCES: audioplayers_darwin: @@ -245,6 +251,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/package_info_plus/ios" path_provider_foundation: :path: ".symlinks/plugins/path_provider_foundation/darwin" + reown_yttrium: + :path: ".symlinks/plugins/reown_yttrium/ios" share_plus: :path: ".symlinks/plugins/share_plus/ios" shared_preferences_foundation: @@ -270,7 +278,7 @@ SPEC CHECKSUMS: FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4 FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843 FirebaseMessaging: 3b26e2cee503815e01c3701236b020aa9b576f09 - Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4 flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12 google_sign_in_ios: 7411fab6948df90490dc4620ecbcabdc3ca04017 @@ -285,14 +293,16 @@ SPEC CHECKSUMS: nfc_manager: d7da7cb781f7744b94df5fe9dbca904ac4a0939e OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94 package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 - path_provider_foundation: 0b743cbb62d8e47eab856f09262bb8c1ddcfe6ba + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 + reown_yttrium: c0e87e5965fa60a3559564cc35cffbba22976089 SDWebImage: 9f177d83116802728e122410fb25ad88f5c7608a share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f - shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6 + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 - url_launcher_ios: bb13df5870e8c4234ca12609d04010a21be43dfa + url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe + YttriumWrapper: 31e937fe9fbe0f1314d2ca6be9ce9b379a059966 PODFILE CHECKSUM: f90b7b7d52ec0d905039aa6f51266424548151c7 From 06f821c5ee4fc51bcf93060f015f89b620e9f209 Mon Sep 17 00:00:00 2001 From: sajee_techi Date: Tue, 13 Jan 2026 11:18:21 +0530 Subject: [PATCH 9/9] fix: format amounts based on decimal support for editable text fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Parse and format amounts according to community decimal support before setting in amount controller - For communities without decimals (decimalDigits == 0): convert to integer format (e.g., "1.0" → "1") - For communities with decimals: format with appropriate precision and remove trailing zeros - Apply same formatting logic to tip amounts to ensure consistency - Fixes issue where pre-filled amounts with decimals were uneditable in communities that don't support decimal values The root cause was that input formatters (integerAmountFormatter vs amountFormatter) expect amounts in specific formats. When pre-filled amounts didn't match the expected format, the text field blocked all editing attempts. --- lib/state/wallet/logic.dart | 38 ++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/lib/state/wallet/logic.dart b/lib/state/wallet/logic.dart index c1a2c0a3..41e6fbe5 100644 --- a/lib/state/wallet/logic.dart +++ b/lib/state/wallet/logic.dart @@ -1820,15 +1820,21 @@ class WalletLogic extends WidgetsBindingObserver { } if (parsedData.amount != null) { - if (format == QRFormat.eip681Transfer) { - final amount = fromDoubleUnit( - parsedData.amount!, - decimals: _wallet.currency.decimals, - ); - _amountController.text = amount; + // Parse amount value + final numValue = double.tryParse(parsedData.amount!) ?? 0; + + // Format amount based on community decimal support + final decimalDigits = _state.wallet?.decimalDigits ?? 0; + if (decimalDigits == 0) { + // No decimal support - use integer format + _amountController.text = numValue.toInt().toString(); } else { - _amountController.text = parsedData.amount!; + // Decimal support - format with appropriate precision + _amountController.text = numValue + .toStringAsFixed(decimalDigits) + .replaceAll(RegExp(r'\.?0+$'), ''); } + updateAmount(); } @@ -1855,10 +1861,24 @@ class WalletLogic extends WidgetsBindingObserver { } // Handle tip information if present - if (parsedData.tip != null) { + if (parsedData.tip != null && parsedData.tip!.amount != null) { + // Format tip amount based on community decimal support + final tipNumValue = double.tryParse(parsedData.tip!.amount!) ?? 0; + final decimalDigits = _state.wallet?.decimalDigits ?? 0; + String formattedTipAmount; + if (decimalDigits == 0) { + // No decimal support - use integer format + formattedTipAmount = tipNumValue.toInt().toString(); + } else { + // Decimal support - format with appropriate precision + formattedTipAmount = tipNumValue + .toStringAsFixed(decimalDigits) + .replaceAll(RegExp(r'\.?0+$'), ''); + } + _state.setTipping( to: parsedData.tip!.to, - amount: parsedData.tip!.amount, + amount: formattedTipAmount, description: parsedData.tip!.description, ); }