Cw 870 ethereum enhancements (#1951)

* fix evm balance display issues * fix adding token * fix tab controller issue * Update cw_evm/lib/evm_chain_client.dart [skip ci] --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

Serhii committed Feb 17, 2025 at 15:12 UTC 7cc9e360164df93ee785714f74f906925b54cae9
6 files changed +60 -24
cw_evm/lib/evm_chain_client.dart
+9 -3
@@ -268,12 +268,18 @@ abstract class EVMChainClient {
268
269 Future<EVMChainERC20Balance> fetchERC20Balances(
270 EthereumAddress userAddress, String contractAddress) async {
271 - final erc20 = ERC20(address: EthereumAddress.fromHex(contractAddress), client: _client!);
272 - final balance = await erc20.balanceOf(userAddress);
271 + try {
272 + final erc20 = ERC20(address: EthereumAddress.fromHex(contractAddress), client: _client!);
273 + final balance = await erc20.balanceOf(userAddress);
274
275 int exponent = (await erc20.decimals()).toInt();
276
276 - return EVMChainERC20Balance(balance, exponent: exponent);
277 + return EVMChainERC20Balance(balance, exponent: exponent);
278 + } on RangeError catch (_) {
279 + throw Exception('Invalid token contract for this network.');
280 + } catch (e) {
281 + throw Exception('Could not fetch balances: ${e.toString()}');
282 + }
283 }
284
285 Future<Erc20Token?> getErc20Token(String contractAddress, String chainName) async {
cw_evm/lib/evm_chain_wallet.dart
+13 -6
@@ -634,14 +634,21 @@ abstract class EVMChainWalletBase
634
635 final newToken = createNewErc20TokenObject(token, iconPath);
636
637 - await evmChainErc20TokensBox.put(newToken.contractAddress, newToken);
638 -
637 if (newToken.enabled) {
640 - balance[newToken] = await _client.fetchERC20Balances(
641 - _evmChainPrivateKey.address,
642 - newToken.contractAddress,
643 - );
638 + try {
639 + final erc20Balance = await _client.fetchERC20Balances(
640 + _evmChainPrivateKey.address,
641 + newToken.contractAddress,
642 + );
643 +
644 + balance[newToken] = erc20Balance;
645 +
646 + await evmChainErc20TokensBox.put(newToken.contractAddress, newToken);
647 + } on Exception catch (_) {
648 + rethrow;
649 + }
650 } else {
651 + await evmChainErc20TokensBox.put(newToken.contractAddress, newToken);
652 balance.remove(newToken);
653 }
654 }
cw_evm/lib/evm_erc20_balance.dart
+5 -2
@@ -1,5 +1,6 @@
1 import 'dart:convert';
2 import 'dart:math';
3 +import 'package:intl/intl.dart';
4
5 import 'package:cw_core/balance.dart';
6
@@ -17,8 +18,10 @@ class EVMChainERC20Balance extends Balance {
18 String get formattedAvailableBalance => _balance();
19
20 String _balance() {
20 - final String formattedBalance = (balance / BigInt.from(10).pow(exponent)).toString();
21 - return formattedBalance.substring(0, min(12, formattedBalance.length));
21 + NumberFormat formatter = NumberFormat('0.00##########', 'en_US');
22 + double numBalance = (balance / BigInt.from(10).pow(exponent)).toDouble();
23 + String formattedBalance = formatter.format(numBalance);
24 + return formattedBalance;
25 }
26
27 String toJSON() => json.encode({
lib/src/screens/dashboard/edit_token_page.dart
+28 -12
@@ -212,15 +212,34 @@ class _EditTokenPageBodyState extends State<EditTokenPageBody> {
212 _contractAddressController.text,
213 );
214 final actionCall = () async {
215 - await widget.homeSettingsViewModel.addToken(
216 - token: CryptoCurrency(
217 - name: _tokenNameController.text,
218 - title: _tokenSymbolController.text.toUpperCase(),
219 - decimals: int.parse(_tokenDecimalController.text),
220 - iconPath: _tokenIconPathController.text,
221 - ),
222 - contractAddress: _contractAddressController.text,
223 - );
215 + try {
216 + await widget.homeSettingsViewModel.addToken(
217 + token: CryptoCurrency(
218 + name: _tokenNameController.text,
219 + title: _tokenSymbolController.text.toUpperCase(),
220 + decimals: int.parse(_tokenDecimalController.text),
221 + iconPath: _tokenIconPathController.text,
222 + ),
223 + contractAddress: _contractAddressController.text,
224 + );
225 +
226 + if (mounted) {
227 + Navigator.pop(context);
228 + }
229 +
230 + } catch (e) {
231 + showPopUp<void>(
232 + context: context,
233 + builder: (dialogContext) {
234 + return AlertWithOneAction(
235 + alertTitle: S.current.warning,
236 + alertContent: e.toString(),
237 + buttonText: S.of(context).ok,
238 + buttonAction: () => Navigator.of(dialogContext).pop(),
239 + );
240 + },
241 + );
242 + }
243 };
244
245 if (hasPotentialError) {
@@ -235,9 +254,6 @@ class _EditTokenPageBodyState extends State<EditTokenPageBody> {
254 actionRightButton: () async {
255 Navigator.of(dialogContext).pop();
256 await actionCall();
238 - if (mounted) {
239 - Navigator.pop(context);
240 - }
257 },
258 actionLeftButton: () => Navigator.of(dialogContext).pop(),
259 );
lib/src/screens/dashboard/pages/balance/balance_page.dart
+1
@@ -25,6 +25,7 @@ class BalancePage extends StatelessWidget {
25 builder: (context) {
26 final isEVMCompatible = isEVMCompatibleChain(dashboardViewModel.type);
27 return DefaultTabController(
28 + key: ValueKey<bool>(isEVMCompatible),
29 length: isEVMCompatible ? 2 : 1,
30 child: Column(
31 children: [
lib/view_model/dashboard/home_settings_view_model.dart
+4 -1
@@ -117,7 +117,10 @@ abstract class HomeSettingsViewModelBase with Store {
117
118 _updateTokensList();
119 _updateFiatPrices(token);
120 - } finally {
120 + } catch (e) {
121 + throw e;
122 + }
123 + finally {
124 isAddingToken = false;
125 }
126 }