Merge branch 'main' into CW-657-New-buy-sell-flow

This commit is contained in:
Serhii 2024-10-05 14:28:19 +03:00
commit e745600b30
97 changed files with 1436 additions and 766 deletions

View file

@ -6,3 +6,6 @@
isDefault: true
-
uri: electrs.cakewallet.com:50001
-
uri: fulcrum.sethforprivacy.com:50002
useSSL: true

BIN
assets/images/ton_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -479,8 +479,14 @@ abstract class ElectrumWalletBase
final result = json.decode(response.body) as Map<String, num>;
final slowFee = result['economyFee']?.toInt() ?? 0;
final mediumFee = result['hourFee']?.toInt() ?? 0;
final fastFee = result['fastestFee']?.toInt() ?? 0;
int mediumFee = result['hourFee']?.toInt() ?? 0;
int fastFee = result['fastestFee']?.toInt() ?? 0;
if (slowFee == mediumFee) {
mediumFee++;
}
while (fastFee <= mediumFee) {
fastFee++;
}
_feeRates = [slowFee, mediumFee, fastFee];
return;
} catch (_) {}
@ -813,6 +819,8 @@ abstract class ElectrumWalletBase
network: network,
memo: memo,
feeRate: feeRate,
inputPrivKeyInfos: utxoDetails.inputPrivKeyInfos,
vinOutpoints: utxoDetails.vinOutpoints,
);
if (fee == 0) {
@ -1639,27 +1647,29 @@ abstract class ElectrumWalletBase
if (verboseTransaction.isEmpty) {
transactionHex = await electrumClient.getTransactionHex(hash: hash);
if (height != null && await checkIfMempoolAPIIsEnabled()) {
final blockHash = await http.get(
Uri.parse(
"http://mempool.cakewallet.com:8999/api/v1/block-height/$height",
),
);
if (blockHash.statusCode == 200 &&
blockHash.body.isNotEmpty &&
jsonDecode(blockHash.body) != null) {
final blockResponse = await http.get(
if (height != null && height > 0 && await checkIfMempoolAPIIsEnabled()) {
try {
final blockHash = await http.get(
Uri.parse(
"http://mempool.cakewallet.com:8999/api/v1/block/${blockHash.body}",
"http://mempool.cakewallet.com:8999/api/v1/block-height/$height",
),
);
if (blockResponse.statusCode == 200 &&
blockResponse.body.isNotEmpty &&
jsonDecode(blockResponse.body)['timestamp'] != null) {
time = int.parse(jsonDecode(blockResponse.body)['timestamp'].toString());
if (blockHash.statusCode == 200 &&
blockHash.body.isNotEmpty &&
jsonDecode(blockHash.body) != null) {
final blockResponse = await http.get(
Uri.parse(
"http://mempool.cakewallet.com:8999/api/v1/block/${blockHash.body}",
),
);
if (blockResponse.statusCode == 200 &&
blockResponse.body.isNotEmpty &&
jsonDecode(blockResponse.body)['timestamp'] != null) {
time = int.parse(jsonDecode(blockResponse.body)['timestamp'].toString());
}
}
}
} catch (_) {}
}
} else {
transactionHex = verboseTransaction['hex'] as String;

View file

@ -100,10 +100,12 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
static const gap = 20;
final ObservableList<BitcoinAddressRecord> _addresses;
late ObservableList<BaseBitcoinAddressRecord> addressesByReceiveType;
final ObservableList<BaseBitcoinAddressRecord> addressesByReceiveType;
final ObservableList<BitcoinAddressRecord> receiveAddresses;
final ObservableList<BitcoinAddressRecord> changeAddresses;
// TODO: add this variable in `bitcoin_wallet_addresses` and just add a cast in cw_bitcoin to use it
final ObservableList<BitcoinSilentPaymentAddressRecord> silentAddresses;
// TODO: add this variable in `litecoin_wallet_addresses` and just add a cast in cw_bitcoin to use it
final ObservableList<BitcoinAddressRecord> mwebAddresses;
final BasedUtxoNetwork network;
final Bip32Slip10Secp256k1 mainHd;

View file

@ -45,6 +45,6 @@ class BitcoinTransactionCommitFailedVoutNegative extends TransactionCommitFailed
class BitcoinTransactionCommitFailedBIP68Final extends TransactionCommitFailedBIP68Final {}
class BitcoinTransactionCommitFailedLessThanMin extends TransactionCommitFailedBIP68Final {}
class BitcoinTransactionCommitFailedLessThanMin extends TransactionCommitFailedLessThanMin {}
class BitcoinTransactionSilentPaymentsNotSupported extends TransactionInputNotSupported {}

View file

@ -236,16 +236,18 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
Future<void> waitForMwebAddresses() async {
// ensure that we have the full 1000 mweb addresses generated before continuing:
// should no longer be needed, but leaving here just in case
final mwebAddrs = (walletAddresses as LitecoinWalletAddresses).mwebAddrs;
while (mwebAddrs.length < 1000) {
print("waiting for mweb addresses to finish generating...");
await Future.delayed(const Duration(milliseconds: 1000));
}
// final mwebAddrs = (walletAddresses as LitecoinWalletAddresses).mwebAddrs;
// while (mwebAddrs.length < 1000) {
// print("waiting for mweb addresses to finish generating...");
// await Future.delayed(const Duration(milliseconds: 1000));
// }
await (walletAddresses as LitecoinWalletAddresses).ensureMwebAddressUpToIndexExists(1020);
}
@action
@override
Future<void> startSync() async {
print("startSync() called!");
if (syncStatus is SyncronizingSyncStatus) {
return;
}
@ -289,46 +291,59 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
_syncTimer = Timer.periodic(const Duration(milliseconds: 1500), (timer) async {
if (syncStatus is FailedSyncStatus) return;
print("SYNCING....");
final nodeHeight =
await electrumClient.getCurrentBlockChainTip() ?? 0; // current block height of our node
final resp = await CwMweb.status(StatusRequest());
print("resp.mwebUtxosHeight: ${resp.mwebUtxosHeight}");
print("resp.mwebHeaderHeight: ${resp.mwebHeaderHeight}");
print("resp.blockHeaderHeight: ${resp.blockHeaderHeight}");
if (resp.blockHeaderHeight < nodeHeight) {
int h = resp.blockHeaderHeight;
syncStatus = SyncingSyncStatus(nodeHeight - h, h / nodeHeight);
} else if (resp.mwebHeaderHeight < nodeHeight) {
int h = resp.mwebHeaderHeight;
syncStatus = SyncingSyncStatus(nodeHeight - h, h / nodeHeight);
} else if (resp.mwebUtxosHeight < nodeHeight) {
syncStatus = SyncingSyncStatus(1, 0.999);
} else {
if (resp.mwebUtxosHeight > walletInfo.restoreHeight) {
await walletInfo.updateRestoreHeight(resp.mwebUtxosHeight);
await checkMwebUtxosSpent();
// update the confirmations for each transaction:
for (final transaction in transactionHistory.transactions.values) {
if (transaction.isPending) continue;
int txHeight = transaction.height ?? resp.mwebUtxosHeight;
final confirmations = (resp.mwebUtxosHeight - txHeight) + 1;
if (transaction.confirmations == confirmations) continue;
transaction.confirmations = confirmations;
transactionHistory.addOne(transaction);
}
await transactionHistory.save();
}
// prevent unnecessary reaction triggers:
if (syncStatus is! SyncedSyncStatus) {
// mwebd is synced, but we could still be processing incoming utxos:
if (!processingUtxos) {
syncStatus = SyncedSyncStatus();
}
if (nodeHeight == 0) {
// we aren't connected to the ltc node yet
if (syncStatus is! NotConnectedSyncStatus) {
syncStatus = FailedSyncStatus(error: "Failed to connect to Litecoin node");
}
return;
}
final resp = await CwMweb.status(StatusRequest());
try {
if (resp.blockHeaderHeight < nodeHeight) {
int h = resp.blockHeaderHeight;
syncStatus = SyncingSyncStatus(nodeHeight - h, h / nodeHeight);
} else if (resp.mwebHeaderHeight < nodeHeight) {
int h = resp.mwebHeaderHeight;
syncStatus = SyncingSyncStatus(nodeHeight - h, h / nodeHeight);
} else if (resp.mwebUtxosHeight < nodeHeight) {
syncStatus = SyncingSyncStatus(1, 0.999);
} else {
if (resp.mwebUtxosHeight > walletInfo.restoreHeight) {
await walletInfo.updateRestoreHeight(resp.mwebUtxosHeight);
await checkMwebUtxosSpent();
// update the confirmations for each transaction:
for (final transaction in transactionHistory.transactions.values) {
if (transaction.isPending) continue;
int txHeight = transaction.height ?? resp.mwebUtxosHeight;
final confirmations = (resp.mwebUtxosHeight - txHeight) + 1;
if (transaction.confirmations == confirmations) continue;
transaction.confirmations = confirmations;
transactionHistory.addOne(transaction);
}
await transactionHistory.save();
}
// prevent unnecessary reaction triggers:
if (syncStatus is! SyncedSyncStatus) {
// mwebd is synced, but we could still be processing incoming utxos:
if (!processingUtxos) {
syncStatus = SyncedSyncStatus();
}
}
return;
}
} catch (e) {
print("error syncing: $e");
syncStatus = FailedSyncStatus(error: e.toString());
}
});
}
@ -411,6 +426,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
}
Future<void> handleIncoming(MwebUtxo utxo, RpcClient stub) async {
print("handleIncoming() called!");
final status = await stub.status(StatusRequest());
var date = DateTime.now();
var confirmations = 0;

View file

@ -70,13 +70,9 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
await Future.delayed(Duration(milliseconds: 100));
}
}
}
Future<void> initMwebAddresses() async {
if (mwebAddrs.length < 1000) {
print("Generating MWEB addresses...");
await ensureMwebAddressUpToIndexExists(1020);
print("done generating MWEB addresses");
// ensure mweb addresses are up to date:
if (mwebAddresses.length < mwebAddrs.length) {
List<BitcoinAddressRecord> addressRecords = mwebAddrs
.asMap()
.entries
@ -88,7 +84,27 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
))
.toList();
addMwebAddresses(addressRecords);
print("added ${addressRecords.length} mweb addresses");
print("set ${addressRecords.length} mweb addresses");
}
}
Future<void> initMwebAddresses() async {
if (mwebAddrs.length < 1000) {
print("Generating MWEB addresses...");
await ensureMwebAddressUpToIndexExists(20);
print("done generating MWEB addresses");
// List<BitcoinAddressRecord> addressRecords = mwebAddrs
// .asMap()
// .entries
// .map((e) => BitcoinAddressRecord(
// e.value,
// index: e.key,
// type: SegwitAddresType.mweb,
// network: network,
// ))
// .toList();
// addMwebAddresses(addressRecords);
// print("added ${addressRecords.length} mweb addresses");
return;
}
}

View file

@ -49,6 +49,15 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.11.0"
bech32:
dependency: "direct main"
description:
path: "."
ref: HEAD
resolved-ref: "05755063b593aa6cca0a4820a318e0ce17de6192"
url: "https://github.com/cake-tech/bech32.git"
source: git
version: "0.2.2"
bip32:
dependency: transitive
description:
@ -78,8 +87,8 @@ packages:
dependency: "direct overridden"
description:
path: "."
ref: cake-update-v7
resolved-ref: f577e83fe78766b2655ea0602baa9299b953a31b
ref: cake-update-v8
resolved-ref: fc045a11db3d85d806ca67f75e8b916c706745a2
url: "https://github.com/cake-tech/bitcoin_base"
source: git
version: "4.7.0"
@ -308,13 +317,13 @@ packages:
source: hosted
version: "1.3.1"
ffi:
dependency: transitive
dependency: "direct overridden"
description:
name: ffi
sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
url: "https://pub.dev"
source: hosted
version: "2.1.3"
version: "2.1.0"
ffigen:
dependency: transitive
description:
@ -450,6 +459,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.2"
http2:
dependency: transitive
description:
name: http2
sha256: "9ced024a160b77aba8fb8674e38f70875e321d319e6f303ec18e87bd5a4b0c1d"
url: "https://pub.dev"
source: hosted
version: "2.3.0"
http_multi_server:
dependency: transitive
description:
@ -693,13 +710,13 @@ packages:
source: hosted
version: "2.1.8"
pointycastle:
dependency: transitive
dependency: "direct overridden"
description:
name: pointycastle
sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe"
sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29"
url: "https://pub.dev"
source: hosted
version: "3.9.1"
version: "3.7.4"
pool:
dependency: transitive
description:
@ -709,13 +726,13 @@ packages:
source: hosted
version: "1.5.1"
protobuf:
dependency: transitive
dependency: "direct overridden"
description:
name: protobuf
sha256: "01dd9bd0fa02548bf2ceee13545d4a0ec6046459d847b6b061d8a27237108a08"
sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
version: "3.1.0"
provider:
dependency: transitive
description:

View file

@ -83,7 +83,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
unspentCoinsInfo: unspentCoinsInfo,
initialAddresses: initialAddresses,
initialBalance: initialBalance,
seedBytes: await MnemonicBip39.toSeed(mnemonic, passphrase: passphrase),
seedBytes: MnemonicBip39.toSeed(mnemonic, passphrase: passphrase),
encryptionFileUtils: encryptionFileUtils,
initialRegularAddressIndex: initialRegularAddressIndex,
initialChangeAddressIndex: initialChangeAddressIndex,

View file

@ -36,7 +36,7 @@ class BitcoinCashWalletService extends WalletService<
final strength = credentials.seedPhraseLength == 24 ? 256 : 128;
final wallet = await BitcoinCashWalletBase.create(
mnemonic: credentials.mnemonic ?? await MnemonicBip39.generate(strength: strength),
mnemonic: credentials.mnemonic ?? MnemonicBip39.generate(strength: strength),
password: credentials.password!,
walletInfo: credentials.walletInfo!,
unspentCoinsInfo: unspentCoinsInfoSource,

View file

@ -106,6 +106,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
CryptoCurrency.usdcTrc20,
CryptoCurrency.tbtc,
CryptoCurrency.wow,
CryptoCurrency.ton,
];
static const havenCurrencies = [
@ -223,6 +224,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
static const usdcTrc20 = CryptoCurrency(title: 'USDC', tag: 'TRX', fullName: 'USDC Coin', raw: 92, name: 'usdctrc20', iconPath: 'assets/images/usdc_icon.png', decimals: 6);
static const tbtc = CryptoCurrency(title: 'tBTC', fullName: 'Testnet Bitcoin', raw: 93, name: 'tbtc', iconPath: 'assets/images/tbtc.png', decimals: 8);
static const wow = CryptoCurrency(title: 'WOW', fullName: 'Wownero', raw: 94, name: 'wow', iconPath: 'assets/images/wownero_icon.png', decimals: 11);
static const ton = CryptoCurrency(title: 'TON', fullName: 'Toncoin', raw: 95, name: 'ton', iconPath: 'assets/images/ton_icon.png', decimals: 8);
static final Map<int, CryptoCurrency> _rawCurrencyMap =

View file

@ -239,12 +239,15 @@ class Node extends HiveObject with Keyable {
// you try to communicate with it
Future<bool> requestElectrumServer() async {
try {
final Socket socket;
if (useSSL == true) {
await SecureSocket.connect(uri.host, uri.port,
socket = await SecureSocket.connect(uri.host, uri.port,
timeout: Duration(seconds: 5), onBadCertificate: (_) => true);
} else {
await Socket.connect(uri.host, uri.port, timeout: Duration(seconds: 5));
socket = await Socket.connect(uri.host, uri.port, timeout: Duration(seconds: 5));
}
socket.destroy();
return true;
} catch (_) {
return false;

View file

@ -67,7 +67,13 @@ class AttemptingScanSyncStatus extends SyncStatus {
double progress() => 0.0;
}
class FailedSyncStatus extends NotConnectedSyncStatus {}
class FailedSyncStatus extends NotConnectedSyncStatus {
String? error;
FailedSyncStatus({this.error});
@override
String toString() => error ?? super.toString();
}
class ConnectingSyncStatus extends SyncStatus {
@override
@ -89,4 +95,4 @@ class TimedOutSyncStatus extends NotConnectedSyncStatus {
class LostConnectionSyncStatus extends NotConnectedSyncStatus {
@override
String toString() => 'Reconnecting';
}
}

View file

@ -27,6 +27,7 @@ class EthereumWallet extends EVMChainWallet {
super.initialBalance,
super.privateKey,
required super.encryptionFileUtils,
super.passphrase,
}) : super(nativeCurrency: CryptoCurrency.eth);
@override
@ -150,8 +151,9 @@ class EthereumWallet extends EVMChainWallet {
if (!hasKeysFile) {
final mnemonic = data!['mnemonic'] as String?;
final privateKey = data['private_key'] as String?;
final passphrase = data['passphrase'] as String?;
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey);
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey, passphrase: passphrase);
} else {
keysData = await WalletKeysFile.readKeysFile(
name,
@ -166,6 +168,7 @@ class EthereumWallet extends EVMChainWallet {
password: password,
mnemonic: keysData.mnemonic,
privateKey: keysData.privateKey,
passphrase: keysData.passphrase,
initialBalance: balance,
client: EthereumClient(),
encryptionFileUtils: encryptionFileUtils,

View file

@ -27,6 +27,7 @@ class EthereumWalletService extends EVMChainWalletService<EthereumWallet> {
walletInfo: credentials.walletInfo!,
mnemonic: mnemonic,
password: credentials.password!,
passphrase: credentials.passphrase,
client: client,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
@ -144,6 +145,7 @@ class EthereumWalletService extends EVMChainWalletService<EthereumWallet> {
password: credentials.password!,
mnemonic: credentials.mnemonic,
walletInfo: credentials.walletInfo!,
passphrase: credentials.passphrase,
client: client,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);

View file

@ -70,6 +70,7 @@ abstract class EVMChainWalletBase
required String password,
EVMChainERC20Balance? initialBalance,
required this.encryptionFileUtils,
this.passphrase,
}) : syncStatus = const NotConnectedSyncStatus(),
_password = password,
_mnemonic = mnemonic,
@ -178,6 +179,7 @@ abstract class EVMChainWalletBase
mnemonic: _mnemonic,
privateKey: _hexPrivateKey,
password: _password,
passphrase: passphrase,
);
walletAddresses.address = _evmChainPrivateKey.address.hexEip55;
}
@ -545,6 +547,7 @@ abstract class EVMChainWalletBase
'mnemonic': _mnemonic,
'private_key': privateKey,
'balance': balance[currency]!.toJSON(),
'passphrase': passphrase,
});
Future<void> _updateBalance() async {
@ -574,15 +577,19 @@ abstract class EVMChainWalletBase
}
}
Future<EthPrivateKey> getPrivateKey(
{String? mnemonic, String? privateKey, required String password}) async {
Future<EthPrivateKey> getPrivateKey({
String? mnemonic,
String? privateKey,
required String password,
String? passphrase,
}) async {
assert(mnemonic != null || privateKey != null);
if (privateKey != null) {
return EthPrivateKey.fromHex(privateKey);
}
final seed = bip39.mnemonicToSeed(mnemonic!);
final seed = bip39.mnemonicToSeed(mnemonic!, passphrase: passphrase ?? '');
final root = bip32.BIP32.fromSeed(seed);
@ -716,4 +723,7 @@ abstract class EVMChainWalletBase
@override
String get password => _password;
@override
final String? passphrase;
}

View file

@ -4,28 +4,25 @@ import 'package:cw_core/wallet_info.dart';
class EVMChainNewWalletCredentials extends WalletCredentials {
EVMChainNewWalletCredentials({
required String name,
WalletInfo? walletInfo,
String? password,
String? parentAddress,
required super.name,
super.walletInfo,
super.password,
super.parentAddress,
this.mnemonic,
}) : super(
name: name,
walletInfo: walletInfo,
password: password,
parentAddress: parentAddress,
);
super.passphrase,
});
final String? mnemonic;
}
class EVMChainRestoreWalletFromSeedCredentials extends WalletCredentials {
EVMChainRestoreWalletFromSeedCredentials({
required String name,
required String password,
required super.name,
required super.password,
required this.mnemonic,
WalletInfo? walletInfo,
}) : super(name: name, password: password, walletInfo: walletInfo);
super.walletInfo,
super.passphrase,
});
final String mnemonic;
}

View file

@ -30,7 +30,8 @@ class CwMwebPlugin: FlutterPlugin, MethodCallHandler {
if (call.method == "start") {
server?.stop()
val dataDir = call.argument("dataDir") ?: ""
server = server ?: Mwebd.newServer("", dataDir, "")
val nodeUri = call.argument("nodeUri") ?: ""
server = server ?: Mwebd.newServer("", dataDir, nodeUri)
port = server?.start(0)
result.success(port)
} else if (call.method == "stop") {

View file

@ -12,6 +12,7 @@ public static func register(with registrar: FlutterPluginRegistrar) {
private static var server: MwebdServer?
private static var port: Int = 0
private static var dataDir: String?
private static var nodeUri: String?
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
@ -22,7 +23,9 @@ public static func register(with registrar: FlutterPluginRegistrar) {
stopServer()
let args = call.arguments as? [String: String]
let dataDir = args?["dataDir"]
let nodeUri = args?["nodeUri"]
CwMwebPlugin.dataDir = dataDir
CwMwebPlugin.nodeUri = nodeUri
startServer(result: result)
break
case "stop":
@ -48,7 +51,7 @@ public static func register(with registrar: FlutterPluginRegistrar) {
private func startServer(result: @escaping FlutterResult) {
if CwMwebPlugin.server == nil {
var error: NSError?
CwMwebPlugin.server = MwebdNewServer("", CwMwebPlugin.dataDir, "", &error)
CwMwebPlugin.server = MwebdNewServer("", CwMwebPlugin.dataDir, CwMwebPlugin.nodeUri, &error)
if let server = CwMwebPlugin.server {
do {

View file

@ -17,7 +17,8 @@ class CwMweb {
await Future.delayed(const Duration(seconds: 5));
final appDir = await getApplicationSupportDirectory();
_port = await CwMwebPlatform.instance.start(appDir.path);
const ltcNodeUri = "45.79.13.180:9333";
_port = await CwMwebPlatform.instance.start(appDir.path, ltcNodeUri);
if (_port == null || _port == 0) {
throw Exception("Failed to start server");
}

View file

@ -10,8 +10,9 @@ class MethodChannelCwMweb extends CwMwebPlatform {
final methodChannel = const MethodChannel('cw_mweb');
@override
Future<int?> start(String dataDir) async {
final result = await methodChannel.invokeMethod<int>('start', {'dataDir': dataDir});
Future<int?> start(String dataDir, String nodeUri) async {
final result =
await methodChannel.invokeMethod<int>('start', {'dataDir': dataDir, 'nodeUri': nodeUri});
return result;
}

View file

@ -25,7 +25,7 @@ abstract class CwMwebPlatform extends PlatformInterface {
_instance = instance;
}
Future<int?> start(String dataDir) {
Future<int?> start(String dataDir, String nodeUri) {
throw UnimplementedError('start() has not been implemented.');
}

View file

@ -42,6 +42,7 @@ abstract class NanoWalletBase
required String password,
NanoBalance? initialBalance,
required EncryptionFileUtils encryptionFileUtils,
this.passphrase,
}) : syncStatus = NotConnectedSyncStatus(),
_password = password,
_mnemonic = mnemonic,
@ -548,4 +549,7 @@ abstract class NanoWalletBase
}
return await NanoSignatures.verifyMessage(message, signature, address);
}
@override
final String? passphrase;
}

View file

@ -9,13 +9,15 @@ class NanoNewWalletCredentials extends WalletCredentials {
DerivationType? derivationType,
this.mnemonic,
String? parentAddress,
String? passphrase,
}) : super(
name: name,
password: password,
walletInfo: walletInfo,
parentAddress: parentAddress,
passphrase: passphrase,
);
final String? mnemonic;
}
@ -25,10 +27,12 @@ class NanoRestoreWalletFromSeedCredentials extends WalletCredentials {
required this.mnemonic,
String? password,
required DerivationType derivationType,
String? passphrase,
}) : super(
name: name,
password: password,
derivationInfo: DerivationInfo(derivationType: derivationType),
passphrase: passphrase,
);
final String mnemonic;

View file

@ -27,6 +27,7 @@ class PolygonWallet extends EVMChainWallet {
super.privateKey,
required super.client,
required super.encryptionFileUtils,
super.passphrase,
}) : super(nativeCurrency: CryptoCurrency.maticpoly);
@override
@ -128,8 +129,9 @@ class PolygonWallet extends EVMChainWallet {
if (!hasKeysFile) {
final mnemonic = data!['mnemonic'] as String?;
final privateKey = data['private_key'] as String?;
final passphrase = data['passphrase'] as String?;
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey);
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey, passphrase: passphrase);
} else {
keysData = await WalletKeysFile.readKeysFile(
name,
@ -144,6 +146,7 @@ class PolygonWallet extends EVMChainWallet {
password: password,
mnemonic: keysData.mnemonic,
privateKey: keysData.privateKey,
passphrase: keysData.passphrase,
initialBalance: balance,
client: PolygonClient(),
encryptionFileUtils: encryptionFileUtils,

View file

@ -30,6 +30,7 @@ class PolygonWalletService extends EVMChainWalletService<PolygonWallet> {
walletInfo: credentials.walletInfo!,
mnemonic: mnemonic,
password: credentials.password!,
passphrase: credentials.passphrase,
client: client,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
@ -125,6 +126,7 @@ class PolygonWalletService extends EVMChainWalletService<PolygonWallet> {
password: credentials.password!,
mnemonic: credentials.mnemonic,
walletInfo: credentials.walletInfo!,
passphrase: credentials.passphrase,
client: client,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);

View file

@ -33,7 +33,6 @@ import 'package:solana/base58.dart';
import 'package:solana/metaplex.dart' as metaplex;
import 'package:solana/solana.dart';
import 'package:solana/src/crypto/ed25519_hd_keypair.dart';
import 'package:cryptography/cryptography.dart';
part 'solana_wallet.g.dart';
@ -49,6 +48,7 @@ abstract class SolanaWalletBase
required String password,
SolanaBalance? initialBalance,
required this.encryptionFileUtils,
this.passphrase,
}) : syncStatus = const NotConnectedSyncStatus(),
_password = password,
_mnemonic = mnemonic,
@ -632,4 +632,7 @@ abstract class SolanaWalletBase
@override
String get password => _password;
@override
final String? passphrase;
}

View file

@ -8,22 +8,30 @@ class SolanaNewWalletCredentials extends WalletCredentials {
String? password,
String? parentAddress,
this.mnemonic,
String? passphrase,
}) : super(
name: name,
walletInfo: walletInfo,
password: password,
parentAddress: parentAddress,
passphrase: passphrase,
);
final String? mnemonic;
}
class SolanaRestoreWalletFromSeedCredentials extends WalletCredentials {
SolanaRestoreWalletFromSeedCredentials(
{required String name,
required String password,
required this.mnemonic,
WalletInfo? walletInfo})
: super(name: name, password: password, walletInfo: walletInfo);
SolanaRestoreWalletFromSeedCredentials({
required String name,
required String password,
required this.mnemonic,
WalletInfo? walletInfo,
String? passphrase,
}) : super(
name: name,
password: password,
walletInfo: walletInfo,
passphrase: passphrase,
);
final String mnemonic;
}

View file

@ -47,6 +47,7 @@ abstract class TronWalletBase
required String password,
TronBalance? initialBalance,
required this.encryptionFileUtils,
this.passphrase,
}) : syncStatus = const NotConnectedSyncStatus(),
_password = password,
_mnemonic = mnemonic,
@ -113,6 +114,7 @@ abstract class TronWalletBase
mnemonic: _mnemonic,
privateKey: _hexPrivateKey,
password: _password,
passphrase: passphrase,
);
_tronPublicKey = _tronPrivateKey.publicKey();
@ -149,8 +151,9 @@ abstract class TronWalletBase
if (!hasKeysFile) {
final mnemonic = data!['mnemonic'] as String?;
final privateKey = data['private_key'] as String?;
final passphrase = data['passphrase'] as String?;
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey);
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey, passphrase: passphrase);
} else {
keysData = await WalletKeysFile.readKeysFile(
name,
@ -165,6 +168,7 @@ abstract class TronWalletBase
password: password,
mnemonic: keysData.mnemonic,
privateKey: keysData.privateKey,
passphrase: keysData.passphrase,
initialBalance: balance,
encryptionFileUtils: encryptionFileUtils,
);
@ -190,12 +194,13 @@ abstract class TronWalletBase
String? mnemonic,
String? privateKey,
required String password,
String? passphrase,
}) async {
assert(mnemonic != null || privateKey != null);
if (privateKey != null) return TronPrivateKey(privateKey);
final seed = bip39.mnemonicToSeed(mnemonic!);
final seed = bip39.mnemonicToSeed(mnemonic!, passphrase: passphrase ?? '');
// Derive a TRON private key from the seed
final bip44 = Bip44.fromSeed(seed, Bip44Coins.tron);
@ -463,6 +468,7 @@ abstract class TronWalletBase
'mnemonic': _mnemonic,
'private_key': privateKey,
'balance': balance[currency]!.toJSON(),
'passphrase': passphrase,
});
Future<void> _updateBalance() async {
@ -607,4 +613,7 @@ abstract class TronWalletBase
@override
String get password => _password;
@override
final String? passphrase;
}

