import 'dart:math'; import 'package:bip39/bip39.dart' as bip39; import 'package:decimal/decimal.dart'; import 'package:stack_wallet_backup/generate_password.dart'; import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/models/paymint/transactions_model.dart'; import 'package:stackwallet/models/paymint/utxo_model.dart'; import 'package:stackwallet/services/price.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'package:stackwallet/utilities/prefs.dart'; import 'package:string_to_hex/string_to_hex.dart'; import 'package:web3dart/web3dart.dart'; // import 'package:string_to_hex/string_to_hex.dart'; // import 'package:web3dart/credentials.dart'; // import 'package:web3dart/web3dart.dart'; import 'package:http/http.dart'; import 'package:stackwallet/hive/db.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/services/coins/coin_service.dart'; const int MINIMUM_CONFIRMATIONS = 1; const int DUST_LIMIT = 294; const String GENESIS_HASH_MAINNET = "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"; class EthereumWallet extends CoinServiceAPI { @override set isFavorite(bool markFavorite) { DB.instance.put( boxName: walletId, key: "isFavorite", value: markFavorite); } @override bool get isFavorite { try { return DB.instance.get(boxName: walletId, key: "isFavorite") as bool; } catch (e, s) { Logging.instance.log( "isFavorite fetch failed (returning false by default): $e\n$s", level: LogLevel.Error); return false; } } @override Coin get coin => _coin; late SecureStorageInterface _secureStore; late PriceAPI _priceAPI; final _prefs = Prefs.instance; final _client = Web3Client( "https://mainnet.infura.io/v3/22677300bf774e49a458b73313ee56ba", Client()); EthereumWallet( {required String walletId, required String walletName, required Coin coin, PriceAPI? priceAPI, required SecureStorageInterface secureStore}) { _walletId = walletId; _walletName = walletName; _coin = coin; _priceAPI = priceAPI ?? PriceAPI(Client()); _secureStore = secureStore; } @override bool shouldAutoSync = false; @override String get walletName => _walletName; late String _walletName; late Coin _coin; @override // TODO: implement allOwnAddresses Future> get allOwnAddresses => throw UnimplementedError(); @override // TODO: implement availableBalance Future get availableBalance => throw UnimplementedError(); @override // TODO: implement balanceMinusMaxFee Future get balanceMinusMaxFee => throw UnimplementedError(); @override Future confirmSend({required Map txData}) { // TODO: implement confirmSend throw UnimplementedError(); } @override // TODO: implement currentReceivingAddress Future get currentReceivingAddress => throw UnimplementedError(); @override Future estimateFeeFor(int satoshiAmount, int feeRate) { // TODO: implement estimateFeeFor throw UnimplementedError(); } @override Future exit() { // TODO: implement exit throw UnimplementedError(); } @override // TODO: implement fees Future get fees => throw UnimplementedError(); @override Future fullRescan( int maxUnusedAddressGap, int maxNumberOfIndexesToCheck) { // TODO: implement fullRescan throw UnimplementedError(); } @override Future generateNewAddress() { // TODO: implement generateNewAddress throw UnimplementedError(); } @override // TODO: implement hasCalledExit bool get hasCalledExit => throw UnimplementedError(); @override Future initializeExisting() async { Logging.instance.log("Opening existing ${coin.prettyName} wallet.", level: LogLevel.Info); if ((DB.instance.get(boxName: walletId, key: "id")) == null) { throw Exception( "Attempted to initialize an existing wallet using an unknown wallet ID!"); } await _prefs.init(); final data = DB.instance.get(boxName: walletId, key: "latest_tx_model") as TransactionData?; if (data != null) { _transactionData = Future(() => data); } } @override Future initializeNew() async { await _prefs.init(); final String mnemonic = bip39.generateMnemonic(strength: 256); final credentials = EthPrivateKey.fromHex(StringToHex.toHexString(mnemonic)); final String password = generatePassword(); var rng = Random.secure(); Wallet wallet = Wallet.createNew(credentials, password, rng); await _secureStore.write(key: '${_walletId}_mnemonic', value: mnemonic); await DB.instance .put(boxName: walletId, key: "id", value: _walletId); await DB.instance.put( boxName: walletId, key: 'receivingAddresses', value: ["0"]); await DB.instance .put(boxName: walletId, key: "receivingIndex", value: 0); await DB.instance .put(boxName: walletId, key: "changeIndex", value: 0); await DB.instance.put( boxName: walletId, key: 'blocked_tx_hashes', value: ["0xdefault"], ); // A list of transaction hashes to represent frozen utxos in wallet // initialize address book entries await DB.instance.put( boxName: walletId, key: 'addressBookEntries', value: {}); await DB.instance .put(boxName: walletId, key: "isFavorite", value: false); } @override // TODO: implement isConnected bool get isConnected => throw UnimplementedError(); @override // TODO: implement isRefreshing bool get isRefreshing => throw UnimplementedError(); @override // TODO: implement maxFee Future get maxFee => throw UnimplementedError(); @override Future> get mnemonic => _getMnemonicList(); Future> _getMnemonicList() async { final mnemonicString = await _secureStore.read(key: '${_walletId}_mnemonic'); if (mnemonicString == null) { return []; } final List data = mnemonicString.split(' '); return data; } @override // TODO: implement pendingBalance Future get pendingBalance => throw UnimplementedError(); @override Future> prepareSend( {required String address, required int satoshiAmount, Map? args}) { // TODO: implement prepareSend throw UnimplementedError(); } @override Future recoverFromMnemonic( {required String mnemonic, required int maxUnusedAddressGap, required int maxNumberOfIndexesToCheck, required int height}) { // TODO: implement recoverFromMnemonic throw UnimplementedError(); } @override Future refresh() { // TODO: implement refresh throw UnimplementedError(); } @override Future send( {required String toAddress, required int amount, Map args = const {}}) { // TODO: implement send throw UnimplementedError(); } @override Future testNetworkConnection() { // TODO: implement testNetworkConnection throw UnimplementedError(); } @override // TODO: implement totalBalance Future get totalBalance => throw UnimplementedError(); @override Future get transactionData => _transactionData ??= _fetchTransactionData(); Future? _transactionData; TransactionData? cachedTxData; @override // TODO: implement unspentOutputs Future> get unspentOutputs => throw UnimplementedError(); @override Future updateNode(bool shouldRefresh) { // TODO: implement updateNode throw UnimplementedError(); } @override Future updateSentCachedTxData(Map txData) { // TODO: implement updateSentCachedTxData throw UnimplementedError(); } @override bool validateAddress(String address) { // TODO: implement validateAddress throw UnimplementedError(); } Future _fetchTransactionData() async { throw UnimplementedError(); } @override String get walletId => _walletId; late String _walletId; @override @override set walletName(String newName) => _walletName = newName; }