properly load eth token wallets

This commit is contained in:
julian 2024-01-10 17:40:42 -06:00
parent 6942a9b3dd
commit 187f3bc462
4 changed files with 142 additions and 111 deletions
lib
pages/token_view/sub_widgets
wallets/wallet
widgets

View file

@ -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/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/wallet/impl/ethereum_wallet.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/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/desktop/primary_button.dart';
import 'package:stackwallet/widgets/dialogs/basic_dialog.dart'; import 'package:stackwallet/widgets/dialogs/basic_dialog.dart';
import 'package:stackwallet/widgets/icon_widgets/eth_token_icon.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); final old = ref.read(tokenServiceStateProvider);
// exit previous if there is one // exit previous if there is one
unawaited(old?.exit()); unawaited(old?.exit());
ref.read(tokenServiceStateProvider.state).state = EthTokenWallet( ref.read(tokenServiceStateProvider.state).state = Wallet.loadTokenWallet(
ref.read(pWallets).getWallet(widget.walletId) as EthereumWallet, ethWallet:
widget.token, ref.read(pWallets).getWallet(widget.walletId) as EthereumWallet,
); contract: widget.token,
) as EthTokenWallet;
final success = await showLoading<bool>( final success = await showLoading<bool>(
whileFuture: _loadTokenWallet(context, ref), whileFuture: _loadTokenWallet(context, ref),

View file

@ -79,119 +79,126 @@ class EthTokenWallet extends Wallet {
@override @override
Future<void> init() async { 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 { try {
_deployedContract = web3dart.DeployedContract( await super.init();
ContractAbiExtensions.fromJsonList(
jsonList: tokenContract.abi!,
name: tokenContract.name,
),
contractAddress,
);
} catch (_) {
rethrow;
}
try { final contractAddress =
_sendFunction = _deployedContract.function('transfer'); web3dart.EthereumAddress.fromHex(tokenContract.address);
} 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 if (tokenContract.abi == null) {
//====================================================================
// 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( _tokenContract = await _updateTokenABI(
forContract: tokenContract, forContract: tokenContract,
usingContractAddress: contractAddressResponse.value!, usingContractAddress: contractAddress.hex,
); );
} else {
throw contractAddressResponse.exception!;
} }
//====================================================================
}
try { // String? mnemonicString = await ethWallet.getMnemonic();
_deployedContract = web3dart.DeployedContract( //
ContractAbiExtensions.fromJsonList( // //Get private key for given mnemonic
jsonList: tokenContract.abi!, // String privateKey = getPrivateKey(
name: tokenContract.name, // mnemonicString,
), // (await ethWallet.getMnemonicPassphrase()),
contractAddress, // );
// _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 @override

View file

@ -5,6 +5,7 @@ import 'package:meta/meta.dart';
import 'package:mutex/mutex.dart'; import 'package:mutex/mutex.dart';
import 'package:stackwallet/db/isar/main_db.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/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/node_model.dart';
import 'package:stackwallet/models/paymint/fee_object_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'; 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/namecoin_wallet.dart';
import 'package:stackwallet/wallets/wallet/impl/nano_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/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/tezos_wallet.dart';
import 'package:stackwallet/wallets/wallet/impl/wownero_wallet.dart'; import 'package:stackwallet/wallets/wallet/impl/wownero_wallet.dart';
import 'package:stackwallet/wallets/wallet/intermediate/cryptonote_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 ==================================================== // ========== Static Util ====================================================

View file

@ -57,10 +57,10 @@ class SimpleWalletCard extends ConsumerWidget {
final old = ref.read(tokenServiceStateProvider); final old = ref.read(tokenServiceStateProvider);
// exit previous if there is one // exit previous if there is one
unawaited(old?.exit()); unawaited(old?.exit());
ref.read(tokenServiceStateProvider.state).state = EthTokenWallet( ref.read(tokenServiceStateProvider.state).state = Wallet.loadTokenWallet(
wallet as EthereumWallet, ethWallet: wallet as EthereumWallet,
contract, contract: contract,
); ) as EthTokenWallet;
try { try {
await ref.read(pCurrentTokenWallet)!.init(); await ref.read(pCurrentTokenWallet)!.init();