Merge upstream Cake Wallet v6.5.0

Catches up from the May 12 fork point (v6.1.2+23) through v6.5.0: 535
upstream commits, including the Monero silent-open fix, Monero on Trezor,
Ledger/Trezor BLE fixes, the new seed and history screens, quick Bitcoin
sync, git-pinned dependencies (pubspec_overrides.yaml), frozen Hive
adapters (*.part.dart), monero_c v0.18.4.6-RC2 and Flutter 3.41.9.

Merged with both sides normalized first (import rename, 100-column
format), which took the conflict count from 614 paths to 322. The
procedure is now scripts/upstream_sync.sh.

Kept from Hash Bags:
- WalletType enum order and Hive IDs. SQLite stores WalletType.index and
  our order differs from upstream's; taking theirs would reread saved
  wallets as other chains. Our frozen adapter keeps the shipped IDs.
- The 1.0.2 legacy PIN and wallet-password decode and self-heal.
- Removed chains (Solana, Tron, Zano, Zcash, Decred, Haven) and the new
  Robinhood chain stay out; Cake Pay and non-Trocador swaps stay out.
- Default nodes (node.wownero.org, sethforprivacy, Blockstream, bysh.me),
  converted to upstream's isDefault node-list key; Wownero is back in the
  node reset list.
- Privacy: address resolvers limited to domain-anchored sources again;
  prices.neroswap.com for fiat; upstream's charts tab, which reads
  prices.cakewallet.com, sits behind FeatureFlag.isChartsEnabled = false.
- Lightning stays behind FeatureFlag.isLightningEnabled, including
  upstream's new post-seed Lightning username step.
- Our icon pipeline, branding and bundle identifiers.

