From 8185b88b4ac8a06772611f8a2f43eda46ad72494 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Tue, 8 Aug 2023 04:02:09 +0300 Subject: [PATCH] Enable Eth/Erc20 auto send in exchange (#1024) * Generate missing secrets file for ethereum * Enable Sending ERC-20 and Ethereum automatically from an Exchange --- .github/workflows/pr_test_build.yml | 1 + cw_core/lib/erc20_token.dart | 3 ++- cw_ethereum/lib/ethereum_wallet.dart | 23 +++++++++++-------- .../exchange/exchange_trade_view_model.dart | 5 +++- .../restore/restore_from_qr_vm.dart | 4 ++++ 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index de8396d59..e2b932202 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -99,6 +99,7 @@ jobs: run: | cd /opt/android/cake_wallet touch lib/.secrets.g.dart + touch cw_ethereum/lib/.secrets.g.dart echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart diff --git a/cw_core/lib/erc20_token.dart b/cw_core/lib/erc20_token.dart index 2e205e484..db5b6db5b 100644 --- a/cw_core/lib/erc20_token.dart +++ b/cw_core/lib/erc20_token.dart @@ -57,7 +57,8 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin { static const boxName = 'Erc20Tokens'; @override - bool operator ==(other) => other is Erc20Token && other.contractAddress == contractAddress; + bool operator ==(other) => (other is Erc20Token && other.contractAddress == contractAddress) || + (other is CryptoCurrency && other.title == title); @override int get hashCode => contractAddress.hashCode; diff --git a/cw_ethereum/lib/ethereum_wallet.dart b/cw_ethereum/lib/ethereum_wallet.dart index 46cb5c39f..ae05e6a4f 100644 --- a/cw_ethereum/lib/ethereum_wallet.dart +++ b/cw_ethereum/lib/ethereum_wallet.dart @@ -156,15 +156,19 @@ abstract class EthereumWalletBase final _credentials = credentials as EthereumTransactionCredentials; final outputs = _credentials.outputs; final hasMultiDestination = outputs.length > 1; - final _erc20Balance = balance[_credentials.currency]!; + + final CryptoCurrency transactionCurrency = + balance.keys.firstWhere((element) => element.title == _credentials.currency.title); + + final _erc20Balance = balance[transactionCurrency]!; BigInt totalAmount = BigInt.zero; - int exponent = - _credentials.currency is Erc20Token ? (_credentials.currency as Erc20Token).decimal : 18; + int exponent = transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18; num amountToEthereumMultiplier = pow(10, exponent); + // so far this can not be made with Ethereum as Ethereum does not support multiple recipients if (hasMultiDestination) { if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) { - throw EthereumTransactionCreationException(_credentials.currency); + throw EthereumTransactionCreationException(transactionCurrency); } final totalOriginalAmount = EthereumFormatter.parseEthereumAmountToDouble( @@ -172,7 +176,7 @@ abstract class EthereumWalletBase totalAmount = BigInt.from(totalOriginalAmount * amountToEthereumMultiplier); if (_erc20Balance.balance < totalAmount) { - throw EthereumTransactionCreationException(_credentials.currency); + throw EthereumTransactionCreationException(transactionCurrency); } } else { final output = outputs.first; @@ -185,7 +189,7 @@ abstract class EthereumWalletBase : BigInt.from(totalOriginalAmount * amountToEthereumMultiplier); if (_erc20Balance.balance < totalAmount) { - throw EthereumTransactionCreationException(_credentials.currency); + throw EthereumTransactionCreationException(transactionCurrency); } } @@ -195,11 +199,10 @@ abstract class EthereumWalletBase amount: totalAmount.toString(), gas: _estimatedGas!, priority: _credentials.priority!, - currency: _credentials.currency, + currency: transactionCurrency, exponent: exponent, - contractAddress: _credentials.currency is Erc20Token - ? (_credentials.currency as Erc20Token).contractAddress - : null, + contractAddress: + transactionCurrency is Erc20Token ? transactionCurrency.contractAddress : null, ); return pendingEthereumTransaction; diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index bfc7f9588..cfabd994f 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -29,7 +29,9 @@ abstract class ExchangeTradeViewModelBase with Store { required this.sendViewModel}) : trade = tradesStore.trade!, isSendable = tradesStore.trade!.from == wallet.currency || - tradesStore.trade!.provider == ExchangeProviderDescription.xmrto, + tradesStore.trade!.provider == ExchangeProviderDescription.xmrto || + (wallet.currency == CryptoCurrency.eth && + tradesStore.trade!.from.tag == CryptoCurrency.eth.title), items = ObservableList() { switch (trade.provider) { case ExchangeProviderDescription.xmrto: @@ -103,6 +105,7 @@ abstract class ExchangeTradeViewModelBase with Store { final output = sendViewModel.outputs.first; output.address = trade.inputAddress ?? ''; output.setCryptoAmount(trade.amount); + sendViewModel.selectedCryptoCurrency = trade.from; await sendViewModel.createTransaction(); } diff --git a/lib/view_model/restore/restore_from_qr_vm.dart b/lib/view_model/restore/restore_from_qr_vm.dart index 7efb92e69..996b3b3fb 100644 --- a/lib/view_model/restore/restore_from_qr_vm.dart +++ b/lib/view_model/restore/restore_from_qr_vm.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/view_model/restore/restore_mode.dart'; import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; import 'package:hive/hive.dart'; @@ -80,6 +81,9 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store case WalletType.litecoin: return bitcoin!.createBitcoinRestoreWalletFromSeedCredentials( name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); + case WalletType.ethereum: + return ethereum!.createEthereumRestoreWalletFromSeedCredentials( + name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); default: throw Exception('Unexpected type: ${type.toString()}'); }