View file

@ -8,23 +8,31 @@ class TronNewWalletCredentials extends WalletCredentials {
String? password,
this.mnemonic,
String? parentAddress,
String? passphrase,
}) : super(
name: name,
walletInfo: walletInfo,
password: password,
parentAddress: parentAddress,
passphrase: passphrase,
);
final String? mnemonic;
}
class TronRestoreWalletFromSeedCredentials extends WalletCredentials {
TronRestoreWalletFromSeedCredentials(
{required String name,
required String password,
required this.mnemonic,
WalletInfo? walletInfo})
: super(name: name, password: password, walletInfo: walletInfo);
TronRestoreWalletFromSeedCredentials({
required String name,
required String password,
required this.mnemonic,
WalletInfo? walletInfo,
String? passphrase,
}) : super(
name: name,
password: password,
walletInfo: walletInfo,
passphrase: passphrase,
);
final String mnemonic;
}

View file

@ -33,10 +33,7 @@ class TronWalletService extends WalletService<
WalletType getType() => WalletType.tron;
@override
Future<TronWallet> create(
TronNewWalletCredentials credentials, {
bool? isTestnet,
}) async {
Future<TronWallet> create(TronNewWalletCredentials credentials, {bool? isTestnet}) async {
final strength = credentials.seedPhraseLength == 24 ? 256 : 128;
final mnemonic = credentials.mnemonic ?? bip39.generateMnemonic(strength: strength);
@ -45,6 +42,7 @@ class TronWalletService extends WalletService<
walletInfo: credentials.walletInfo!,
mnemonic: mnemonic,
password: credentials.password!,
passphrase: credentials.passphrase,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
@ -120,6 +118,7 @@ class TronWalletService extends WalletService<
password: credentials.password!,
mnemonic: credentials.mnemonic,
walletInfo: credentials.walletInfo!,
passphrase: credentials.passphrase,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);

View file

@ -654,4 +654,15 @@ class CWBitcoin extends Bitcoin {
// TODO: this could be improved:
return inputAddressesContainMweb || outputAddressesContainMweb;
}
String? getUnusedMwebAddress(Object wallet) {
try {
final electrumWallet = wallet as ElectrumWallet;
final walletAddresses = electrumWallet.walletAddresses as ElectrumWalletAddresses;
final mwebAddress = walletAddresses.mwebAddresses.firstWhere((element) => !element.isUsed);
return mwebAddress.address;
} catch (_) {
return null;
}
}
}

View file