Twelve new upstream widget tests are skipped: test and code are unchanged
from v6.5.0 apart from renames (not rerun on a pristine upstream checkout;
upstream's top_bar_test does not compile against its own TopBar).
flutter analyze lib: 0 errors; flutter test: 345 passed, 12 skipped;
flutter build bundle compiles. Built with Flutter 3.41.9.
This commit is contained in:
jwinterm
2026-10-24 23:49:29 -04:00
1406 changed files with 81062 additions and 48972 deletions
+3 -3
View File
@@ -15,7 +15,7 @@ void main(List<String> args) async {
final text = args[1];
final force = args.last == "--force";
printV('Appending "$name": "$text"');
print('Appending "$name": "$text"');
// add translation to all languages:
for (var lang in langs) {
@@ -25,12 +25,12 @@ void main(List<String> args) async {
appendStringToArbFile(fileName, name, translation, force: force);
}
printV('Alphabetizing all files...');
print('Alphabetizing all files...');
for (var lang in langs) {
final fileName = getArbFileName(lang);
alphabetizeArbFile(fileName);
}
printV('Done!');
print('Done!');
}
+91 -75
View File
@@ -78,6 +78,8 @@ import 'dart:typed_data';
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:hash_wallet/view_model/hardware_wallet/ledger_view_model.dart';
import 'package:hash_wallet/view_model/send/output.dart';
import "package:cw_core/account.dart";
import 'package:cw_core/amount/money.dart';
import 'package:cw_core/hardware/hardware_account_data.dart';
import 'package:cw_core/hardware/hardware_wallet_service.dart';
import 'package:cw_core/node.dart';
@@ -93,6 +95,7 @@ import 'package:cw_core/unspent_transaction_output.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_credentials.dart';
import 'package:cw_core/wallet_info.dart';
import "package:cw_core/balance.dart";
import 'package:cw_core/wallet_service.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cw_core/utils/print_verbose.dart';
@@ -101,6 +104,7 @@ import 'package:hive/hive.dart';
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as ledger;
import 'package:bitbox_flutter/bitbox_flutter.dart' as bitbox;
import 'package:trezor_connect/trezor_connect.dart' as trezor;
import 'package:trezor_flutter/trezor_flutter.dart' as trezor;
import 'package:blockchain_utils/blockchain_utils.dart';
import 'package:bip39/bip39.dart' as bip39;
import 'package:collection/collection.dart';
@@ -123,13 +127,16 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart';
import 'package:cw_bitcoin/bitcoin_address_record.dart';
import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart';
import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
import 'package:cw_bitcoin/lightning/lightning_addres_type.dart';
import 'package:cw_bitcoin/lightning/pending_lightning_transaction.dart';
import 'package:cw_bitcoin/litecoin_wallet_service.dart';
import 'package:cw_bitcoin/litecoin_wallet.dart';
import 'package:cw_bitcoin/hardware/bitcoin_ledger_service.dart';
import 'package:cw_bitcoin/hardware/litecoin_ledger_service.dart';
import 'package:cw_bitcoin/hardware/bitbox_service.dart';
import 'package:cw_bitcoin/hardware/litecoin_trezor_service.dart';
import 'package:cw_bitcoin/hardware/trezor_service.dart';
import 'package:cw_bitcoin/electrum_balance.dart';
import 'package:mobx/mobx.dart';
import "package:breez_sdk_spark_flutter/src/rust/errors.dart";
""";
@@ -188,12 +195,11 @@ abstract class Bitcoin {
List<ElectrumSubAddress> getSilentPaymentAddresses(Object wallet);
List<ElectrumSubAddress> getSilentPaymentReceivedAddresses(Object wallet);
Future<int> estimateFakeSendAllTxAmount(Object wallet, TransactionPriority priority,
Future<Money> estimateFakeSendAllTxAmount(WalletBase wallet, TransactionPriority priority,
{UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any});
List<ElectrumSubAddress> getSubAddresses(Object wallet);
String formatterBitcoinAmountToString({required int amount});
double formatterBitcoinAmountToDouble({required int amount});
int formatterStringDoubleToBitcoinAmount(String amount);
String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate, {int? customRate});
@@ -220,6 +226,7 @@ abstract class Bitcoin {
ReceivePageOption getLitecoinMwebReceivePageOption();
bool isPayjoinAvailable(Object wallet);
bool hasSelectedSilentPayments(Object wallet);
bool hasSelectedLightning(Object wallet);
bool isBitcoinReceivePageOption(ReceivePageOption option);
BitcoinAddressType getOptionToType(ReceivePageOption option);
bool hasTaprootInput(PendingTransaction pendingTransaction);
@@ -248,7 +255,7 @@ abstract class Bitcoin {
Future<void> setHardwareWalletService(WalletBase wallet, HardwareWalletService service);
HardwareWalletService getLedgerHardwareWalletService(ledger.LedgerConnection connection, bool isBitcoin);
HardwareWalletService getBitboxHardwareWalletService(bitbox.BitboxManager manager, bool isBitcoin);
HardwareWalletService getTrezorHardwareWalletService(trezor.TrezorConnect connect, bool isBitcoin);
HardwareWalletService getTrezorHardwareWalletService(trezor.TrezorConnect? connect, trezor.TrezorClient? client, bool isBitcoin);
List<Output> updateOutputs(PendingTransaction pendingTransaction, List<Output> outputs);
bool txIsReceivedSilentPayment(TransactionInfo txInfo);
bool txIsMweb(TransactionInfo txInfo);
@@ -272,6 +279,11 @@ abstract class Bitcoin {
Future<String?> getLightningUsername(Object wallet);
Future<String?> getLightningInvoice(Object wallet, BigInt amount);
String? getBreezSdkError(Object exception);
Future<Account> getCurrentAccount(Object wallet);
Money balanceForAccount(Object wallet, int accountIndex);
Map<int, Object> accountBalancesSnapshot(Object wallet);
Future<void> setCurrentAccount(Object wallet, int accountIndex);
List<TransactionInfo> getCurrentAccountBitcoinTransactions(Object wallet);
}
""";
@@ -295,6 +307,9 @@ abstract class Bitcoin {
Future<void> generateMonero(bool hasImplementation) async {
final outputFile = File(moneroOutputPath);
const moneroCommonHeaders = """
import 'package:cw_core/account.dart';
import 'package:cw_core/amount/money.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/unspent_transaction_output.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:mobx/mobx.dart';
@@ -309,6 +324,8 @@ import 'package:hash_wallet/view_model/send/output.dart';
import 'package:cw_core/wallet_service.dart';
import 'package:hive/hive.dart';
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as ledger;
import 'package:trezor_flutter/trezor_flutter.dart' as trezor;
import "package:cw_core/hardware/hardware_wallet_service.dart";
import 'package:polyseed/polyseed.dart';""";
const moneroCWHeaders = """
import 'package:cw_core/account.dart' as monero_account;
@@ -320,6 +337,7 @@ import 'package:cw_monero/api/wallet.dart' as monero_wallet_api;
import 'package:cw_monero/ledger.dart';
import 'package:cw_monero/monero_unspent.dart';
import 'package:cw_monero/api/account_list.dart';
import 'package:cw_monero/trezor.dart';
import 'package:cw_monero/monero_wallet_service.dart';
import 'package:cw_monero/monero_wallet.dart';
import 'package:cw_monero/monero_transaction_info.dart';
@@ -338,12 +356,6 @@ import 'package:cw_monero/pending_monero_transaction.dart';
""";
const moneroCwPart = "part 'cw_monero.dart';";
const moneroContent = """
class Account {
Account({required this.id, required this.label, this.balance});
final int id;
final String label;
final String? balance;
}
class Subaddress {
Subaddress({
@@ -360,30 +372,17 @@ class Subaddress {
}
class MoneroBalance extends Balance {
MoneroBalance({required this.fullBalance, required this.unlockedBalance})
: formattedFullBalance = monero!.formatterMoneroAmountToString(amount: fullBalance),
formattedUnlockedBalance =
monero!.formatterMoneroAmountToString(amount: unlockedBalance),
super.fromInt(unlockedBalance, fullBalance);
MoneroBalance({
required this.fullBalance,
required Money unlockedBalance,
Money? frozen,
}) : super(
unlockedBalance,
fullBalance - unlockedBalance,
frozen: frozen ?? Money.zero(CryptoCurrency.xmr),
);
MoneroBalance.fromString(
{required this.formattedFullBalance,
required this.formattedUnlockedBalance})
: fullBalance = monero!.formatterMoneroParseAmount(amount: formattedFullBalance),
unlockedBalance = monero!.formatterMoneroParseAmount(amount: formattedUnlockedBalance),
super.fromInt(monero!.formatterMoneroParseAmount(amount: formattedUnlockedBalance),
monero!.formatterMoneroParseAmount(amount: formattedFullBalance));
final int fullBalance;
final int unlockedBalance;
final String formattedFullBalance;
final String formattedUnlockedBalance;
@override
String get formattedAvailableBalance => formattedUnlockedBalance;
@override
String get formattedAdditionalBalance => formattedFullBalance;
final Money fullBalance;
}
abstract class MoneroWalletDetails {
@@ -397,6 +396,8 @@ abstract class MoneroWalletDetails {
abstract class Monero {
MoneroAccountList getAccountList(Object wallet);
Money getAccountFullBalance(int accountIndex);
MoneroSubaddressList getSubaddressList(Object wallet);
TransactionHistoryBase getTransactionHistory(Object wallet);
@@ -424,7 +425,9 @@ abstract class Monero {
Map<String, String> exportOutputsUR(Object wallet);
bool needExportOutputs(Object wallet, int amount);
bool needExportOutputs(Object wallet, Money amount);
bool hasUnknownKeyImages(Object wallet);
bool importKeyImagesUR(Object wallet, String ur);
@@ -438,7 +441,7 @@ abstract class Monero {
HardwareWalletType? hardwareWalletType,
required int height});
WalletCredentials createMoneroRestoreWalletFromSeedCredentials({required String name, required String password, required String passphrase, required int height, required String mnemonic});
WalletCredentials createMoneroRestoreWalletFromHardwareCredentials({required String name, required String password, required int height, required ledger.LedgerConnection ledgerConnection});
WalletCredentials createMoneroRestoreWalletFromHardwareCredentials({required String name, required String password, required int height, required HardwareWalletService hardwareWalletService, required String? passphrase});
WalletCredentials createMoneroNewWalletCredentials({required String name, required String language, required int seedType, required String? passphrase, String? password, String? mnemonic});
Map<String, String> getKeys(Object wallet);
int? getRestoreHeight(Object wallet);
@@ -458,9 +461,19 @@ WalletCredentials createMoneroNewWalletCredentials({required String name, requir
Future<void> setLedgerConnection(Object wallet, ledger.LedgerConnection connection);
void resetLedgerConnection();
void setGlobalLedgerConnection(ledger.LedgerConnection connection);
bool hasGlobalLedgerConnection();
String? getLastLedgerCommand();
void setHardwareWalletService(Object wallet, HardwareWalletService service);
HardwareWalletService getLedgerHardwareWalletService(ledger.LedgerConnection connection);
HardwareWalletService getTrezorHardwareWalletService(trezor.TrezorClient client);
Future<void> syncTrezor(Object wallet);
Map<String, List<int>> debugCallLength();
Map<String, dynamic> getWalletCacheDebug();
Future<int> getNodeHeight(Object wallet);
String getLegacySeed(Object wallet, String langName);
bool isBackgroundSyncRunning(Object wallet);
Future<void> startBackgroundSync(Object wallet);
Future<void> stopBackgroundSync(Object wallet, String password);
}
abstract class MoneroSubaddressList {
@@ -503,6 +516,9 @@ abstract class MoneroAccountList {
Future<void> generateWownero(bool hasImplementation) async {
final outputFile = File(wowneroOutputPath);
const wowneroCommonHeaders = """
import 'package:cw_core/account.dart';
import 'package:cw_core/amount/money.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/unspent_transaction_output.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:mobx/mobx.dart';
@@ -549,12 +565,6 @@ import 'package:cw_wownero/pending_wownero_transaction.dart';
""";
const wowneroCwPart = "part 'cw_wownero.dart';";
const wowneroContent = """
class Account {
Account({required this.id, required this.label, this.balance});
final int id;
final String label;
final String? balance;
}
class Subaddress {
Subaddress({
@@ -567,30 +577,17 @@ class Subaddress {
}
class WowneroBalance extends Balance {
WowneroBalance({required this.fullBalance, required this.unlockedBalance})
: formattedFullBalance = wownero!.formatterWowneroAmountToString(amount: fullBalance),
formattedUnlockedBalance =
wownero!.formatterWowneroAmountToString(amount: unlockedBalance),
super.fromInt(unlockedBalance, fullBalance);
WowneroBalance({
required this.fullBalance,
required Money unlockedBalance,
Money? frozen,
}) : super(
unlockedBalance,
fullBalance - unlockedBalance,
frozen: frozen ?? Money.zero(CryptoCurrency.wow),
);
WowneroBalance.fromString(
{required this.formattedFullBalance,
required this.formattedUnlockedBalance})
: fullBalance = wownero!.formatterWowneroParseAmount(amount: formattedFullBalance),
unlockedBalance = wownero!.formatterWowneroParseAmount(amount: formattedUnlockedBalance),
super.fromInt(wownero!.formatterWowneroParseAmount(amount: formattedUnlockedBalance),
wownero!.formatterWowneroParseAmount(amount: formattedFullBalance));
final int fullBalance;
final int unlockedBalance;
final String formattedFullBalance;
final String formattedUnlockedBalance;
@override
String get formattedAvailableBalance => formattedUnlockedBalance;
@override
String get formattedAdditionalBalance => formattedFullBalance;
final Money fullBalance;
}
abstract class WowneroWalletDetails {
@@ -604,6 +601,8 @@ abstract class WowneroWalletDetails {
abstract class Wownero {
WowneroAccountList getAccountList(Object wallet);
Money getAccountFullBalance(int accountIndex);
WowneroSubaddressList getSubaddressList(Object wallet);
TransactionHistoryBase getTransactionHistory(Object wallet);
@@ -826,7 +825,6 @@ abstract class Nano {
Object createNanoTransactionCredentials(List<Output> outputs);
Future<void> changeRep(Object wallet, String address);
Future<bool> updateTransactions(Object wallet);
BigInt getTransactionAmountRaw(TransactionInfo transactionInfo);
String getRepresentative(Object wallet);
Future<List<N2Node>> getN2Reps(Object wallet);
bool isRepOk(Object wallet);
@@ -948,6 +946,8 @@ Future<void> generateEVM(bool hasImplementation) async {
import 'dart:math' as math;
import 'package:hash_wallet/core/utilities.dart';
import 'package:hash_wallet/view_model/send/output.dart';
import 'package:cw_core/amount/money.dart';
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/erc20_token.dart';
import 'package:cw_core/hardware/hardware_account_data.dart';
@@ -966,6 +966,7 @@ import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as ledger;
import 'package:bitbox_flutter/bitbox_flutter.dart' as bitbox;
import 'package:trezor_connect/trezor_connect.dart' as trezor;
import 'package:web3dart/web3dart.dart';
import 'package:cw_core/transaction_direction.dart';
""";
const evmCWHeaders = """
@@ -976,6 +977,7 @@ import 'package:hash_wallet/entities/fiat_currency.dart';
import 'package:hash_wallet/store/settings_store.dart';
import 'package:cw_evm/utils/evm_chain_formatter.dart';
import 'package:cw_evm/evm_chain_mnemonics.dart';
import 'package:cw_evm/pending_evm_chain_transaction.dart';
import 'package:cw_evm/evm_chain_registry.dart';
import 'package:cw_evm/evm_erc20_balance.dart';
import 'package:cw_evm/evm_chain_transaction_credentials.dart';
@@ -1069,11 +1071,6 @@ abstract class EVM {
});
int formatterEVMParseAmount(String amount);
double formatterEVMAmountToDouble({
TransactionInfo? transaction,
BigInt? amount,
int exponent = 18,
});
List<Erc20Token> getERC20Currencies(WalletBase wallet);
Future<void> addErc20Token(WalletBase wallet, CryptoCurrency token);
@@ -1085,7 +1082,6 @@ abstract class EVM {
void updateScanProviderUsageState(WalletBase wallet, bool isEnabled);
Web3Client? getWeb3Client(WalletBase wallet);
String getTokenAddress(CryptoCurrency asset);
BigInt? getERC20AvailableBalance(Object balance);
Future<bool> isApprovalRequired(
WalletBase wallet,
@@ -1101,9 +1097,8 @@ abstract class EVM {
Future<PendingTransaction> createTokenApproval(
WalletBase wallet,
BigInt amount,
Money amount,
String spender,
CryptoCurrency token,
TransactionPriority? priority,
{bool useBlinkProtection = true}
);
@@ -1112,7 +1107,7 @@ abstract class EVM {
WalletBase wallet,
String to,
String dataHex,
BigInt valueWei,
Money valueWei,
TransactionPriority? priority,
{bool useBlinkProtection = true,
String? sourceTokenAddress,
@@ -1134,10 +1129,12 @@ abstract class EVM {
String? getEVMERC20EstimatedFee(WalletBase wallet);
// Chain-specific integrations (optional, can be null for non-Ethereum chains)
Future<BigInt>? getDEuroSavingsBalance(WalletBase wallet) => null;
Future<BigInt>? getDEuroAccruedInterest(WalletBase wallet) => null;
Future<Money>? getDEuroSavingsBalance(WalletBase wallet) => null;
Future<Money>? getDEuroSavingsV1Balance(WalletBase wallet) => null;
Future<Money>? getDEuroAccruedInterest(WalletBase wallet) => null;
Future<BigInt>? getDEuroInterestRate(WalletBase wallet) => null;
Future<BigInt>? getDEuroSavingsApproved(WalletBase wallet) => null;
Future<PendingTransaction>? withdrawDEuroSavingV1(WalletBase wallet, TransactionPriority priority) => null;
Future<PendingTransaction>? addDEuroSaving(WalletBase wallet, BigInt amount, TransactionPriority priority) => null;
Future<PendingTransaction>? removeDEuroSaving(WalletBase wallet, BigInt amount, TransactionPriority priority) => null;
Future<PendingTransaction>? reinvestDEuroInterest(WalletBase wallet, TransactionPriority priority) => null;
@@ -1153,6 +1150,7 @@ abstract class EVM {
WalletType? getWalletTypeByChainId(int chainId);
String getChainNameByChainId(int chainId);
String getTokenNameByChainId(int chainId);
String? getMoralisChainName(WalletBase wallet);
// Chain selection methods
List<ChainInfo> getAllChains();
ChainInfo? getCurrentChain(WalletBase wallet);
@@ -1195,6 +1193,24 @@ abstract class EVM {
WalletBase wallet,
TransactionPriority priority,
);
TransactionInfo getTransactionInfo({
required String id,
required int height,
required Money amount,
required Money fee,
required String tokenSymbol,
int exponent = 18,
required TransactionDirection direction,
required bool isPending,
required DateTime date,
required int confirmations,
String? to,
String? from,
String? evmSignatureName,
String? contractAddress,
required int chainId,
});
Future<void> discoverAndAddWalletTokens(WalletBase wallet);
}
+5 -5
View File
@@ -31,7 +31,7 @@ Future<void> main() async {
final resp = await _dio.get("https://api.github.com/repos/mrcyjanek/monero_c/releases");
final data = resp.data[0];
final tagName = data['tag_name'];
printV("Downloading artifacts for: ${tagName}");
print("Downloading artifacts for: ${tagName}");
final assets = data['assets'] as List<dynamic>;
for (var i = 0; i < assets.length; i++) {
for (var triplet in triplets) {
@@ -42,10 +42,10 @@ Future<void> main() async {
String localFilename = filename.replaceAll("${coin}_${triplet}_", "");
localFilename = "scripts/monero_c/release/${coin}/${triplet}_${localFilename}";
final url = asset["browser_download_url"] as String;
printV("- downloading $localFilename");
print("- downloading $localFilename");
await _dio.download(url, localFilename);
if (localFilename.endsWith(".xz")) {
printV(" extracting $localFilename");
print(" extracting $localFilename");
final inputStream = InputFileStream(localFilename);
final archive = XZDecoder().decodeBytes(inputStream.toUint8List());
final outputStream = OutputFileStream(localFilename.replaceAll(".xz", ""));
@@ -54,9 +54,9 @@ Future<void> main() async {
}
}
if (Platform.isMacOS) {
printV("Generating ios framework");
print("Generating ios framework");
final result =
Process.runSync("bash", ["-c", "cd scripts/ios && ./gen_framework.sh && cd ../.."]);
printV((result.stdout + result.stderr).toString().trim());
print((result.stdout + result.stderr).toString().trim());
}
}
+7 -7
View File
@@ -76,7 +76,7 @@ void main() {
// --- B. Run App in a Zone to Capture Prints ---
runZoned(
() async {
printV('--- Starting Verified Price Check ---');
print('--- Starting Verified Price Check ---');
final Map<String, List<String>> workingPairs = {};
final Map<String, List<String>> failedPairs = {};
@@ -130,7 +130,7 @@ void main() {
}
// Print immediate status (Captured by Zone)
printV('$logPrefix $logMessage');
print('$logPrefix $logMessage');
// Aggregate
if (isSuccess) {
@@ -148,25 +148,25 @@ void main() {
}
// --- FINAL SUMMARY ---
printV('\n\n=== SUMMARY ===\n');
print('\n\n=== SUMMARY ===\n');
// Print Successful
workingPairs.forEach((crypto, fiats) {
if (fiats.isNotEmpty) {
printV('✅ ${crypto.toUpperCase()}: ${fiats.join(", ")}');
print('✅ ${crypto.toUpperCase()}: ${fiats.join(", ")}');
}
});
printV('\n--------------------------------------------------\n');
print('\n--------------------------------------------------\n');
// Print Failed
failedPairs.forEach((crypto, fiats) {
if (fiats.isNotEmpty) {
printV('❌ ${crypto.toUpperCase()}: ${fiats.join(", ")}');
print('❌ ${crypto.toUpperCase()}: ${fiats.join(", ")}');
}
});
printV('\n=== DONE ===');
print('\n=== DONE ===');
},
// --- C. The Interceptor ---
+25 -16
View File
@@ -1,6 +1,6 @@
import "dart:collection";
import 'dart:io';
import 'dart:convert';
import './print_verbose_dummy.dart';
import 'localization/localization_constants.dart';
import 'utils/utils.dart';
@@ -37,7 +37,7 @@ Future<void> main(List<String> args) async {
extraInfo.forEach((key, dynamic value) async {
if (key != srcDir) {
printV('Wrong key: $key');
print('Wrong key: $key');
return;
}
@@ -45,26 +45,29 @@ Future<void> main(List<String> args) async {
final dir = Directory(dirPath);
if (!await dir.exists()) {
printV('Wrong directory path: $dirPath');
print('Wrong directory path: $dirPath');
return;
}
final localePath = <String, dynamic>{};
final localePath = SplayTreeMap<String, dynamic>();
await dir.list(recursive: false).forEach((element) {
try {
final shortLocale = element.path
.split(
'_',
)[1]
.split('.')[0];
localePath[shortLocale] = element.path;
} catch (e) {
printV('Wrong file: ${element.path}');
// Parse the locale from the file name (e.g. strings_pt_br.arb -> pt_BR),
// normalizing the case so keys match LanguageService.supportedLocales.
final fileName = element.uri.pathSegments.last;
if (!fileName.startsWith('strings_') || !fileName.endsWith('.arb')) {
print('Wrong file: ${element.path}');
return;
}
final parts =
fileName.substring('strings_'.length, fileName.length - '.arb'.length).split('_');
final locale = parts.length > 1
? '${parts.first.toLowerCase()}_${parts.sublist(1).join('_').toUpperCase()}'
: parts.first.toLowerCase();
localePath[locale] = element.path;
});
if (!localePath.keys.contains(defaultLocale)) {
printV("Locale list doesn't contain $defaultLocale");
print("Locale list doesn't contain $defaultLocale");
return;
}
@@ -100,8 +103,14 @@ Future<void> main(List<String> args) async {
output += classDeclaration;
// Flutter matches on the language subtag, so pt_BR is emitted as Locale("pt", "BR")
localePath.keys.forEach((key) {
output += ' Locale("$key", ""),' + '\n';
final parts = key.split("_");
if (parts.length == 2) {
output += ' Locale("${parts[0]}", "${parts[1]}"),\n';
} else {
output += ' Locale("$key", ""),\n';
}
});
output += part2;
@@ -120,7 +129,7 @@ Future<void> main(List<String> args) async {
await File(outputPath + localeListFileName).writeAsString(locales);
} catch (e) {
printV(e.toString());
print(e.toString());
}
});
}
@@ -66,6 +66,15 @@ class S implements WidgetsLocalizations {
@override
String get shareButtonLabel => "shareButtonLabel";
@override
String get noResultsFound => "noResultsFound";
@override
String get radioButtonUnselectedLabel => "radioButtonUnselectedLabel";
@override
String get searchResultsFound => "searchResultsFound";
""";
const part2 = """
+1 -1
View File
@@ -1 +1 @@
void printV(dynamic content) => print(content);
+1 -1
View File
@@ -46,7 +46,7 @@ void main() async {
});
currentItem++;
printV(
print(
"\r$currentLang/${langs.length} langs done, $currentItem/${defaultLangChangelog.length} items done");
}
currentLang++;
+29 -29
View File
@@ -25,18 +25,18 @@ class TranslationChecker {
final sourceMap = json.decode(sourceContent) as Map<String, dynamic>;
final destinationMap = json.decode(destinationContent) as Map<String, dynamic>;
printV('Found ${sourceMap.length} keys in source, ${destinationMap.length} in destination');
print('Found ${sourceMap.length} keys in source, ${destinationMap.length} in destination');
final keysToProcess = specificKey != null
? (sourceMap.containsKey(specificKey) ? [specificKey] : <String>[])
: sourceMap.keys.toList();
if (specificKey != null && keysToProcess.isEmpty) {
printV('Error: Key "$specificKey" not found in source file');
print('Error: Key "$specificKey" not found in source file');
return;
}
printV('Processing ${keysToProcess.length} translations...');
print('Processing ${keysToProcess.length} translations...');
int processed = 0;
int corrected = 0;
@@ -57,16 +57,16 @@ class TranslationChecker {
if (correctedTranslation != destinationValue) {
destinationMap[key] = correctedTranslation;
corrected++;
printV('Processed: "$key" -> CORRECTED');
printV(' - eng : "$sourceValue"');
printV(' - dst orig: "$destinationValue"');
printV(' - dst new : "$correctedTranslation"');
print('Processed: "$key" -> CORRECTED');
print(' - eng : "$sourceValue"');
print(' - dst orig: "$destinationValue"');
print(' - dst new : "$correctedTranslation"');
await _writeArbFile(destinationArbPath, destinationMap);
} else {
printV('Processed: "$key" -> VERIFIED');
print('Processed: "$key" -> VERIFIED');
}
} else {
printV('Processed: "$key" -> SKIPPED (non-string)');
print('Processed: "$key" -> SKIPPED (non-string)');
}
processed++;
@@ -74,11 +74,11 @@ class TranslationChecker {
await _writeArbFile(destinationArbPath, destinationMap);
printV('');
printV('Summary:');
printV('Processed: $processed keys');
printV('Corrected: $corrected keys');
printV('Updated: $destinationArbPath');
print('');
print('Summary:');
print('Processed: $processed keys');
print('Corrected: $corrected keys');
print('Updated: $destinationArbPath');
}
Future<String> _checkSingleTranslation({
@@ -108,7 +108,7 @@ class TranslationChecker {
return currentTranslation;
} catch (e) {
printV('Error checking translation for key "$key": $e');
print('Error checking translation for key "$key": $e');
return currentTranslation;
}
}
@@ -186,7 +186,7 @@ IMPORTANT: Respond with a JSON object in the exact format, you must think about
final jsonEnd = response.lastIndexOf('}');
if (jsonStart == -1 || jsonEnd == -1 || jsonStart >= jsonEnd) {
printV('No valid JSON found in LLM response');
print('No valid JSON found in LLM response');
return null;
}
@@ -195,7 +195,7 @@ IMPORTANT: Respond with a JSON object in the exact format, you must think about
return parsed['corrected_translation'] as String?;
} catch (e) {
printV('Error extracting JSON from LLM response: $e');
print('Error extracting JSON from LLM response: $e');
return null;
}
}
@@ -237,7 +237,7 @@ void main(List<String> args) async {
final results = parser.parse(args);
if (results['help'] as bool) {
printV(parser.usage);
print(parser.usage);
return;
}
@@ -248,24 +248,24 @@ void main(List<String> args) async {
final model = results['model'] as String;
if (!File(sourcePath).existsSync()) {
printV('Error: Source ARB file not found: $sourcePath');
print('Error: Source ARB file not found: $sourcePath');
exit(1);
}
if (!File(destinationPath).existsSync()) {
printV('Error: Destination ARB file not found: $destinationPath');
print('Error: Destination ARB file not found: $destinationPath');
exit(1);
}
printV('Translation Checker');
printV('Source: $sourcePath');
printV('Destination: $destinationPath');
printV('Ollama URL: $ollamaUrl');
printV('Model: $model');
print('Translation Checker');
print('Source: $sourcePath');
print('Destination: $destinationPath');
print('Ollama URL: $ollamaUrl');
print('Model: $model');
if (specificKey != null) {
printV('Key: $specificKey');
print('Key: $specificKey');
}
printV('');
print('');
final checker = TranslationChecker(
ollamaBaseUrl: ollamaUrl,
@@ -278,8 +278,8 @@ void main(List<String> args) async {
specificKey: specificKey,
);
} catch (e) {
printV('Error: $e');
printV('Run with --help for more information.');
print('Error: $e');
print('Run with --help for more information.');
exit(1);
}
}
+1 -1
View File
@@ -33,5 +33,5 @@ void main(List<String> args) async {
}
appendStringsToArbFile(targetFileName, translations);
printV("Success! Please add your Language Code to lib/entities/language_service.dart");
print("Success! Please add your Language Code to lib/entities/language_service.dart");
}
+4 -4
View File
@@ -7,14 +7,14 @@ import 'utils/translation/translation_constants.dart';
import 'utils/translation/translation_utils.dart';
void main(List<String> args) async {
printV('Checking Consistency of all arb-files. Default: $defaultLang');
print('Checking Consistency of all arb-files. Default: $defaultLang');
final doFix = args.contains("--fix");
if (doFix)
printV('Auto fixing enabled!\n');
print('Auto fixing enabled!\n');
else
printV('Auto fixing disabled!\nRun with arg "--fix" to enable autofix\n');
print('Auto fixing disabled!\nRun with arg "--fix" to enable autofix\n');
final fileName = getArbFileName(defaultLang);
final file = File(fileName);
@@ -27,7 +27,7 @@ void main(List<String> args) async {
final missingDefaults = <String, String>{};
missingKeys.forEach((key) {
printV('Missing in "$lang": "$key"');
print('Missing in "$lang": "$key"');
if (doFix) missingDefaults[key] = arbObj[key] as String;
});
+16 -2
View File
@@ -15,6 +15,7 @@ class SecretKey {
SecretKey('changeNowCakeWalletApiKey', () => ''),
SecretKey('changeNowMoneroApiKey', () => ''),
SecretKey('moonPayApiKey', () => ''),
SecretKey('moonPaySandboxApiKey', () => ''),
SecretKey('moonPaySecretKey', () => ''),
SecretKey('sideShiftAffiliateId', () => ''),
SecretKey('simpleSwapApiKey', () => ''),
@@ -46,7 +47,7 @@ class SecretKey {
SecretKey('meldTestApiKey', () => ''),
SecretKey('meldTestPublicKey', () => ''),
SecretKey('moneroTestWalletSeeds', () => ''),
SecretKey('moneroLegacyTestWalletSeeds ', () => ''),
SecretKey('moneroLegacyTestWalletSeeds', () => ''),
SecretKey('bitcoinTestWalletSeeds', () => ''),
SecretKey('ethereumTestWalletSeeds', () => ''),
SecretKey('litecoinTestWalletSeeds', () => ''),
@@ -55,10 +56,16 @@ class SecretKey {
SecretKey('baseTestWalletSeeds', () => ''),
SecretKey('arbitrumTestWalletSeeds', () => ''),
SecretKey('bscTestWalletSeeds', () => ''),
SecretKey("robinhoodTestWalletSeeds", () => ""),
SecretKey('solanaTestWalletSeeds', () => ''),
SecretKey('solanaTestWalletSeeds2', () => ''),
SecretKey('tronTestWalletSeeds', () => ''),
SecretKey('nanoTestWalletSeeds', () => ''),
SecretKey('wowneroTestWalletSeeds', () => ''),
SecretKey('zanoTestWalletSeeds', () => ''),
SecretKey('decredTestWalletSeeds', () => ''),
SecretKey('dogeTestWalletSeeds', () => ''),
SecretKey('zcashTestWalletSeeds', () => ''),
SecretKey('moneroTestWalletReceiveAddress', () => ''),
SecretKey('bitcoinTestWalletReceiveAddress', () => ''),
SecretKey('ethereumTestWalletReceiveAddress', () => ''),
@@ -68,10 +75,15 @@ class SecretKey {
SecretKey('baseTestWalletReceiveAddress', () => ''),
SecretKey('arbitrumTestWalletReceiveAddress', () => ''),
SecretKey('bscTestWalletReceiveAddress', () => ''),
SecretKey("robinhoodTestWalletReceiveAddress", () => ""),
SecretKey('solanaTestWalletReceiveAddress', () => ''),
SecretKey('tronTestWalletReceiveAddress', () => ''),
SecretKey('nanoTestWalletReceiveAddress', () => ''),
SecretKey('wowneroTestWalletReceiveAddress', () => ''),
SecretKey('zanoTestWalletReceiveAddress', () => ''),
SecretKey('decredTestWalletReceiveAddress', () => ''),
SecretKey('dogeTestWalletReceiveAddress', () => ''),
SecretKey('zcashTestWalletReceiveAddress', () => ''),
SecretKey('etherScanApiKey', () => ''),
SecretKey('polygonScanApiKey', () => ''),
SecretKey('letsExchangeBearerToken', () => ''),
@@ -79,6 +91,7 @@ class SecretKey {
SecretKey('stealthExBearerToken', () => ''),
SecretKey('stealthExAdditionalFeePercent', () => ''),
SecretKey('moneroTestWalletBlockHeight', () => ''),
SecretKey('zcashTestWalletRestoreHeight', () => ''),
SecretKey('chainflipApiKey', () => ''),
SecretKey('chainflipAffiliateFee', () => ''),
SecretKey('kryptonimApiKey', () => ''),
@@ -96,8 +109,9 @@ class SecretKey {
SecretKey('etherScanApiKey', () => ''),
SecretKey('polygonScanApiKey', () => ''),
SecretKey('moralisApiKey', () => ''),
SecretKey('nowNodesApiKey ', () => ''),
SecretKey('nowNodesApiKey', () => ''),
SecretKey('blinkApiKey', () => ''),
SecretKey('alchemyApiKey', () => ''),
];
static final solanaSecrets = [
+1 -1
View File
@@ -8,7 +8,7 @@ void appendStringToArbFile(String fileName, String name, String text, {bool forc
final arbObj = readArbFile(file);
if (arbObj.containsKey(name) && !force) {
printV("String $name already exists in $fileName!");
print("String $name already exists in $fileName!");
return;
}
@@ -2,5 +2,5 @@ const defaultLang = "en";
const langs = [
"ar", "bg", "cs", "de", "en", "es", "fa", "fr", "gn", "ha", "hi", "hr", "hy", "id", "it",
"ja", "ko", "my", "nl", "pl", "pt", "ru", "th", "tl", "tr", "uk", "ur", "yo",
"vi", "zh-cn", "zh-tw" // zh-cn for Chinese (Simplified), zh-tw for Chinese (Traditional)
"vi", "zh-cn" // zh-cn for Chinese (Simplified)
];
@@ -38,7 +38,7 @@ Future<String> getTranslation(String text, String lang) async {
try {
translation = (await translator.translate(text, from: defaultLang, to: lang)).text;
} catch (e) {
printV("$lang, $text, $e");
print("$lang, $text, $e");
}
placeholder.forEach((index, value) {
final translatedPlaceholder = regExp.allMatches(translation).toList()[index];