From 187f3bc462f41037b142586bb94d08545a7a6986 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Wed, 10 Jan 2024 17:40:42 -0600
Subject: [PATCH] properly load eth token wallets

---
 .../sub_widgets/my_token_select_item.dart     |  10 +-
 .../impl/sub_wallets/eth_token_wallet.dart    | 213 +++++++++---------
 lib/wallets/wallet/wallet.dart                |  22 ++
 lib/widgets/wallet_card.dart                  |   8 +-
 4 files changed, 142 insertions(+), 111 deletions(-)

diff --git a/lib/pages/token_view/sub_widgets/my_token_select_item.dart b/lib/pages/token_view/sub_widgets/my_token_select_item.dart
index 08835a329..b293c2a2e 100644
--- a/lib/pages/token_view/sub_widgets/my_token_select_item.dart
+++ b/lib/pages/token_view/sub_widgets/my_token_select_item.dart
@@ -30,6 +30,7 @@ import 'package:stackwallet/wallets/isar/providers/eth/token_balance_provider.da
 import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
 import 'package:stackwallet/wallets/wallet/impl/ethereum_wallet.dart';
 import 'package:stackwallet/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart';
+import 'package:stackwallet/wallets/wallet/wallet.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/dialogs/basic_dialog.dart';
 import 'package:stackwallet/widgets/icon_widgets/eth_token_icon.dart';