@ -2,14 +2,13 @@ import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:cake_wallet/entities/transaction_description.dart';
import 'package:cake_wallet/themes/theme_list.dart';
import 'package:cw_core/root_dir.dart';
import 'package:cake_wallet/utils/device_info.dart';
import 'package:cw_core/root_dir.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
import 'package:path_provider/path_provider.dart';
import 'package:cryptography/cryptography.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:archive/archive_io.dart';
@ -24,8 +23,8 @@ import 'package:cake_wallet/wallet_types.g.dart';
import 'package:cake_backup/backup.dart' as cake_backup;
class BackupService {
BackupService(
this._secureStorage, this._walletInfoSource, this._keyService, this._sharedPreferences)
BackupService(this._secureStorage, this._walletInfoSource, this._transactionDescriptionBox,
this._keyService, this._sharedPreferences)
: _cipher = Cryptography.instance.chacha20Poly1305Aead(),
_correctWallets = <WalletInfo>[];
@ -38,6 +37,7 @@ class BackupService {
final SecureStorage _secureStorage;
final SharedPreferences _sharedPreferences;
final Box<WalletInfo> _walletInfoSource;
final Box<TransactionDescription> _transactionDescriptionBox;
final KeyService _keyService;
List<WalletInfo> _correctWallets;
@ -86,6 +86,13 @@ class BackupService {
final preferencesDump = await _exportPreferencesJSON();
final preferencesDumpFile = File('${tmpDir.path}/~_preferences_dump_TMP');
final keychainDumpFile = File('${tmpDir.path}/~_keychain_dump_TMP');
final transactionDescriptionDumpFile =
File('${tmpDir.path}/~_transaction_descriptions_dump_TMP');
final transactionDescriptionData = _transactionDescriptionBox
.toMap()
.map((key, value) => MapEntry(key.toString(), value.toJson()));
final transactionDescriptionDump = jsonEncode(transactionDescriptionData);
if (tmpDir.existsSync()) {
tmpDir.deleteSync(recursive: true);
@ -107,8 +114,10 @@ class BackupService {
});
await keychainDumpFile.writeAsBytes(keychainDump.toList());
await preferencesDumpFile.writeAsString(preferencesDump);
await transactionDescriptionDumpFile.writeAsString(transactionDescriptionDump);
await zipEncoder.addFile(preferencesDumpFile, '~_preferences_dump');
await zipEncoder.addFile(keychainDumpFile, '~_keychain_dump');
await zipEncoder.addFile(transactionDescriptionDumpFile, '~_transaction_descriptions_dump');
zipEncoder.close();
final content = File(archivePath).readAsBytesSync();
@ -121,18 +130,18 @@ class BackupService {
final decryptedData = await _decryptV1(data, password, nonce);
final zip = ZipDecoder().decodeBytes(decryptedData);
zip.files.forEach((file) {
for (var file in zip.files) {
final filename = file.name;
if (file.isFile) {
final content = file.content as List<int>;
File('${appDir.path}/' + filename)
..createSync(recursive: true)
..writeAsBytesSync(content);
..writeAsBytesSync(content, flush: true);
} else {
Directory('${appDir.path}/' + filename)..create(recursive: true);
}
});
};
await _verifyWallets();
await _importKeychainDumpV1(password, nonce: nonce);
@ -144,22 +153,23 @@ class BackupService {
final decryptedData = await _decryptV2(data, password);
final zip = ZipDecoder().decodeBytes(decryptedData);
zip.files.forEach((file) {
for (var file in zip.files) {
final filename = file.name;
if (file.isFile) {
final content = file.content as List<int>;
File('${appDir.path}/' + filename)
..createSync(recursive: true)
..writeAsBytesSync(content);
..writeAsBytesSync(content, flush: true);
} else {
Directory('${appDir.path}/' + filename)..create(recursive: true);
}
});
};
await _verifyWallets();
await _importKeychainDumpV2(password);
await _importPreferencesDump();
await _importTransactionDescriptionDump();
}
Future<void> _verifyWallets() async {
@ -184,6 +194,21 @@ class BackupService {
return await CakeHive.openBox<WalletInfo>(WalletInfo.boxName);
}
Future<void> _importTransactionDescriptionDump() async {
final appDir = await getAppDir();
final transactionDescriptionFile = File('${appDir.path}/~_transaction_descriptions_dump');
if (!transactionDescriptionFile.existsSync()) {
return;
}
final jsonData =
json.decode(transactionDescriptionFile.readAsStringSync()) as Map<String, dynamic>;
final descriptionsMap = jsonData.map((key, value) =>
MapEntry(key, TransactionDescription.fromJson(value as Map<String, dynamic>)));
await _transactionDescriptionBox.putAll(descriptionsMap);
}
Future<void> _importPreferencesDump() async {
final appDir = await getAppDir();
final preferencesFile = File('${appDir.path}/~_preferences_dump');

View file

@ -16,6 +16,13 @@ String syncStatusTitle(SyncStatus syncStatus) {
return S.current.sync_status_syncronized;
}
if (syncStatus is FailedSyncStatus) {
if (syncStatus.error != null) {
return syncStatus.error!;
}
return S.current.sync_status_failed_connect;
}
if (syncStatus is NotConnectedSyncStatus) {
return S.current.sync_status_not_connected;
}
@ -24,10 +31,6 @@ String syncStatusTitle(SyncStatus syncStatus) {
return S.current.sync_status_attempting_sync;
}
if (syncStatus is FailedSyncStatus) {
return S.current.sync_status_failed_connect;
}
if (syncStatus is ConnectingSyncStatus) {
return S.current.sync_status_connecting;
}

View file

@ -1158,6 +1158,7 @@ Future<void> setup({
getIt.registerFactory(() => CakeFeaturesViewModel(getIt.get<CakePayService>()));
getIt.registerFactory(() => BackupService(getIt.get<SecureStorage>(), _walletInfoSource,
_transactionDescriptionBox,
getIt.get<KeyService>(), getIt.get<SharedPreferences>()));
getIt.registerFactory(() => BackupViewModel(

View file

@ -1,3 +1,4 @@
import 'dart:convert';
import 'dart:io' show Directory, File, Platform;
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/core/secure_storage.dart';
@ -234,7 +235,8 @@ Future<void> defaultSettingsMigration(
break;
case 36:
await addWowneroNodeList(nodes: nodes);
await changeWowneroCurrentNodeToDefault(sharedPreferences: sharedPreferences, nodes: nodes);
await changeWowneroCurrentNodeToDefault(
sharedPreferences: sharedPreferences, nodes: nodes);
break;
case 37:
await replaceTronDefaultNode(sharedPreferences: sharedPreferences, nodes: nodes);
@ -249,6 +251,10 @@ Future<void> defaultSettingsMigration(
case 40:
await removeMoneroWorld(sharedPreferences: sharedPreferences, nodes: nodes);
break;
case 41:
_deselectQuantex(sharedPreferences);
await _addSethNode(nodes, sharedPreferences);
break;
default:
break;
}
@ -263,6 +269,19 @@ Future<void> defaultSettingsMigration(
await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version);
}
void _deselectQuantex(SharedPreferences sharedPreferences) {
final Map<String, dynamic> exchangeProvidersSelection =
json.decode(sharedPreferences.getString(PreferencesKey.exchangeProvidersSelection) ?? "{}")
as Map<String, dynamic>;
exchangeProvidersSelection['Quantex'] = false;
sharedPreferences.setString(
PreferencesKey.exchangeProvidersSelection,
json.encode(exchangeProvidersSelection),
);
}
void _fixNodesUseSSLFlag(Box<Node> nodes) {
for (Node node in nodes.values) {
switch (node.uriRaw) {
@ -887,7 +906,30 @@ Future<void> changeDefaultBitcoinNode(
}
}
Future<void> _addSethNode(Box<Node> nodeSource, SharedPreferences sharedPreferences) async {
_addBitcoinNode(
nodeSource: nodeSource,
sharedPreferences: sharedPreferences,
nodeUri: "fulcrum.sethforprivacy.com:50002",
useSSL: false,
);
}
Future<void> _addElectRsNode(Box<Node> nodeSource, SharedPreferences sharedPreferences) async {
_addBitcoinNode(
nodeSource: nodeSource,
sharedPreferences: sharedPreferences,
nodeUri: cakeWalletSilentPaymentsElectrsUri,
);
}
Future<void> _addBitcoinNode({
required Box<Node> nodeSource,
required SharedPreferences sharedPreferences,
required String nodeUri,
bool replaceExisting = false,
bool useSSL = false,
}) async {
const cakeWalletBitcoinNodeUriPattern = '.cakewallet.com';
final currentBitcoinNodeId =
sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
@ -896,12 +938,11 @@ Future<void> _addElectRsNode(Box<Node> nodeSource, SharedPreferences sharedPrefe
final needToReplaceCurrentBitcoinNode =
currentBitcoinNode.uri.toString().contains(cakeWalletBitcoinNodeUriPattern);
final newElectRsBitcoinNode =
Node(uri: cakeWalletSilentPaymentsElectrsUri, type: WalletType.bitcoin, useSSL: false);
final newElectRsBitcoinNode = Node(uri: nodeUri, type: WalletType.bitcoin, useSSL: useSSL);
await nodeSource.add(newElectRsBitcoinNode);
if (needToReplaceCurrentBitcoinNode) {
if (needToReplaceCurrentBitcoinNode && replaceExisting) {
await sharedPreferences.setInt(
PreferencesKey.currentBitcoinElectrumSererIdKey, newElectRsBitcoinNode.key as int);
}
@ -1262,7 +1303,8 @@ Future<void> removeMoneroWorld(
const cakeWalletMoneroNodeUriPattern = '.moneroworld.com';
final currentMoneroNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
final currentMoneroNode = nodes.values.firstWhere((node) => node.key == currentMoneroNodeId);
final needToReplaceCurrentMoneroNode = currentMoneroNode.uri.toString().contains(cakeWalletMoneroNodeUriPattern);
final needToReplaceCurrentMoneroNode =
currentMoneroNode.uri.toString().contains(cakeWalletMoneroNodeUriPattern);
nodes.values.forEach((node) async {
if (node.type == WalletType.monero &&

View file

@ -21,4 +21,18 @@ class TransactionDescription extends HiveObject {
String? transactionNote;
String get note => transactionNote ?? '';
Map<String, dynamic> toJson() => {
'id': id,
'recipientAddress': recipientAddress,
'transactionNote': transactionNote,
};
factory TransactionDescription.fromJson(Map<String, dynamic> json) {
return TransactionDescription(
id: json['id'] as String,
recipientAddress: json['recipientAddress'] as String?,
transactionNote: json['transactionNote'] as String?,
);
}
}

View file

@ -1,10 +1,7 @@
import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
const channel = MethodChannel('com.cake_wallet/native_utils');
Future<String> fetchUnstoppableDomainAddress(String domain, String ticker) async {
var address = '';

View file

@ -14,6 +14,7 @@ class CWEthereum extends Ethereum {
String? parentAddress,
WalletInfo? walletInfo,
String? password,
String? passphrase,
}) =>
EVMChainNewWalletCredentials(
name: name,
@ -21,6 +22,7 @@ class CWEthereum extends Ethereum {
password: password,
parentAddress: parentAddress,
mnemonic: mnemonic,
passphrase: passphrase,
);
@override
@ -28,8 +30,14 @@ class CWEthereum extends Ethereum {
required String name,
required String mnemonic,
required String password,
String? passphrase,
}) =>
EVMChainRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic);
EVMChainRestoreWalletFromSeedCredentials(
name: name,
password: password,
mnemonic: mnemonic,
passphrase: passphrase,
);
@override
WalletCredentials createEthereumRestoreWalletFromPrivateKey({

View file

@ -192,7 +192,7 @@ Future<void> initializeAppConfigs() async {
transactionDescriptions: transactionDescriptions,
secureStorage: secureStorage,
anonpayInvoiceInfo: anonpayInvoiceInfo,
initialMigrationVersion: 40,
initialMigrationVersion: 41,
);
}

View file

@ -95,6 +95,7 @@ class CWNano extends Nano {
String? password,
String? mnemonic,
String? parentAddress,
String? passphrase,
}) =>
NanoNewWalletCredentials(
name: name,
@ -102,6 +103,7 @@ class CWNano extends Nano {
mnemonic: mnemonic,
parentAddress: parentAddress,
walletInfo: walletInfo,
passphrase: passphrase,
);
@override
@ -110,6 +112,7 @@ class CWNano extends Nano {
required String password,
required String mnemonic,
required DerivationType derivationType,
String? passphrase,
}) {
if (mnemonic.split(" ").length == 12 && derivationType != DerivationType.bip39) {
throw Exception("Invalid mnemonic for derivation type!");
@ -120,6 +123,7 @@ class CWNano extends Nano {
password: password,
mnemonic: mnemonic,
derivationType: derivationType,
passphrase: passphrase,
);
}

View file

@ -8,18 +8,21 @@ class CWPolygon extends Polygon {
PolygonWalletService(walletInfoSource, isDirect, client: PolygonClient());
@override
WalletCredentials createPolygonNewWalletCredentials(
{required String name,
String? mnemonic,
String? parentAddress,
WalletInfo? walletInfo,
String? password}) =>
WalletCredentials createPolygonNewWalletCredentials({
required String name,
String? mnemonic,
String? parentAddress,
WalletInfo? walletInfo,
String? password,
String? passphrase,
}) =>
EVMChainNewWalletCredentials(
name: name,
walletInfo: walletInfo,
password: password,
mnemonic: mnemonic,
parentAddress: parentAddress,
passphrase: passphrase,
);
@override
@ -27,8 +30,14 @@ class CWPolygon extends Polygon {
required String name,
required String mnemonic,
required String password,
String? passphrase,
}) =>
EVMChainRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic);
EVMChainRestoreWalletFromSeedCredentials(
name: name,
password: password,
mnemonic: mnemonic,
passphrase: passphrase,
);
@override
WalletCredentials createPolygonRestoreWalletFromPrivateKey({

View file

@ -11,6 +11,8 @@ Timer? _checkConnectionTimer;
void startCheckConnectionReaction(WalletBase wallet, SettingsStore settingsStore,
{int timeInterval = 5}) {
_checkConnectionTimer?.cancel();
// TODO: check the validity of this code, and if it's working fine, then no need for
// having the connect function in electrum.dart when the syncstatus is lost or failed and add the not connected state
_checkConnectionTimer = Timer.periodic(Duration(seconds: timeInterval), (_) async {
if (wallet.type == WalletType.bitcoin && wallet.syncStatus is SyncingSyncStatus) {
return;

View file

@ -152,11 +152,6 @@ void _setAutoGenerateSubaddressStatus(
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet,
SettingsStore settingsStore,
) async {
final walletHasAddresses = await wallet.walletAddresses.addressesMap.length > 1;
if (settingsStore.autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.initialized &&
walletHasAddresses) {
settingsStore.autoGenerateSubaddressStatus = AutoGenerateSubaddressStatus.disabled;
}
wallet.isEnabledAutoGenerateSubaddress =
settingsStore.autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.enabled ||
settingsStore.autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.initialized;

View file

@ -14,6 +14,7 @@ class CWSolana extends Solana {
String? parentAddress,
WalletInfo? walletInfo,
String? password,
String? passphrase,
}) =>
SolanaNewWalletCredentials(
name: name,
@ -21,6 +22,7 @@ class CWSolana extends Solana {
password: password,
mnemonic: mnemonic,
parentAddress: parentAddress,
passphrase: passphrase,
);
@override
@ -28,8 +30,14 @@ class CWSolana extends Solana {
required String name,
required String mnemonic,
required String password,
String? passphrase,
}) =>
SolanaRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic);
SolanaRestoreWalletFromSeedCredentials(
name: name,
password: password,
mnemonic: mnemonic,
passphrase: passphrase,
);
@override
WalletCredentials createSolanaRestoreWalletFromPrivateKey({

View file

@ -6,6 +6,7 @@ import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/reactions/wallet_connect.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/dashboard/pages/nft_listing_page.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/action_button.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/home_screen_account_widget.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
@ -19,14 +20,14 @@ import 'package:cake_wallet/themes/extensions/balance_page_theme.dart';
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
import 'package:cake_wallet/utils/feature_flag.dart';
import 'package:cake_wallet/utils/payment_request.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart';
import 'package:cw_bitcoin/bitcoin_receive_page_option.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:mobx/mobx.dart';
import 'package:url_launcher/url_launcher.dart';
class BalancePage extends StatelessWidget {
@ -238,8 +239,8 @@ class CryptoBalanceWidget extends StatelessWidget {
return Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
child: DashBoardRoundedCardWidget(
title: S.current.rep_warning,
subTitle: S.current.rep_warning_sub,
title: S.of(context).rep_warning,
subTitle: S.of(context).rep_warning_sub,
onTap: () => Navigator.of(context).pushNamed(Routes.changeRep),
onClose: () {
dashboardViewModel.settingsStore.shouldShowRepWarning = false;
@ -259,6 +260,7 @@ class CryptoBalanceWidget extends StatelessWidget {
dashboardViewModel.balanceViewModel.formattedBalances.elementAt(index);
return Observer(builder: (_) {
return BalanceRowWidget(
dashboardViewModel: dashboardViewModel,
availableBalanceLabel:
'${dashboardViewModel.balanceViewModel.availableBalanceLabel}',
availableBalance: balance.availableBalance,
@ -379,57 +381,68 @@ class CryptoBalanceWidget extends StatelessWidget {
padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
child: DashBoardRoundedCardWidget(
customBorder: 30,
title: S.current.litecoin_mweb,
subTitle: S.current.litecoin_enable_mweb_sync,
title: S.of(context).litecoin_mweb,
subTitle: '',
hint: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => launchUrl(
Uri.parse(
"https://guides.cakewallet.com/docs/cryptos/litecoin/#mweb"),
mode: LaunchMode.externalApplication,
Text(
S.of(context).litecoin_mweb_description,
style: TextStyle(
color: Colors.white,
fontSize: 14,
),
textAlign: TextAlign.center,
),
SizedBox(height: 8),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => launchUrl(
Uri.parse(
"https://guides.cakewallet.com/docs/cryptos/litecoin/#mweb"),
mode: LaunchMode.externalApplication,
),
child: Center(
child: Text(
S.of(context).learn_more,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.labelTextColor,
height: 1,
),
child: Row(
children: [
Text(
S.current.litecoin_what_is_mweb,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.labelTextColor,
height: 1,
),
softWrap: true,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Icon(Icons.help_outline,
size: 16,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.labelTextColor),
)
],
softWrap: true,
),
),
),
SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () => _dismissMweb(context),
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).primaryColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
),
child: Text(
S.of(context).litecoin_mweb_dismiss,
style: TextStyle(color: Colors.white),
),
),
Observer(
builder: (_) => StandardSwitch(
value: dashboardViewModel.mwebScanningActive,
onTaped: () => _toggleMweb(context),
),
)
ElevatedButton(
onPressed: () => _enableMweb(context),
child: Text(S.of(context).litecoin_enable_mweb_sync),
),
],
),
],
),
onTap: () => _toggleMweb(context),
onTap: () => {},
icon: ImageIcon(
AssetImage('assets/images/mweb_logo.png'),
color:
@ -479,20 +492,34 @@ class CryptoBalanceWidget extends StatelessWidget {
return dashboardViewModel.setSilentPaymentsScanning(newValue);
}
Future<void> _toggleMweb(BuildContext context) async {
Future<void> _enableMweb(BuildContext context) async {
if (!dashboardViewModel.hasEnabledMwebBefore) {
await showPopUp<void>(
context: context,
builder: (BuildContext context) => AlertWithOneAction(
alertTitle: S.of(context).warning,
alertContent: S.current.litecoin_mweb_warning,
buttonText: S.of(context).ok,
alertTitle: S.of(context).alert_notice,
alertContent: S.of(context).litecoin_mweb_warning,
buttonText: S.of(context).understand,
buttonAction: () {
Navigator.of(context).pop();
},
));
}
dashboardViewModel.setMwebScanningActive(!dashboardViewModel.mwebScanningActive);
dashboardViewModel.setMwebScanningActive();
}
Future<void> _dismissMweb(BuildContext context) async {
await showPopUp<void>(
context: context,
builder: (BuildContext context) => AlertWithOneAction(
alertTitle: S.of(context).alert_notice,
alertContent: S.of(context).litecoin_mweb_enable_later,
buttonText: S.of(context).understand,
buttonAction: () {
Navigator.of(context).pop();
},
));
dashboardViewModel.dismissMweb();
}
}
@ -517,6 +544,7 @@ class BalanceRowWidget extends StatelessWidget {
required this.hasSecondAvailableBalance,
required this.hasSecondAdditionalBalance,
required this.isTestnet,
required this.dashboardViewModel,
super.key,
});
@ -539,187 +567,238 @@ class BalanceRowWidget extends StatelessWidget {
final bool hasSecondAvailableBalance;
final bool hasSecondAdditionalBalance;
final bool isTestnet;
final DashboardViewModel dashboardViewModel;
// void _showBalanceDescription(BuildContext context) {
// showPopUp<void>(
// context: context,
// builder: (_) =>
// InformationPage(information: S.current.available_balance_description),
// InformationPage(information: S.of(context).available_balance_description),
// );
// }
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(left: 16, right: 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
border: Border.all(
color: Theme.of(context).extension<BalancePageTheme>()!.cardBorderColor,
width: 1,
return Column(children: [
Container(
margin: const EdgeInsets.only(left: 16, right: 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
border: Border.all(
color: Theme.of(context).extension<BalancePageTheme>()!.cardBorderColor,
width: 1,
),
color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor,
),
color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor,
),
child: Container(
margin: const EdgeInsets.only(top: 16, left: 24, right: 8, bottom: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
child: Container(
margin: const EdgeInsets.only(top: 16, left: 24, right: 8, bottom: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: hasAdditionalBalance
? () => _showBalanceDescription(
context, S.of(context).available_balance_description)
: null,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Semantics(
hint: 'Double tap to see more information',
container: true,
child: Text('${availableBalanceLabel}',
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.labelTextColor,
height: 1)),
),
if (hasAdditionalBalance)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Icon(Icons.help_outline,
size: 16,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.labelTextColor),
),
],
),
SizedBox(height: 6),
AutoSizeText(availableBalance,
style: TextStyle(
fontSize: 24,
fontFamily: 'Lato',
fontWeight: FontWeight.w900,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.balanceAmountColor,
height: 1),
maxLines: 1,
textAlign: TextAlign.start),
SizedBox(height: 6),
if (isTestnet)
Text(S.of(context).testnet_coins_no_value,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<BalancePageTheme>()!.textColor,
height: 1)),
if (!isTestnet)
Text('${availableFiatBalance}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
fontFamily: 'Lato',
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<BalancePageTheme>()!.textColor,
height: 1)),
],
),
),
SizedBox(
width: min(MediaQuery.of(context).size.width * 0.2, 100),
child: Center(
child: Column(
children: [
CakeImageWidget(
imageUrl: currency.iconPath,
height: 40,
width: 40,
displayOnError: Container(
height: 30.0,
width: 30.0,
child: Center(
child: Text(
currency.title.substring(0, min(currency.title.length, 2)),
style: TextStyle(fontSize: 11),
),
),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey.shade400,
),
),
),
const SizedBox(height: 10),
Text(
currency.title,
style: TextStyle(
fontSize: 15,
fontFamily: 'Lato',
fontWeight: FontWeight.w800,
color:
Theme.of(context).extension<BalancePageTheme>()!.assetTitleColor,
height: 1,
),
),
],
),
),
),
],
),
if (frozenBalance.isNotEmpty)
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: hasAdditionalBalance
? () =>
_showBalanceDescription(context, S.current.available_balance_description)
? () => _showBalanceDescription(
context, S.of(context).unavailable_balance_description)
: null,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 26),
Row(
children: [
Semantics(
hint: 'Double tap to see more information',
container: true,
child: Text('${availableBalanceLabel}',
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.labelTextColor,
height: 1)),
),
if (hasAdditionalBalance)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Icon(Icons.help_outline,
size: 16,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.labelTextColor),
Text(
S.of(context).unavailable_balance,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color:
Theme.of(context).extension<BalancePageTheme>()!.labelTextColor,
height: 1,
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Icon(Icons.help_outline,
size: 16,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.labelTextColor),
),
],
),
SizedBox(height: 6),
AutoSizeText(availableBalance,
style: TextStyle(
fontSize: 24,
fontFamily: 'Lato',
fontWeight: FontWeight.w900,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.balanceAmountColor,
height: 1),
maxLines: 1,
textAlign: TextAlign.start),
SizedBox(height: 6),
if (isTestnet)
Text(S.current.testnet_coins_no_value,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<BalancePageTheme>()!.textColor,
height: 1)),
SizedBox(height: 8),
AutoSizeText(
frozenBalance,
style: TextStyle(
fontSize: 20,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color:
Theme.of(context).extension<BalancePageTheme>()!.balanceAmountColor,
height: 1,
),
maxLines: 1,
textAlign: TextAlign.center,
),
SizedBox(height: 4),
if (!isTestnet)
Text('${availableFiatBalance}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
fontFamily: 'Lato',
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<BalancePageTheme>()!.textColor,
height: 1)),
],
),
),
SizedBox(
width: min(MediaQuery.of(context).size.width * 0.2, 100),
child: Center(
child: Column(
children: [
CakeImageWidget(
imageUrl: currency.iconPath,
height: 40,
width: 40,
displayOnError: Container(
height: 30.0,
width: 30.0,
child: Center(
child: Text(
currency.title.substring(0, min(currency.title.length, 2)),
style: TextStyle(fontSize: 11),
),
),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey.shade400,
),
),
),
const SizedBox(height: 10),
Text(
currency.title,
style: TextStyle(
fontSize: 15,
fontFamily: 'Lato',
fontWeight: FontWeight.w800,
color: Theme.of(context).extension<BalancePageTheme>()!.assetTitleColor,
height: 1,
),
),
],
),
),
),
],
),
if (frozenBalance.isNotEmpty)
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: hasAdditionalBalance
? () =>
_showBalanceDescription(context, S.current.unavailable_balance_description)
: null,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 26),
Row(
children: [
Text(
S.current.unavailable_balance,
frozenFiatBalance,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor,
color: Theme.of(context).extension<BalancePageTheme>()!.textColor,
height: 1,
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Icon(Icons.help_outline,
size: 16,
color:
Theme.of(context).extension<BalancePageTheme>()!.labelTextColor),
),
],
],
),
),
if (hasAdditionalBalance)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24),
Text(
'${additionalBalanceLabel}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor,
height: 1,
),
),
SizedBox(height: 8),
AutoSizeText(
frozenBalance,
additionalBalance,
style: TextStyle(
fontSize: 20,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<BalancePageTheme>()!.balanceAmountColor,
color: Theme.of(context).extension<BalancePageTheme>()!.assetTitleColor,
height: 1,
),
maxLines: 1,
@ -728,7 +807,7 @@ class BalanceRowWidget extends StatelessWidget {
SizedBox(height: 4),
if (!isTestnet)
Text(
frozenFiatBalance,
'${additionalFiatBalance}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
@ -740,143 +819,247 @@ class BalanceRowWidget extends StatelessWidget {
),
],
),
),
if (hasAdditionalBalance)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24),
Text(
'${additionalBalanceLabel}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor,
height: 1,
),
),
SizedBox(height: 8),
AutoSizeText(
additionalBalance,
style: TextStyle(
fontSize: 20,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<BalancePageTheme>()!.assetTitleColor,
height: 1,
),
maxLines: 1,
textAlign: TextAlign.center,
),
SizedBox(height: 4),
if (!isTestnet)
Text(
'${additionalFiatBalance}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<BalancePageTheme>()!.textColor,
height: 1,
),
),
],
),
if (hasSecondAvailableBalance)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24),
Text(
'${secondAvailableBalanceLabel}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor,
height: 1,
),
),
SizedBox(height: 8),
AutoSizeText(
secondAvailableBalance,
style: TextStyle(
fontSize: 20,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<BalancePageTheme>()!.assetTitleColor,
height: 1,
),
maxLines: 1,
textAlign: TextAlign.center,
),
SizedBox(height: 4),
if (!isTestnet)
Text(
'${secondAvailableFiatBalance}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<BalancePageTheme>()!.textColor,
height: 1,
),
),
],
),
if (hasSecondAdditionalBalance)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24),
Text(
'${secondAdditionalBalanceLabel}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor,
height: 1,
),
),
SizedBox(height: 8),
AutoSizeText(
secondAdditionalBalance,
style: TextStyle(
fontSize: 20,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<BalancePageTheme>()!.assetTitleColor,
height: 1,
),
maxLines: 1,
textAlign: TextAlign.center,
),
SizedBox(height: 4),
if (!isTestnet)
Text(
'${secondAdditionalFiatBalance}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<BalancePageTheme>()!.textColor,
height: 1,
),
),
],
),
],
],
),
),
),
);
if (hasSecondAdditionalBalance || hasSecondAvailableBalance) ...[
SizedBox(height: 16),
Container(
margin: const EdgeInsets.only(left: 16, right: 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
border: Border.all(
color: Theme.of(context).extension<BalancePageTheme>()!.cardBorderColor,
width: 1,
),
color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor,
),
child: Container(
margin: const EdgeInsets.only(top: 0, left: 24, right: 8, bottom: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(
children: [
if (currency == CryptoCurrency.ltc)
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
padding: EdgeInsets.only(right: 16, top: 16),
child: Column(
children: [
CakeImageWidget(
imageUrl: 'assets/images/mweb_logo.png',
height: 40,
width: 40,
displayOnError: Container(
height: 30.0,
width: 30.0,
child: Center(
child: Text(
currency.title.substring(0, min(currency.title.length, 2)),
style: TextStyle(fontSize: 11),
),
),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey.shade400,
),
),
),
const SizedBox(height: 10),
Text(
'MWEB',
style: TextStyle(
fontSize: 15,
fontFamily: 'Lato',
fontWeight: FontWeight.w800,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.assetTitleColor,
height: 1,
),
),
],
),
),
],
),
if (hasSecondAvailableBalance)
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24),
Text(
'${secondAvailableBalanceLabel}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.labelTextColor,
height: 1,
),
),
SizedBox(height: 8),
AutoSizeText(
secondAvailableBalance,
style: TextStyle(
fontSize: 20,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.assetTitleColor,
height: 1,
),
maxLines: 1,
textAlign: TextAlign.center,
),
SizedBox(height: 4),
if (!isTestnet)
Text(
'${secondAvailableFiatBalance}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color:
Theme.of(context).extension<BalancePageTheme>()!.textColor,
height: 1,
),
),
],
),
],
),
],
),
Stack(
children: [
if (hasSecondAdditionalBalance)
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24),
Text(
'${secondAdditionalBalanceLabel}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.labelTextColor,
height: 1,
),
),
SizedBox(height: 8),
AutoSizeText(
secondAdditionalBalance,
style: TextStyle(
fontSize: 20,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.assetTitleColor,
height: 1,
),
maxLines: 1,
textAlign: TextAlign.center,
),
SizedBox(height: 4),
if (!isTestnet)
Text(
'${secondAdditionalFiatBalance}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color:
Theme.of(context).extension<BalancePageTheme>()!.textColor,
height: 1,
),
),
],
),
],
),
// TODO: smarter peg in / out buttons
// if (currency == CryptoCurrency.ltc)
// Row(
// mainAxisAlignment: MainAxisAlignment.end,
// children: [
// Container(
// margin: EdgeInsets.only(top: 24, right: 8),
// child: ElevatedButton(
// style: ElevatedButton.styleFrom(
// backgroundColor: Theme.of(context).highlightColor,
// ),
// onPressed: () {
// final mwebAddress =
// bitcoin!.getUnusedMwebAddress(dashboardViewModel.wallet);
// if (mwebAddress == null) return;
// final paymentRequest =
// PaymentRequest.fromUri(Uri.parse("litecoin:${mwebAddress}"));
// Navigator.of(context)
// .pushNamed(Routes.send, arguments: paymentRequest);
// },
// child: Container(
// color: Colors.transparent,
// margin: EdgeInsets.all(4),
// child: Column(
// mainAxisSize: MainAxisSize.max,
// crossAxisAlignment: CrossAxisAlignment.center,
// children: <Widget>[
// Container(
// alignment: Alignment.center,
// decoration: BoxDecoration(shape: BoxShape.circle),
// child: Image.asset(
// 'assets/images/received.png',
// color: Theme.of(context)
// .extension<BalancePageTheme>()!
// .balanceAmountColor,
// width: 64,
// height: 32,
// ),
// ),
// SizedBox(height: 4),
// Text(
// S.of(context).litecoin_mweb_pegin,
// style: TextStyle(
// fontSize: 10,
// color: Theme.of(context)
// .extension<DashboardPageTheme>()!
// .cardTextColor),
// )
// ],
// ),
// ),
// ),
// ),
// ],
// ),
],
),
],
),
),
),
],
]);
}
void _showBalanceDescription(BuildContext context, String content) {

View file

@ -192,7 +192,7 @@ class MenuWidgetState extends State<MenuWidget> {
final item = items[index];
if (!widget.dashboardViewModel.hasMweb &&
item.name(context) == S.current.litecoin_mweb_settings) {
item.name(context) == S.of(context).litecoin_mweb_settings) {
return const SizedBox();
}

View file

@ -189,7 +189,7 @@ class _AdvancedPrivacySettingsBodyState extends State<_AdvancedPrivacySettingsBo
),
);
}),
if (!widget.isFromRestore) ...[
if (!widget.isFromRestore)
Observer(builder: (_) {
if (widget.privacySettingsViewModel.hasSeedPhraseLengthOption)
return SettingsPickerCell<SeedPhraseLength>(
@ -202,54 +202,53 @@ class _AdvancedPrivacySettingsBodyState extends State<_AdvancedPrivacySettingsBo
);
return Container();
}),
if (widget.privacySettingsViewModel.hasPassphraseOption)
Padding(
padding: EdgeInsets.all(24),
child: Form(
key: _passphraseFormKey,
child: Column(
children: [
BaseTextFormField(
hintText: S.of(context).passphrase,
controller: passphraseController,
obscureText: obscurePassphrase,
suffixIcon: GestureDetector(
onTap: () => setState(() {
obscurePassphrase = !obscurePassphrase;
}),
child: Icon(
Icons.remove_red_eye,
color: obscurePassphrase ? Colors.black54 : Colors.black26,
),
if (widget.privacySettingsViewModel.hasPassphraseOption)
Padding(
padding: EdgeInsets.all(24),
child: Form(
key: _passphraseFormKey,
child: Column(
children: [
BaseTextFormField(
hintText: S.of(context).passphrase,
controller: passphraseController,
obscureText: obscurePassphrase,
suffixIcon: GestureDetector(
onTap: () => setState(() {
obscurePassphrase = !obscurePassphrase;
}),
child: Icon(
Icons.remove_red_eye,
color: obscurePassphrase ? Colors.black54 : Colors.black26,
),
),
const SizedBox(height: 10),
BaseTextFormField(
hintText: S.of(context).confirm_passphrase,
controller: confirmPassphraseController,
obscureText: obscurePassphrase,
validator: (text) {
if (text == passphraseController.text) {
return null;
}
),
const SizedBox(height: 10),
BaseTextFormField(
hintText: S.of(context).confirm_passphrase,
controller: confirmPassphraseController,
obscureText: obscurePassphrase,
validator: (text) {
if (text == passphraseController.text) {
return null;
}
return S.of(context).passphrases_doesnt_match;
},
suffixIcon: GestureDetector(
onTap: () => setState(() {
obscurePassphrase = !obscurePassphrase;
}),
child: Icon(
Icons.remove_red_eye,
color: obscurePassphrase ? Colors.black54 : Colors.black26,
),
return S.of(context).passphrases_doesnt_match;
},
suffixIcon: GestureDetector(
onTap: () => setState(() {
obscurePassphrase = !obscurePassphrase;
}),
child: Icon(
Icons.remove_red_eye,
color: obscurePassphrase ? Colors.black54 : Colors.black26,
),
),
],
),
),
],
),
),
],
),
Observer(builder: (_) {
return Column(
children: [
@ -311,13 +310,14 @@ class _AdvancedPrivacySettingsBodyState extends State<_AdvancedPrivacySettingsBo
widget.nodeViewModel.save();
}
if (passphraseController.text.isNotEmpty) {
if (_passphraseFormKey.currentState != null && !_passphraseFormKey.currentState!.validate()) {
if (_passphraseFormKey.currentState != null &&
!_passphraseFormKey.currentState!.validate()) {
return;
}
widget.seedTypeViewModel.setPassphrase(passphraseController.text);
}
widget.seedTypeViewModel.setPassphrase(passphraseController.text);
Navigator.pop(context);
},
text: S.of(context).continue_text,

View file

@ -7,7 +7,6 @@ import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:flutter_svg/svg.dart';
class WalletGroupDescriptionPage extends BasePage {
WalletGroupDescriptionPage({required this.selectedWalletType});
@ -21,12 +20,6 @@ class WalletGroupDescriptionPage extends BasePage {
@override
Widget body(BuildContext context) {
final lightImage = 'assets/images/wallet_group_light.png';
final darkImage = 'assets/images/wallet_group_dark.png';
final brightImage = 'assets/images/wallet_group_bright.png';
final image = currentTheme.type == ThemeType.light ? lightImage : darkImage;
return Container(
alignment: Alignment.center,
padding: EdgeInsets.all(24),

View file

@ -4,11 +4,11 @@ import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/new_wallet/widgets/grouped_wallet_expansion_tile.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/view_model/wallet_groups_display_view_model.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import '../../../themes/extensions/cake_text_theme.dart';
class WalletGroupsDisplayPage extends BasePage {
@ -16,22 +16,24 @@ class WalletGroupsDisplayPage extends BasePage {
final WalletGroupsDisplayViewModel walletGroupsDisplayViewModel;
final walletTypeImage = Image.asset('assets/images/wallet_type.png');
final walletTypeLightImage = Image.asset('assets/images/wallet_type_light.png');
@override
String get title => S.current.wallet_group;
@override
Widget body(BuildContext context) => WalletGroupsDisplayBody(
walletGroupsDisplayViewModel: walletGroupsDisplayViewModel,
currentTheme: currentTheme,
);
}
class WalletGroupsDisplayBody extends StatelessWidget {
WalletGroupsDisplayBody({required this.walletGroupsDisplayViewModel});
WalletGroupsDisplayBody({
required this.walletGroupsDisplayViewModel,
required this.currentTheme,
});
final WalletGroupsDisplayViewModel walletGroupsDisplayViewModel;
final ThemeBase currentTheme;
@override
Widget build(BuildContext context) {
@ -47,7 +49,9 @@ class WalletGroupsDisplayBody extends StatelessWidget {
return Column(
children: [
if (walletGroupsDisplayViewModel.hasNoFilteredWallet) ...{
WalletGroupEmptyStateWidget(),
WalletGroupEmptyStateWidget(
currentTheme: currentTheme,
),
},
...walletGroupsDisplayViewModel.multiWalletGroups.map(
(walletGroup) {
@ -153,17 +157,17 @@ class WalletGroupsDisplayBody extends StatelessWidget {
}
class WalletGroupEmptyStateWidget extends StatelessWidget {
const WalletGroupEmptyStateWidget({
super.key,
});
const WalletGroupEmptyStateWidget({required this.currentTheme, super.key});
final ThemeBase currentTheme;
@override
Widget build(BuildContext context) {
return Column(
children: [
Image.asset(
'assets/images/wallet_group.png',
scale: 0.8,
_getThemedWalletGroupImage(currentTheme.type),
scale: 1.8,
),
SizedBox(height: 32),
Text.rich(
@ -190,4 +194,19 @@ class WalletGroupEmptyStateWidget extends StatelessWidget {
],
);
}
String _getThemedWalletGroupImage(ThemeType theme) {
final lightImage = 'assets/images/wallet_group_light.png';
final darkImage = 'assets/images/wallet_group_dark.png';
final brightImage = 'assets/images/wallet_group_bright.png';
switch (theme) {
case ThemeType.bright:
return brightImage;
case ThemeType.light:
return lightImage;
default:
return darkImage;
}
}
}

View file

@ -23,7 +23,7 @@ class QrImage extends StatelessWidget {
return qr.QrImageView(
data: data,
errorCorrectionLevel: errorCorrectionLevel,
version: version ?? 9, // Previous value: 7 something happened after flutter upgrade monero wallets addresses are longer than ver. 7 ???
version: version ?? qr.QrVersions.auto,
size: size,
foregroundColor: foregroundColor,
backgroundColor: backgroundColor,

View file

@ -19,7 +19,6 @@ class WalletRestoreFromSeedForm extends StatefulWidget {
WalletRestoreFromSeedForm({Key? key,
required this.displayLanguageSelector,
required this.displayBlockHeightSelector,
required this.displayPassphrase,
required this.type,
required this.displayWalletPassword,
required this.seedSettingsViewModel,
@ -35,7 +34,6 @@ class WalletRestoreFromSeedForm extends StatefulWidget {
final bool displayLanguageSelector;
final bool displayBlockHeightSelector;
final bool displayWalletPassword;
final bool displayPassphrase;
final SeedSettingsViewModel seedSettingsViewModel;
final FocusNode? blockHeightFocusNode;
final Function(bool)? onHeightOrDateEntered;
@ -60,7 +58,6 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
repeatedPasswordTextEditingController = displayWalletPassword
? TextEditingController()
: null,
passphraseController = TextEditingController(),
seedTypeController = TextEditingController();
final GlobalKey<SeedWidgetState> seedWidgetStateKey;
@ -70,15 +67,11 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
final TextEditingController? passwordTextEditingController;
final TextEditingController? repeatedPasswordTextEditingController;
final TextEditingController seedTypeController;
final TextEditingController passphraseController;
final GlobalKey<FormState> formKey;
late ReactionDisposer moneroSeedTypeReaction;
String language;
void Function()? passwordListener;
void Function()? repeatedPasswordListener;
void Function()? passphraseListener;
bool obscurePassphrase = true;
@override
void initState() {
@ -96,9 +89,6 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
repeatedPasswordTextEditingController?.addListener(repeatedPasswordListener!);
}
passphraseListener = () => widget.seedSettingsViewModel.setPassphrase(passphraseController.text);
passphraseController.addListener(passphraseListener!);
moneroSeedTypeReaction =
reaction((_) => widget.seedSettingsViewModel.moneroSeedType, (MoneroSeedType item) {
_setSeedType(item);
@ -120,8 +110,6 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
repeatedPasswordTextEditingController?.removeListener(repeatedPasswordListener!);
}
passphraseController.removeListener(passphraseListener!);
super.dispose();
}
@ -280,23 +268,6 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
hasDatePicker: widget.type == WalletType.monero || widget.type == WalletType.wownero,
walletType: widget.type,
),
if (widget.displayPassphrase) ...[
const SizedBox(height: 10),
BaseTextFormField(
hintText: S.current.passphrase,
controller: passphraseController,
obscureText: obscurePassphrase,
suffixIcon: GestureDetector(
onTap: () => setState(() {
obscurePassphrase = !obscurePassphrase;
}),
child: Icon(
Icons.remove_red_eye,
color: obscurePassphrase ? Colors.black54 : Colors.black26,
),
),
),
]
]));
}

View file

@ -37,7 +37,6 @@ class WalletRestorePage extends BasePage {
displayBlockHeightSelector:
walletRestoreViewModel.hasBlockchainHeightLanguageSelector,
displayLanguageSelector: walletRestoreViewModel.hasSeedLanguageSelector,
displayPassphrase: walletRestoreViewModel.hasPassphrase,
type: walletRestoreViewModel.type,
key: walletRestoreFromSeedFormKey,
blockHeightFocusNode: _blockHeightFocusNode,
@ -320,9 +319,7 @@ class WalletRestorePage extends BasePage {
-1;
}
if (walletRestoreViewModel.hasPassphrase) {
credentials['passphrase'] = seedSettingsViewModel.passphrase;
}
credentials['passphrase'] = seedSettingsViewModel.passphrase;
credentials['name'] =
walletRestoreFromSeedFormKey.currentState!.nameTextEditingController.text;

View file

@ -1,27 +1,49 @@
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
import 'package:flutter/material.dart';
class TextFieldListRow extends StatelessWidget {
class TextFieldListRow extends StatefulWidget {
TextFieldListRow(
{required this.title,
required this.value,
this.titleFontSize = 14,
this.valueFontSize = 16,
this.onSubmitted,
this.onTapOutside})
: _textController = TextEditingController() {
_textController.text = value;
}
this.onSubmitted});
final String title;
final String value;
final double titleFontSize;
final double valueFontSize;
final Function(String value)? onSubmitted;
final Function(String value)? onTapOutside;
final TextEditingController _textController;
@override
_TextFieldListRowState createState() => _TextFieldListRowState();
}
class _TextFieldListRowState extends State<TextFieldListRow> {
late TextEditingController _textController;
late FocusNode _focusNode;
@override
void initState() {
super.initState();
_textController = TextEditingController(text: widget.value);
_focusNode = FocusNode();
_focusNode.addListener(() {
if (!_focusNode.hasFocus) {
widget.onSubmitted?.call(_textController.text);
}
});
}
@override
void dispose() {
_textController.dispose();
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
@ -29,41 +51,48 @@ class TextFieldListRow extends StatelessWidget {
width: double.infinity,
color: Theme.of(context).colorScheme.background,
child: Padding(
padding:
const EdgeInsets.only(left: 24, top: 16, bottom: 16, right: 24),
padding: const EdgeInsets.only(left: 24, top: 16, bottom: 16, right: 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(title,
style: TextStyle(
fontSize: titleFontSize,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor),
textAlign: TextAlign.left),
TextField(
controller: _textController,
keyboardType: TextInputType.multiline,
textInputAction: TextInputAction.done,
maxLines: null,
textAlign: TextAlign.start,
style: TextStyle(
fontSize: valueFontSize,
fontWeight: FontWeight.w500,
color:
Theme.of(context).extension<CakeTextTheme>()!.titleColor),
decoration: InputDecoration(
isDense: true,
contentPadding: EdgeInsets.only(top: 12, bottom: 0),
hintText: S.of(context).enter_your_note,
hintStyle: TextStyle(
fontSize: valueFontSize,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor),
border: InputBorder.none),
onTapOutside: (_) => onTapOutside?.call(_textController.text),
onSubmitted: (value) => onSubmitted?.call(value),
)
]),
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
widget.title,
style: TextStyle(
fontSize: widget.titleFontSize,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor,
),
textAlign: TextAlign.left,
),
TextField(
controller: _textController,
focusNode: _focusNode,
keyboardType: TextInputType.multiline,
textInputAction: TextInputAction.done,
maxLines: null,
textAlign: TextAlign.start,
style: TextStyle(
fontSize: widget.valueFontSize,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
),
decoration: InputDecoration(
isDense: true,
contentPadding: EdgeInsets.only(top: 12, bottom: 0),
hintText: S.of(context).enter_your_note,
hintStyle: TextStyle(
fontSize: widget.valueFontSize,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor,
),
border: InputBorder.none,
),
onSubmitted: (value) {
widget.onSubmitted?.call(value);
},
),
],
),
),
);
}

View file

@ -44,7 +44,6 @@ class UnspentCoinsDetailsPage extends BasePage {
return TextFieldListRow(
title: item.title,
value: item.value,
onTapOutside: item.onSubmitted,
onSubmitted: item.onSubmitted,
);
}

View file

@ -49,7 +49,7 @@ class SettingActions {
);
static SettingActions litecoinMwebSettingAction = SettingActions._(
name: (context) => S.current.litecoin_mweb_settings,
name: (context) => S.of(context).litecoin_mweb_settings,
image: 'assets/images/bitcoin_menu.png',
onTap: (BuildContext context) {
Navigator.pop(context);

View file

@ -15,12 +15,14 @@ class CWTron extends Tron {
String? password,
String? mnemonic,
String? parentAddress,
String? passphrase,
}) =>
TronNewWalletCredentials(
name: name,
walletInfo: walletInfo,
password: password,
mnemonic: mnemonic,
passphrase: passphrase,
parentAddress: parentAddress);
@override
@ -28,8 +30,14 @@ class CWTron extends Tron {
required String name,
required String mnemonic,
required String password,
String? passphrase,
}) =>
TronRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic);
TronRestoreWalletFromSeedCredentials(
name: name,
password: password,
mnemonic: mnemonic,
passphrase: passphrase,
);
@override
WalletCredentials createTronRestoreWalletFromPrivateKey({

View file

@ -9,15 +9,12 @@ class BrightnessUtil {
return;
}
// Get the current brightness:
final brightness = await DeviceDisplayBrightness.getBrightness();
// ignore: unawaited_futures
DeviceDisplayBrightness.setBrightness(1.0);
await func();
// ignore: unawaited_futures
DeviceDisplayBrightness.setBrightness(brightness);
DeviceDisplayBrightness.resetBrightness();
}
}

View file

@ -75,6 +75,9 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
WalletType.bitcoin,
WalletType.litecoin,
WalletType.bitcoinCash,
WalletType.ethereum,
WalletType.polygon,
WalletType.tron,
].contains(type);
@computed

View file

@ -26,22 +26,23 @@ abstract class ContactListViewModelBase with Store {
isAutoGenerateEnabled =
settingsStore.autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.enabled {
walletInfoSource.values.forEach((info) {
if (isAutoGenerateEnabled && info.type == WalletType.monero && info.addressInfos != null) {
final key = info.addressInfos!.keys.first;
final value = info.addressInfos![key];
final address = value?.first;
if (address != null) {
final name = _createName(info.name, address.label);
walletContacts.add(WalletContact(
address.address,
name,
walletTypeToCryptoCurrency(info.type),
));
if ([WalletType.monero, WalletType.wownero, WalletType.haven].contains(info.type) && info.addressInfos != null) {
for (var key in info.addressInfos!.keys) {
final value = info.addressInfos![key];
final address = value?.first;
if (address != null) {
final name = _createName(info.name, address.label, key: key);
walletContacts.add(WalletContact(
address.address,
name,
walletTypeToCryptoCurrency(info.type),
));
}
}
} else if (info.addresses?.isNotEmpty == true && info.addresses!.length > 1) {
if ([WalletType.monero, WalletType.wownero, WalletType.haven].contains(info.type)) {
final address = info.address;
final name = _createName(info.name, "");
final name = _createName(info.name, "", key: 0);
walletContacts.add(WalletContact(
address,
name,
@ -52,7 +53,7 @@ abstract class ContactListViewModelBase with Store {
if (label.isEmpty) {
return;
}
final name = _createName(info.name, label);
final name = _createName(info.name, label, key: null);
walletContacts.add(WalletContact(
address,
name,
@ -65,7 +66,7 @@ abstract class ContactListViewModelBase with Store {
} else {
walletContacts.add(WalletContact(
info.address,
info.name,
_createName(info.name, "", key: [WalletType.monero, WalletType.wownero, WalletType.haven].contains(info.type) ? 0 : null),
walletTypeToCryptoCurrency(info.type),
));
}
@ -76,10 +77,9 @@ abstract class ContactListViewModelBase with Store {
initialFire: true);
}
String _createName(String walletName, String label) {
return label.isNotEmpty
? '$walletName (${label.replaceAll(RegExp(r'active', caseSensitive: false), S.current.active).replaceAll(RegExp(r'silent payments', caseSensitive: false), S.current.silent_payments)})'
: walletName;
String _createName(String walletName, String label, {int? key = null}) {
final actualLabel = label.replaceAll(RegExp(r'active', caseSensitive: false), S.current.active).replaceAll(RegExp(r'silent payments', caseSensitive: false), S.current.silent_payments);
return '$walletName${key == null ? "" : " [#${key}]"} ${actualLabel.isNotEmpty ? "($actualLabel)" : ""}'.trim();
}
final bool isAutoGenerateEnabled;

View file

@ -358,14 +358,15 @@ abstract class BalanceViewModelBase with Store {
}
bool _hasSecondAdditionalBalanceForWalletType(WalletType type) {
if (wallet.type == WalletType.litecoin && settingsStore.mwebEnabled) {
if (wallet.type == WalletType.litecoin && settingsStore.mwebAlwaysScan) {
// if ((wallet.balance[CryptoCurrency.ltc]?.secondAdditional ?? 0) > 0)
return true;
}
return false;
}
bool _hasSecondAvailableBalanceForWalletType(WalletType type) {
if (wallet.type == WalletType.litecoin && settingsStore.mwebEnabled) {
if (wallet.type == WalletType.litecoin && settingsStore.mwebAlwaysScan) {
return true;
}
return false;

View file

@ -261,6 +261,8 @@ abstract class DashboardViewModelBase with Store {
reaction((_) => settingsStore.mwebAlwaysScan, (bool alwaysScan) {
if (alwaysScan) {
mwebScanningActive = true;
} else {
mwebScanningActive = false;
}
});
}
@ -430,7 +432,7 @@ abstract class DashboardViewModelBase with Store {
bool get hasMweb => wallet.type == WalletType.litecoin;
@computed
bool get showMwebCard => hasMweb && settingsStore.mwebCardDisplay;
bool get showMwebCard => hasMweb && settingsStore.mwebCardDisplay && !mwebScanningActive;
@observable
bool mwebScanningActive = false;
@ -439,18 +441,23 @@ abstract class DashboardViewModelBase with Store {
bool get hasEnabledMwebBefore => settingsStore.hasEnabledMwebBefore;
@action
void setMwebScanningActive(bool active) {
void setMwebScanningActive() {
if (!hasMweb) {
return;
}
if (active) {
settingsStore.hasEnabledMwebBefore = true;
}
settingsStore.hasEnabledMwebBefore = true;
mwebScanningActive = true;
bitcoin!.setMwebEnabled(wallet, true);
settingsStore.mwebAlwaysScan = true;
}
settingsStore.mwebEnabled = active;
mwebScanningActive = active;
bitcoin!.setMwebEnabled(wallet, active);
@action
void dismissMweb() {
settingsStore.mwebCardDisplay = false;
settingsStore.mwebAlwaysScan = false;
mwebScanningActive = false;
bitcoin!.setMwebEnabled(wallet, false);
}
BalanceViewModel balanceViewModel;

View file

@ -13,7 +13,7 @@ import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/monero/monero.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cake_wallet/core/generate_wallet_password.dart';
import 'package:cake_wallet/core/wallet_creation_service.dart';
import 'package:cw_core/wallet_credentials.dart';
@ -26,8 +26,12 @@ part 'restore_from_qr_vm.g.dart';
class WalletRestorationFromQRVM = WalletRestorationFromQRVMBase with _$WalletRestorationFromQRVM;
abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store {
WalletRestorationFromQRVMBase(AppStore appStore, WalletCreationService walletCreationService,
Box<WalletInfo> walletInfoSource, WalletType type, SeedSettingsViewModel seedSettingsViewModel)
WalletRestorationFromQRVMBase(
AppStore appStore,
WalletCreationService walletCreationService,
Box<WalletInfo> walletInfoSource,
WalletType type,
SeedSettingsViewModel seedSettingsViewModel)
: height = 0,
viewKey = '',
spendKey = '',
@ -53,13 +57,10 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store
bool get hasRestorationHeight => type == WalletType.monero || type == WalletType.wownero;
@override
WalletCredentials getCredentialsFromRestoredWallet(
dynamic options, RestoredWallet restoreWallet) {
Future<WalletCredentials> getWalletCredentialsFromQRCredentials(
RestoredWallet restoreWallet) async {
final password = generateWalletPassword();
DerivationInfo? derivationInfo;
derivationInfo ??= getDefaultCreateDerivation();
switch (restoreWallet.restoreMode) {
case WalletRestoreMode.keys:
switch (restoreWallet.type) {
@ -111,12 +112,13 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store
);
case WalletType.bitcoin:
case WalletType.litecoin:
final derivationInfo = (await getDerivationInfoFromQRCredentials(restoreWallet)).first;
return bitcoin!.createBitcoinRestoreWalletFromSeedCredentials(
name: name,
mnemonic: restoreWallet.mnemonicSeed ?? '',
password: password,
passphrase: restoreWallet.passphrase,
derivationType: derivationInfo!.derivationType!,
derivationType: derivationInfo.derivationType!,
derivationPath: derivationInfo.derivationPath!,
);
case WalletType.bitcoinCash:
@ -124,26 +126,46 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store
name: name,
mnemonic: restoreWallet.mnemonicSeed ?? '',
password: password,
passphrase: restoreWallet.passphrase,
);
case WalletType.ethereum:
return ethereum!.createEthereumRestoreWalletFromSeedCredentials(
name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password);
name: name,
mnemonic: restoreWallet.mnemonicSeed ?? '',
password: password,
passphrase: restoreWallet.passphrase,
);
case WalletType.nano:
final derivationInfo =
(await getDerivationInfoFromQRCredentials(restoreWallet)).first;
return nano!.createNanoRestoreWalletFromSeedCredentials(
name: name,
mnemonic: restoreWallet.mnemonicSeed ?? '',
password: password,
derivationType: derivationInfo!.derivationType!,
derivationType: derivationInfo.derivationType!,
passphrase: restoreWallet.passphrase,
);
case WalletType.polygon:
return polygon!.createPolygonRestoreWalletFromSeedCredentials(
name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password);
name: name,
mnemonic: restoreWallet.mnemonicSeed ?? '',
password: password,
passphrase: restoreWallet.passphrase,
);
case WalletType.solana:
return solana!.createSolanaRestoreWalletFromSeedCredentials(
name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password);
name: name,
mnemonic: restoreWallet.mnemonicSeed ?? '',
password: password,
passphrase: restoreWallet.passphrase,
);
case WalletType.tron:
return tron!.createTronRestoreWalletFromSeedCredentials(
name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password);
name: name,
mnemonic: restoreWallet.mnemonicSeed ?? '',
password: password,
passphrase: restoreWallet.passphrase,
);
case WalletType.wownero:
return wownero!.createWowneroRestoreWalletFromSeedCredentials(
name: name,
@ -160,8 +182,8 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store
}
@override
Future<WalletBase> processFromRestoredWallet(
WalletCredentials credentials, RestoredWallet restoreWallet) async {
Future<WalletBase> processFromRestoredWallet(WalletCredentials credentials,
RestoredWallet restoreWallet) async {
try {
switch (restoreWallet.restoreMode) {
case WalletRestoreMode.keys:

View file

@ -142,6 +142,10 @@ class WalletRestoreFromQRCode {
return WalletRestoreMode.seed;
}
if ((type == WalletType.monero || type == WalletType.wownero)) {
return WalletRestoreMode.seed;
}
seedValue.split(' ').forEach((element) {
if (!words.contains(element)) {
throw Exception(

View file

@ -326,13 +326,13 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
final isPrimary = subaddress == primaryAddress;
return WalletAddressListItem(
id: subaddress.id,
isPrimary: isPrimary,
name: subaddress.label,
address: subaddress.address,
balance: subaddress.received,
txCount: subaddress.txCount,
);
id: subaddress.id,
isPrimary: isPrimary,
name: subaddress.label,
address: subaddress.address,
balance: subaddress.received,
txCount: subaddress.txCount,
);
});
addressList.addAll(addressItems);
}
@ -418,8 +418,10 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
if (wallet.type == WalletType.litecoin && addressItems.length >= 1000) {
// find the index of the last item with a txCount > 0
final addressItemsList = addressItems.toList();
final lastItemWithTxCount = addressItemsList.lastWhere((item) => (item.txCount ?? 0) > 0);
final index = addressItemsList.indexOf(lastItemWithTxCount);
int index = addressItemsList.lastIndexWhere((item) => (item.txCount ?? 0) > 0);
if (index == -1) {
index = 0;
}
// show only up to that index + 20:
addressItems = addressItemsList.sublist(0, index + 20);
}
@ -461,14 +463,16 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
for (var i = 0; i < addressList.length; i++) {
if (!(addressList[i] is WalletAddressListItem)) continue;
(addressList[i] as WalletAddressListItem).isHidden = wallet.walletAddresses.hiddenAddresses.contains((addressList[i] as WalletAddressListItem).address);
(addressList[i] as WalletAddressListItem).isHidden = wallet.walletAddresses.hiddenAddresses
.contains((addressList[i] as WalletAddressListItem).address);
}
for (var i = 0; i < addressList.length; i++) {
if (!(addressList[i] is WalletAddressListItem)) continue;
(addressList[i] as WalletAddressListItem).isManual = wallet.walletAddresses.manualAddresses.contains((addressList[i] as WalletAddressListItem).address);
(addressList[i] as WalletAddressListItem).isManual = wallet.walletAddresses.manualAddresses
.contains((addressList[i] as WalletAddressListItem).address);
}
if (searchText.isNotEmpty) {
return ObservableList.of(addressList.where((item) {
if (item is WalletAddressListItem) {
@ -480,6 +484,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
return addressList;
}
Future<void> toggleHideAddress(WalletAddressListItem item) async {
if (item.isHidden) {
wallet.walletAddresses.hiddenAddresses.removeWhere((element) => element == item.address);
@ -488,13 +493,20 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
}
await wallet.walletAddresses.saveAddressesInBox();
if (wallet.type == WalletType.monero) {
monero!.getSubaddressList(wallet).update(wallet, accountIndex: monero!.getCurrentAccount(wallet).id);
monero!
.getSubaddressList(wallet)
.update(wallet, accountIndex: monero!.getCurrentAccount(wallet).id);
} else if (wallet.type == WalletType.wownero) {
wownero!.getSubaddressList(wallet).update(wallet, accountIndex: wownero!.getCurrentAccount(wallet).id);
wownero!
.getSubaddressList(wallet)
.update(wallet, accountIndex: wownero!.getCurrentAccount(wallet).id);
} else if (wallet.type == WalletType.haven) {
haven!.getSubaddressList(wallet).update(wallet, accountIndex: haven!.getCurrentAccount(wallet).id);
haven!
.getSubaddressList(wallet)
.update(wallet, accountIndex: haven!.getCurrentAccount(wallet).id);
}
}
@observable
bool hasAccounts;
@ -535,8 +547,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
@computed
bool get isReceivedAvailable =>
wallet.type == WalletType.monero ||
wallet.type == WalletType.wownero;
wallet.type == WalletType.monero || wallet.type == WalletType.wownero;
@computed
bool get isSilentPayments =>
@ -549,9 +560,9 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
@computed
bool get showAddManualAddresses =>
!isAutoGenerateSubaddressEnabled ||
wallet.type == WalletType.monero ||
wallet.type == WalletType.wownero;
!isAutoGenerateSubaddressEnabled ||
wallet.type == WalletType.monero ||
wallet.type == WalletType.wownero;
List<ListItem> _baseItems;

View file

@ -85,21 +85,9 @@ abstract class WalletCreationVMBase with Store {
final dirPath = await pathForWalletDir(name: name, type: type);
final path = await pathForWallet(name: name, type: type);
WalletCredentials credentials;
if (restoreWallet != null) {
if (restoreWallet.restoreMode == WalletRestoreMode.seed &&
options == null &&
(type == WalletType.nano ||
type == WalletType.bitcoin ||
type == WalletType.litecoin)) {
final derivationInfo = await getDerivationInfo(restoreWallet);
options ??= {};
options["derivationInfo"] = derivationInfo.first;
}
credentials = getCredentialsFromRestoredWallet(options, restoreWallet);
} else {
credentials = getCredentials(options);
}
final credentials = restoreWallet != null
? await getWalletCredentialsFromQRCredentials(restoreWallet)
: getCredentials(options);
final walletInfo = WalletInfo.external(
id: WalletBase.idFor(name, type),
@ -200,36 +188,36 @@ abstract class WalletCreationVMBase with Store {
}
}
Future<List<DerivationInfo>> getDerivationInfo(RestoredWallet restoreWallet) async {
var list = <DerivationInfo>[];
final walletType = restoreWallet.type;
var appStore = getIt.get<AppStore>();
var node = appStore.settingsStore.getCurrentNode(walletType);
Future<List<DerivationInfo>> getDerivationInfoFromQRCredentials(RestoredWallet restoreWallet) async {
var list = <DerivationInfo>[];
final walletType = restoreWallet.type;
var appStore = getIt.get<AppStore>();
var node = appStore.settingsStore.getCurrentNode(walletType);
switch (walletType) {
case WalletType.bitcoin:
case WalletType.litecoin:
return bitcoin!.getDerivationsFromMnemonic(
mnemonic: restoreWallet.mnemonicSeed!,
node: node,
);
case WalletType.nano:
return nanoUtil!.getDerivationsFromMnemonic(
mnemonic: restoreWallet.mnemonicSeed!,
node: node,
);
default:
break;
switch (walletType) {
case WalletType.bitcoin:
case WalletType.litecoin:
return bitcoin!.getDerivationsFromMnemonic(
mnemonic: restoreWallet.mnemonicSeed!,
node: node,
passphrase: restoreWallet.passphrase,
);
case WalletType.nano:
return nanoUtil!.getDerivationsFromMnemonic(
mnemonic: restoreWallet.mnemonicSeed!,
node: node,
);
default:
break;
}
return list;
}
return list;
}
WalletCredentials getCredentials(dynamic options) => throw UnimplementedError();
Future<WalletBase> process(WalletCredentials credentials) => throw UnimplementedError();
WalletCredentials getCredentialsFromRestoredWallet(
dynamic options, RestoredWallet restoreWallet) =>
Future<WalletCredentials> getWalletCredentialsFromQRCredentials(RestoredWallet restoreWallet) async =>
throw UnimplementedError();
Future<WalletBase> processFromRestoredWallet(

View file

@ -106,6 +106,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
password: walletPassword,
mnemonic: newWalletArguments!.mnemonic,
parentAddress: newWalletArguments!.parentAddress,
passphrase: passphrase,
);
case WalletType.bitcoinCash:
return bitcoinCash!.createBitcoinCashNewWalletCredentials(
@ -122,6 +123,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
password: walletPassword,
mnemonic: newWalletArguments!.mnemonic,
parentAddress: newWalletArguments!.parentAddress,
passphrase: passphrase,
);
case WalletType.polygon:
return polygon!.createPolygonNewWalletCredentials(
@ -129,6 +131,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
password: walletPassword,
mnemonic: newWalletArguments!.mnemonic,
parentAddress: newWalletArguments!.parentAddress,
passphrase: passphrase,
);
case WalletType.solana:
return solana!.createSolanaNewWalletCredentials(
@ -136,6 +139,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
password: walletPassword,
mnemonic: newWalletArguments!.mnemonic,
parentAddress: newWalletArguments!.parentAddress,
passphrase: passphrase,
);
case WalletType.tron:
return tron!.createTronNewWalletCredentials(
@ -143,6 +147,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
password: walletPassword,
mnemonic: newWalletArguments!.mnemonic,
parentAddress: newWalletArguments!.parentAddress,
passphrase: passphrase,
);
case WalletType.wownero:
return wownero!.createWowneroNewWalletCredentials(

View file

@ -78,9 +78,6 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
final bool hasBlockchainHeightLanguageSelector;
final bool hasRestoreFromPrivateKey;
bool get hasPassphrase =>
[WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(type);
@observable
WalletRestoreMode mode;
@ -116,10 +113,18 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
name: name, height: height, mnemonic: seed, password: password);
case WalletType.ethereum:
return ethereum!.createEthereumRestoreWalletFromSeedCredentials(
name: name, mnemonic: seed, password: password);
name: name,
mnemonic: seed,
password: password,
passphrase: passphrase,
);
case WalletType.bitcoinCash:
return bitcoinCash!.createBitcoinCashRestoreWalletFromSeedCredentials(
name: name, mnemonic: seed, password: password);
name: name,
mnemonic: seed,
password: password,
passphrase: passphrase,
);
case WalletType.nano:
case WalletType.banano:
return nano!.createNanoRestoreWalletFromSeedCredentials(
@ -127,24 +132,28 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
mnemonic: seed,
password: password,
derivationType: derivationInfo!.derivationType!,
passphrase: passphrase,
);
case WalletType.polygon:
return polygon!.createPolygonRestoreWalletFromSeedCredentials(
name: name,
mnemonic: seed,
password: password,
passphrase: passphrase,
);
case WalletType.solana:
return solana!.createSolanaRestoreWalletFromSeedCredentials(
name: name,
mnemonic: seed,
password: password,
passphrase: passphrase,
);
case WalletType.tron:
return tron!.createTronRestoreWalletFromSeedCredentials(
name: name,
mnemonic: seed,
password: password,
passphrase: passphrase,
);
case WalletType.wownero:
return wownero!.createWowneroRestoreWalletFromSeedCredentials(

View file

@ -36,6 +36,7 @@
"agree": "موافق",
"agree_and_continue": "الموافقة ومتابعة",
"agree_to": "من خلال إنشاء حساب فإنك توافق على",
"alert_notice": "يلاحظ",
"all": "الكل",
"all_trades": "جميع عمليات التداول",
"all_transactions": "كل التحركات المالية",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "تمكين MWEB المسح الضوئي",
"litecoin_mweb": "mweb",
"litecoin_mweb_always_scan": "اضبط MWEB دائمًا على المسح الضوئي",
"litecoin_mweb_description": "MWEB هو بروتوكول جديد يجلب معاملات أسرع وأرخص وأكثر خصوصية إلى Litecoin",
"litecoin_mweb_dismiss": "رفض",
"litecoin_mweb_display_card": "عرض بطاقة mweb",
"litecoin_mweb_enable_later": "يمكنك اختيار تمكين MWEB مرة أخرى ضمن إعدادات العرض.",
"litecoin_mweb_pegin": "ربط في",
"litecoin_mweb_pegout": "ربط",
"litecoin_mweb_scanning": "MWEB المسح الضوئي",
"litecoin_mweb_settings": "إعدادات MWEB",
"litecoin_mweb_warning": "سيقوم استخدام MWEB في البداية بتنزيل ~ 600 ميجابايت من البيانات ، وقد يستغرق ما يصل إلى 30 دقيقة حسب سرعة الشبكة. سيتم تنزيل هذه البيانات الأولية مرة واحدة فقط وستكون متاحة لجميع محافظ Litecoin",

View file

@ -36,6 +36,7 @@
"agree": "Съгласен/а съм",
"agree_and_continue": "Съгласяване и продължаване",
"agree_to": "Чрез създаването на акаунт вие се съгласявате с ",
"alert_notice": "Забележете",
"all": "ALL",
"all_trades": "Всички сделкки",
"all_transactions": "Всички транзакции",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "Активирайте сканирането на MWeb",
"litecoin_mweb": "Mweb",
"litecoin_mweb_always_scan": "Задайте MWeb винаги сканиране",
"litecoin_mweb_description": "MWeb е нов протокол, който носи по -бърз, по -евтин и повече частни транзакции на Litecoin",
"litecoin_mweb_dismiss": "Уволнение",
"litecoin_mweb_display_card": "Показване на MWEB карта",
"litecoin_mweb_enable_later": "Можете да изберете да активирате MWEB отново под настройките на дисплея.",
"litecoin_mweb_pegin": "PEG в",
"litecoin_mweb_pegout": "PEG OUT",
"litecoin_mweb_scanning": "Сканиране на MWEB",
"litecoin_mweb_settings": "Настройки на MWEB",
"litecoin_mweb_warning": "Използването на MWEB първоначално ще изтегли ~ 600MB данни и може да отнеме до 30 минути в зависимост от скоростта на мрежата. Тези първоначални данни ще изтеглят само веднъж и ще бъдат достъпни за всички портфейли Litecoin",

View file

@ -36,6 +36,7 @@
"agree": "Souhlasím",
"agree_and_continue": "Souhlasím & pokračovat",
"agree_to": "Vytvořením účtu souhlasíte s ",
"alert_notice": "Oznámení",
"all": "VŠE",
"all_trades": "Všechny obchody",
"all_transactions": "Všechny transakce",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "Povolit skenování MWeb",
"litecoin_mweb": "MWeb",
"litecoin_mweb_always_scan": "Nastavit MWeb vždy skenování",
"litecoin_mweb_description": "MWEB je nový protokol, který do Litecoin přináší rychlejší, levnější a více soukromých transakcí",
"litecoin_mweb_dismiss": "Propustit",
"litecoin_mweb_display_card": "Zobrazit kartu MWeb",
"litecoin_mweb_enable_later": "V nastavení zobrazení můžete vybrat znovu povolit MWeb.",
"litecoin_mweb_pegin": "Peg in",
"litecoin_mweb_pegout": "Zkrachovat",
"litecoin_mweb_scanning": "Skenování mWeb",
"litecoin_mweb_settings": "Nastavení mWeb",
"litecoin_mweb_warning": "Pomocí MWeb zpočátku stahuje ~ 600 MB dat a může trvat až 30 minut v závislosti na rychlosti sítě. Tato počáteční data si stáhnou pouze jednou a budou k dispozici pro všechny litecoinové peněženky",

View file

@ -36,6 +36,7 @@
"agree": "stimme zu",
"agree_and_continue": "Zustimmen & fortfahren",
"agree_to": "Indem Sie ein Konto erstellen, stimmen Sie den ",
"alert_notice": "Beachten",
"all": "ALLES",
"all_trades": "Alle Trades",
"all_transactions": "Alle Transaktionen",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "Aktivieren Sie das MWEB -Scannen",
"litecoin_mweb": "MWeb",
"litecoin_mweb_always_scan": "Setzen Sie MWeb immer scannen",
"litecoin_mweb_description": "MWEB ist ein neues Protokoll, das schnellere, billigere und privatere Transaktionen zu Litecoin bringt",
"litecoin_mweb_dismiss": "Zurückweisen",
"litecoin_mweb_display_card": "MWEB -Karte anzeigen",
"litecoin_mweb_enable_later": "Sie können MWEB unter Anzeigeeinstellungen erneut aktivieren.",
"litecoin_mweb_pegin": "Peg in",
"litecoin_mweb_pegout": "Abstecken",
"litecoin_mweb_scanning": "MWEB Scanning",
"litecoin_mweb_settings": "MWEB -Einstellungen",
"litecoin_mweb_warning": "Durch die Verwendung von MWEB wird zunächst ~ 600 MB Daten heruntergeladen und kann je nach Netzwerkgeschwindigkeit bis zu 30 Minuten dauern. Diese ersten Daten werden nur einmal heruntergeladen und für alle Litecoin -Brieftaschen verfügbar",

View file

@ -36,6 +36,7 @@
"agree": "Agree",
"agree_and_continue": "Agree & Continue",
"agree_to": "By creating account you agree to the ",
"alert_notice": "Notice",
"all": "ALL",
"all_trades": "All trades",
"all_transactions": "All transactions",
@ -147,7 +148,7 @@
"confirm_fee_deduction_content": "Do you agree to deduct the fee from the output?",
"confirm_passphrase": "Confirm passphrase",
"confirm_sending": "Confirm sending",
"confirm_silent_payments_switch_node": "Your current node does not support silent payments\\nCake Wallet will switch to a compatible node, just for scanning",
"confirm_silent_payments_switch_node": "Your current node does not support Silent Payments.\\n\\nCake Wallet will switch to a compatible node while scanning.",
"confirmations": "Confirmations",
"confirmed": "Confirmed Balance",
"confirmed_tx": "Confirmed",
@ -239,7 +240,7 @@
"email_address": "Email Address",
"enable_mempool_api": "Mempool API for accurate fees and dates",
"enable_replace_by_fee": "Enable Replace-By-Fee",
"enable_silent_payments_scanning": "Start scanning silent payments, until the tip is reached",
"enable_silent_payments_scanning": "Start scanning for transactions sent to your Silent Payment address.",
"enabled": "Enabled",
"enter_amount": "Enter Amount",
"enter_backup_password": "Enter backup password here",
@ -336,9 +337,9 @@
"haven_app": "Haven by Cake Wallet",
"haven_app_wallet_text": "Awesome wallet for Haven",
"help": "help",
"hide": "Hide",
"hidden_addresses": "Hidden Addresses",
"hidden_balance": "Hidden Balance",
"hide": "Hide",
"hide_details": "Hide Details",
"high_contrast_theme": "High Contrast Theme",
"home_screen_settings": "Home screen settings",
@ -371,7 +372,12 @@
"litecoin_enable_mweb_sync": "Enable MWEB scanning",
"litecoin_mweb": "MWEB",
"litecoin_mweb_always_scan": "Set MWEB always scanning",
"litecoin_mweb_description": "MWEB is a new protocol that brings faster, cheaper, and more private transactions to Litecoin",
"litecoin_mweb_dismiss": "Dismiss",
"litecoin_mweb_display_card": "Show MWEB card",
"litecoin_mweb_enable_later": "You can choose to enable MWEB again under Display Settings.",
"litecoin_mweb_pegin": "Peg In",
"litecoin_mweb_pegout": "Peg Out",
"litecoin_mweb_scanning": "MWEB Scanning",
"litecoin_mweb_settings": "MWEB settings",
"litecoin_mweb_warning": "Using MWEB will initially download ~600MB of data, and may take up to 30 minutes depending on network speed. This initial data will only download once and be available for all Litecoin wallets",
@ -688,8 +694,8 @@
"setup_your_debit_card": "Set up your debit card",
"share": "Share",
"share_address": "Share address",
"show": "Show",
"shared_seed_wallet_groups": "Shared Seed Wallet Groups",
"show": "Show",
"show_details": "Show Details",
"show_keys": "Show seed/keys",
"show_market_place": "Show Marketplace",
@ -709,7 +715,7 @@
"silent_payments_disclaimer": "New addresses are not new identities. It is a re-use of an existing identity with a different label.",
"silent_payments_display_card": "Show Silent Payments card",
"silent_payments_scan_from_date": "Scan from date",
"silent_payments_scan_from_date_or_blockheight": "Please enter the block height you want to start scanning for incoming silent payments, or, use the date instead. You can choose if the wallet continues scanning every block, or checks only the specified height.",
"silent_payments_scan_from_date_or_blockheight": "Please enter the block height you want to start scanning for incoming Silent Payments or use the date instead. You can choose if the wallet continues scanning every block, or checks only the specified height.",
"silent_payments_scan_from_height": "Scan from block height",
"silent_payments_scanned_tip": "SCANNED TO TIP! (${tip})",
"silent_payments_scanning": "Silent Payments Scanning",
@ -908,7 +914,7 @@
"warning": "Warning",
"welcome": "Welcome to",
"welcome_to_cakepay": "Welcome to Cake Pay!",
"what_is_silent_payments": "What is silent payments?",
"what_is_silent_payments": "What are Silent Payments?",
"widgets_address": "Address",
"widgets_or": "or",
"widgets_restore_from_blockheight": "Restore from blockheight",
@ -937,4 +943,4 @@
"you_will_get": "Convert to",
"you_will_send": "Convert from",
"yy": "YY"
}
}

View file

@ -36,6 +36,7 @@
"agree": "De acuerdo",
"agree_and_continue": "Aceptar y continuar",
"agree_to": "Al crear una cuenta, aceptas ",
"alert_notice": "Aviso",
"all": "TODOS",
"all_trades": "Todos los oficios",
"all_transactions": "Todas las transacciones",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "Habilitar el escaneo mweb",
"litecoin_mweb": "Mweb",
"litecoin_mweb_always_scan": "Establecer mweb siempre escaneo",
"litecoin_mweb_description": "Mweb es un nuevo protocolo que trae transacciones más rápidas, más baratas y más privadas a Litecoin",
"litecoin_mweb_dismiss": "Despedir",
"litecoin_mweb_display_card": "Mostrar tarjeta MWEB",
"litecoin_mweb_enable_later": "Puede elegir habilitar MWEB nuevamente en la configuración de visualización.",
"litecoin_mweb_pegin": "Meter",
"litecoin_mweb_pegout": "Estirar la pata",
"litecoin_mweb_scanning": "Escaneo mweb",
"litecoin_mweb_settings": "Configuración de MWEB",
"litecoin_mweb_warning": "El uso de MWEB inicialmente descargará ~ 600 MB de datos, y puede tomar hasta 30 minutos según la velocidad de la red. Estos datos iniciales solo se descargarán una vez y estarán disponibles para todas las billeteras de Litecoin",

View file

@ -36,6 +36,7 @@
"agree": "d'accord",
"agree_and_continue": "Accepter et continuer",
"agree_to": "En créant un compte, vous acceptez les ",
"alert_notice": "Avis",
"all": "TOUT",
"all_trades": "Tous échanges",
"all_transactions": "Toutes transactions",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "Activer la numérisation MWEB",
"litecoin_mweb": "Mweb",
"litecoin_mweb_always_scan": "Définir MWEB Score Scanning",
"litecoin_mweb_description": "MWEB est un nouveau protocole qui apporte des transactions plus rapides, moins chères et plus privées à Litecoin",
"litecoin_mweb_dismiss": "Rejeter",
"litecoin_mweb_display_card": "Afficher la carte MWeb",
"litecoin_mweb_enable_later": "Vous pouvez choisir d'activer à nouveau MWEB sous Paramètres d'affichage.",
"litecoin_mweb_pegin": "Entraver",
"litecoin_mweb_pegout": "Crever",
"litecoin_mweb_scanning": "Scann mweb",
"litecoin_mweb_settings": "Paramètres MWEB",
"litecoin_mweb_warning": "L'utilisation de MWEB téléchargera initialement ~ 600 Mo de données et peut prendre jusqu'à 30 minutes en fonction de la vitesse du réseau. Ces données initiales ne téléchargeront qu'une seule fois et seront disponibles pour tous les portefeuilles litecoin",

View file

@ -36,6 +36,7 @@
"agree": "Yarda",
"agree_and_continue": "Amincewa & Ci gaba",
"agree_to": "Ta hanyar ƙirƙirar asusu kun yarda da",
"alert_notice": "Sanarwa",
"all": "DUK",
"all_trades": "Duk ciniki",
"all_transactions": "Dukan Ma'amaloli",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "Kunna binciken Mweb",
"litecoin_mweb": "Mweb",
"litecoin_mweb_always_scan": "Saita Mweb koyaushe",
"litecoin_mweb_description": "Mweb shine sabon tsarin yarjejeniya da ya kawo da sauri, mai rahusa, da kuma ma'amaloli masu zaman kansu zuwa Litecoin",
"litecoin_mweb_dismiss": "Tuɓe \\ sallama",
"litecoin_mweb_display_card": "Nuna katin Mweb",
"litecoin_mweb_enable_later": "Kuna iya zaɓar kunna Mweb kuma a ƙarƙashin saitunan nuni.",
"litecoin_mweb_pegin": "Peg in",
"litecoin_mweb_pegout": "Peg fita",
"litecoin_mweb_scanning": "Mweb scanning",
"litecoin_mweb_settings": "Saitunan Mweb",
"litecoin_mweb_warning": "Amfani da Mweb zai fara saukewa ~ 600MB na bayanai, kuma yana iya ɗaukar minti 30 dangane da saurin cibiyar sadarwa. Wannan bayanan farko zai saika saukarwa sau ɗaya kawai kuma a samu don duk wuraren shakatawa",

View file

@ -36,6 +36,7 @@
"agree": "सहमत",
"agree_and_continue": "सहमत और जारी रखें",
"agree_to": "खाता बनाकर आप इससे सहमत होते हैं ",
"alert_notice": "सूचना",
"all": "सब",
"all_trades": "सभी व्यापार",
"all_transactions": "सभी लेन - देन",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "MWEB स्कैनिंग सक्षम करें",
"litecoin_mweb": "मावली",
"litecoin_mweb_always_scan": "MWEB हमेशा स्कैनिंग सेट करें",
"litecoin_mweb_description": "MWEB एक नया प्रोटोकॉल है जो लिटकोइन के लिए तेजी से, सस्ता और अधिक निजी लेनदेन लाता है",
"litecoin_mweb_dismiss": "नकार देना",
"litecoin_mweb_display_card": "MWEB कार्ड दिखाएं",
"litecoin_mweb_enable_later": "आप प्रदर्शन सेटिंग्स के तहत फिर से MWEB को सक्षम करने के लिए चुन सकते हैं।",
"litecoin_mweb_pegin": "खूंटी",
"litecoin_mweb_pegout": "मरना",
"litecoin_mweb_scanning": "MWEB स्कैनिंग",
"litecoin_mweb_settings": "MWEB सेटिंग्स",
"litecoin_mweb_warning": "MWEB का उपयोग शुरू में ~ 600MB डेटा डाउनलोड करेगा, और नेटवर्क की गति के आधार पर 30 मिनट तक का समय लग सकता है। यह प्रारंभिक डेटा केवल एक बार डाउनलोड करेगा और सभी लिटकोइन वॉलेट के लिए उपलब्ध होगा",

View file

@ -36,6 +36,7 @@
"agree": "Slažem se",
"agree_and_continue": "Slažem se i nastavi",
"agree_to": "Stvaranjem računa pristajete na ",
"alert_notice": "Obavijest",
"all": "SVE",
"all_trades": "Svi obrti",
"all_transactions": "Sve transakcije",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "Omogućite MWEB skeniranje",
"litecoin_mweb": "MWeb",
"litecoin_mweb_always_scan": "Postavite MWeb uvijek skeniranje",
"litecoin_mweb_description": "MWEB je novi protokol koji u Litecoin donosi brže, jeftinije i privatnije transakcije",
"litecoin_mweb_dismiss": "Odbaciti",
"litecoin_mweb_display_card": "Prikaži MWeb karticu",
"litecoin_mweb_enable_later": "Možete odabrati da MWEB ponovo omogućite pod postavkama zaslona.",
"litecoin_mweb_pegin": "Uvući se",
"litecoin_mweb_pegout": "Odapeti",
"litecoin_mweb_scanning": "MWEB skeniranje",
"litecoin_mweb_settings": "Postavke MWEB -a",
"litecoin_mweb_warning": "Korištenje MWEB -a u početku će preuzeti ~ 600MB podataka, a može potrajati do 30 minuta, ovisno o brzini mreže. Ovi početni podaci preuzet će samo jednom i biti dostupni za sve Litecoin novčanike",

View file

@ -36,6 +36,7 @@
"agree": "Համաձայն եմ",
"agree_and_continue": "Համաձայն եմ և շարունակեմ",
"agree_to": "Ստեղծելով հաշիվ դուք համաձայնում եք ",
"alert_notice": "Ծանուցում",
"all": "Բոլորը",
"all_trades": "Բոլոր գործարքները",
"all_transactions": "Բոլոր գործառնությունները",
@ -366,6 +367,11 @@
"ledger_error_wrong_app": "Խնդրում ենք համոզվել, որ դուք բացել եք ճիշտ ծրագիրը ձեր Ledger-ում",
"ledger_please_enable_bluetooth": "Խնդրում ենք միացնել Bluetooth-ը ձեր Ledger-ը հայտնաբերելու համար",
"light_theme": "Լուսավոր",
"litecoin_mweb_description": "Mweb- ը նոր արձանագրություն է, որը բերում է ավելի արագ, ավելի էժան եւ ավելի մասնավոր գործարքներ դեպի LITECOIN",
"litecoin_mweb_dismiss": "Հեռացնել",
"litecoin_mweb_enable_later": "Կարող եք ընտրել Mweb- ը կրկին միացնել ցուցադրման պարամետրերը:",
"litecoin_mweb_pegin": "Peg in",
"litecoin_mweb_pegout": "Հափշտակել",
"live_fee_rates": "Ապակի վարձավճարներ API- ի միջոցով",
"load_more": "Բեռնել ավելին",
"loading_your_wallet": "Ձեր հաշվեհամարը բեռնում է",

View file

@ -36,6 +36,7 @@
"agree": "Setuju",
"agree_and_continue": "Setuju & Lanjutkan",
"agree_to": "Dengan membuat akun Anda setuju dengan ",
"alert_notice": "Melihat",
"all": "SEMUA",
"all_trades": "Semua perdagangan",
"all_transactions": "Semua transaksi",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "Aktifkan pemindaian MWEB",
"litecoin_mweb": "Mweb",
"litecoin_mweb_always_scan": "Atur mWeb selalu memindai",
"litecoin_mweb_description": "MWEB adalah protokol baru yang membawa transaksi yang lebih cepat, lebih murah, dan lebih pribadi ke Litecoin",
"litecoin_mweb_dismiss": "Membubarkan",
"litecoin_mweb_display_card": "Tunjukkan kartu mWeb",
"litecoin_mweb_enable_later": "Anda dapat memilih untuk mengaktifkan MWEB lagi di bawah pengaturan tampilan.",
"litecoin_mweb_pegin": "Pasak masuk",
"litecoin_mweb_pegout": "Mati",
"litecoin_mweb_scanning": "Pemindaian MWEB",
"litecoin_mweb_settings": "Pengaturan MWEB",
"litecoin_mweb_warning": "Menggunakan MWEB pada awalnya akan mengunduh ~ 600MB data, dan dapat memakan waktu hingga 30 menit tergantung pada kecepatan jaringan. Data awal ini hanya akan mengunduh sekali dan tersedia untuk semua dompet litecoin",

View file

@ -36,6 +36,7 @@
"agree": "d'accordo",
"agree_and_continue": "Accetta e continua",
"agree_to": "Creando un account accetti il ",
"alert_notice": "Avviso",
"all": "TUTTO",
"all_trades": "Svi obrti",
"all_transactions": "Sve transakcije",
@ -370,7 +371,12 @@
"litecoin_enable_mweb_sync": "Abilita la scansione MWeb",
"litecoin_mweb": "MWeb",
"litecoin_mweb_always_scan": "Imposta MWeb per scansionare sempre",
"litecoin_mweb_description": "MWeb è un nuovo protocollo che porta transazioni più veloci, più economiche e più private a Litecoin",
"litecoin_mweb_dismiss": "Congedare",
"litecoin_mweb_display_card": "Mostra la scheda MWeb",
"litecoin_mweb_enable_later": "È possibile scegliere di abilitare nuovamente MWeb nelle impostazioni di visualizzazione.",
"litecoin_mweb_pegin": "Piolo in",
"litecoin_mweb_pegout": "PEG OUT",
"litecoin_mweb_scanning": "Scansione MWeb",
"litecoin_mweb_settings": "Impostazioni MWeb",
"litecoin_mweb_warning": "L'uso di MWeb inizialmente scaricherà ~ 600 MB di dati e potrebbe richiedere fino a 30 minuti a seconda della velocità di rete. Questi dati iniziali scaricheranno solo una volta e saranno disponibili per tutti i portafogli Litecoin",

View file

@ -36,6 +36,7 @@
"agree": "同意する",
"agree_and_continue": "同意して続行",
"agree_to": "アカウントを作成することにより、",
"alert_notice": "知らせ",
"all": "すべて",
"all_trades": "すべての取引",
"all_transactions": "全取引",
@ -370,7 +371,12 @@
"litecoin_enable_mweb_sync": "MWEBスキャンを有効にします",
"litecoin_mweb": "mweb",
"litecoin_mweb_always_scan": "MWEBを常にスキャンします",
"litecoin_mweb_description": "MWEBは、Litecoinにより速く、より安価で、よりプライベートなトランザクションをもたらす新しいプロトコルです",
"litecoin_mweb_dismiss": "却下する",
"litecoin_mweb_display_card": "MWEBカードを表示します",
"litecoin_mweb_enable_later": "表示設定の下で、MWEBを再度有効にすることを選択できます。",
"litecoin_mweb_pegin": "ペグイン",
"litecoin_mweb_pegout": "ペグアウト",
"litecoin_mweb_scanning": "MWEBスキャン",
"litecoin_mweb_settings": "MWEB設定",
"litecoin_mweb_warning": "MWEBを使用すると、最初は〜600MBのデータをダウンロードし、ネットワーク速度に応じて最大30分かかる場合があります。この最初のデータは一度だけダウンロードされ、すべてのLitecoinウォレットで利用可能になります",

View file

@ -36,6 +36,7 @@
"agree": "동의하다",
"agree_and_continue": "동의 및 계속",
"agree_to": "계정을 생성하면 ",
"alert_notice": "알아채다",
"all": "모든",
"all_trades": "A모든 거래",
"all_transactions": "모든 거래 창구",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "mweb 스캔을 활성화합니다",
"litecoin_mweb": "mweb",
"litecoin_mweb_always_scan": "mweb는 항상 스캔을 설정합니다",
"litecoin_mweb_description": "MWEB는 Litecoin에 더 빠르고 저렴하며 개인 거래를 제공하는 새로운 프로토콜입니다.",
"litecoin_mweb_dismiss": "해고하다",
"litecoin_mweb_display_card": "mweb 카드를 보여주십시오",
"litecoin_mweb_enable_later": "디스플레이 설정에서 MWEB를 다시 활성화하도록 선택할 수 있습니다.",
"litecoin_mweb_pegin": "페그를 입력하십시오",
"litecoin_mweb_pegout": "죽다",
"litecoin_mweb_scanning": "mweb 스캔",
"litecoin_mweb_settings": "mweb 설정",
"litecoin_mweb_warning": "MWEB를 사용하면 처음에는 ~ 600MB의 데이터를 다운로드하며 네트워크 속도에 따라 최대 30 분이 소요될 수 있습니다. 이 초기 데이터는 한 번만 다운로드하여 모든 조명 지갑에 사용할 수 있습니다.",

View file

@ -36,6 +36,7 @@
"agree": "သဘောတူသည်။",
"agree_and_continue": "သဘောတူပြီး ရှေ့ဆက်ပါ။",
"agree_to": "အကောင့်ဖန်တီးခြင်းဖြင့် သင်သည် ဤအရာကို သဘောတူပါသည်။",
"alert_notice": "မှတ်သား",
"all": "အားလုံး",
"all_trades": "ကုန်သွယ်မှုအားလုံး",
"all_transactions": "အရောင်းအဝယ်အားလုံး",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "mweb scanning ဖွင့်ပါ",
"litecoin_mweb": "မင်္ဂလာပါ",
"litecoin_mweb_always_scan": "Mweb အမြဲစကင်ဖတ်စစ်ဆေးပါ",
"litecoin_mweb_description": "Mweb သည် Protocol အသစ်ဖြစ်ပြီး LitCoin သို့ပိုမိုဈေးချိုသာသော, စျေးသက်သက်သာသာသုံးခြင်းနှင့်ပိုမိုများပြားသောပုဂ္ဂလိကငွေပို့ဆောင်မှုများကိုဖြစ်ပေါ်စေသည်",
"litecoin_mweb_dismiss": "ထုတ်ပစ်",
"litecoin_mweb_display_card": "MweB ကဒ်ကိုပြပါ",
"litecoin_mweb_enable_later": "သင် MweB ကို display settings အောက်ရှိ ထပ်မံ. ခွင့်ပြုရန်ရွေးချယ်နိုင်သည်။",
"litecoin_mweb_pegin": "တံစို့",
"litecoin_mweb_pegout": "တံစို့",
"litecoin_mweb_scanning": "mweb scanning",
"litecoin_mweb_settings": "Mweb ဆက်တင်များ",
"litecoin_mweb_warning": "MweB ကိုအသုံးပြုခြင်းသည်အစပိုင်းတွင် ~ 600MB ဒေတာများကို download လုပ်ပြီးကွန်ယက်အမြန်နှုန်းပေါ် မူတည်. မိနစ် 30 အထိကြာနိုင်သည်။ ဤကန ဦး ဒေတာကိုတစ်ကြိမ်သာ download လုပ်ပြီး litecoin Walkets အားလုံးအတွက်ရနိုင်သည်",

View file

@ -36,6 +36,7 @@
"agree": "mee eens",
"agree_and_continue": "Akkoord & doorgaan",
"agree_to": "Door een account aan te maken gaat u akkoord met de ",
"alert_notice": "Kennisgeving",
"all": "ALLE",
"all_trades": "Alle transacties",
"all_transactions": "Alle transacties",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "MWEB -scanning inschakelen",
"litecoin_mweb": "Mweb",
"litecoin_mweb_always_scan": "Stel mweb altijd op scannen",
"litecoin_mweb_description": "MWEB is een nieuw protocol dat snellere, goedkopere en meer privé -transacties naar Litecoin brengt",
"litecoin_mweb_dismiss": "Afwijzen",
"litecoin_mweb_display_card": "Toon MWEB -kaart",
"litecoin_mweb_enable_later": "U kunt ervoor kiezen om MWeb opnieuw in te schakelen onder weergave -instellingen.",
"litecoin_mweb_pegin": "Vastmaken",
"litecoin_mweb_pegout": "Uithakken",
"litecoin_mweb_scanning": "MWEB -scanning",
"litecoin_mweb_settings": "MWEB -instellingen",
"litecoin_mweb_warning": "Het gebruik van MWeb downloadt in eerste instantie ~ 600 MB aan gegevens en kan tot 30 minuten duren, afhankelijk van de netwerksnelheid. Deze eerste gegevens worden slechts eenmaal gedownload en zijn beschikbaar voor alle Litecoin -portefeuilles",

View file

@ -36,6 +36,7 @@
"agree": "Zgadzam się",
"agree_and_continue": "Zgadzam się i kontynuuj",
"agree_to": "Tworząc konto wyrażasz zgodę na ",
"alert_notice": "Ogłoszenie",
"all": "WSZYSTKO",
"all_trades": "Wszystkie operacje",
"all_transactions": "Wszystkie transakcje",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "Włącz skanowanie MWEB",
"litecoin_mweb": "MWEB",
"litecoin_mweb_always_scan": "Ustaw MWEB zawsze skanowanie",
"litecoin_mweb_description": "MWEB to nowy protokół, który przynosi szybciej, tańsze i bardziej prywatne transakcje do Litecoin",
"litecoin_mweb_dismiss": "Odrzucać",
"litecoin_mweb_display_card": "Pokaż kartę MWEB",
"litecoin_mweb_enable_later": "Możesz ponownie włączyć MWEB w ustawieniach wyświetlania.",
"litecoin_mweb_pegin": "Kołek",
"litecoin_mweb_pegout": "Palikować",
"litecoin_mweb_scanning": "Skanowanie MWEB",
"litecoin_mweb_settings": "Ustawienia MWEB",
"litecoin_mweb_warning": "Korzystanie z MWEB początkowo pobiera ~ 600 MB danych i może potrwać do 30 minut w zależności od prędkości sieci. Te początkowe dane pobierają tylko raz i będą dostępne dla wszystkich portfeli Litecoin",

View file

@ -36,6 +36,7 @@
"agree": "Concordo",
"agree_and_continue": "Concordar e continuar",
"agree_to": "Ao criar conta você concorda com ",
"alert_notice": "Perceber",
"all": "TUDO",
"all_trades": "Todas as negociações",
"all_transactions": "Todas as transacções",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "Ativar digitalização do MWEB",
"litecoin_mweb": "Mweb",
"litecoin_mweb_always_scan": "Definir mweb sempre digitalizando",
"litecoin_mweb_description": "MWEB é um novo protocolo que traz transações mais rápidas, baratas e mais privadas para o Litecoin",
"litecoin_mweb_dismiss": "Liberar",
"litecoin_mweb_display_card": "Mostre o cartão MWEB",
"litecoin_mweb_enable_later": "Você pode optar por ativar o MWEB novamente em Configurações de exibição.",
"litecoin_mweb_pegin": "Peg in",
"litecoin_mweb_pegout": "Peg fora",
"litecoin_mweb_scanning": "MWEB Scanning",
"litecoin_mweb_settings": "Configurações do MWEB",
"litecoin_mweb_warning": "O uso do MWEB baixará inicialmente ~ 600 MB de dados e pode levar até 30 minutos, dependendo da velocidade da rede. Esses dados iniciais serão baixados apenas uma vez e estarão disponíveis para todas as carteiras Litecoin",

View file

@ -36,6 +36,7 @@
"agree": "согласен",
"agree_and_continue": "Согласиться и продолжить",
"agree_to": "Создавая аккаунт, вы соглашаетесь с ",
"alert_notice": "Уведомление",
"all": "ВСЕ",
"all_trades": "Все сделки",
"all_transactions": "Все транзакции",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "Включить MWEB сканирование",
"litecoin_mweb": "Мвеб",
"litecoin_mweb_always_scan": "Установить MWEB всегда сканирование",
"litecoin_mweb_description": "MWEB - это новый протокол, который приносит быстрее, дешевле и более частные транзакции в Litecoin",
"litecoin_mweb_dismiss": "Увольнять",
"litecoin_mweb_display_card": "Показать карту MWEB",
"litecoin_mweb_enable_later": "Вы можете снова включить MWEB в настройках отображения.",
"litecoin_mweb_pegin": "Внедрять",
"litecoin_mweb_pegout": "Выкрикивать",
"litecoin_mweb_scanning": "MWEB сканирование",
"litecoin_mweb_settings": "Настройки MWEB",
"litecoin_mweb_warning": "Использование MWEB изначально загрузит ~ 600 МБ данных и может занять до 30 минут в зависимости от скорости сети. Эти начальные данные будут загружаться только один раз и будут доступны для всех кошельков Litecoin",

View file

@ -36,6 +36,7 @@
"agree": "ยอมรับ",
"agree_and_continue": "ยอมรับและดำเนินการต่อ",
"agree_to": "การสร้างบัญชีของคุณยอมรับเงื่อนไขของ",
"alert_notice": "สังเกต",
"all": "ทั้งหมด",
"all_trades": "การซื้อขายทั้งหมด",
"all_transactions": "การทำธุรกรรมทั้งหมด",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "เปิดใช้งานการสแกน MWEB",
"litecoin_mweb": "mweb",
"litecoin_mweb_always_scan": "ตั้งค่าการสแกน MWEB เสมอ",
"litecoin_mweb_description": "MWEB เป็นโปรโตคอลใหม่ที่นำการทำธุรกรรมที่เร็วกว่าราคาถูกกว่าและเป็นส่วนตัวมากขึ้นไปยัง Litecoin",
"litecoin_mweb_dismiss": "อนุญาตให้ออกไป",
"litecoin_mweb_display_card": "แสดงการ์ด mweb",
"litecoin_mweb_enable_later": "คุณสามารถเลือกเปิดใช้งาน MWEB อีกครั้งภายใต้การตั้งค่าการแสดงผล",
"litecoin_mweb_pegin": "หมุด",
"litecoin_mweb_pegout": "ตรึง",
"litecoin_mweb_scanning": "การสแกน MWEB",
"litecoin_mweb_settings": "การตั้งค่า MWEB",
"litecoin_mweb_warning": "การใช้ MWEB จะดาวน์โหลดข้อมูล ~ 600MB ในขั้นต้นและอาจใช้เวลาสูงสุด 30 นาทีขึ้นอยู่กับความเร็วเครือข่าย ข้อมูลเริ่มต้นนี้จะดาวน์โหลดได้เพียงครั้งเดียวและพร้อมใช้งานสำหรับกระเป๋าเงินทั้งหมดของ Litecoin",

View file

@ -36,6 +36,7 @@
"agree": "Sumang-ayon",
"agree_and_continue": "Sumang-ayon & Magpatuloy",
"agree_to": "Sa pamamagitan ng paggawa ng account sumasang-ayon ka sa ",
"alert_notice": "PAUNAWA",
"all": "LAHAT",
"all_trades": "Lahat ng mga trade",
"all_transactions": "Lahat ng mga transaksyon",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "Paganahin ang pag -scan ng MWeb",
"litecoin_mweb": "Mweb",
"litecoin_mweb_always_scan": "Itakda ang MWeb na laging nag -scan",
"litecoin_mweb_description": "Ang MWeb ay isang bagong protocol na nagdadala ng mas mabilis, mas mura, at mas maraming pribadong mga transaksyon sa Litecoin",
"litecoin_mweb_dismiss": "Tanggalin",
"litecoin_mweb_display_card": "Ipakita ang MWEB Card",
"litecoin_mweb_enable_later": "Maaari kang pumili upang paganahin muli ang MWeb sa ilalim ng mga setting ng pagpapakita.",
"litecoin_mweb_pegin": "Peg in",
"litecoin_mweb_pegout": "Peg out",
"litecoin_mweb_scanning": "Pag -scan ng Mweb",
"litecoin_mweb_settings": "Mga Setting ng Mweb",
"litecoin_mweb_warning": "Ang paggamit ng MWEB ay unang i -download ang ~ 600MB ng data, at maaaring tumagal ng hanggang sa 30 minuto depende sa bilis ng network. Ang paunang data na ito ay mag -download lamang ng isang beses at magagamit para sa lahat ng mga wallets ng Litecoin",

View file

@ -36,6 +36,7 @@
"agree": "Kabul Et",
"agree_and_continue": "Kabul Et & Devam Et",
"agree_to": "Hesap oluşturarak bunları kabul etmiş olursunuz ",
"alert_notice": "Fark etme",
"all": "HEPSİ",
"all_trades": "Tüm takaslar",
"all_transactions": "Tüm transferler",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "MWEB taramasını etkinleştir",
"litecoin_mweb": "Mweb",
"litecoin_mweb_always_scan": "MWEB'i her zaman taramayı ayarlayın",
"litecoin_mweb_description": "MWEB, Litecoin'e daha hızlı, daha ucuz ve daha fazla özel işlem getiren yeni bir protokoldür",
"litecoin_mweb_dismiss": "Azletmek",
"litecoin_mweb_display_card": "MWEB kartını göster",
"litecoin_mweb_enable_later": "Ekran ayarlarının altında MWEB'yi tekrar etkinleştirmeyi seçebilirsiniz.",
"litecoin_mweb_pegin": "Takılmak",
"litecoin_mweb_pegout": "Çiğnemek",
"litecoin_mweb_scanning": "MWEB taraması",
"litecoin_mweb_settings": "MWEB ayarları",
"litecoin_mweb_warning": "MWEB kullanmak başlangıçta ~ 600MB veri indirir ve ağ hızına bağlı olarak 30 dakikaya kadar sürebilir. Bu ilk veriler yalnızca bir kez indirilecek ve tüm Litecoin cüzdanları için kullanılabilir olacak",

View file

@ -36,6 +36,7 @@
"agree": "Згоден",
"agree_and_continue": "Погодитися та продовжити",
"agree_to": "Створюючи обліковий запис, ви погоджуєтеся з ",
"alert_notice": "Ув'язнення",
"all": "ВСЕ",
"all_trades": "Всі операції",
"all_transactions": "Всі транзакції",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "Увімкнути сканування MWEB",
"litecoin_mweb": "Мвеб",
"litecoin_mweb_always_scan": "Встановити mweb завжди сканувати",
"litecoin_mweb_description": "MWEB - це новий протокол, який приносить швидкі, дешевші та більш приватні транзакції Litecoin",
"litecoin_mweb_dismiss": "Звільнити",
"litecoin_mweb_display_card": "Показати карту MWeb",
"litecoin_mweb_enable_later": "Ви можете знову ввімкнути MWEB в налаштуваннях дисплея.",
"litecoin_mweb_pegin": "Подякувати",
"litecoin_mweb_pegout": "Подякувати",
"litecoin_mweb_scanning": "Сканування Mweb",
"litecoin_mweb_settings": "Налаштування MWEB",
"litecoin_mweb_warning": "Використання MWEB спочатку завантажить ~ 600 Мб даних і може зайняти до 30 хвилин залежно від швидкості мережі. Ці початкові дані завантажуються лише один раз і будуть доступні для всіх гаманців Litecoin",

View file

@ -36,6 +36,7 @@
"agree": "متفق",
"agree_and_continue": "اتفاق کریں اور جاری رکھیں",
"agree_to": "اکاؤنٹ بنا کر آپ اس سے اتفاق کرتے ہیں۔",
"alert_notice": "نوٹس",
"all": "تمام",
"all_trades": "تمام تجارت",
"all_transactions": "تمام لین دین",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "MWEB اسکیننگ کو فعال کریں",
"litecoin_mweb": "MWEB",
"litecoin_mweb_always_scan": "MWEB ہمیشہ اسکیننگ سیٹ کریں",
"litecoin_mweb_description": "MWEB ایک نیا پروٹوکول ہے جو لیٹیکوئن میں تیز ، سستا اور زیادہ نجی لین دین لاتا ہے",
"litecoin_mweb_dismiss": "خارج",
"litecoin_mweb_display_card": "MWEB کارڈ دکھائیں",
"litecoin_mweb_enable_later": "آپ ڈسپلے کی ترتیبات کے تحت MWEB کو دوبارہ فعال کرنے کا انتخاب کرسکتے ہیں۔",
"litecoin_mweb_pegin": "پیگ میں",
"litecoin_mweb_pegout": "پیگ آؤٹ",
"litecoin_mweb_scanning": "MWEB اسکیننگ",
"litecoin_mweb_settings": "MWEB کی ترتیبات",
"litecoin_mweb_warning": "MWEB کا استعمال ابتدائی طور پر m 600mb ڈیٹا ڈاؤن لوڈ کرے گا ، اور نیٹ ورک کی رفتار کے لحاظ سے 30 منٹ تک کا وقت لگ سکتا ہے۔ یہ ابتدائی اعداد و شمار صرف ایک بار ڈاؤن لوڈ کریں گے اور تمام لیٹیکوئن بٹوے کے لئے دستیاب ہوں گے",

View file

@ -36,6 +36,7 @@
"agree": "Đồng ý",
"agree_and_continue": "Đồng ý & Tiếp tục",
"agree_to": "Bằng cách tạo tài khoản, bạn đồng ý với ",
"alert_notice": "Để ý",
"all": "TẤT CẢ",
"all_trades": "Tất cả giao dịch",
"all_transactions": "Tất cả giao dịch",
@ -365,6 +366,11 @@
"ledger_error_wrong_app": "Vui lòng đảm bảo bạn đã mở đúng ứng dụng trên Ledger của mình",
"ledger_please_enable_bluetooth": "Vui lòng bật Bluetooth để phát hiện Ledger của bạn",
"light_theme": "Chủ đề sáng",
"litecoin_mweb_description": "MWEB là một giao thức mới mang lại các giao dịch nhanh hơn, rẻ hơn và riêng tư hơn cho Litecoin",
"litecoin_mweb_dismiss": "Miễn nhiệm",
"litecoin_mweb_enable_later": "Bạn có thể chọn bật lại MWEB trong cài đặt hiển thị.",
"litecoin_mweb_pegin": "Chốt vào",
"litecoin_mweb_pegout": "Chốt ra",
"live_fee_rates": "Tỷ lệ phí hiện tại qua API",
"load_more": "Tải thêm",
"loading_your_wallet": "Đang tải ví của bạn",

View file

@ -36,6 +36,7 @@
"agree": "Jọ rò",
"agree_and_continue": "Jọ Rò àti Tẹ̀síwájú",
"agree_to": "Tẹ́ ẹ bá dá àkáǹtì ẹ jọ rò ",
"alert_notice": "Akiyesi",
"all": "Gbogbo",
"all_trades": "Gbogbo àwọn pàṣípààrọ̀",
"all_transactions": "Gbogbo àwọn àránṣẹ́",
@ -370,7 +371,12 @@
"litecoin_enable_mweb_sync": "Mu mweb ọlọjẹ",
"litecoin_mweb": "Mweb",
"litecoin_mweb_always_scan": "Ṣeto mweb nigbagbogbo n ṣayẹwo",
"litecoin_mweb_description": "Mweb jẹ ilana ilana tuntun ti o mu iyara wa yiyara, din owo, ati awọn iṣowo ikọkọ diẹ sii si Livcoin",
"litecoin_mweb_dismiss": "Tuka",
"litecoin_mweb_display_card": "Fihan kaadi Mweb",
"litecoin_mweb_enable_later": "O le yan lati ṣiṣẹ Mweb lẹẹkansi labẹ awọn eto ifihan.",
"litecoin_mweb_pegin": "Peg in",
"litecoin_mweb_pegout": "Peg jade",
"litecoin_mweb_scanning": "Mweb scanning",
"litecoin_mweb_settings": "Awọn eto Mweb",
"litecoin_mweb_warning": "Lilo Mweb yoo wa lakoko igbasilẹ ~ 600MB ti data, o le gba to iṣẹju 30 da lori iyara nẹtiwọọki. Awọn data akọkọ yii yoo ṣe igbasilẹ lẹẹkan si ki o wa fun gbogbo awọn Wolinkun LiveCooin",

View file

@ -36,6 +36,7 @@
"agree": "同意",
"agree_and_continue": "同意并继续",
"agree_to": "创建账户即表示您同意 ",
"alert_notice": "注意",
"all": "全部",
"all_trades": "所有的变化",
"all_transactions": "所有交易",
@ -369,7 +370,12 @@
"litecoin_enable_mweb_sync": "启用MWEB扫描",
"litecoin_mweb": "MWEB",
"litecoin_mweb_always_scan": "设置MWEB总是扫描",
"litecoin_mweb_description": "MWEB是一项新协议它将更快更便宜和更多的私人交易带给Litecoin",
"litecoin_mweb_dismiss": "解雇",
"litecoin_mweb_display_card": "显示MWEB卡",
"litecoin_mweb_enable_later": "您可以选择在显示设置下再次启用MWEB。",
"litecoin_mweb_pegin": "钉进",
"litecoin_mweb_pegout": "昏倒",
"litecoin_mweb_scanning": "MWEB扫描",
"litecoin_mweb_settings": "MWEB设置",
"litecoin_mweb_warning": "使用MWEB最初将下载约600MB的数据并且最多可能需要30分钟的时间具体取决于网络速度。此初始数据只能下载一次并适用于所有莱特币钱包",

View file

@ -84,6 +84,7 @@ import 'package:cw_core/node.dart';
import 'package:cw_core/output_info.dart';
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_core/receive_page_option.dart';
import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:cw_core/unspent_transaction_output.dart';
@ -106,6 +107,7 @@ import 'package:cw_bitcoin/pending_bitcoin_transaction.dart';
import 'package:cw_bitcoin/bitcoin_receive_page_option.dart';
import 'package:cw_bitcoin/bitcoin_wallet.dart';
import 'package:cw_bitcoin/electrum_wallet.dart';
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
import 'package:cw_bitcoin/bitcoin_unspent.dart';
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
@ -229,6 +231,7 @@ abstract class Bitcoin {
bool txIsMweb(TransactionInfo txInfo);
Future<void> setMwebEnabled(Object wallet, bool enabled);
bool getMwebEnabled(Object wallet);
String? getUnusedMwebAddress(Object wallet);
}
""";
@ -843,8 +846,8 @@ import 'package:eth_sig_util/util/utils.dart';
abstract class Ethereum {
List<String> getEthereumWordList(String language);
WalletService createEthereumWalletService(Box<WalletInfo> walletInfoSource, bool isDirect);
WalletCredentials createEthereumNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress});
WalletCredentials createEthereumRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password});
WalletCredentials createEthereumNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress, String? passphrase});
WalletCredentials createEthereumRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password, String? passphrase});
WalletCredentials createEthereumRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password});
WalletCredentials createEthereumHardwareWalletCredentials({required String name, required HardwareAccountData hwAccountData, WalletInfo? walletInfo});
String getAddress(WalletBase wallet);
@ -947,8 +950,8 @@ import 'package:eth_sig_util/util/utils.dart';
abstract class Polygon {
List<String> getPolygonWordList(String language);
WalletService createPolygonWalletService(Box<WalletInfo> walletInfoSource, bool isDirect);
WalletCredentials createPolygonNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress});
WalletCredentials createPolygonRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password});
WalletCredentials createPolygonNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress, String? passphrase});
WalletCredentials createPolygonRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password, String? passphrase});
WalletCredentials createPolygonRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password});
WalletCredentials createPolygonHardwareWalletCredentials({required String name, required HardwareAccountData hwAccountData, WalletInfo? walletInfo});
String getAddress(WalletBase wallet);
@ -1119,6 +1122,7 @@ abstract class Nano {
String? mnemonic,
String? parentAddress,
WalletInfo? walletInfo,
String? passphrase,
});
WalletCredentials createNanoRestoreWalletFromSeedCredentials({
@ -1126,6 +1130,7 @@ abstract class Nano {
required String password,
required String mnemonic,
required DerivationType derivationType,
String? passphrase,
});
WalletCredentials createNanoRestoreWalletFromKeysCredentials({
@ -1234,9 +1239,9 @@ abstract class Solana {
List<String> getSolanaWordList(String language);
WalletService createSolanaWalletService(Box<WalletInfo> walletInfoSource, bool isDirect);
WalletCredentials createSolanaNewWalletCredentials(
{required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress,});
{required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress, String? passphrase});
WalletCredentials createSolanaRestoreWalletFromSeedCredentials(
{required String name, required String mnemonic, required String password});
{required String name, required String mnemonic, required String password, String? passphrase});
WalletCredentials createSolanaRestoreWalletFromPrivateKey(
{required String name, required String privateKey, required String password});
@ -1320,9 +1325,8 @@ import 'package:cw_tron/tron_wallet_service.dart';
abstract class Tron {
List<String> getTronWordList(String language);
WalletService createTronWalletService(Box<WalletInfo> walletInfoSource, bool isDirect);
WalletCredentials createTronNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic,
String? parentAddress});
WalletCredentials createTronRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password});
WalletCredentials createTronNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress, String? passphrase});
WalletCredentials createTronRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password, String? passphrase});
WalletCredentials createTronRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password});
String getAddress(WalletBase wallet);