Enable Eth/Erc20 auto send in exchange (#1024)

* Generate missing secrets file for ethereum * Enable Sending ERC-20 and Ethereum automatically from an Exchange

Omar Hatem committed Aug 8, 2023 at 04:02 UTC 8185b88b4ac8a06772611f8a2f43eda46ad72494
5 files changed +24 -12
.github/workflows/pr_test_build.yml
+1
@@ -99,6 +99,7 @@ jobs:
99 run: |
100 cd /opt/android/cake_wallet
101 touch lib/.secrets.g.dart
102 + touch cw_ethereum/lib/.secrets.g.dart
103 echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart
104 echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart
105 echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart
cw_core/lib/erc20_token.dart
+2 -1
@@ -57,7 +57,8 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin {
57 static const boxName = 'Erc20Tokens';
58
59 @override
60 - bool operator ==(other) => other is Erc20Token && other.contractAddress == contractAddress;
60 + bool operator ==(other) => (other is Erc20Token && other.contractAddress == contractAddress) ||
61 + (other is CryptoCurrency && other.title == title);
62
63 @override
64 int get hashCode => contractAddress.hashCode;
cw_ethereum/lib/ethereum_wallet.dart
+13 -10
@@ -156,15 +156,19 @@ abstract class EthereumWalletBase
156 final _credentials = credentials as EthereumTransactionCredentials;
157 final outputs = _credentials.outputs;
158 final hasMultiDestination = outputs.length > 1;
159 - final _erc20Balance = balance[_credentials.currency]!;
159 +
160 + final CryptoCurrency transactionCurrency =
161 + balance.keys.firstWhere((element) => element.title == _credentials.currency.title);
162 +
163 + final _erc20Balance = balance[transactionCurrency]!;
164 BigInt totalAmount = BigInt.zero;
161 - int exponent =
162 - _credentials.currency is Erc20Token ? (_credentials.currency as Erc20Token).decimal : 18;
165 + int exponent = transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18;
166 num amountToEthereumMultiplier = pow(10, exponent);
167
168 + // so far this can not be made with Ethereum as Ethereum does not support multiple recipients
169 if (hasMultiDestination) {
170 if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) {
167 - throw EthereumTransactionCreationException(_credentials.currency);
171 + throw EthereumTransactionCreationException(transactionCurrency);
172 }
173
174 final totalOriginalAmount = EthereumFormatter.parseEthereumAmountToDouble(
@@ -172,7 +176,7 @@ abstract class EthereumWalletBase
176 totalAmount = BigInt.from(totalOriginalAmount * amountToEthereumMultiplier);
177
178 if (_erc20Balance.balance < totalAmount) {
175 - throw EthereumTransactionCreationException(_credentials.currency);
179 + throw EthereumTransactionCreationException(transactionCurrency);
180 }
181 } else {
182 final output = outputs.first;
@@ -185,7 +189,7 @@ abstract class EthereumWalletBase
189 : BigInt.from(totalOriginalAmount * amountToEthereumMultiplier);
190
191 if (_erc20Balance.balance < totalAmount) {
188 - throw EthereumTransactionCreationException(_credentials.currency);
192 + throw EthereumTransactionCreationException(transactionCurrency);
193 }
194 }
195
@@ -195,11 +199,10 @@ abstract class EthereumWalletBase
199 amount: totalAmount.toString(),
200 gas: _estimatedGas!,
201 priority: _credentials.priority!,
198 - currency: _credentials.currency,
202 + currency: transactionCurrency,
203 exponent: exponent,
200 - contractAddress: _credentials.currency is Erc20Token
201 - ? (_credentials.currency as Erc20Token).contractAddress
202 - : null,
204 + contractAddress:
205 + transactionCurrency is Erc20Token ? transactionCurrency.contractAddress : null,
206 );
207
208 return pendingEthereumTransaction;
lib/view_model/exchange/exchange_trade_view_model.dart
+4 -1
@@ -29,7 +29,9 @@ abstract class ExchangeTradeViewModelBase with Store {
29 required this.sendViewModel})
30 : trade = tradesStore.trade!,
31 isSendable = tradesStore.trade!.from == wallet.currency ||
32 - tradesStore.trade!.provider == ExchangeProviderDescription.xmrto,
32 + tradesStore.trade!.provider == ExchangeProviderDescription.xmrto ||
33 + (wallet.currency == CryptoCurrency.eth &&
34 + tradesStore.trade!.from.tag == CryptoCurrency.eth.title),
35 items = ObservableList<ExchangeTradeItem>() {
36 switch (trade.provider) {
37 case ExchangeProviderDescription.xmrto:
@@ -103,6 +105,7 @@ abstract class ExchangeTradeViewModelBase with Store {
105 final output = sendViewModel.outputs.first;
106 output.address = trade.inputAddress ?? '';
107 output.setCryptoAmount(trade.amount);
108 + sendViewModel.selectedCryptoCurrency = trade.from;
109 await sendViewModel.createTransaction();
110 }
111
lib/view_model/restore/restore_from_qr_vm.dart
+4
@@ -1,4 +1,5 @@
1 import 'package:cake_wallet/bitcoin/bitcoin.dart';
2 +import 'package:cake_wallet/ethereum/ethereum.dart';
3 import 'package:cake_wallet/view_model/restore/restore_mode.dart';
4 import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
5 import 'package:hive/hive.dart';
@@ -80,6 +81,9 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store
81 case WalletType.litecoin:
82 return bitcoin!.createBitcoinRestoreWalletFromSeedCredentials(
83 name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password);
84 + case WalletType.ethereum:
85 + return ethereum!.createEthereumRestoreWalletFromSeedCredentials(
86 + name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password);
87 default:
88 throw Exception('Unexpected type: ${type.toString()}');
89 }