diff --git a/cw_ethereum/lib/ethereum_client.dart b/cw_ethereum/lib/ethereum_client.dart index c2639827f..532eb2b99 100644 --- a/cw_ethereum/lib/ethereum_client.dart +++ b/cw_ethereum/lib/ethereum_client.dart @@ -208,6 +208,10 @@ I/flutter ( 4474): Gas Used: 53000 } } + Web3Client? getWeb3Client() { + return _client; + } + // Future _getDecimalPlacesForContract(DeployedContract contract) async { // final String abi = await rootBundle.loadString("assets/abi_json/erc20_abi.json"); // final contractAbi = ContractAbi.fromJson(abi, "ERC20"); diff --git a/cw_ethereum/lib/ethereum_wallet.dart b/cw_ethereum/lib/ethereum_wallet.dart index 90e5ea0c1..21bde1233 100644 --- a/cw_ethereum/lib/ethereum_wallet.dart +++ b/cw_ethereum/lib/ethereum_wallet.dart @@ -510,4 +510,6 @@ abstract class EthereumWalletBase @override String signMessage(String message, {String? address = null}) => bytesToHex(_ethPrivateKey.signPersonalMessageToUint8List(ascii.encode(message))); + + Web3Client? getWeb3Client() => _client.getWeb3Client(); } diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index f2a235363..abafea0d5 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -267,4 +267,4 @@ class AddressValidator extends TextValidator { return null; } } -} +} \ No newline at end of file diff --git a/lib/di.dart b/lib/di.dart index a08e84cfb..678a8a325 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -912,7 +912,7 @@ Future setup({ getIt.registerFactory(() => YatService()); getIt.registerFactory(() => AddressResolver( - yatService: getIt.get(), walletType: getIt.get().wallet!.type)); + yatService: getIt.get(), wallet: getIt.get().wallet!)); getIt.registerFactoryParam( (QrViewData viewData, _) => FullscreenQRPage(qrViewData: viewData)); diff --git a/lib/entities/ens_record.dart b/lib/entities/ens_record.dart new file mode 100644 index 000000000..8cf62d79b --- /dev/null +++ b/lib/entities/ens_record.dart @@ -0,0 +1,46 @@ +import 'package:cake_wallet/ethereum/ethereum.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:ens_dart/ens_dart.dart'; +import 'package:http/http.dart'; +import 'package:web3dart/web3dart.dart'; + +class EnsRecord { + static Future fetchEnsAddress(String name, {WalletBase? wallet}) async { + Web3Client? _client; + + if (wallet != null && wallet.type == WalletType.ethereum) { + _client = ethereum!.getWeb3Client(wallet); + } + + if (_client == null) { + _client = Web3Client("https://ethereum.publicnode.com", Client()); + } + + try { + final ens = Ens(client: _client); + + if (wallet != null) { + switch (wallet.type) { + case WalletType.monero: + return await ens.withName(name).getCoinAddress(CoinType.XMR); + case WalletType.bitcoin: + return await ens.withName(name).getCoinAddress(CoinType.BTC); + case WalletType.litecoin: + return await ens.withName(name).getCoinAddress(CoinType.LTC); + case WalletType.haven: + return await ens.withName(name).getCoinAddress(CoinType.XHV); + case WalletType.ethereum: + default: + return (await ens.withName(name).getAddress()).hex; + } + } + + final addr = await ens.withName(name).getAddress(); + return addr.hex; + } catch (e) { + print(e); + return ""; + } + } +} diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart index c0eab6d65..515b9a2df 100644 --- a/lib/entities/parse_address_from_domain.dart +++ b/lib/entities/parse_address_from_domain.dart @@ -1,19 +1,22 @@ import 'package:cake_wallet/core/address_validator.dart'; import 'package:cake_wallet/core/yat_service.dart'; +import 'package:cake_wallet/entities/ens_record.dart'; import 'package:cake_wallet/entities/openalias_record.dart'; import 'package:cake_wallet/entities/parsed_address.dart'; import 'package:cake_wallet/entities/unstoppable_domain_address.dart'; import 'package:cake_wallet/entities/emoji_string_extension.dart'; import 'package:cake_wallet/twitter/twitter_api.dart'; import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/entities/fio_address_provider.dart'; class AddressResolver { - AddressResolver({required this.yatService, required this.walletType}); + AddressResolver({required this.yatService, required this.wallet}) : walletType = wallet.type; final YatService yatService; final WalletType walletType; + final WalletBase wallet; static const unstoppableDomains = [ 'crypto', @@ -63,7 +66,7 @@ class AddressResolver { }); final userTweetsText = subString.toString(); final addressFromPinnedTweet = - extractAddressByType(raw: userTweetsText, type: CryptoCurrency.fromString(ticker)); + extractAddressByType(raw: userTweetsText, type: CryptoCurrency.fromString(ticker)); if (addressFromPinnedTweet != null) { return ParsedAddress.fetchTwitterAddress(address: addressFromPinnedTweet, name: text); @@ -96,6 +99,13 @@ class AddressResolver { return ParsedAddress.fetchUnstoppableDomainAddress(address: address, name: text); } + if (text.endsWith(".eth")) { + final address = await EnsRecord.fetchEnsAddress(text, wallet: wallet); + if (address.isNotEmpty && address != "0x0000000000000000000000000000000000000000") { + return ParsedAddress.fetchEnsAddress(name: text, address: address); + } + } + if (formattedName.contains(".")) { final txtRecord = await OpenaliasRecord.lookupOpenAliasRecord(formattedName); if (txtRecord != null) { diff --git a/lib/entities/parsed_address.dart b/lib/entities/parsed_address.dart index 67caebcb5..b8c0a81d5 100644 --- a/lib/entities/parsed_address.dart +++ b/lib/entities/parsed_address.dart @@ -1,7 +1,7 @@ import 'package:cake_wallet/entities/openalias_record.dart'; import 'package:cake_wallet/entities/yat_record.dart'; -enum ParseFrom { unstoppableDomains, openAlias, yatRecord, fio, notParsed, twitter, contact } +enum ParseFrom { unstoppableDomains, openAlias, yatRecord, fio, notParsed, twitter, ens, contact } class ParsedAddress { ParsedAddress({ @@ -77,8 +77,17 @@ class ParsedAddress { ); } + factory ParsedAddress.fetchEnsAddress({required String address, required String name}) { + return ParsedAddress( + addresses: [address], + name: name, + parseFrom: ParseFrom.ens, + ); + } + final List addresses; final String name; final String description; final ParseFrom parseFrom; + } diff --git a/lib/ethereum/cw_ethereum.dart b/lib/ethereum/cw_ethereum.dart index d3c11c361..602db2d49 100644 --- a/lib/ethereum/cw_ethereum.dart +++ b/lib/ethereum/cw_ethereum.dart @@ -145,4 +145,9 @@ class CWEthereum extends Ethereum { void updateEtherscanUsageState(WalletBase wallet, bool isEnabled) { (wallet as EthereumWallet).updateEtherscanUsageState(isEnabled); } + + @override + Web3Client? getWeb3Client(WalletBase wallet) { + return (wallet as EthereumWallet).getWeb3Client(); + } } diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 961cf4ba5..6b35158e3 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -66,9 +66,8 @@ class SendPage extends BasePage { color: titleColor(context), size: 16, ); - final _closeButton = currentTheme.type == ThemeType.dark - ? closeButtonImageDarkTheme - : closeButtonImage; + final _closeButton = + currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage; bool isMobileView = ResponsiveLayoutUtil.instance.isMobile; @@ -79,13 +78,10 @@ class SendPage extends BasePage { child: ButtonTheme( minWidth: double.minPositive, child: Semantics( - label: !isMobileView - ? S.of(context).close - : S.of(context).seed_alert_back, + label: !isMobileView ? S.of(context).close : S.of(context).seed_alert_back, child: TextButton( style: ButtonStyle( - overlayColor: MaterialStateColor.resolveWith( - (states) => Colors.transparent), + overlayColor: MaterialStateColor.resolveWith((states) => Colors.transparent), ), onPressed: () => onClose(context), child: !isMobileView ? _closeButton : _backButton, @@ -123,8 +119,7 @@ class SendPage extends BasePage { Padding( padding: const EdgeInsets.only(right: 8.0), child: Observer( - builder: (_) => - SyncIndicatorIcon(isSynced: sendViewModel.isReadyForSend), + builder: (_) => SyncIndicatorIcon(isSynced: sendViewModel.isReadyForSend), ), ), if (supMiddle != null) supMiddle @@ -158,10 +153,10 @@ class SendPage extends BasePage { _setEffects(context); return GestureDetector( - onLongPress: () => sendViewModel.balanceViewModel.isReversing = - !sendViewModel.balanceViewModel.isReversing, - onLongPressUp: () => sendViewModel.balanceViewModel.isReversing = - !sendViewModel.balanceViewModel.isReversing, + onLongPress: () => + sendViewModel.balanceViewModel.isReversing = !sendViewModel.balanceViewModel.isReversing, + onLongPressUp: () => + sendViewModel.balanceViewModel.isReversing = !sendViewModel.balanceViewModel.isReversing, child: Form( key: _formKey, child: ScrollableWithBottomSection( @@ -191,8 +186,7 @@ class SendPage extends BasePage { }, )), Padding( - padding: EdgeInsets.only( - top: 10, left: 24, right: 24, bottom: 10), + padding: EdgeInsets.only(top: 10, left: 24, right: 24, bottom: 10), child: Container( height: 10, child: Observer( @@ -208,8 +202,12 @@ class SendPage extends BasePage { radius: 6.0, dotWidth: 6.0, dotHeight: 6.0, - dotColor: Theme.of(context).extension()!.indicatorDotColor, - activeDotColor: Theme.of(context).extension()!.templateBackgroundColor), + dotColor: Theme.of(context) + .extension()! + .indicatorDotColor, + activeDotColor: Theme.of(context) + .extension()! + .templateBackgroundColor), ) : Offstage(); }, @@ -230,8 +228,7 @@ class SendPage extends BasePage { return Row( children: [ AddTemplateButton( - onTap: () => Navigator.of(context) - .pushNamed(Routes.sendTemplate), + onTap: () => Navigator.of(context).pushNamed(Routes.sendTemplate), currentTemplatesLength: templates.length, ), ListView.builder( @@ -244,9 +241,8 @@ class SendPage extends BasePage { return TemplateTile( key: UniqueKey(), to: template.name, - hasMultipleRecipients: - template.additionalRecipients != null && - template.additionalRecipients!.length > 1, + hasMultipleRecipients: template.additionalRecipients != null && + template.additionalRecipients!.length > 1, amount: template.isCurrencySelected ? template.amount : template.amountFiat, @@ -257,7 +253,9 @@ class SendPage extends BasePage { if (template.additionalRecipients?.isNotEmpty ?? false) { sendViewModel.clearOutputs(); - for (int i = 0;i < template.additionalRecipients!.length;i++) { + for (int i = 0; + i < template.additionalRecipients!.length; + i++) { Output output; try { output = sendViewModel.outputs[i]; @@ -286,26 +284,17 @@ class SendPage extends BasePage { context: context, builder: (dialogContext) { return AlertWithTwoActions( - alertTitle: - S.of(context).template, - alertContent: S - .of(context) - .confirm_delete_template, - rightButtonText: - S.of(context).delete, - leftButtonText: - S.of(context).cancel, + alertTitle: S.of(context).template, + alertContent: S.of(context).confirm_delete_template, + rightButtonText: S.of(context).delete, + leftButtonText: S.of(context).cancel, actionRightButton: () { - Navigator.of(dialogContext) - .pop(); - sendViewModel - .sendTemplateViewModel - .removeTemplate( - template: template); + Navigator.of(dialogContext).pop(); + sendViewModel.sendTemplateViewModel + .removeTemplate(template: template); }, actionLeftButton: () => - Navigator.of(dialogContext) - .pop()); + Navigator.of(dialogContext).pop()); }, ); }, @@ -321,8 +310,7 @@ class SendPage extends BasePage { ], ), ), - bottomSectionPadding: - EdgeInsets.only(left: 24, right: 24, bottom: 24), + bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), bottomSection: Column( children: [ if (sendViewModel.hasCurrecyChanger) @@ -331,10 +319,10 @@ class SendPage extends BasePage { padding: EdgeInsets.only(bottom: 12), child: PrimaryButton( onPressed: () => presentCurrencyPicker(context), - text: - 'Change your asset (${sendViewModel.selectedCryptoCurrency})', + text: 'Change your asset (${sendViewModel.selectedCryptoCurrency})', color: Colors.transparent, - textColor: Theme.of(context).extension()!.hintTextColor, + textColor: + Theme.of(context).extension()!.hintTextColor, ))), if (sendViewModel.sendTemplateViewModel.hasMultiRecipient) Padding( @@ -343,22 +331,21 @@ class SendPage extends BasePage { onPressed: () { sendViewModel.addOutput(); Future.delayed(const Duration(milliseconds: 250), () { - controller - .jumpToPage(sendViewModel.outputs.length - 1); + controller.jumpToPage(sendViewModel.outputs.length - 1); }); }, text: S.of(context).add_receiver, color: Colors.transparent, textColor: Theme.of(context).extension()!.hintTextColor, isDottedBorder: true, - borderColor: Theme.of(context).extension()!.templateDottedBorderColor, + borderColor: + Theme.of(context).extension()!.templateDottedBorderColor, )), Observer( builder: (_) { return LoadingPrimaryButton( onPressed: () async { - if (_formKey.currentState != null && - !_formKey.currentState!.validate()) { + if (_formKey.currentState != null && !_formKey.currentState!.validate()) { if (sendViewModel.outputs.length > 1) { showErrorValidationAlert(context); } @@ -367,9 +354,7 @@ class SendPage extends BasePage { } final notValidItems = sendViewModel.outputs - .where((item) => - item.address.isEmpty || - item.cryptoAmount.isEmpty) + .where((item) => item.address.isEmpty || item.cryptoAmount.isEmpty) .toList(); if (notValidItems.isNotEmpty) { @@ -389,8 +374,7 @@ class SendPage extends BasePage { ); }, text: S.of(context).send, - color: - Theme.of(context).primaryColor, + color: Theme.of(context).primaryColor, textColor: Colors.white, isLoading: sendViewModel.state is IsExecutingState || sendViewModel.state is TransactionCommitting, @@ -433,14 +417,11 @@ class SendPage extends BasePage { return ConfirmSendingAlert( alertTitle: S.of(context).confirm_sending, amount: S.of(context).send_amount, - amountValue: - sendViewModel.pendingTransaction!.amountFormatted, - fiatAmountValue: - sendViewModel.pendingTransactionFiatAmountFormatted, + amountValue: sendViewModel.pendingTransaction!.amountFormatted, + fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted, fee: S.of(context).send_fee, feeValue: sendViewModel.pendingTransaction!.feeFormatted, - feeFiatAmount: sendViewModel - .pendingTransactionFeeFiatAmountFormatted, + feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted, outputs: sendViewModel.outputs, rightButtonText: S.of(context).ok, leftButtonText: S.of(context).cancel, @@ -461,8 +442,7 @@ class SendPage extends BasePage { return AlertWithOneAction( alertTitle: '', alertContent: S.of(context).send_success( - sendViewModel.selectedCryptoCurrency - .toString()), + sendViewModel.selectedCryptoCurrency.toString()), buttonText: S.of(context).ok, buttonAction: () { Navigator.of(context).pop(); @@ -492,8 +472,8 @@ class SendPage extends BasePage { Future _setInputsFromTemplate(BuildContext context, {required Output output, required Template template}) async { - final fiatFromTemplate = FiatCurrency.all - .singleWhere((element) => element.title == template.fiatCurrency); + final fiatFromTemplate = + FiatCurrency.all.singleWhere((element) => element.title == template.fiatCurrency); output.address = template.address; @@ -534,12 +514,11 @@ class SendPage extends BasePage { builder: (_) => Picker( items: sendViewModel.currencies, displayItem: (Object item) => item.toString(), - selectedAtIndex: sendViewModel.currencies - .indexOf(sendViewModel.selectedCryptoCurrency), + selectedAtIndex: + sendViewModel.currencies.indexOf(sendViewModel.selectedCryptoCurrency), title: S.of(context).please_select, mainAxisAlignment: MainAxisAlignment.center, - onItemSelected: (CryptoCurrency cur) => - sendViewModel.selectedCryptoCurrency = cur, + onItemSelected: (CryptoCurrency cur) => sendViewModel.selectedCryptoCurrency = cur, ), context: context); } diff --git a/lib/src/screens/send/widgets/extract_address_from_parsed.dart b/lib/src/screens/send/widgets/extract_address_from_parsed.dart index d7e0e3d7f..2d0847158 100644 --- a/lib/src/screens/send/widgets/extract_address_from_parsed.dart +++ b/lib/src/screens/send/widgets/extract_address_from_parsed.dart @@ -18,6 +18,11 @@ Future extractAddressFromParsed( content = S.of(context).address_from_domain(parsedAddress.name); address = parsedAddress.addresses.first; break; + case ParseFrom.ens: + title = S.of(context).address_detected; + content = S.of(context).extracted_address_content('${parsedAddress.name} (ENS)'); + address = parsedAddress.addresses.first; + break; case ParseFrom.openAlias: title = S.of(context).address_detected; content = S.of(context).extracted_address_content('${parsedAddress.name} (OpenAlias)'); diff --git a/pubspec_base.yaml b/pubspec_base.yaml index f11876423..041bac19d 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -84,6 +84,10 @@ dependencies: sensitive_clipboard: ^1.0.0 walletconnect_flutter_v2: ^2.1.4 eth_sig_util: ^0.0.9 + ens_dart: + git: + url: https://github.com/cake-tech/ens_dart.git + ref: main bitcoin_flutter: git: url: https://github.com/cake-tech/bitcoin_flutter.git diff --git a/tool/configure.dart b/tool/configure.dart index 2f594925e..196230929 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -18,8 +18,10 @@ Future main(List args) async { await generateMonero(hasMonero); await generateHaven(hasHaven); await generateEthereum(hasEthereum); - await generatePubspec(hasMonero: hasMonero, hasBitcoin: hasBitcoin, hasHaven: hasHaven, hasEthereum: hasEthereum); - await generateWalletTypes(hasMonero: hasMonero, hasBitcoin: hasBitcoin, hasHaven: hasHaven, hasEthereum: hasEthereum); + await generatePubspec( + hasMonero: hasMonero, hasBitcoin: hasBitcoin, hasHaven: hasHaven, hasEthereum: hasEthereum); + await generateWalletTypes( + hasMonero: hasMonero, hasBitcoin: hasBitcoin, hasHaven: hasHaven, hasEthereum: hasEthereum); } Future generateBitcoin(bool hasImplementation) async { @@ -88,12 +90,12 @@ abstract class Bitcoin { const bitcoinEmptyDefinition = 'Bitcoin? bitcoin;\n'; const bitcoinCWDefinition = 'Bitcoin? bitcoin = CWBitcoin();\n'; - final output = '$bitcoinCommonHeaders\n' - + (hasImplementation ? '$bitcoinCWHeaders\n' : '\n') - + (hasImplementation ? '$bitcoinCwPart\n\n' : '\n') - + (hasImplementation ? bitcoinCWDefinition : bitcoinEmptyDefinition) - + '\n' - + bitcoinContent; + final output = '$bitcoinCommonHeaders\n' + + (hasImplementation ? '$bitcoinCWHeaders\n' : '\n') + + (hasImplementation ? '$bitcoinCwPart\n\n' : '\n') + + (hasImplementation ? bitcoinCWDefinition : bitcoinEmptyDefinition) + + '\n' + + bitcoinContent; if (outputFile.existsSync()) { await outputFile.delete(); @@ -268,12 +270,12 @@ abstract class MoneroAccountList { const moneroEmptyDefinition = 'Monero? monero;\n'; const moneroCWDefinition = 'Monero? monero = CWMonero();\n'; - final output = '$moneroCommonHeaders\n' - + (hasImplementation ? '$moneroCWHeaders\n' : '\n') - + (hasImplementation ? '$moneroCwPart\n\n' : '\n') - + (hasImplementation ? moneroCWDefinition : moneroEmptyDefinition) - + '\n' - + moneroContent; + final output = '$moneroCommonHeaders\n' + + (hasImplementation ? '$moneroCWHeaders\n' : '\n') + + (hasImplementation ? '$moneroCwPart\n\n' : '\n') + + (hasImplementation ? moneroCWDefinition : moneroEmptyDefinition) + + '\n' + + moneroContent; if (outputFile.existsSync()) { await outputFile.delete(); @@ -283,7 +285,6 @@ abstract class MoneroAccountList { } Future generateHaven(bool hasImplementation) async { - final outputFile = File(havenOutputPath); const havenCommonHeaders = """ import 'package:mobx/mobx.dart'; @@ -448,12 +449,12 @@ abstract class HavenAccountList { const havenEmptyDefinition = 'Haven? haven;\n'; const havenCWDefinition = 'Haven? haven = CWHaven();\n'; - final output = '$havenCommonHeaders\n' - + (hasImplementation ? '$havenCWHeaders\n' : '\n') - + (hasImplementation ? '$havenCwPart\n\n' : '\n') - + (hasImplementation ? havenCWDefinition : havenEmptyDefinition) - + '\n' - + havenContent; + final output = '$havenCommonHeaders\n' + + (hasImplementation ? '$havenCWHeaders\n' : '\n') + + (hasImplementation ? '$havenCwPart\n\n' : '\n') + + (hasImplementation ? havenCWDefinition : havenEmptyDefinition) + + '\n' + + havenContent; if (outputFile.existsSync()) { await outputFile.delete(); @@ -463,11 +464,9 @@ abstract class HavenAccountList { } Future generateEthereum(bool hasImplementation) async { - final outputFile = File(ethereumOutputPath); const ethereumCommonHeaders = """ import 'package:cake_wallet/view_model/send/output.dart'; -import 'package:cw_core/crypto_amount_format.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/erc20_token.dart'; import 'package:cw_core/output_info.dart'; @@ -479,6 +478,7 @@ import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:eth_sig_util/util/utils.dart'; import 'package:hive/hive.dart'; +import 'package:web3dart/web3dart.dart'; """; const ethereumCWHeaders = """ import 'package:cw_ethereum/ethereum_formatter.dart'; @@ -528,18 +528,19 @@ abstract class Ethereum { CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction); void updateEtherscanUsageState(WalletBase wallet, bool isEnabled); + Web3Client? getWeb3Client(WalletBase wallet); } """; const ethereumEmptyDefinition = 'Ethereum? ethereum;\n'; const ethereumCWDefinition = 'Ethereum? ethereum = CWEthereum();\n'; - final output = '$ethereumCommonHeaders\n' - + (hasImplementation ? '$ethereumCWHeaders\n' : '\n') - + (hasImplementation ? '$ethereumCwPart\n\n' : '\n') - + (hasImplementation ? ethereumCWDefinition : ethereumEmptyDefinition) - + '\n' - + ethereumContent; + final output = '$ethereumCommonHeaders\n' + + (hasImplementation ? '$ethereumCWHeaders\n' : '\n') + + (hasImplementation ? '$ethereumCwPart\n\n' : '\n') + + (hasImplementation ? ethereumCWDefinition : ethereumEmptyDefinition) + + '\n' + + ethereumContent; if (outputFile.existsSync()) { await outputFile.delete(); @@ -548,8 +549,12 @@ abstract class Ethereum { await outputFile.writeAsString(output); } -Future generatePubspec({required bool hasMonero, required bool hasBitcoin, required bool hasHaven, required bool hasEthereum}) async { - const cwCore = """ +Future generatePubspec( + {required bool hasMonero, + required bool hasBitcoin, + required bool hasHaven, + required bool hasEthereum}) async { + const cwCore = """ cw_core: path: ./cw_core """; @@ -601,7 +606,7 @@ Future generatePubspec({required bool hasMonero, required bool hasBitcoin, inputLines.insertAll(dependenciesIndex + 1, outputLines); final outputContent = inputLines.join('\n'); final outputFile = File(pubspecOutputPath); - + if (outputFile.existsSync()) { await outputFile.delete(); } @@ -609,9 +614,13 @@ Future generatePubspec({required bool hasMonero, required bool hasBitcoin, await outputFile.writeAsString(outputContent); } -Future generateWalletTypes({required bool hasMonero, required bool hasBitcoin, required bool hasHaven, required bool hasEthereum}) async { +Future generateWalletTypes( + {required bool hasMonero, + required bool hasBitcoin, + required bool hasHaven, + required bool hasEthereum}) async { final walletTypesFile = File(walletTypesPath); - + if (walletTypesFile.existsSync()) { await walletTypesFile.delete(); } diff --git a/tool/utils/translation/translation_constants.dart b/tool/utils/translation/translation_constants.dart index 6563feb32..3a472d8c4 100644 --- a/tool/utils/translation/translation_constants.dart +++ b/tool/utils/translation/translation_constants.dart @@ -1,6 +1,6 @@ const defaultLang = "en"; const langs = [ "ar", "bg", "cs", "de", "en", "es", "fr", "ha", "hi", "hr", "id", "it", - "ja", "ko", "my", "nl", "pl", "pt", "ru", "th", "tr", "uk", "ur", "yo", + "ja", "ko", "my", "nl", "pl", "pt", "ru", "th", "tl", "tr", "uk", "ur", "yo", "zh-cn" // zh, but Google Translate uses zh-cn for Chinese (Simplified) ];