@@ -88,10 +89,11 @@ class _MyTokenSelectItemState extends ConsumerState<MyTokenSelectItem> {
     final old = ref.read(tokenServiceStateProvider);
     // exit previous if there is one
     unawaited(old?.exit());
-    ref.read(tokenServiceStateProvider.state).state = EthTokenWallet(
-      ref.read(pWallets).getWallet(widget.walletId) as EthereumWallet,
-      widget.token,
-    );
+    ref.read(tokenServiceStateProvider.state).state = Wallet.loadTokenWallet(
+      ethWallet:
+          ref.read(pWallets).getWallet(widget.walletId) as EthereumWallet,
+      contract: widget.token,
+    ) as EthTokenWallet;
 
     final success = await showLoading<bool>(
       whileFuture: _loadTokenWallet(context, ref),
diff --git a/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart b/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart
index 6c7201903..64b53a094 100644
--- a/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart
+++ b/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart
@@ -79,119 +79,126 @@ class EthTokenWallet extends Wallet {
 
   @override
   Future<void> init() async {
-    await super.init();
-
-    final contractAddress =
-        web3dart.EthereumAddress.fromHex(tokenContract.address);
-
-    if (tokenContract.abi == null) {
-      _tokenContract = await _updateTokenABI(
-        forContract: tokenContract,
-        usingContractAddress: contractAddress.hex,
-      );
-    }
-
-    // String? mnemonicString = await ethWallet.getMnemonic();
-    //
-    // //Get private key for given mnemonic
-    // String privateKey = getPrivateKey(
-    //   mnemonicString,
-    //   (await ethWallet.getMnemonicPassphrase()),
-    // );
-    // _credentials = web3dart.EthPrivateKey.fromHex(privateKey);
-
     try {
-      _deployedContract = web3dart.DeployedContract(
-        ContractAbiExtensions.fromJsonList(
-          jsonList: tokenContract.abi!,
-          name: tokenContract.name,
-        ),
-        contractAddress,
-      );
-    } catch (_) {
-      rethrow;
-    }
+      await super.init();
 
-    try {
-      _sendFunction = _deployedContract.function('transfer');
-    } catch (_) {
-      //====================================================================
-      // final list = List<Map<String, dynamic>>.from(
-      //     jsonDecode(tokenContract.abi!) as List);
-      // final functionNames = list.map((e) => e["name"] as String);
-      //
-      // if (!functionNames.contains("balanceOf")) {
-      //   list.add(
-      //     {
-      //       "encoding": "0x70a08231",
-      //       "inputs": [
-      //         {"name": "account", "type": "address"}
-      //       ],
-      //       "name": "balanceOf",
-      //       "outputs": [
-      //         {"name": "val_0", "type": "uint256"}
-      //       ],
-      //       "signature": "balanceOf(address)",
-      //       "type": "function"
-      //     },
-      //   );
-      // }
-      //
-      // if (!functionNames.contains("transfer")) {
-      //   list.add(
-      //     {
-      //       "encoding": "0xa9059cbb",
-      //       "inputs": [
-      //         {"name": "dst", "type": "address"},
-      //         {"name": "rawAmount", "type": "uint256"}
-      //       ],
-      //       "name": "transfer",
-      //       "outputs": [
-      //         {"name": "val_0", "type": "bool"}
-      //       ],
-      //       "signature": "transfer(address,uint256)",
-      //       "type": "function"
-      //     },
-      //   );
-      // }
-      //--------------------------------------------------------------------
-      //====================================================================
+      final contractAddress =
+          web3dart.EthereumAddress.fromHex(tokenContract.address);
 
-      // function not found so likely a proxy so we need to fetch the impl
-      //====================================================================
-      // final updatedToken = tokenContract.copyWith(abi: jsonEncode(list));
-      // // Store updated contract
-      // final id = await MainDB.instance.putEthContract(updatedToken);
-      // _tokenContract = updatedToken..id = id;
-      //--------------------------------------------------------------------
-      final contractAddressResponse =
-          await EthereumAPI.getProxyTokenImplementationAddress(
-              contractAddress.hex);
-
-      if (contractAddressResponse.value != null) {
+      if (tokenContract.abi == null) {
         _tokenContract = await _updateTokenABI(
           forContract: tokenContract,
-          usingContractAddress: contractAddressResponse.value!,
+          usingContractAddress: contractAddress.hex,
         );
-      } else {
-        throw contractAddressResponse.exception!;
       }
-      //====================================================================
-    }
 
-    try {
-      _deployedContract = web3dart.DeployedContract(
-        ContractAbiExtensions.fromJsonList(
-          jsonList: tokenContract.abi!,
-          name: tokenContract.name,
-        ),
-        contractAddress,
+      // String? mnemonicString = await ethWallet.getMnemonic();
+      //
+      // //Get private key for given mnemonic
+      // String privateKey = getPrivateKey(
+      //   mnemonicString,
+      //   (await ethWallet.getMnemonicPassphrase()),
+      // );
+      // _credentials = web3dart.EthPrivateKey.fromHex(privateKey);
+
+      try {
+        _deployedContract = web3dart.DeployedContract(
+          ContractAbiExtensions.fromJsonList(
+            jsonList: tokenContract.abi!,
+            name: tokenContract.name,
+          ),
+          contractAddress,
+        );
+      } catch (_) {
+        rethrow;
+      }
+
+      try {
+        _sendFunction = _deployedContract.function('transfer');
+      } catch (_) {
+        //====================================================================
+        // final list = List<Map<String, dynamic>>.from(
+        //     jsonDecode(tokenContract.abi!) as List);
+        // final functionNames = list.map((e) => e["name"] as String);
+        //
+        // if (!functionNames.contains("balanceOf")) {
+        //   list.add(
+        //     {
+        //       "encoding": "0x70a08231",
+        //       "inputs": [
+        //         {"name": "account", "type": "address"}
+        //       ],
+        //       "name": "balanceOf",
+        //       "outputs": [
+        //         {"name": "val_0", "type": "uint256"}
+        //       ],
+        //       "signature": "balanceOf(address)",
+        //       "type": "function"
+        //     },
+        //   );
+        // }
+        //
+        // if (!functionNames.contains("transfer")) {
+        //   list.add(
+        //     {
+        //       "encoding": "0xa9059cbb",
+        //       "inputs": [
+        //         {"name": "dst", "type": "address"},
+        //         {"name": "rawAmount", "type": "uint256"}
+        //       ],
+        //       "name": "transfer",
+        //       "outputs": [
+        //         {"name": "val_0", "type": "bool"}
+        //       ],
+        //       "signature": "transfer(address,uint256)",
+        //       "type": "function"
+        //     },
+        //   );
+        // }
+        //--------------------------------------------------------------------
+        //====================================================================
+
+        // function not found so likely a proxy so we need to fetch the impl
+        //====================================================================
+        // final updatedToken = tokenContract.copyWith(abi: jsonEncode(list));
+        // // Store updated contract
+        // final id = await MainDB.instance.putEthContract(updatedToken);
+        // _tokenContract = updatedToken..id = id;
+        //--------------------------------------------------------------------
+        final contractAddressResponse =
+            await EthereumAPI.getProxyTokenImplementationAddress(
+                contractAddress.hex);
+
+        if (contractAddressResponse.value != null) {
+          _tokenContract = await _updateTokenABI(
+            forContract: tokenContract,
+            usingContractAddress: contractAddressResponse.value!,
+          );
+        } else {
+          throw contractAddressResponse.exception!;
+        }
+        //====================================================================
+      }
+
+      try {
+        _deployedContract = web3dart.DeployedContract(
+          ContractAbiExtensions.fromJsonList(
+            jsonList: tokenContract.abi!,
+            name: tokenContract.name,
+          ),
+          contractAddress,
+        );
+      } catch (_) {
+        rethrow;
+      }
+
+      _sendFunction = _deployedContract.function('transfer');
+    } catch (e, s) {
+      Logging.instance.log(
+        "$runtimeType wallet failed init(): $e\n$s",
+        level: LogLevel.Warning,
       );
-    } catch (_) {
-      rethrow;
     }
-
-    _sendFunction = _deployedContract.function('transfer');
   }
 
   @override
diff --git a/lib/wallets/wallet/wallet.dart b/lib/wallets/wallet/wallet.dart
index 403e0e51d..b9cf73521 100644
--- a/lib/wallets/wallet/wallet.dart
+++ b/lib/wallets/wallet/wallet.dart
@@ -5,6 +5,7 @@ import 'package:meta/meta.dart';
 import 'package:mutex/mutex.dart';
 import 'package:stackwallet/db/isar/main_db.dart';
 import 'package:stackwallet/models/isar/models/blockchain_data/address.dart';
+import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
 import 'package:stackwallet/models/node_model.dart';
 import 'package:stackwallet/models/paymint/fee_object_model.dart';
 import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart';
@@ -35,6 +36,7 @@ import 'package:stackwallet/wallets/wallet/impl/monero_wallet.dart';
 import 'package:stackwallet/wallets/wallet/impl/namecoin_wallet.dart';
 import 'package:stackwallet/wallets/wallet/impl/nano_wallet.dart';
 import 'package:stackwallet/wallets/wallet/impl/particl_wallet.dart';
+import 'package:stackwallet/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart';
 import 'package:stackwallet/wallets/wallet/impl/tezos_wallet.dart';
 import 'package:stackwallet/wallets/wallet/impl/wownero_wallet.dart';
 import 'package:stackwallet/wallets/wallet/intermediate/cryptonote_wallet.dart';
@@ -203,6 +205,26 @@ abstract class Wallet<T extends CryptoCurrency> {
     );
   }
 
+  // TODO: [prio=med] refactor to more generalized token rather than eth specific
+  static Wallet loadTokenWallet({
+    required EthereumWallet ethWallet,
+    required EthContract contract,
+  })  {
+    final Wallet wallet = EthTokenWallet(
+      ethWallet,
+      contract,
+    );
+
+    wallet.prefs = ethWallet.prefs;
+    wallet.nodeService = ethWallet.nodeService;
+    wallet.secureStorageInterface = ethWallet.secureStorageInterface;
+    wallet.mainDB = ethWallet.mainDB;
+
+    return wallet
+      .._walletInfo = ethWallet.info
+      .._watchWalletInfo();
+  }
+
   //============================================================================
   // ========== Static Util ====================================================
 
diff --git a/lib/widgets/wallet_card.dart b/lib/widgets/wallet_card.dart
index 4d661ab57..7bcf26597 100644
--- a/lib/widgets/wallet_card.dart
+++ b/lib/widgets/wallet_card.dart
@@ -57,10 +57,10 @@ class SimpleWalletCard extends ConsumerWidget {
     final old = ref.read(tokenServiceStateProvider);
     // exit previous if there is one
     unawaited(old?.exit());
-    ref.read(tokenServiceStateProvider.state).state = EthTokenWallet(
-      wallet as EthereumWallet,
-      contract,
-    );
+    ref.read(tokenServiceStateProvider.state).state = Wallet.loadTokenWallet(
+      ethWallet: wallet as EthereumWallet,
+      contract: contract,
+    ) as EthTokenWallet;
 
     try {
       await ref.read(pCurrentTokenWallet)!.init();