V4.20.0 rc2 (#1727)

* version 4.20.0

* update build numbers

* UI updates and script fix for ios bundle identifier

* disable mweb for desktop

* change hardcoded ltc server ip address
electrum connection enhancement

* MWEB enhancements 2.0 (#1735)

* additional logging and minor fixes

* additional logging and minor fixes

* addresses pt.1

* Allow Wallet Group Names to be the same as Wallet Names (#1730)

* fix: Issues with imaging

* fix: Allow group names to be the same as wallet names

* fix: Bug with wallet grouping when a wallet is minimized

* fix: Bug with wallet grouping when a wallet is minimized

* logs of fixes and experimental changes, close wallet before opening next

* save

* fix icon

* fixes

* [skip ci] updates

* [skip ci] updates

* updates

* minor optimizations

* fix for when switching between wallets

* [skip ci] updates

* [skip ci] updates

* Update cw_bitcoin/lib/litecoin_wallet.dart

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

* Update cw_bitcoin/lib/litecoin_wallet.dart

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

* mobx

* mostly logging

* stream fix pt.1 [skip ci]

* updates

* some fixes and enhancements

* [skip ci] minor

* potential partial fix for streamsink closed

* fix stream sink closed errors

* fix mweb logo colors

* save

* minor enhancements [skip ci]

* save

* experimental

* minor

* minor [skip ci]

---------

Co-authored-by: David Adegoke <64401859+Blazebrain@users.noreply.github.com>
Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

* fix menu list removing from original list

---------

Co-authored-by: Matthew Fosse <matt@fosse.co>
Co-authored-by: David Adegoke <64401859+Blazebrain@users.noreply.github.com>
This commit is contained in:
Omar Hatem 2024-10-13 02:13:52 +03:00 committed by GitHub
parent 8acf8bdfb2
commit 380f7653b2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
80 changed files with 572 additions and 329 deletions

View file

@ -1,2 +1,4 @@
Enhance auto-address generation for Monero Monero enhancements for sending and address generation
Bug fixes and enhancements StealthEx
LetsExchange
Visual enhancements and bug fixes

View file

@ -1,4 +1,9 @@
Enable BIP39 by default for wallet creation also on Bitcoin/Litecoin (Electrum seed type is still accessible through advanced settings page) Add Litecoin MWEB
Improve fee calculation for Bitcoin to protect against overpaying or underpaying Wallet groups (same seed, multiple wallets)
Enhance auto-address generation for Monero Silent Payments enhancements
Bug fixes and enhancements Monero enhancements for sending and address generation
StealthEx
LetsExchange
Replace-By-Fee improvements
ERC20 tokens potential scam detection
Visual enhancements and bug fixes

View file

@ -30,7 +30,7 @@ class BitcoinReceivePageOption implements ReceivePageOption {
static const allLitecoin = [ static const allLitecoin = [
BitcoinReceivePageOption.p2wpkh, BitcoinReceivePageOption.p2wpkh,
BitcoinReceivePageOption.mweb BitcoinReceivePageOption.mweb,
]; ];
BitcoinAddressType toType() { BitcoinAddressType toType() {

View file

@ -116,7 +116,7 @@ class ElectrumClient {
_parseResponse(message); _parseResponse(message);
} }
} catch (e) { } catch (e) {
print(e.toString()); print("socket.listen: $e");
} }
}, },
onError: (Object error) { onError: (Object error) {
@ -125,14 +125,15 @@ class ElectrumClient {
unterminatedString = ''; unterminatedString = '';
}, },
onDone: () { onDone: () {
print("SOCKET CLOSED!!!!!");
unterminatedString = ''; unterminatedString = '';
try { try {
if (host == socket?.address.host) { if (host == socket?.address.host) {
socket?.destroy();
_setConnectionStatus(ConnectionStatus.disconnected); _setConnectionStatus(ConnectionStatus.disconnected);
socket?.destroy();
} }
} catch (e) { } catch (e) {
print(e.toString()); print("onDone: $e");
} }
}, },
cancelOnError: true, cancelOnError: true,
@ -421,7 +422,7 @@ class ElectrumClient {
BehaviorSubject<T>? subscribe<T>( BehaviorSubject<T>? subscribe<T>(
{required String id, required String method, List<Object> params = const []}) { {required String id, required String method, List<Object> params = const []}) {
try { try {
if (socket == null) { if (socket == null || !isConnected) {
return null; return null;
} }
final subscription = BehaviorSubject<T>(); final subscription = BehaviorSubject<T>();
@ -437,7 +438,7 @@ class ElectrumClient {
Future<dynamic> call( Future<dynamic> call(
{required String method, List<Object> params = const [], Function(int)? idCallback}) async { {required String method, List<Object> params = const [], Function(int)? idCallback}) async {
if (socket == null) { if (socket == null || !isConnected) {
return null; return null;
} }
final completer = Completer<dynamic>(); final completer = Completer<dynamic>();
@ -453,7 +454,7 @@ class ElectrumClient {
Future<dynamic> callWithTimeout( Future<dynamic> callWithTimeout(
{required String method, List<Object> params = const [], int timeout = 5000}) async { {required String method, List<Object> params = const [], int timeout = 5000}) async {
try { try {
if (socket == null) { if (socket == null || !isConnected) {
return null; return null;
} }
final completer = Completer<dynamic>(); final completer = Completer<dynamic>();

View file

@ -4,7 +4,6 @@ import 'dart:io';
import 'dart:isolate'; import 'dart:isolate';
import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:cw_bitcoin/litecoin_wallet_addresses.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:cw_core/encryption_file_utils.dart'; import 'package:cw_core/encryption_file_utils.dart';
import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:blockchain_utils/blockchain_utils.dart';
@ -23,7 +22,6 @@ import 'package:cw_bitcoin/electrum_transaction_history.dart';
import 'package:cw_bitcoin/electrum_transaction_info.dart'; import 'package:cw_bitcoin/electrum_transaction_info.dart';
import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
import 'package:cw_bitcoin/exceptions.dart'; import 'package:cw_bitcoin/exceptions.dart';
import 'package:cw_bitcoin/litecoin_wallet.dart';
import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart';
import 'package:cw_bitcoin/utils.dart'; import 'package:cw_bitcoin/utils.dart';
import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/crypto_currency.dart';
@ -168,7 +166,10 @@ abstract class ElectrumWalletBase
@observable @observable
SyncStatus syncStatus; SyncStatus syncStatus;
Set<String> get addressesSet => walletAddresses.allAddresses.map((addr) => addr.address).toSet(); Set<String> get addressesSet => walletAddresses.allAddresses
.where((element) => element.type != SegwitAddresType.mweb)
.map((addr) => addr.address)
.toSet();
List<String> get scriptHashes => walletAddresses.addressesByReceiveType List<String> get scriptHashes => walletAddresses.addressesByReceiveType
.where((addr) => RegexUtils.addressTypeFromStr(addr.address, network) is! MwebAddress) .where((addr) => RegexUtils.addressTypeFromStr(addr.address, network) is! MwebAddress)
@ -1174,6 +1175,7 @@ abstract class ElectrumWalletBase
'silent_addresses': walletAddresses.silentAddresses.map((addr) => addr.toJSON()).toList(), 'silent_addresses': walletAddresses.silentAddresses.map((addr) => addr.toJSON()).toList(),
'silent_address_index': walletAddresses.currentSilentAddressIndex.toString(), 'silent_address_index': walletAddresses.currentSilentAddressIndex.toString(),
'mweb_addresses': walletAddresses.mwebAddresses.map((addr) => addr.toJSON()).toList(), 'mweb_addresses': walletAddresses.mwebAddresses.map((addr) => addr.toJSON()).toList(),
'alwaysScan': alwaysScan,
}); });
int feeRate(TransactionPriority priority) { int feeRate(TransactionPriority priority) {
@ -1291,7 +1293,7 @@ abstract class ElectrumWalletBase
} }
@override @override
Future<void> close() async { Future<void> close({required bool shouldCleanup}) async {
try { try {
await _receiveStream?.cancel(); await _receiveStream?.cancel();
await electrumClient.close(); await electrumClient.close();
@ -1314,11 +1316,15 @@ abstract class ElectrumWalletBase
} }
// Set the balance of all non-silent payment addresses to 0 before updating // Set the balance of all non-silent payment addresses to 0 before updating
walletAddresses.allAddresses.forEach((addr) { walletAddresses.allAddresses
.where((element) => element.type != SegwitAddresType.mweb)
.forEach((addr) {
if (addr is! BitcoinSilentPaymentAddressRecord) addr.balance = 0; if (addr is! BitcoinSilentPaymentAddressRecord) addr.balance = 0;
}); });
await Future.wait(walletAddresses.allAddresses.map((address) async { await Future.wait(walletAddresses.allAddresses
.where((element) => element.type != SegwitAddresType.mweb)
.map((address) async {
updatedUnspentCoins.addAll(await fetchUnspent(address)); updatedUnspentCoins.addAll(await fetchUnspent(address));
})); }));
@ -1878,6 +1884,7 @@ abstract class ElectrumWalletBase
} }
Future<void> updateTransactions() async { Future<void> updateTransactions() async {
print("updateTransactions() called!");
try { try {
if (_isTransactionUpdating) { if (_isTransactionUpdating) {
return; return;
@ -1903,12 +1910,16 @@ abstract class ElectrumWalletBase
Future<void> subscribeForUpdates() async { Future<void> subscribeForUpdates() async {
final unsubscribedScriptHashes = walletAddresses.allAddresses.where( final unsubscribedScriptHashes = walletAddresses.allAddresses.where(
(address) => !_scripthashesUpdateSubject.containsKey(address.getScriptHash(network)), (address) =>
!_scripthashesUpdateSubject.containsKey(address.getScriptHash(network)) &&
address.type != SegwitAddresType.mweb,
); );
await Future.wait(unsubscribedScriptHashes.map((address) async { await Future.wait(unsubscribedScriptHashes.map((address) async {
final sh = address.getScriptHash(network); final sh = address.getScriptHash(network);
if (!(_scripthashesUpdateSubject[sh]?.isClosed ?? true)) {
await _scripthashesUpdateSubject[sh]?.close(); await _scripthashesUpdateSubject[sh]?.close();
}
_scripthashesUpdateSubject[sh] = await electrumClient.scripthashUpdate(sh); _scripthashesUpdateSubject[sh] = await electrumClient.scripthashUpdate(sh);
_scripthashesUpdateSubject[sh]?.listen((event) async { _scripthashesUpdateSubject[sh]?.listen((event) async {
try { try {
@ -1918,7 +1929,7 @@ abstract class ElectrumWalletBase
await _fetchAddressHistory(address, await getCurrentChainTip()); await _fetchAddressHistory(address, await getCurrentChainTip());
} catch (e, s) { } catch (e, s) {
print(e.toString()); print("sub error: $e");
_onError?.call(FlutterErrorDetails( _onError?.call(FlutterErrorDetails(
exception: e, exception: e,
stack: s, stack: s,
@ -1996,6 +2007,7 @@ abstract class ElectrumWalletBase
} }
Future<void> updateBalance() async { Future<void> updateBalance() async {
print("updateBalance() called!");
balance[currency] = await fetchBalances(); balance[currency] = await fetchBalances();
await save(); await save();
} }

View file

@ -1,3 +1,5 @@
import 'dart:io' show Platform;
import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:blockchain_utils/blockchain_utils.dart';
import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart';
@ -238,7 +240,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
await _generateInitialAddresses(type: P2pkhAddressType.p2pkh); await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
} else if (walletInfo.type == WalletType.litecoin) { } else if (walletInfo.type == WalletType.litecoin) {
await _generateInitialAddresses(type: SegwitAddresType.p2wpkh); await _generateInitialAddresses(type: SegwitAddresType.p2wpkh);
if (Platform.isAndroid || Platform.isIOS) {
await _generateInitialAddresses(type: SegwitAddresType.mweb); await _generateInitialAddresses(type: SegwitAddresType.mweb);
}
} else if (walletInfo.type == WalletType.bitcoin) { } else if (walletInfo.type == WalletType.bitcoin) {
await _generateInitialAddresses(); await _generateInitialAddresses();
await _generateInitialAddresses(type: P2pkhAddressType.p2pkh); await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);

View file

@ -24,6 +24,7 @@ class ElectrumWalletSnapshot {
required this.silentAddresses, required this.silentAddresses,
required this.silentAddressIndex, required this.silentAddressIndex,
required this.mwebAddresses, required this.mwebAddresses,
required this.alwaysScan,
this.passphrase, this.passphrase,
this.derivationType, this.derivationType,
this.derivationPath, this.derivationPath,
@ -46,6 +47,7 @@ class ElectrumWalletSnapshot {
List<BitcoinAddressRecord> addresses; List<BitcoinAddressRecord> addresses;
List<BitcoinSilentPaymentAddressRecord> silentAddresses; List<BitcoinSilentPaymentAddressRecord> silentAddresses;
List<BitcoinAddressRecord> mwebAddresses; List<BitcoinAddressRecord> mwebAddresses;
bool alwaysScan;
ElectrumBalance balance; ElectrumBalance balance;
Map<String, int> regularAddressIndex; Map<String, int> regularAddressIndex;
@ -54,8 +56,8 @@ class ElectrumWalletSnapshot {
DerivationType? derivationType; DerivationType? derivationType;
String? derivationPath; String? derivationPath;
static Future<ElectrumWalletSnapshot> load( static Future<ElectrumWalletSnapshot> load(EncryptionFileUtils encryptionFileUtils, String name,
EncryptionFileUtils encryptionFileUtils, String name, WalletType type, String password, BasedUtxoNetwork network) async { WalletType type, String password, BasedUtxoNetwork network) async {
final path = await pathForWallet(name: name, type: type); final path = await pathForWallet(name: name, type: type);
final jsonSource = await encryptionFileUtils.read(path: path, password: password); final jsonSource = await encryptionFileUtils.read(path: path, password: password);
final data = json.decode(jsonSource) as Map; final data = json.decode(jsonSource) as Map;
@ -81,6 +83,8 @@ class ElectrumWalletSnapshot {
.map((addr) => BitcoinAddressRecord.fromJSON(addr, network: network)) .map((addr) => BitcoinAddressRecord.fromJSON(addr, network: network))
.toList(); .toList();
final alwaysScan = data['alwaysScan'] as bool? ?? false;
final balance = ElectrumBalance.fromJSON(data['balance'] as String?) ?? final balance = ElectrumBalance.fromJSON(data['balance'] as String?) ??
ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0); ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0);
var regularAddressIndexByType = {SegwitAddresType.p2wpkh.toString(): 0}; var regularAddressIndexByType = {SegwitAddresType.p2wpkh.toString(): 0};
@ -124,6 +128,7 @@ class ElectrumWalletSnapshot {
silentAddresses: silentAddresses, silentAddresses: silentAddresses,
silentAddressIndex: silentAddressIndex, silentAddressIndex: silentAddressIndex,
mwebAddresses: mwebAddresses, mwebAddresses: mwebAddresses,
alwaysScan: alwaysScan,
); );
} }
} }

View file

@ -76,6 +76,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
seedBytes: seedBytes, seedBytes: seedBytes,
encryptionFileUtils: encryptionFileUtils, encryptionFileUtils: encryptionFileUtils,
currency: CryptoCurrency.ltc, currency: CryptoCurrency.ltc,
alwaysScan: alwaysScan,
) { ) {
mwebHd = Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath("m/1000'") as Bip32Slip10Secp256k1; mwebHd = Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath("m/1000'") as Bip32Slip10Secp256k1;
mwebEnabled = alwaysScan ?? false; mwebEnabled = alwaysScan ?? false;
@ -101,7 +102,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
Timer? _feeRatesTimer; Timer? _feeRatesTimer;
Timer? _processingTimer; Timer? _processingTimer;
StreamSubscription<Utxo>? _utxoStream; StreamSubscription<Utxo>? _utxoStream;
late RpcClient _stub;
late bool mwebEnabled; late bool mwebEnabled;
bool processingUtxos = false; bool processingUtxos = false;
@ -229,18 +229,14 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
initialRegularAddressIndex: snp?.regularAddressIndex, initialRegularAddressIndex: snp?.regularAddressIndex,
initialChangeAddressIndex: snp?.changeAddressIndex, initialChangeAddressIndex: snp?.changeAddressIndex,
addressPageType: snp?.addressPageType, addressPageType: snp?.addressPageType,
alwaysScan: alwaysScan, alwaysScan: snp?.alwaysScan,
); );
} }
Future<void> waitForMwebAddresses() async { Future<void> waitForMwebAddresses() async {
print("waitForMwebAddresses() called!");
// ensure that we have the full 1000 mweb addresses generated before continuing: // ensure that we have the full 1000 mweb addresses generated before continuing:
// should no longer be needed, but leaving here just in case // 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));
// }
await (walletAddresses as LitecoinWalletAddresses).ensureMwebAddressUpToIndexExists(1020); await (walletAddresses as LitecoinWalletAddresses).ensureMwebAddressUpToIndexExists(1020);
} }
@ -252,16 +248,20 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
return; return;
} }
print("STARTING SYNC - MWEB ENABLED: $mwebEnabled"); print("STARTING SYNC - MWEB ENABLED: $mwebEnabled");
_syncTimer?.cancel();
try { try {
syncStatus = SyncronizingSyncStatus(); syncStatus = SyncronizingSyncStatus();
await subscribeForUpdates(); await subscribeForUpdates();
updateFeeRates(); updateFeeRates();
_feeRatesTimer?.cancel(); _feeRatesTimer?.cancel();
_feeRatesTimer = _feeRatesTimer =
Timer.periodic(const Duration(minutes: 1), (timer) async => await updateFeeRates()); Timer.periodic(const Duration(minutes: 1), (timer) async => await updateFeeRates());
if (!mwebEnabled) { if (!mwebEnabled) {
try {
// in case we're switching from a litecoin wallet that had mweb enabled
CwMweb.stop();
} catch (_) {}
try { try {
await updateAllUnspents(); await updateAllUnspents();
await updateTransactions(); await updateTransactions();
@ -276,23 +276,19 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
} }
await waitForMwebAddresses(); await waitForMwebAddresses();
await getStub();
await processMwebUtxos(); await processMwebUtxos();
await updateTransactions(); await updateTransactions();
await updateUnspent(); await updateUnspent();
await updateBalance(); await updateBalance();
} catch (e) { } catch (e) {
print("failed to start mweb sync: $e"); print("failed to start mweb sync: $e");
syncStatus = FailedSyncStatus(); syncStatus = FailedSyncStatus(error: "failed to start");
return; return;
} }
_syncTimer?.cancel(); _syncTimer = Timer.periodic(const Duration(milliseconds: 3000), (timer) async {
_syncTimer = Timer.periodic(const Duration(milliseconds: 1500), (timer) async {
if (syncStatus is FailedSyncStatus) return; if (syncStatus is FailedSyncStatus) return;
print("SYNCING....");
final nodeHeight = final nodeHeight =
await electrumClient.getCurrentBlockChainTip() ?? 0; // current block height of our node await electrumClient.getCurrentBlockChainTip() ?? 0; // current block height of our node
@ -350,10 +346,12 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
@action @action
@override @override
Future<void> stopSync() async { Future<void> stopSync() async {
print("stopSync() called!");
_syncTimer?.cancel(); _syncTimer?.cancel();
_utxoStream?.cancel(); _utxoStream?.cancel();
_feeRatesTimer?.cancel(); _feeRatesTimer?.cancel();
await CwMweb.stop(); await CwMweb.stop();
print("stopped syncing!");
} }
Future<void> initMwebUtxosBox() async { Future<void> initMwebUtxosBox() async {
@ -425,9 +423,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
await initMwebUtxosBox(); await initMwebUtxosBox();
} }
Future<void> handleIncoming(MwebUtxo utxo, RpcClient stub) async { Future<void> handleIncoming(MwebUtxo utxo) async {
print("handleIncoming() called!"); print("handleIncoming() called!");
final status = await stub.status(StatusRequest()); final status = await CwMweb.status(StatusRequest());
var date = DateTime.now(); var date = DateTime.now();
var confirmations = 0; var confirmations = 0;
if (utxo.height > 0) { if (utxo.height > 0) {
@ -493,6 +491,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
} }
Future<void> processMwebUtxos() async { Future<void> processMwebUtxos() async {
print("processMwebUtxos() called!");
if (!mwebEnabled) { if (!mwebEnabled) {
return; return;
} }
@ -502,7 +501,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
final req = UtxosRequest(scanSecret: scanSecret, fromHeight: restoreHeight); final req = UtxosRequest(scanSecret: scanSecret, fromHeight: restoreHeight);
// process new utxos as they come in: // process new utxos as they come in:
_utxoStream?.cancel(); await _utxoStream?.cancel();
ResponseStream<Utxo>? responseStream = await CwMweb.utxos(req); ResponseStream<Utxo>? responseStream = await CwMweb.utxos(req);
if (responseStream == null) { if (responseStream == null) {
throw Exception("failed to get utxos stream!"); throw Exception("failed to get utxos stream!");
@ -544,7 +543,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
await mwebUtxosBox.put(utxo.outputId, utxo); await mwebUtxosBox.put(utxo.outputId, utxo);
await handleIncoming(utxo, _stub); await handleIncoming(utxo);
}); });
} }
@ -662,6 +661,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
} }
Future<void> updateUnspent() async { Future<void> updateUnspent() async {
print("updateUnspent() called!");
await checkMwebUtxosSpent(); await checkMwebUtxosSpent();
await updateAllUnspents(); await updateAllUnspents();
} }
@ -675,7 +675,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
if (!mwebEnabled) { if (!mwebEnabled) {
return; return;
} }
await getStub();
// add the mweb unspents to the list: // add the mweb unspents to the list:
List<BitcoinUnspent> mwebUnspentCoins = []; List<BitcoinUnspent> mwebUnspentCoins = [];
@ -718,7 +717,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
if (!mwebEnabled) { if (!mwebEnabled) {
return balance; return balance;
} }
await getStub();
// update unspent balances: // update unspent balances:
await updateUnspent(); await updateUnspent();
@ -891,7 +889,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
return tx; return tx;
} }
await waitForMwebAddresses(); await waitForMwebAddresses();
await getStub();
final resp = await CwMweb.create(CreateRequest( final resp = await CwMweb.create(CreateRequest(
rawTx: hex.decode(tx.hex), rawTx: hex.decode(tx.hex),
@ -1000,13 +997,17 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
} }
@override @override
Future<void> close() async { Future<void> close({required bool shouldCleanup}) async {
_utxoStream?.cancel(); _utxoStream?.cancel();
_feeRatesTimer?.cancel(); _feeRatesTimer?.cancel();
_syncTimer?.cancel(); _syncTimer?.cancel();
_processingTimer?.cancel(); _processingTimer?.cancel();
if (shouldCleanup) {
try {
await stopSync(); await stopSync();
await super.close(); } catch (_) {}
}
await super.close(shouldCleanup: shouldCleanup);
} }
Future<void> setMwebEnabled(bool enabled) async { Future<void> setMwebEnabled(bool enabled) async {
@ -1014,17 +1015,16 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
return; return;
} }
alwaysScan = enabled;
mwebEnabled = enabled; mwebEnabled = enabled;
(walletAddresses as LitecoinWalletAddresses).mwebEnabled = enabled; (walletAddresses as LitecoinWalletAddresses).mwebEnabled = enabled;
await save();
try {
await stopSync(); await stopSync();
} catch (_) {}
await startSync(); await startSync();
} }
Future<RpcClient> getStub() async {
_stub = await CwMweb.stub();
return _stub;
}
Future<StatusResponse> getStatusRequest() async { Future<StatusResponse> getStatusRequest() async {
final resp = await CwMweb.status(StatusRequest()); final resp = await CwMweb.status(StatusRequest());
return resp; return resp;

View file

@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:io' show Platform;
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_base/bitcoin_base.dart';
@ -39,8 +40,10 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
bool mwebEnabled; bool mwebEnabled;
int mwebTopUpIndex = 1000; int mwebTopUpIndex = 1000;
List<String> mwebAddrs = []; List<String> mwebAddrs = [];
bool generating = false;
List<int> get scanSecret => mwebHd.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw; List<int> get scanSecret => mwebHd.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw;
List<int> get spendPubkey => List<int> get spendPubkey =>
mwebHd.childKey(Bip32KeyIndex(0x80000001)).publicKey.pubKey.compressed; mwebHd.childKey(Bip32KeyIndex(0x80000001)).publicKey.pubKey.compressed;
@ -57,19 +60,37 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
} }
Future<void> ensureMwebAddressUpToIndexExists(int index) async { Future<void> ensureMwebAddressUpToIndexExists(int index) async {
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
return null;
}
Uint8List scan = Uint8List.fromList(scanSecret); Uint8List scan = Uint8List.fromList(scanSecret);
Uint8List spend = Uint8List.fromList(spendPubkey); Uint8List spend = Uint8List.fromList(spendPubkey);
int count = 0;
if (index < mwebAddresses.length && index < mwebAddrs.length) {
return;
}
while (generating) {
print("generating.....");
// this function was called multiple times in multiple places:
await Future.delayed(const Duration(milliseconds: 100));
}
print("Generating MWEB addresses up to index $index");
generating = true;
try {
while (mwebAddrs.length <= (index + 1)) { while (mwebAddrs.length <= (index + 1)) {
final address = await CwMweb.address(scan, spend, mwebAddrs.length); final addresses =
mwebAddrs.add(address!); await CwMweb.addresses(scan, spend, mwebAddrs.length, mwebAddrs.length + 50);
count++; print("generated up to index ${mwebAddrs.length}");
// sleep for a bit to avoid making the main thread unresponsive: // sleep for a bit to avoid making the main thread unresponsive:
if (count > 50) { await Future.delayed(Duration(milliseconds: 200));
count = 0; mwebAddrs.addAll(addresses!);
await Future.delayed(Duration(milliseconds: 100));
}
} }
} catch (_) {}
generating = false;
print("Done generating MWEB addresses len: ${mwebAddrs.length}");
// ensure mweb addresses are up to date: // ensure mweb addresses are up to date:
if (mwebAddresses.length < mwebAddrs.length) { if (mwebAddresses.length < mwebAddrs.length) {
@ -90,21 +111,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
Future<void> initMwebAddresses() async { Future<void> initMwebAddresses() async {
if (mwebAddrs.length < 1000) { if (mwebAddrs.length < 1000) {
print("Generating MWEB addresses...");
await ensureMwebAddressUpToIndexExists(20); 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; return;
} }
} }

View file

@ -117,6 +117,8 @@ class PendingBitcoinTransaction with PendingTransaction {
idOverride = resp.txid; idOverride = resp.txid;
} on GrpcError catch (e) { } on GrpcError catch (e) {
throw BitcoinTransactionCommitFailed(errorMessage: e.message); throw BitcoinTransactionCommitFailed(errorMessage: e.message);
} catch (e) {
throw BitcoinTransactionCommitFailed(errorMessage: "Unknown error: ${e.toString()}");
} }
} }

View file

@ -83,7 +83,7 @@ abstract class WalletBase<BalanceType extends Balance, HistoryType extends Trans
Future<void> rescan({required int height}); Future<void> rescan({required int height});
void close(); Future<void> close({required bool shouldCleanup});
Future<void> changePassword(String password); Future<void> changePassword(String password);

View file

@ -264,7 +264,7 @@ abstract class EVMChainWalletBase
} }
@override @override
void close() { Future<void> close({required bool shouldCleanup}) async {
_client.stop(); _client.stop();
_transactionsUpdateTimer?.cancel(); _transactionsUpdateTimer?.cancel();
_updateFeesTimer?.cancel(); _updateFeesTimer?.cancel();

View file

@ -106,7 +106,7 @@ abstract class HavenWalletBase
Future<void>? updateBalance() => null; Future<void>? updateBalance() => null;
@override @override
void close() { Future<void> close({required bool shouldCleanup}) async {
_listener?.stop(); _listener?.stop();
_onAccountChangeReaction?.reaction.dispose(); _onAccountChangeReaction?.reaction.dispose();
_autoSaveTimer?.cancel(); _autoSaveTimer?.cancel();

View file

@ -116,7 +116,7 @@ class HavenWalletService extends WalletService<
if (!isValid) { if (!isValid) {
await restoreOrResetWalletFiles(name); await restoreOrResetWalletFiles(name);
wallet.close(); wallet.close(shouldCleanup: false);
return openWallet(name, password); return openWallet(name, password);
} }

View file

@ -170,7 +170,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
Future<void>? updateBalance() => null; Future<void>? updateBalance() => null;
@override @override
void close() async { Future<void> close({required bool shouldCleanup}) async {
_listener?.stop(); _listener?.stop();
_onAccountChangeReaction?.reaction.dispose(); _onAccountChangeReaction?.reaction.dispose();
_onTxHistoryChangeReaction?.reaction.dispose(); _onTxHistoryChangeReaction?.reaction.dispose();

View file

@ -137,7 +137,7 @@ class MoneroWalletService extends WalletService<
if (!isValid) { if (!isValid) {
await restoreOrResetWalletFiles(name); await restoreOrResetWalletFiles(name);
wallet.close(); wallet.close(shouldCleanup: false);
return openWallet(name, password); return openWallet(name, password);
} }

View file

@ -40,10 +40,17 @@ class CwMwebPlugin: FlutterPlugin, MethodCallHandler {
port = null port = null
result.success(null) result.success(null)
} else if (call.method == "address") { } else if (call.method == "address") {
// val scanSecret: ByteArray = call.argument<ByteArray>("scanSecret") ?: ByteArray(0)
// val spendPub: ByteArray = call.argument<ByteArray>("spendPub") ?: ByteArray(0)
// val index: Int = call.argument<Int>("index") ?: 0
// val res = Mwebd.address(scanSecret, spendPub, index)
// result.success(res)
} else if (call.method == "addresses") {
val scanSecret: ByteArray = call.argument<ByteArray>("scanSecret") ?: ByteArray(0) val scanSecret: ByteArray = call.argument<ByteArray>("scanSecret") ?: ByteArray(0)
val spendPub: ByteArray = call.argument<ByteArray>("spendPub") ?: ByteArray(0) val spendPub: ByteArray = call.argument<ByteArray>("spendPub") ?: ByteArray(0)
val index: Int = call.argument<Int>("index") ?: 0 val fromIndex: Int = call.argument<Int>("fromIndex") ?: 0
val res = Mwebd.address(scanSecret, spendPub, index) val toIndex: Int = call.argument<Int>("toIndex") ?: 0
val res = Mwebd.addresses(scanSecret, spendPub, fromIndex, toIndex)
result.success(res) result.success(res)
} else { } else {
result.notImplemented() result.notImplemented()

View file

@ -32,15 +32,26 @@ public static func register(with registrar: FlutterPluginRegistrar) {
stopServer() stopServer()
result(nil) result(nil)
break break
case "address": // case "address":
// let args = call.arguments as! [String: Any]
// let scanSecret = args["scanSecret"] as! FlutterStandardTypedData
// let spendPub = args["spendPub"] as! FlutterStandardTypedData
// let index = args["index"] as! Int32
// let scanSecretData = scanSecret.data
// let spendPubData = spendPub.data
// result(MwebdAddress(scanSecretData, spendPubData, index))
// break
case "addresses":
let args = call.arguments as! [String: Any] let args = call.arguments as! [String: Any]
let scanSecret = args["scanSecret"] as! FlutterStandardTypedData let scanSecret = args["scanSecret"] as! FlutterStandardTypedData
let spendPub = args["spendPub"] as! FlutterStandardTypedData let spendPub = args["spendPub"] as! FlutterStandardTypedData
let index = args["index"] as! Int32 let fromIndex = args["fromIndex"] as! Int32
let toIndex = args["toIndex"] as! Int32
let scanSecretData = scanSecret.data let scanSecretData = scanSecret.data
let spendPubData = spendPub.data let spendPubData = spendPub.data
result(MwebdAddress(scanSecretData, spendPubData, index)) result(MwebdAddresses(scanSecretData, spendPubData, fromIndex, toIndex))
break break
default: default:
result(FlutterMethodNotImplemented) result(FlutterMethodNotImplemented)

View file

@ -1,3 +1,7 @@
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:grpc/grpc.dart'; import 'package:grpc/grpc.dart';
@ -10,25 +14,51 @@ class CwMweb {
static ClientChannel? _clientChannel; static ClientChannel? _clientChannel;
static int? _port; static int? _port;
static const TIMEOUT_DURATION = Duration(seconds: 5); static const TIMEOUT_DURATION = Duration(seconds: 5);
static Timer? logTimer;
static void readFileWithTimer(String filePath) {
final file = File(filePath);
int lastLength = 0;
logTimer?.cancel();
logTimer = Timer.periodic(const Duration(seconds: 1), (timer) async {
try {
final currentLength = await file.length();
if (currentLength != lastLength) {
final fileStream = file.openRead(lastLength, currentLength);
final newLines = await fileStream.transform(utf8.decoder).join();
lastLength = currentLength;
log(newLines);
}
} on GrpcError catch (e) {
log('Caught grpc error: ${e.message}');
} catch (e) {
log('The mwebd debug log probably is not initialized yet.');
}
});
}
static Future<void> _initializeClient() async { static Future<void> _initializeClient() async {
await stop(); print("initialize client called!");
// wait a few seconds to make sure the server is stopped
await Future.delayed(const Duration(seconds: 5));
final appDir = await getApplicationSupportDirectory(); final appDir = await getApplicationSupportDirectory();
const ltcNodeUri = "45.79.13.180:9333"; const ltcNodeUri = "ltc-electrum.cakewallet.com:9333";
String debugLogPath = "${appDir.path}/logs/debug.log";
readFileWithTimer(debugLogPath);
_port = await CwMwebPlatform.instance.start(appDir.path, ltcNodeUri); _port = await CwMwebPlatform.instance.start(appDir.path, ltcNodeUri);
if (_port == null || _port == 0) { if (_port == null || _port == 0) {
throw Exception("Failed to start server"); throw Exception("Failed to start server");
} }
print("Attempting to connect to server on port: $_port"); log("Attempting to connect to server on port: $_port");
// wait for the server to finish starting up before we try to connect to it: // wait for the server to finish starting up before we try to connect to it:
await Future.delayed(const Duration(seconds: 5)); await Future.delayed(const Duration(seconds: 5));
_clientChannel = ClientChannel('127.0.0.1', port: _port!, channelShutdownHandler: () { _clientChannel = ClientChannel('127.0.0.1', port: _port!, channelShutdownHandler: () {
print("Channel is shutting down!"); _rpcClient = null;
log("Channel is shutting down!");
}, },
options: const ChannelOptions( options: const ChannelOptions(
credentials: ChannelCredentials.insecure(), credentials: ChannelCredentials.insecure(),
@ -49,9 +79,15 @@ class CwMweb {
throw Exception("blockTime shouldn't be 0! (this connection is likely broken)"); throw Exception("blockTime shouldn't be 0! (this connection is likely broken)");
} }
return _rpcClient!; return _rpcClient!;
} catch (e) { } on GrpcError catch (e) {
print("Attempt $i failed: $e"); log("Attempt $i failed: $e");
log('Caught grpc error: ${e.message}');
_rpcClient = null; _rpcClient = null;
await Future.delayed(const Duration(seconds: 3));
} catch (e) {
log("Attempt $i failed: $e");
_rpcClient = null;
await Future.delayed(const Duration(seconds: 3));
} }
} }
throw Exception("Failed to connect after $maxRetries attempts"); throw Exception("Failed to connect after $maxRetries attempts");
@ -61,22 +97,43 @@ class CwMweb {
try { try {
await CwMwebPlatform.instance.stop(); await CwMwebPlatform.instance.stop();
await cleanup(); await cleanup();
} on GrpcError catch (e) {
log('Caught grpc error: ${e.message}');
} catch (e) { } catch (e) {
print("Error stopping server: $e"); log("Error stopping server: $e");
} }
} }
static Future<String?> address(Uint8List scanSecret, Uint8List spendPub, int index) async { static Future<String?> address(Uint8List scanSecret, Uint8List spendPub, int index) async {
try { try {
return CwMwebPlatform.instance.address(scanSecret, spendPub, index); return (await CwMwebPlatform.instance.addresses(scanSecret, spendPub, index, index + 1))
?.split(',')
.first;
} on GrpcError catch (e) {
log('Caught grpc error: ${e.message}');
} catch (e) { } catch (e) {
print("Error getting address: $e"); log("Error getting address: $e");
}
return null; return null;
} }
static Future<List<String>?> addresses(
Uint8List scanSecret, Uint8List spendPub, int fromIndex, int toIndex) async {
try {
return (await CwMwebPlatform.instance.addresses(scanSecret, spendPub, fromIndex, toIndex))
?.split(',');
} on GrpcError catch (e) {
log('Caught grpc error: ${e.message}');
} catch (e) {
log("Error getting addresses: $e");
}
return null;
} }
static Future<void> cleanup() async { static Future<void> cleanup() async {
try {
await _clientChannel?.terminate(); await _clientChannel?.terminate();
} catch (_) {}
_rpcClient = null; _rpcClient = null;
_clientChannel = null; _clientChannel = null;
_port = null; _port = null;
@ -84,51 +141,57 @@ class CwMweb {
// wrappers that handle the connection issues: // wrappers that handle the connection issues:
static Future<SpentResponse> spent(SpentRequest request) async { static Future<SpentResponse> spent(SpentRequest request) async {
log("mweb.spent() called");
try { try {
if (_rpcClient == null) { _rpcClient = await stub();
await _initializeClient();
}
return await _rpcClient!.spent(request, options: CallOptions(timeout: TIMEOUT_DURATION)); return await _rpcClient!.spent(request, options: CallOptions(timeout: TIMEOUT_DURATION));
} on GrpcError catch (e) {
log('Caught grpc error: ${e.message}');
} catch (e) { } catch (e) {
print("Error getting spent: $e"); log("Error getting spent: $e");
return SpentResponse();
} }
return SpentResponse();
} }
static Future<StatusResponse> status(StatusRequest request) async { static Future<StatusResponse> status(StatusRequest request) async {
log("mweb.status() called");
try { try {
if (_rpcClient == null) { _rpcClient = await stub();
await _initializeClient();
}
return await _rpcClient!.status(request, options: CallOptions(timeout: TIMEOUT_DURATION)); return await _rpcClient!.status(request, options: CallOptions(timeout: TIMEOUT_DURATION));
} on GrpcError catch (e) {
log('Caught grpc error: ${e.message}');
} catch (e) { } catch (e) {
print("Error getting status: $e"); log("Error getting status: $e");
return StatusResponse();
} }
return StatusResponse();
} }
static Future<CreateResponse> create(CreateRequest request) async { static Future<CreateResponse> create(CreateRequest request) async {
log("mweb.create() called");
try { try {
if (_rpcClient == null) { _rpcClient = await stub();
await _initializeClient();
}
return await _rpcClient!.create(request, options: CallOptions(timeout: TIMEOUT_DURATION)); return await _rpcClient!.create(request, options: CallOptions(timeout: TIMEOUT_DURATION));
} on GrpcError catch (e) {
log('Caught grpc error: ${e.message}');
} catch (e) { } catch (e) {
print("Error getting create: $e"); log("Error getting create: $e");
return CreateResponse();
} }
return CreateResponse();
} }
static Future<ResponseStream<Utxo>?> utxos(UtxosRequest request) async { static Future<ResponseStream<Utxo>?> utxos(UtxosRequest request) async {
log("mweb.utxos() called");
try { try {
if (_rpcClient == null) { _rpcClient = await stub();
await _initializeClient(); final resp = _rpcClient!
} .utxos(request, options: CallOptions(timeout: const Duration(days: 1000 * 365)));
// this is a stream, so we should have an effectively infinite timeout: log("got utxo stream");
return _rpcClient!.utxos(request, options: CallOptions(timeout: const Duration(days: 1000 * 365))); return resp;
} on GrpcError catch (e) {
log('Caught grpc error: ${e.message}');
} catch (e) { } catch (e) {
print("Error getting utxos: $e"); log("Error getting utxos: $e");
}
return null; return null;
} }
}
} }

View file

@ -1,3 +1,5 @@
import 'dart:io' show Platform;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -11,6 +13,9 @@ class MethodChannelCwMweb extends CwMwebPlatform {
@override @override
Future<int?> start(String dataDir, String nodeUri) async { Future<int?> start(String dataDir, String nodeUri) async {
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
return null;
}
final result = final result =
await methodChannel.invokeMethod<int>('start', {'dataDir': dataDir, 'nodeUri': nodeUri}); await methodChannel.invokeMethod<int>('start', {'dataDir': dataDir, 'nodeUri': nodeUri});
return result; return result;
@ -18,11 +23,17 @@ class MethodChannelCwMweb extends CwMwebPlatform {
@override @override
Future<void> stop() async { Future<void> stop() async {
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
return;
}
await methodChannel.invokeMethod<void>('stop'); await methodChannel.invokeMethod<void>('stop');
} }
@override @override
Future<String?> address(Uint8List scanSecret, Uint8List spendPub, int index) async { Future<String?> address(Uint8List scanSecret, Uint8List spendPub, int index) async {
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
return null;
}
final result = await methodChannel.invokeMethod<String>('address', { final result = await methodChannel.invokeMethod<String>('address', {
'scanSecret': scanSecret, 'scanSecret': scanSecret,
'spendPub': spendPub, 'spendPub': spendPub,
@ -30,4 +41,18 @@ class MethodChannelCwMweb extends CwMwebPlatform {
}); });
return result; return result;
} }
@override
Future<String?> addresses(Uint8List scanSecret, Uint8List spendPub, int fromIndex, int toIndex) async {
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
return null;
}
final result = await methodChannel.invokeMethod<String>('addresses', {
'scanSecret': scanSecret,
'spendPub': spendPub,
'fromIndex': fromIndex,
'toIndex': toIndex,
});
return result;
}
} }

View file

@ -36,4 +36,8 @@ abstract class CwMwebPlatform extends PlatformInterface {
Future<String?> address(Uint8List scanSecret, Uint8List spendPub, int index) { Future<String?> address(Uint8List scanSecret, Uint8List spendPub, int index) {
throw UnimplementedError('address(int) has not been implemented.'); throw UnimplementedError('address(int) has not been implemented.');
} }
Future<String?> addresses(Uint8List scanSecret, Uint8List spendPub, int fromIndex, int toIndex) {
throw UnimplementedError('addresses has not been implemented.');
}
} }

View file

@ -149,7 +149,7 @@ abstract class NanoWalletBase
Future<void> changePassword(String password) => throw UnimplementedError("changePassword"); Future<void> changePassword(String password) => throw UnimplementedError("changePassword");
@override @override
void close() { Future<void> close({required bool shouldCleanup}) async {
_client.stop(); _client.stop();
_receiveTimer?.cancel(); _receiveTimer?.cancel();
} }

View file

@ -117,10 +117,10 @@ packages:
dependency: "direct overridden" dependency: "direct overridden"
description: description:
name: build_runner_core name: build_runner_core
sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" sha256: "0671ad4162ed510b70d0eb4ad6354c249f8429cab4ae7a4cec86bbc2886eb76e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.2.7" version: "7.2.7+1"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:

View file

@ -179,7 +179,7 @@ abstract class SolanaWalletBase
Future<void> changePassword(String password) => throw UnimplementedError("changePassword"); Future<void> changePassword(String password) => throw UnimplementedError("changePassword");
@override @override
void close() { Future<void> close({required bool shouldCleanup}) async {
_client.stop(); _client.stop();
_transactionsUpdateTimer?.cancel(); _transactionsUpdateTimer?.cancel();
} }

View file

@ -217,7 +217,7 @@ abstract class TronWalletBase
Future<void> changePassword(String password) => throw UnimplementedError("changePassword"); Future<void> changePassword(String password) => throw UnimplementedError("changePassword");
@override @override
void close() => _transactionsUpdateTimer?.cancel(); Future<void> close({required bool shouldCleanup}) async => _transactionsUpdateTimer?.cancel();
@action @action
@override @override

View file

@ -160,7 +160,7 @@ abstract class WowneroWalletBase
Future<void>? updateBalance() => null; Future<void>? updateBalance() => null;
@override @override
void close() async { Future<void> close({required bool shouldCleanup}) async {
_listener?.stop(); _listener?.stop();
_onAccountChangeReaction?.reaction.dispose(); _onAccountChangeReaction?.reaction.dispose();
_onTxHistoryChangeReaction?.reaction.dispose(); _onTxHistoryChangeReaction?.reaction.dispose();

View file

@ -134,7 +134,7 @@ class WowneroWalletService extends WalletService<
if (!isValid) { if (!isValid) {
await restoreOrResetWalletFiles(name); await restoreOrResetWalletFiles(name);
wallet.close(); wallet.close(shouldCleanup: false);
return openWallet(name, password); return openWallet(name, password);
} }

View file

@ -7,7 +7,38 @@ PODS:
- Flutter - Flutter
- ReachabilitySwift - ReachabilitySwift
- CryptoSwift (1.8.2) - CryptoSwift (1.8.2)
- cw_haven (0.0.1):
- cw_haven/Boost (= 0.0.1)
- cw_haven/Haven (= 0.0.1)
- cw_haven/OpenSSL (= 0.0.1)
- cw_haven/Sodium (= 0.0.1)
- cw_shared_external
- Flutter
- cw_haven/Boost (0.0.1):
- cw_shared_external
- Flutter
- cw_haven/Haven (0.0.1):
- cw_shared_external
- Flutter
- cw_haven/OpenSSL (0.0.1):
- cw_shared_external
- Flutter
- cw_haven/Sodium (0.0.1):
- cw_shared_external
- Flutter
- cw_mweb (0.0.1): - cw_mweb (0.0.1):
- Flutter
- cw_shared_external (0.0.1):
- cw_shared_external/Boost (= 0.0.1)
- cw_shared_external/OpenSSL (= 0.0.1)
- cw_shared_external/Sodium (= 0.0.1)
- Flutter
- cw_shared_external/Boost (0.0.1):
- Flutter
- cw_shared_external/OpenSSL (0.0.1):
- Flutter
- cw_shared_external/Sodium (0.0.1):
- Flutter
- device_display_brightness (0.0.1): - device_display_brightness (0.0.1):
- Flutter - Flutter
- device_info_plus (0.0.1): - device_info_plus (0.0.1):
@ -96,7 +127,7 @@ PODS:
- FlutterMacOS - FlutterMacOS
- sp_scanner (0.0.1): - sp_scanner (0.0.1):
- Flutter - Flutter
- SwiftProtobuf (1.26.0) - SwiftProtobuf (1.27.1)
- SwiftyGif (5.4.5) - SwiftyGif (5.4.5)
- Toast (4.1.1) - Toast (4.1.1)
- uni_links (0.0.1): - uni_links (0.0.1):
@ -112,7 +143,9 @@ DEPENDENCIES:
- barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`) - barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`)
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
- CryptoSwift - CryptoSwift
- cw_haven (from `.symlinks/plugins/cw_haven/ios`)
- cw_mweb (from `.symlinks/plugins/cw_mweb/ios`) - cw_mweb (from `.symlinks/plugins/cw_mweb/ios`)
- cw_shared_external (from `.symlinks/plugins/cw_shared_external/ios`)
- device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`) - device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- devicelocale (from `.symlinks/plugins/devicelocale/ios`) - devicelocale (from `.symlinks/plugins/devicelocale/ios`)
@ -125,7 +158,6 @@ DEPENDENCIES:
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- in_app_review (from `.symlinks/plugins/in_app_review/ios`) - in_app_review (from `.symlinks/plugins/in_app_review/ios`)
- integration_test (from `.symlinks/plugins/integration_test/ios`) - integration_test (from `.symlinks/plugins/integration_test/ios`)
- package_info (from `.symlinks/plugins/package_info/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
@ -158,8 +190,12 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/barcode_scan2/ios" :path: ".symlinks/plugins/barcode_scan2/ios"
connectivity_plus: connectivity_plus:
:path: ".symlinks/plugins/connectivity_plus/ios" :path: ".symlinks/plugins/connectivity_plus/ios"
cw_haven:
:path: ".symlinks/plugins/cw_haven/ios"
cw_mweb: cw_mweb:
:path: ".symlinks/plugins/cw_mweb/ios" :path: ".symlinks/plugins/cw_mweb/ios"
cw_shared_external:
:path: ".symlinks/plugins/cw_shared_external/ios"
device_display_brightness: device_display_brightness:
:path: ".symlinks/plugins/device_display_brightness/ios" :path: ".symlinks/plugins/device_display_brightness/ios"
device_info_plus: device_info_plus:
@ -184,8 +220,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/in_app_review/ios" :path: ".symlinks/plugins/in_app_review/ios"
integration_test: integration_test:
:path: ".symlinks/plugins/integration_test/ios" :path: ".symlinks/plugins/integration_test/ios"
package_info:
:path: ".symlinks/plugins/package_info/ios"
package_info_plus: package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios" :path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation: path_provider_foundation:
@ -215,7 +249,9 @@ SPEC CHECKSUMS:
barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0 barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0
connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d
CryptoSwift: c63a805d8bb5e5538e88af4e44bb537776af11ea CryptoSwift: c63a805d8bb5e5538e88af4e44bb537776af11ea
cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a
cw_mweb: 87af74f9659fed0c1a2cbfb44413f1070e79e3ae cw_mweb: 87af74f9659fed0c1a2cbfb44413f1070e79e3ae
cw_shared_external: 2972d872b8917603478117c9957dfca611845a92
device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7 device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
devicelocale: b22617f40038496deffba44747101255cee005b0 devicelocale: b22617f40038496deffba44747101255cee005b0
@ -243,7 +279,7 @@ SPEC CHECKSUMS:
share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sp_scanner: eaa617fa827396b967116b7f1f43549ca62e9a12 sp_scanner: eaa617fa827396b967116b7f1f43549ca62e9a12
SwiftProtobuf: 5e8349171e7c2f88f5b9e683cb3cb79d1dc780b3 SwiftProtobuf: b109bd17979d7993a84da14b1e1fdd8b0ded934a
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a uni_links: d97da20c7701486ba192624d99bffaaffcfc298a

View file

@ -14,12 +14,12 @@
2193F104374FA2746CE8945B /* ResourceHelper.swift in Resources */ = {isa = PBXBuildFile; fileRef = 78D25C60B94E9D9E48D52E5E /* ResourceHelper.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; }; 2193F104374FA2746CE8945B /* ResourceHelper.swift in Resources */ = {isa = PBXBuildFile; fileRef = 78D25C60B94E9D9E48D52E5E /* ResourceHelper.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
495FEFF9B395392FED3425DE /* TaskProtocol.swift in Resources */ = {isa = PBXBuildFile; fileRef = 0F42D8065219E0653321EE2B /* TaskProtocol.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; }; 495FEFF9B395392FED3425DE /* TaskProtocol.swift in Resources */ = {isa = PBXBuildFile; fileRef = 0F42D8065219E0653321EE2B /* TaskProtocol.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; };
4DFD1BB54A3A50573E19A583 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C663361C56EBB242598F609 /* Pods_Runner.framework */; };
525A2200C6C2A43EDC5C8FC5 /* BreezSDKConnector.swift in Resources */ = {isa = PBXBuildFile; fileRef = 1FB06A93B13D606F06B3924D /* BreezSDKConnector.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; }; 525A2200C6C2A43EDC5C8FC5 /* BreezSDKConnector.swift in Resources */ = {isa = PBXBuildFile; fileRef = 1FB06A93B13D606F06B3924D /* BreezSDKConnector.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; };
6909E1D79C9986ADF2DE41E9 /* LnurlPayInvoice.swift in Resources */ = {isa = PBXBuildFile; fileRef = DCEA540E3586164FB47AD13E /* LnurlPayInvoice.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; }; 6909E1D79C9986ADF2DE41E9 /* LnurlPayInvoice.swift in Resources */ = {isa = PBXBuildFile; fileRef = DCEA540E3586164FB47AD13E /* LnurlPayInvoice.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; };
724FDA327BF191BC29DCAA2E /* Constants.swift in Resources */ = {isa = PBXBuildFile; fileRef = 0CCA7ADAD6FF9185EBBB2BCA /* Constants.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; }; 724FDA327BF191BC29DCAA2E /* Constants.swift in Resources */ = {isa = PBXBuildFile; fileRef = 0CCA7ADAD6FF9185EBBB2BCA /* Constants.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; };
73138617307FA4F838D21D62 /* ServiceLogger.swift in Resources */ = {isa = PBXBuildFile; fileRef = F42258C3697CFE3C8C8D1933 /* ServiceLogger.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; }; 73138617307FA4F838D21D62 /* ServiceLogger.swift in Resources */ = {isa = PBXBuildFile; fileRef = F42258C3697CFE3C8C8D1933 /* ServiceLogger.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
8B1F4FCAA5EB9F3A83D32D5F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D7CD6B6020744E8FA471915D /* Pods_Runner.framework */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
@ -50,6 +50,7 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
014D7E4DBCFD76DDE652A4D9 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
0C400E0F25B21ABB0025E469 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; }; 0C400E0F25B21ABB0025E469 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
0C44A7192518EF8000B570ED /* decrypt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = decrypt.swift; sourceTree = "<group>"; }; 0C44A7192518EF8000B570ED /* decrypt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = decrypt.swift; sourceTree = "<group>"; };
0C50DFB82BF3CB56002B0EB3 /* MoneroWallet.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = MoneroWallet.framework; sourceTree = "<group>"; }; 0C50DFB82BF3CB56002B0EB3 /* MoneroWallet.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = MoneroWallet.framework; sourceTree = "<group>"; };
@ -57,13 +58,11 @@
0C9D68C8264854B60011B691 /* secRandom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = secRandom.swift; sourceTree = "<group>"; }; 0C9D68C8264854B60011B691 /* secRandom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = secRandom.swift; sourceTree = "<group>"; };
0CCA7ADAD6FF9185EBBB2BCA /* Constants.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Constants.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/Constants.swift"; sourceTree = "<group>"; }; 0CCA7ADAD6FF9185EBBB2BCA /* Constants.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Constants.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/Constants.swift"; sourceTree = "<group>"; };
0F42D8065219E0653321EE2B /* TaskProtocol.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TaskProtocol.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/TaskProtocol.swift"; sourceTree = "<group>"; }; 0F42D8065219E0653321EE2B /* TaskProtocol.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TaskProtocol.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/TaskProtocol.swift"; sourceTree = "<group>"; };
11F9FC13F9EE2A705B213FA9 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
1F083F2041D1F553F2AF8B62 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
1FB06A93B13D606F06B3924D /* BreezSDKConnector.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BreezSDKConnector.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/BreezSDKConnector.swift"; sourceTree = "<group>"; }; 1FB06A93B13D606F06B3924D /* BreezSDKConnector.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BreezSDKConnector.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/BreezSDKConnector.swift"; sourceTree = "<group>"; };
28F61114229803070973270D /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3C663361C56EBB242598F609 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
41102141140E57B1DC27FBA1 /* SDKNotificationService.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SDKNotificationService.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/SDKNotificationService.swift"; sourceTree = "<group>"; }; 41102141140E57B1DC27FBA1 /* SDKNotificationService.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SDKNotificationService.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/SDKNotificationService.swift"; sourceTree = "<group>"; };
58C22CBD8C22B9D6023D59F8 /* LnurlPayInfo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LnurlPayInfo.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/Task/LnurlPayInfo.swift"; sourceTree = "<group>"; }; 58C22CBD8C22B9D6023D59F8 /* LnurlPayInfo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LnurlPayInfo.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/Task/LnurlPayInfo.swift"; sourceTree = "<group>"; };
5AFFEBFC279AD49C00F906A4 /* wakeLock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = wakeLock.swift; sourceTree = "<group>"; }; 5AFFEBFC279AD49C00F906A4 /* wakeLock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = wakeLock.swift; sourceTree = "<group>"; };
@ -83,11 +82,12 @@
9D2F2C9F2555316C95EE7EA3 /* RedeemSwap.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RedeemSwap.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/Task/RedeemSwap.swift"; sourceTree = "<group>"; }; 9D2F2C9F2555316C95EE7EA3 /* RedeemSwap.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RedeemSwap.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/Task/RedeemSwap.swift"; sourceTree = "<group>"; };
9F46EE5D2BC11178009318F5 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; }; 9F46EE5D2BC11178009318F5 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
ABD6FCBB0F4244B090459128 /* BreezSDK.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BreezSDK.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/BreezSDK.swift"; sourceTree = "<group>"; }; ABD6FCBB0F4244B090459128 /* BreezSDK.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BreezSDK.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/BreezSDK.swift"; sourceTree = "<group>"; };
AD0937B0140D5A4C24E73BEA /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
B3D5E78267F5F18D882FDC3B /* ServiceConfig.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ServiceConfig.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/ServiceConfig.swift"; sourceTree = "<group>"; }; B3D5E78267F5F18D882FDC3B /* ServiceConfig.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ServiceConfig.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/ServiceConfig.swift"; sourceTree = "<group>"; };
C58D93382C00FAC6004BCF69 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; }; C58D93382C00FAC6004BCF69 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; };
CE291CFD2C15DB9A00B9F709 /* WowneroWallet.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = WowneroWallet.framework; sourceTree = "<group>"; }; CE291CFD2C15DB9A00B9F709 /* WowneroWallet.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = WowneroWallet.framework; sourceTree = "<group>"; };
CEAFE49D2C539250009FF3AD /* Mwebd.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Mwebd.xcframework; sourceTree = "<group>"; }; CEAFE49D2C539250009FF3AD /* Mwebd.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Mwebd.xcframework; sourceTree = "<group>"; };
D139E30AEB36740C21C00A9E /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
D7CD6B6020744E8FA471915D /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DCEA540E3586164FB47AD13E /* LnurlPayInvoice.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LnurlPayInvoice.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/Task/LnurlPayInvoice.swift"; sourceTree = "<group>"; }; DCEA540E3586164FB47AD13E /* LnurlPayInvoice.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LnurlPayInvoice.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/Task/LnurlPayInvoice.swift"; sourceTree = "<group>"; };
F42258C3697CFE3C8C8D1933 /* ServiceLogger.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ServiceLogger.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/ServiceLogger.swift"; sourceTree = "<group>"; }; F42258C3697CFE3C8C8D1933 /* ServiceLogger.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ServiceLogger.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/ServiceLogger.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@ -97,8 +97,8 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
4DFD1BB54A3A50573E19A583 /* Pods_Runner.framework in Frameworks */,
CEAFE4A02C53926F009FF3AD /* libresolv.tbd in Frameworks */, CEAFE4A02C53926F009FF3AD /* libresolv.tbd in Frameworks */,
8B1F4FCAA5EB9F3A83D32D5F /* Pods_Runner.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -111,7 +111,7 @@
CEAFE49D2C539250009FF3AD /* Mwebd.xcframework */, CEAFE49D2C539250009FF3AD /* Mwebd.xcframework */,
C58D93382C00FAC6004BCF69 /* libresolv.tbd */, C58D93382C00FAC6004BCF69 /* libresolv.tbd */,
0C9986A3251A932F00D566FD /* CryptoSwift.framework */, 0C9986A3251A932F00D566FD /* CryptoSwift.framework */,
3C663361C56EBB242598F609 /* Pods_Runner.framework */, D7CD6B6020744E8FA471915D /* Pods_Runner.framework */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
@ -137,10 +137,10 @@
84389F1A05D5860790D82820 /* Pods */ = { 84389F1A05D5860790D82820 /* Pods */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
11F9FC13F9EE2A705B213FA9 /* Pods-Runner.debug.xcconfig */,
1F083F2041D1F553F2AF8B62 /* Pods-Runner.release.xcconfig */,
AD0937B0140D5A4C24E73BEA /* Pods-Runner.profile.xcconfig */,
0B80439B9064C9708DDB0ADA /* breez_sdk-OnDemandResources */, 0B80439B9064C9708DDB0ADA /* breez_sdk-OnDemandResources */,
014D7E4DBCFD76DDE652A4D9 /* Pods-Runner.debug.xcconfig */,
28F61114229803070973270D /* Pods-Runner.release.xcconfig */,
D139E30AEB36740C21C00A9E /* Pods-Runner.profile.xcconfig */,
); );
path = Pods; path = Pods;
sourceTree = "<group>"; sourceTree = "<group>";
@ -222,14 +222,14 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = ( buildPhases = (
B91154210ADCED81FBF06A85 /* [CP] Check Pods Manifest.lock */, 11278EDF4D5DB437B3FDB787 /* [CP] Check Pods Manifest.lock */,
CE5E8A222BEE19C700608EA1 /* CopyFiles */, CE5E8A222BEE19C700608EA1 /* CopyFiles */,
9740EEB61CF901F6004384FC /* Run Script */, 9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */, 97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */, 97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */, 97C146EC1CF9000F007C117D /* Resources */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
32D0076A9969C0C38D68AF62 /* [CP] Embed Pods Frameworks */, F6F67323547956BC4F7B67F1 /* [CP] Embed Pods Frameworks */,
); );
buildRules = ( buildRules = (
); );
@ -305,21 +305,26 @@
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
32D0076A9969C0C38D68AF62 /* [CP] Embed Pods Frameworks */ = { 11278EDF4D5DB437B3FDB787 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputFileListPaths = ( inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
); );
name = "[CP] Embed Pods Frameworks"; inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = ( outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", );
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
@ -353,26 +358,21 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
}; };
B91154210ADCED81FBF06A85 /* [CP] Check Pods Manifest.lock */ = { F6F67323547956BC4F7B67F1 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputFileListPaths = ( inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
); );
inputPaths = ( name = "[CP] Embed Pods Frameworks";
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = ( outputFileListPaths = (
); "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
/* End PBXShellScriptBuildPhase section */ /* End PBXShellScriptBuildPhase section */

View file

@ -262,7 +262,14 @@ class CWBitcoin extends Bitcoin {
List<ReceivePageOption> getBitcoinReceivePageOptions() => BitcoinReceivePageOption.all; List<ReceivePageOption> getBitcoinReceivePageOptions() => BitcoinReceivePageOption.all;
@override @override
List<ReceivePageOption> getLitecoinReceivePageOptions() => BitcoinReceivePageOption.allLitecoin; List<ReceivePageOption> getLitecoinReceivePageOptions() {
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
return BitcoinReceivePageOption.allLitecoin
.where((element) => element != BitcoinReceivePageOption.mweb)
.toList();
}
return BitcoinReceivePageOption.allLitecoin;
}
@override @override
BitcoinAddressType getBitcoinAddressType(ReceivePageOption option) { BitcoinAddressType getBitcoinAddressType(ReceivePageOption option) {
@ -608,7 +615,7 @@ class CWBitcoin extends Bitcoin {
final updatedOutputs = outputs.map((output) { final updatedOutputs = outputs.map((output) {
try { try {
final pendingOut = pendingTx!.outputs[outputs.indexOf(output)]; final pendingOut = pendingTx.outputs[outputs.indexOf(output)];
final updatedOutput = output; final updatedOutput = output;
updatedOutput.stealthAddress = P2trAddress.fromScriptPubkey(script: pendingOut.scriptPubKey) updatedOutput.stealthAddress = P2trAddress.fromScriptPubkey(script: pendingOut.scriptPubKey)
@ -658,8 +665,8 @@ class CWBitcoin extends Bitcoin {
String? getUnusedMwebAddress(Object wallet) { String? getUnusedMwebAddress(Object wallet) {
try { try {
final electrumWallet = wallet as ElectrumWallet; final electrumWallet = wallet as ElectrumWallet;
final walletAddresses = electrumWallet.walletAddresses as ElectrumWalletAddresses; final mwebAddress =
final mwebAddress = walletAddresses.mwebAddresses.firstWhere((element) => !element.isUsed); electrumWallet.walletAddresses.mwebAddresses.firstWhere((element) => !element.isUsed);
return mwebAddress.address; return mwebAddress.address;
} catch (_) { } catch (_) {
return null; return null;

View file

@ -6,7 +6,6 @@ import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart';
import 'package:cake_wallet/routes.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/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/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_one_action.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
@ -20,12 +19,11 @@ 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/dashboard_page_theme.dart';
import 'package:cake_wallet/themes/extensions/sync_indicator_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/feature_flag.dart';
import 'package:cake_wallet/utils/payment_request.dart';
import 'package:cake_wallet/utils/show_pop_up.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/dashboard_view_model.dart';
import 'package:cake_wallet/view_model/dashboard/nft_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:cw_core/crypto_currency.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
@ -382,18 +380,10 @@ class CryptoBalanceWidget extends StatelessWidget {
child: DashBoardRoundedCardWidget( child: DashBoardRoundedCardWidget(
customBorder: 30, customBorder: 30,
title: S.of(context).litecoin_mweb, title: S.of(context).litecoin_mweb,
subTitle: '', subTitle: S.of(context).litecoin_mweb_description,
hint: Column( hint: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text(
S.of(context).litecoin_mweb_description,
style: TextStyle(
color: Colors.white,
fontSize: 14,
),
textAlign: TextAlign.center,
),
SizedBox(height: 8),
GestureDetector( GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () => launchUrl( onTap: () => launchUrl(
@ -401,7 +391,6 @@ class CryptoBalanceWidget extends StatelessWidget {
"https://guides.cakewallet.com/docs/cryptos/litecoin/#mweb"), "https://guides.cakewallet.com/docs/cryptos/litecoin/#mweb"),
mode: LaunchMode.externalApplication, mode: LaunchMode.externalApplication,
), ),
child: Center(
child: Text( child: Text(
S.of(context).learn_more, S.of(context).learn_more,
style: TextStyle( style: TextStyle(
@ -416,38 +405,50 @@ class CryptoBalanceWidget extends StatelessWidget {
softWrap: true, softWrap: true,
), ),
), ),
), SizedBox(height: 8),
SizedBox(height: 24),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
ElevatedButton( Expanded(
child: ElevatedButton(
onPressed: () => _dismissMweb(context), onPressed: () => _dismissMweb(context),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).primaryColor, backgroundColor: Theme.of(context).primaryColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
), ),
child: Text( child: Text(
S.of(context).litecoin_mweb_dismiss, S.of(context).litecoin_mweb_dismiss,
style: TextStyle(color: Colors.white), style: TextStyle(color: Colors.white),
), ),
), ),
ElevatedButton( ),
const SizedBox(width: 8),
Expanded(
child: ElevatedButton(
onPressed: () => _enableMweb(context), onPressed: () => _enableMweb(context),
child: Text(S.of(context).litecoin_enable_mweb_sync), style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
foregroundColor: Colors.black,
),
child: Text(
S.of(context).enable,
maxLines: 1,
),
),
), ),
], ],
), ),
], ],
), ),
onTap: () => {}, onTap: () => {},
icon: ImageIcon( icon: Container(
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: ImageIcon(
AssetImage('assets/images/mweb_logo.png'), AssetImage('assets/images/mweb_logo.png'),
color: color: Color.fromARGB(255, 11, 70, 129),
Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor, size: 40,
size: 50, ),
), ),
), ),
), ),
@ -505,7 +506,7 @@ class CryptoBalanceWidget extends StatelessWidget {
}, },
)); ));
} }
dashboardViewModel.setMwebScanningActive(); dashboardViewModel.setMwebEnabled();
} }
Future<void> _dismissMweb(BuildContext context) async { Future<void> _dismissMweb(BuildContext context) async {
@ -850,23 +851,15 @@ class BalanceRowWidget extends StatelessWidget {
padding: EdgeInsets.only(right: 16, top: 16), padding: EdgeInsets.only(right: 16, top: 16),
child: Column( child: Column(
children: [ children: [
CakeImageWidget( Container(
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( decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle, shape: BoxShape.circle,
color: Colors.grey.shade400,
), ),
child: ImageIcon(
AssetImage('assets/images/mweb_logo.png'),
color: Color.fromARGB(255, 11, 70, 129),
size: 40,
), ),
), ),
const SizedBox(height: 10), const SizedBox(height: 10),

View file

@ -97,14 +97,13 @@ class MenuWidgetState extends State<MenuWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
List<SettingActions> items = SettingActions.all; List<SettingActions> items = List.of(SettingActions.all);
if (!widget.dashboardViewModel.hasSilentPayments) { if (!widget.dashboardViewModel.hasSilentPayments) {
items.removeWhere((element) => element.name(context) == S.of(context).silent_payments_settings); items.removeWhere((element) => element.name(context) == S.of(context).silent_payments_settings);
} }
// if (!widget.dashboardViewModel.hasMweb) { if (!widget.dashboardViewModel.hasMweb) {
// itemCount--; items.removeWhere((element) => element.name(context) == S.of(context).litecoin_mweb_settings);
// items.removeWhere((element) => element.name(context) == S.of(context).litecoin_mweb_settings); }
// }
int itemCount = items.length; int itemCount = items.length;
moneroIcon = Image.asset('assets/images/monero_menu.png', moneroIcon = Image.asset('assets/images/monero_menu.png',
@ -191,11 +190,6 @@ class MenuWidgetState extends State<MenuWidget> {
final item = items[index]; final item = items[index];
if (!widget.dashboardViewModel.hasMweb &&
item.name(context) == S.of(context).litecoin_mweb_settings) {
return const SizedBox();
}
final isLastTile = index == itemCount - 1; final isLastTile = index == itemCount - 1;
return SettingActionButton( return SettingActionButton(

View file

@ -135,10 +135,6 @@ class RootState extends State<Root> with WidgetsBindingObserver {
setState(() => _setInactive(true)); setState(() => _setInactive(true));
} }
if (widget.appStore.wallet?.type == WalletType.litecoin) {
widget.appStore.wallet?.stopSync();
}
break; break;
case AppLifecycleState.resumed: case AppLifecycleState.resumed:
widget.authService.requireAuth().then((value) { widget.authService.requireAuth().then((value) {
@ -148,9 +144,6 @@ class RootState extends State<Root> with WidgetsBindingObserver {
}); });
} }
}); });
if (widget.appStore.wallet?.type == WalletType.litecoin) {
widget.appStore.wallet?.startSync();
}
break; break;
default: default:
break; break;

View file

@ -4,7 +4,6 @@ import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
import 'package:cake_wallet/view_model/settings/mweb_settings_view_model.dart'; import 'package:cake_wallet/view_model/settings/mweb_settings_view_model.dart';
import 'package:cake_wallet/view_model/settings/silent_payments_settings_view_model.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart';
@ -33,9 +32,9 @@ class MwebSettingsPage extends BasePage {
), ),
SettingsSwitcherCell( SettingsSwitcherCell(
title: S.current.litecoin_mweb_always_scan, title: S.current.litecoin_mweb_always_scan,
value: _mwebSettingsViewModel.mwebAlwaysScan, value: _mwebSettingsViewModel.mwebEnabled,
onValueChange: (_, bool value) { onValueChange: (_, bool value) {
_mwebSettingsViewModel.setMwebAlwaysScan(value); _mwebSettingsViewModel.setMwebEnabled(value);
}, },
), ),
SettingsCellWithArrow( SettingsCellWithArrow(

View file

@ -31,7 +31,6 @@ class SettingActions {
walletSettingAction, walletSettingAction,
addressBookSettingAction, addressBookSettingAction,
silentPaymentsSettingAction, silentPaymentsSettingAction,
litecoinMwebSettingAction,
securityBackupSettingAction, securityBackupSettingAction,
privacySettingAction, privacySettingAction,
displaySettingAction, displaySettingAction,
@ -50,7 +49,7 @@ class SettingActions {
static SettingActions litecoinMwebSettingAction = SettingActions._( static SettingActions litecoinMwebSettingAction = SettingActions._(
name: (context) => S.of(context).litecoin_mweb_settings, name: (context) => S.of(context).litecoin_mweb_settings,
image: 'assets/images/bitcoin_menu.png', image: 'assets/images/litecoin_menu.png',
onTap: (BuildContext context) { onTap: (BuildContext context) {
Navigator.pop(context); Navigator.pop(context);
Navigator.of(context).pushNamed(Routes.mwebSettings); Navigator.of(context).pushNamed(Routes.mwebSettings);

View file

@ -37,7 +37,8 @@ abstract class AppStoreBase with Store {
@action @action
Future<void> changeCurrentWallet( Future<void> changeCurrentWallet(
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet) async { WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet) async {
this.wallet?.close(); bool changingToSameWalletType = this.wallet?.type == wallet.type;
this.wallet?.close(shouldCleanup: !changingToSameWalletType);
this.wallet = wallet; this.wallet = wallet;
this.wallet!.setExceptionHandler(ExceptionHandler.onError); this.wallet!.setExceptionHandler(ExceptionHandler.onError);

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart';
import 'package:cake_wallet/entities/sort_balance_types.dart'; import 'package:cake_wallet/entities/sort_balance_types.dart';
import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart';
@ -31,6 +32,7 @@ class BalanceRecord {
required this.fiatSecondAdditionalBalance, required this.fiatSecondAdditionalBalance,
required this.asset, required this.asset,
required this.formattedAssetTitle}); required this.formattedAssetTitle});
final String fiatAdditionalBalance; final String fiatAdditionalBalance;
final String fiatAvailableBalance; final String fiatAvailableBalance;
final String fiatFrozenBalance; final String fiatFrozenBalance;
@ -53,7 +55,22 @@ abstract class BalanceViewModelBase with Store {
: isReversing = false, : isReversing = false,
isShowCard = appStore.wallet!.walletInfo.isShowIntroCakePayCard, isShowCard = appStore.wallet!.walletInfo.isShowIntroCakePayCard,
wallet = appStore.wallet! { wallet = appStore.wallet! {
reaction((_) => appStore.wallet, _onWalletChange); reaction((_) => appStore.wallet, (wallet) {
_onWalletChange(wallet);
_checkMweb();
});
_checkMweb();
reaction((_) => settingsStore.mwebAlwaysScan, (bool value) {
_checkMweb();
});
}
void _checkMweb() {
if (wallet.type == WalletType.litecoin) {
mwebEnabled = bitcoin!.getMwebEnabled(wallet);
}
} }
final AppStore appStore; final AppStore appStore;
@ -336,14 +353,19 @@ abstract class BalanceViewModelBase with Store {
}); });
} }
@observable
bool mwebEnabled = false;
@computed @computed
bool get hasAdditionalBalance => _hasAdditionalBalanceForWalletType(wallet.type); bool get hasAdditionalBalance => _hasAdditionalBalanceForWalletType(wallet.type);
@computed @computed
bool get hasSecondAdditionalBalance => _hasSecondAdditionalBalanceForWalletType(wallet.type); bool get hasSecondAdditionalBalance =>
mwebEnabled && _hasSecondAdditionalBalanceForWalletType(wallet.type);
@computed @computed
bool get hasSecondAvailableBalance => _hasSecondAvailableBalanceForWalletType(wallet.type); bool get hasSecondAvailableBalance =>
mwebEnabled && _hasSecondAvailableBalanceForWalletType(wallet.type);
bool _hasAdditionalBalanceForWalletType(WalletType type) { bool _hasAdditionalBalanceForWalletType(WalletType type) {
switch (type) { switch (type) {
@ -358,15 +380,16 @@ abstract class BalanceViewModelBase with Store {
} }
bool _hasSecondAdditionalBalanceForWalletType(WalletType type) { bool _hasSecondAdditionalBalanceForWalletType(WalletType type) {
if (wallet.type == WalletType.litecoin && settingsStore.mwebAlwaysScan) { if (wallet.type == WalletType.litecoin) {
// if ((wallet.balance[CryptoCurrency.ltc]?.secondAdditional ?? 0) > 0) if ((wallet.balance[CryptoCurrency.ltc]?.secondAdditional ?? 0) > 0) {
return true; return true;
} }
}
return false; return false;
} }
bool _hasSecondAvailableBalanceForWalletType(WalletType type) { bool _hasSecondAvailableBalanceForWalletType(WalletType type) {
if (wallet.type == WalletType.litecoin && settingsStore.mwebAlwaysScan) { if (wallet.type == WalletType.litecoin) {
return true; return true;
} }
return false; return false;

View file

@ -1,4 +1,6 @@
import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io' show Platform;
import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/.secrets.g.dart' as secrets;
import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart';
@ -222,7 +224,10 @@ abstract class DashboardViewModelBase with Store {
// subname = nano!.getCurrentAccount(_wallet).label; // subname = nano!.getCurrentAccount(_wallet).label;
// } // }
reaction((_) => appStore.wallet, _onWalletChange); reaction((_) => appStore.wallet, (wallet) {
_onWalletChange(wallet);
_checkMweb();
});
connectMapToListWithTransform( connectMapToListWithTransform(
appStore.wallet!.transactionHistory.transactions, appStore.wallet!.transactionHistory.transactions,
@ -256,17 +261,17 @@ abstract class DashboardViewModelBase with Store {
}); });
} }
if (hasMweb) { _checkMweb();
mwebScanningActive = bitcoin!.getMwebEnabled(wallet); reaction((_) => settingsStore.mwebAlwaysScan, (bool value) {
settingsStore.mwebEnabled = mwebScanningActive; _checkMweb();
reaction((_) => settingsStore.mwebAlwaysScan, (bool alwaysScan) {
if (alwaysScan) {
mwebScanningActive = true;
} else {
mwebScanningActive = false;
}
}); });
} }
void _checkMweb() {
if (hasMweb) {
mwebEnabled = bitcoin!.getMwebEnabled(wallet);
balanceViewModel.mwebEnabled = mwebEnabled;
}
} }
@observable @observable
@ -430,34 +435,36 @@ abstract class DashboardViewModelBase with Store {
} }
@computed @computed
bool get hasMweb => wallet.type == WalletType.litecoin; bool get hasMweb => wallet.type == WalletType.litecoin && (Platform.isIOS || Platform.isAndroid);
@computed @computed
bool get showMwebCard => hasMweb && settingsStore.mwebCardDisplay && !mwebScanningActive; bool get showMwebCard => hasMweb && settingsStore.mwebCardDisplay && !mwebEnabled;
@observable @observable
bool mwebScanningActive = false; bool mwebEnabled = false;
@computed @computed
bool get hasEnabledMwebBefore => settingsStore.hasEnabledMwebBefore; bool get hasEnabledMwebBefore => settingsStore.hasEnabledMwebBefore;
@action @action
void setMwebScanningActive() { void setMwebEnabled() {
if (!hasMweb) { if (!hasMweb) {
return; return;
} }
settingsStore.hasEnabledMwebBefore = true; settingsStore.hasEnabledMwebBefore = true;
mwebScanningActive = true; mwebEnabled = true;
bitcoin!.setMwebEnabled(wallet, true); bitcoin!.setMwebEnabled(wallet, true);
balanceViewModel.mwebEnabled = true;
settingsStore.mwebAlwaysScan = true; settingsStore.mwebAlwaysScan = true;
} }
@action @action
void dismissMweb() { void dismissMweb() {
settingsStore.mwebCardDisplay = false; settingsStore.mwebCardDisplay = false;
balanceViewModel.mwebEnabled = false;
settingsStore.mwebAlwaysScan = false; settingsStore.mwebAlwaysScan = false;
mwebScanningActive = false; mwebEnabled = false;
bitcoin!.setMwebEnabled(wallet, false); bitcoin!.setMwebEnabled(wallet, false);
} }

View file

@ -8,7 +8,10 @@ part 'mweb_settings_view_model.g.dart';
class MwebSettingsViewModel = MwebSettingsViewModelBase with _$MwebSettingsViewModel; class MwebSettingsViewModel = MwebSettingsViewModelBase with _$MwebSettingsViewModel;
abstract class MwebSettingsViewModelBase with Store { abstract class MwebSettingsViewModelBase with Store {
MwebSettingsViewModelBase(this._settingsStore, this._wallet); MwebSettingsViewModelBase(this._settingsStore, this._wallet) {
mwebEnabled = bitcoin!.getMwebEnabled(_wallet);
_settingsStore.mwebAlwaysScan = mwebEnabled;
}
final SettingsStore _settingsStore; final SettingsStore _settingsStore;
final WalletBase _wallet; final WalletBase _wallet;
@ -16,8 +19,8 @@ abstract class MwebSettingsViewModelBase with Store {
@computed @computed
bool get mwebCardDisplay => _settingsStore.mwebCardDisplay; bool get mwebCardDisplay => _settingsStore.mwebCardDisplay;
@computed @observable
bool get mwebAlwaysScan => _settingsStore.mwebAlwaysScan; late bool mwebEnabled;
@action @action
void setMwebCardDisplay(bool value) { void setMwebCardDisplay(bool value) {
@ -25,8 +28,9 @@ abstract class MwebSettingsViewModelBase with Store {
} }
@action @action
void setMwebAlwaysScan(bool value) { void setMwebEnabled(bool value) {
_settingsStore.mwebAlwaysScan = value; mwebEnabled = value;
bitcoin!.setMwebEnabled(_wallet, value); bitcoin!.setMwebEnabled(_wallet, value);
_settingsStore.mwebAlwaysScan = value;
} }
} }

View file

@ -188,7 +188,8 @@ abstract class WalletCreationVMBase with Store {
} }
} }
Future<List<DerivationInfo>> getDerivationInfoFromQRCredentials(RestoredWallet restoreWallet) async { Future<List<DerivationInfo>> getDerivationInfoFromQRCredentials(
RestoredWallet restoreWallet) async {
var list = <DerivationInfo>[]; var list = <DerivationInfo>[];
final walletType = restoreWallet.type; final walletType = restoreWallet.type;
var appStore = getIt.get<AppStore>(); var appStore = getIt.get<AppStore>();
@ -217,7 +218,8 @@ abstract class WalletCreationVMBase with Store {
Future<WalletBase> process(WalletCredentials credentials) => throw UnimplementedError(); Future<WalletBase> process(WalletCredentials credentials) => throw UnimplementedError();
Future<WalletCredentials> getWalletCredentialsFromQRCredentials(RestoredWallet restoreWallet) async => Future<WalletCredentials> getWalletCredentialsFromQRCredentials(
RestoredWallet restoreWallet) async =>
throw UnimplementedError(); throw UnimplementedError();
Future<WalletBase> processFromRestoredWallet( Future<WalletBase> processFromRestoredWallet(

View file

@ -70,6 +70,8 @@ abstract class WalletListViewModelBase with Store {
@action @action
Future<void> loadWallet(WalletListItem walletItem) async { Future<void> loadWallet(WalletListItem walletItem) async {
// bool switchingToSameWalletType = walletItem.type == _appStore.wallet?.type;
// await _appStore.wallet?.close(shouldCleanup: !switchingToSameWalletType);
final wallet = await _walletLoadingService.load(walletItem.type, walletItem.name); final wallet = await _walletLoadingService.load(walletItem.type, walletItem.name);
await _appStore.changeCurrentWallet(wallet); await _appStore.changeCurrentWallet(wallet);
} }

View file

@ -2,6 +2,8 @@ PODS:
- connectivity_plus (0.0.1): - connectivity_plus (0.0.1):
- FlutterMacOS - FlutterMacOS
- ReachabilitySwift - ReachabilitySwift
- cw_mweb (0.0.1):
- FlutterMacOS
- device_info_plus (0.0.1): - device_info_plus (0.0.1):
- FlutterMacOS - FlutterMacOS
- devicelocale (0.0.1): - devicelocale (0.0.1):
@ -37,6 +39,7 @@ PODS:
DEPENDENCIES: DEPENDENCIES:
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`) - connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`)
- cw_mweb (from `Flutter/ephemeral/.symlinks/plugins/cw_mweb/macos`)
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
- devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`) - devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`)
- flutter_inappwebview_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos`) - flutter_inappwebview_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos`)
@ -60,6 +63,8 @@ SPEC REPOS:
EXTERNAL SOURCES: EXTERNAL SOURCES:
connectivity_plus: connectivity_plus:
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos :path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos
cw_mweb:
:path: Flutter/ephemeral/.symlinks/plugins/cw_mweb/macos
device_info_plus: device_info_plus:
:path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos :path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
devicelocale: devicelocale:
@ -91,6 +96,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS: SPEC CHECKSUMS:
connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747 connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747
cw_mweb: 7440b12ead811dda972a9918442ea2a458e8742c
device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225 devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225
flutter_inappwebview_macos: 9600c9df9fdb346aaa8933812009f8d94304203d flutter_inappwebview_macos: 9600c9df9fdb346aaa8933812009f8d94304203d
@ -105,7 +111,7 @@ SPEC CHECKSUMS:
share_plus: 36537c04ce0c3e3f5bd297ce4318b6d5ee5fd6cf share_plus: 36537c04ce0c3e3f5bd297ce4318b6d5ee5fd6cf
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sp_scanner: 269d96e0ec3173e69156be7239b95182be3b8303 sp_scanner: 269d96e0ec3173e69156be7239b95182be3b8303
url_launcher_macos: 5f437abeda8c85500ceb03f5c1938a8c5a705399 url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404
wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269 wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269
PODFILE CHECKSUM: 65ec1541137fb5b35d00490dec1bb48d4d9586bb PODFILE CHECKSUM: 65ec1541137fb5b35d00490dec1bb48d4d9586bb

View file

@ -235,6 +235,7 @@
"edit_token": "تحرير الرمز المميز", "edit_token": "تحرير الرمز المميز",
"electrum_address_disclaimer": "نقوم بإنشاء عناوين جديدة في كل مرة تستخدم فيها عنوانًا ، لكن العناوين السابقة تستمر في العمل", "electrum_address_disclaimer": "نقوم بإنشاء عناوين جديدة في كل مرة تستخدم فيها عنوانًا ، لكن العناوين السابقة تستمر في العمل",
"email_address": "عنوان البريد الالكترونى", "email_address": "عنوان البريد الالكترونى",
"enable": "يُمكَِن",
"enable_mempool_api": "MEMPOOL API للحصول على رسوم وتواريخ دقيقة", "enable_mempool_api": "MEMPOOL API للحصول على رسوم وتواريخ دقيقة",
"enable_replace_by_fee": "تمكين الاستبدال", "enable_replace_by_fee": "تمكين الاستبدال",
"enable_silent_payments_scanning": "ابدأ في مسح المدفوعات الصامتة ، حتى يتم الوصول إلى الطرف", "enable_silent_payments_scanning": "ابدأ في مسح المدفوعات الصامتة ، حتى يتم الوصول إلى الطرف",

View file

@ -235,6 +235,7 @@
"edit_token": "Редактиране на токена", "edit_token": "Редактиране на токена",
"electrum_address_disclaimer": "Нови адреси се генерират всеки път, когато използвате този, но и предишните продължават да работят", "electrum_address_disclaimer": "Нови адреси се генерират всеки път, когато използвате този, но и предишните продължават да работят",
"email_address": "Имейл адрес", "email_address": "Имейл адрес",
"enable": "Активиране",
"enable_mempool_api": "Mempool API за точни такси и дати", "enable_mempool_api": "Mempool API за точни такси и дати",
"enable_replace_by_fee": "Активиране на замяна по забрана", "enable_replace_by_fee": "Активиране на замяна по забрана",
"enable_silent_payments_scanning": "Започнете да сканирате безшумните плащания, докато се достигне съветът", "enable_silent_payments_scanning": "Започнете да сканирате безшумните плащания, докато се достигне съветът",

View file

@ -235,6 +235,7 @@
"edit_token": "Upravit token", "edit_token": "Upravit token",
"electrum_address_disclaimer": "Po každém použití je generována nová adresa, ale předchozí adresy také stále fungují", "electrum_address_disclaimer": "Po každém použití je generována nová adresa, ale předchozí adresy také stále fungují",
"email_address": "E-mailová adresa", "email_address": "E-mailová adresa",
"enable": "Umožnit",
"enable_mempool_api": "Mempool API pro přesné poplatky a data", "enable_mempool_api": "Mempool API pro přesné poplatky a data",
"enable_replace_by_fee": "Povolit výměnu podle poplatku", "enable_replace_by_fee": "Povolit výměnu podle poplatku",
"enable_silent_payments_scanning": "Začněte skenovat tiché platby, dokud není dosaženo špičky", "enable_silent_payments_scanning": "Začněte skenovat tiché platby, dokud není dosaženo špičky",

View file

@ -235,6 +235,7 @@
"edit_token": "Token bearbeiten", "edit_token": "Token bearbeiten",
"electrum_address_disclaimer": "Wir generieren jedes Mal neue Adressen, wenn Sie eine verwenden, aber vorherige Adressen funktionieren weiterhin", "electrum_address_disclaimer": "Wir generieren jedes Mal neue Adressen, wenn Sie eine verwenden, aber vorherige Adressen funktionieren weiterhin",
"email_address": "E-Mail-Adresse", "email_address": "E-Mail-Adresse",
"enable": "Aktivieren",
"enable_mempool_api": "Mempool -API für genaue Gebühren und Daten", "enable_mempool_api": "Mempool -API für genaue Gebühren und Daten",
"enable_replace_by_fee": "Aktivieren Sie Ersatz für Fee", "enable_replace_by_fee": "Aktivieren Sie Ersatz für Fee",
"enable_silent_payments_scanning": "Scannen Sie stille Zahlungen, bis die Spitze erreicht ist", "enable_silent_payments_scanning": "Scannen Sie stille Zahlungen, bis die Spitze erreicht ist",

View file

@ -235,6 +235,7 @@
"edit_token": "Edit token", "edit_token": "Edit token",
"electrum_address_disclaimer": "We generate new addresses each time you use one, but previous addresses continue to work", "electrum_address_disclaimer": "We generate new addresses each time you use one, but previous addresses continue to work",
"email_address": "Email Address", "email_address": "Email Address",
"enable": "Enable",
"enable_mempool_api": "Mempool API for accurate fees and dates", "enable_mempool_api": "Mempool API for accurate fees and dates",
"enable_replace_by_fee": "Enable Replace-By-Fee", "enable_replace_by_fee": "Enable Replace-By-Fee",
"enable_silent_payments_scanning": "Start scanning for transactions sent to your Silent Payment address.", "enable_silent_payments_scanning": "Start scanning for transactions sent to your Silent Payment address.",

View file

@ -235,6 +235,7 @@
"edit_token": "Editar token", "edit_token": "Editar token",
"electrum_address_disclaimer": "Generamos nuevas direcciones cada vez que usa una, pero las direcciones anteriores siguen funcionando", "electrum_address_disclaimer": "Generamos nuevas direcciones cada vez que usa una, pero las direcciones anteriores siguen funcionando",
"email_address": "Dirección de correo electrónico", "email_address": "Dirección de correo electrónico",
"enable": "Permitir",
"enable_mempool_api": "API de Mempool para tarifas y fechas precisas", "enable_mempool_api": "API de Mempool para tarifas y fechas precisas",
"enable_replace_by_fee": "Habilitar reemplazar por tarea", "enable_replace_by_fee": "Habilitar reemplazar por tarea",
"enable_silent_payments_scanning": "Comience a escanear pagos silenciosos, hasta que se alcance la punta", "enable_silent_payments_scanning": "Comience a escanear pagos silenciosos, hasta que se alcance la punta",

View file

@ -235,6 +235,7 @@
"edit_token": "Modifier le token", "edit_token": "Modifier le token",
"electrum_address_disclaimer": "Nous générons de nouvelles adresses à chaque fois que vous en utilisez une, mais les adresses précédentes continuent à fonctionner", "electrum_address_disclaimer": "Nous générons de nouvelles adresses à chaque fois que vous en utilisez une, mais les adresses précédentes continuent à fonctionner",
"email_address": "Adresse e-mail", "email_address": "Adresse e-mail",
"enable": "Activer",
"enable_mempool_api": "API Mempool pour les frais et dates précis", "enable_mempool_api": "API Mempool pour les frais et dates précis",
"enable_replace_by_fee": "Activer Remplace-by-Fee", "enable_replace_by_fee": "Activer Remplace-by-Fee",
"enable_silent_payments_scanning": "Commencez à scanner les paiements silencieux, jusqu'à ce que la pointe soit atteinte", "enable_silent_payments_scanning": "Commencez à scanner les paiements silencieux, jusqu'à ce que la pointe soit atteinte",

View file

@ -235,6 +235,7 @@
"edit_token": "Gyara alamar", "edit_token": "Gyara alamar",
"electrum_address_disclaimer": "Muna samar da sababbin adireshi duk lokacin da kuka yi amfani da ɗaya, amma adiresoshin da suka gabata suna ci gaba da aiki", "electrum_address_disclaimer": "Muna samar da sababbin adireshi duk lokacin da kuka yi amfani da ɗaya, amma adiresoshin da suka gabata suna ci gaba da aiki",
"email_address": "Adireshin i-mel", "email_address": "Adireshin i-mel",
"enable": "Ba dama",
"enable_mempool_api": "Mampool API don ingantattun kudade da kwanakin", "enable_mempool_api": "Mampool API don ingantattun kudade da kwanakin",
"enable_replace_by_fee": "Ba da damar maye gurbin-by-kudin", "enable_replace_by_fee": "Ba da damar maye gurbin-by-kudin",
"enable_silent_payments_scanning": "Fara bincika biya na shiru, har sai tip ɗin ya kai", "enable_silent_payments_scanning": "Fara bincika biya na shiru, har sai tip ɗin ya kai",

View file

@ -235,6 +235,7 @@
"edit_token": "टोकन संपादित करें", "edit_token": "टोकन संपादित करें",
"electrum_address_disclaimer": "हर बार जब आप एक का उपयोग करते हैं तो हम नए पते उत्पन्न करते हैं, लेकिन पिछले पते काम करना जारी रखते हैं", "electrum_address_disclaimer": "हर बार जब आप एक का उपयोग करते हैं तो हम नए पते उत्पन्न करते हैं, लेकिन पिछले पते काम करना जारी रखते हैं",
"email_address": "ईमेल पता", "email_address": "ईमेल पता",
"enable": "सक्षम",
"enable_mempool_api": "सटीक शुल्क और तिथियों के लिए मेमपूल एपीआई", "enable_mempool_api": "सटीक शुल्क और तिथियों के लिए मेमपूल एपीआई",
"enable_replace_by_fee": "प्रतिस्थापित-दर-शुल्क सक्षम करें", "enable_replace_by_fee": "प्रतिस्थापित-दर-शुल्क सक्षम करें",
"enable_silent_payments_scanning": "मूक भुगतान स्कैनिंग सक्षम करें", "enable_silent_payments_scanning": "मूक भुगतान स्कैनिंग सक्षम करें",

View file

@ -235,6 +235,7 @@
"edit_token": "Uredi token", "edit_token": "Uredi token",
"electrum_address_disclaimer": "Minden egyes alkalommal új címeket generálunk, de a korábbi címek továbbra is működnek", "electrum_address_disclaimer": "Minden egyes alkalommal új címeket generálunk, de a korábbi címek továbbra is működnek",
"email_address": "Adresa e-pošte", "email_address": "Adresa e-pošte",
"enable": "Omogućiti",
"enable_mempool_api": "Mempool API za točne naknade i datume", "enable_mempool_api": "Mempool API za točne naknade i datume",
"enable_replace_by_fee": "Omogući zamjenu", "enable_replace_by_fee": "Omogući zamjenu",
"enable_silent_payments_scanning": "Započnite skeniranje tihih plaćanja, dok se ne postigne savjet", "enable_silent_payments_scanning": "Započnite skeniranje tihih plaćanja, dok se ne postigne savjet",

View file

@ -235,6 +235,7 @@
"edit_token": "Փոփոխել տոկեն", "edit_token": "Փոփոխել տոկեն",
"electrum_address_disclaimer": "Մենք ստեղծում ենք նոր հասցե ամեն անգամ, երբ դուք օգտագործում եք այն, բայց նախորդ հասցեները շարունակում են աշխատել", "electrum_address_disclaimer": "Մենք ստեղծում ենք նոր հասցե ամեն անգամ, երբ դուք օգտագործում եք այն, բայց նախորդ հասցեները շարունակում են աշխատել",
"email_address": "Էլ. փոստի հասցե", "email_address": "Էլ. փոստի հասցե",
"enable": "Միացնել",
"enable_mempool_api": "Mempool API ճշգրիտ վճարների եւ ամսաթվերի համար", "enable_mempool_api": "Mempool API ճշգրիտ վճարների եւ ամսաթվերի համար",
"enable_replace_by_fee": "Միացնել փոխարինումը միջնորդավճարով", "enable_replace_by_fee": "Միացնել փոխարինումը միջնորդավճարով",
"enable_silent_payments_scanning": "Միացնել Լուռ Վճարումների սկանավորումը", "enable_silent_payments_scanning": "Միացնել Լուռ Վճարումների սկանավորումը",

View file

@ -235,6 +235,7 @@
"edit_token": "Mengedit token", "edit_token": "Mengedit token",
"electrum_address_disclaimer": "Kami menghasilkan alamat baru setiap kali Anda menggunakan satu, tetapi alamat sebelumnya tetap berfungsi", "electrum_address_disclaimer": "Kami menghasilkan alamat baru setiap kali Anda menggunakan satu, tetapi alamat sebelumnya tetap berfungsi",
"email_address": "Alamat Email", "email_address": "Alamat Email",
"enable": "Memungkinkan",
"enable_mempool_api": "API Mempool untuk biaya dan tanggal yang akurat", "enable_mempool_api": "API Mempool untuk biaya dan tanggal yang akurat",
"enable_replace_by_fee": "Aktifkan ganti-by-fee", "enable_replace_by_fee": "Aktifkan ganti-by-fee",
"enable_silent_payments_scanning": "Mulailah memindai pembayaran diam, sampai ujung tercapai", "enable_silent_payments_scanning": "Mulailah memindai pembayaran diam, sampai ujung tercapai",

View file

@ -236,6 +236,7 @@
"edit_token": "Modifica token", "edit_token": "Modifica token",
"electrum_address_disclaimer": "Generiamo nuovi indirizzi ogni volta che ne utilizzi uno, ma gli indirizzi precedenti continuano a funzionare", "electrum_address_disclaimer": "Generiamo nuovi indirizzi ogni volta che ne utilizzi uno, ma gli indirizzi precedenti continuano a funzionare",
"email_address": "Indirizzo e-mail", "email_address": "Indirizzo e-mail",
"enable": "Abilitare",
"enable_mempool_api": "API di Mempool per commissioni e date accurate", "enable_mempool_api": "API di Mempool per commissioni e date accurate",
"enable_replace_by_fee": "Abilita sostituzione per fee", "enable_replace_by_fee": "Abilita sostituzione per fee",
"enable_silent_payments_scanning": "Inizia a scansionare i pagamenti silenziosi, fino a raggiungere la punta", "enable_silent_payments_scanning": "Inizia a scansionare i pagamenti silenziosi, fino a raggiungere la punta",

View file

@ -235,6 +235,7 @@
"edit_token": "トークンの編集", "edit_token": "トークンの編集",
"electrum_address_disclaimer": "使用するたびに新しいアドレスが生成されますが、以前のアドレスは引き続き機能します", "electrum_address_disclaimer": "使用するたびに新しいアドレスが生成されますが、以前のアドレスは引き続き機能します",
"email_address": "メールアドレス", "email_address": "メールアドレス",
"enable": "有効にする",
"enable_mempool_api": "正確な料金と日付のMempool API", "enable_mempool_api": "正確な料金と日付のMempool API",
"enable_replace_by_fee": "交換ごとに有効にします", "enable_replace_by_fee": "交換ごとに有効にします",
"enable_silent_payments_scanning": "先端に達するまで、サイレント決済のスキャンを開始します", "enable_silent_payments_scanning": "先端に達するまで、サイレント決済のスキャンを開始します",

View file

@ -235,6 +235,7 @@
"edit_token": "토큰 편집", "edit_token": "토큰 편집",
"electrum_address_disclaimer": "사용할 때마다 새 주소가 생성되지만 이전 주소는 계속 작동합니다.", "electrum_address_disclaimer": "사용할 때마다 새 주소가 생성되지만 이전 주소는 계속 작동합니다.",
"email_address": "이메일 주소", "email_address": "이메일 주소",
"enable": "할 수 있게 하다",
"enable_mempool_api": "정확한 수수료 및 날짜에 대한 Mempool API", "enable_mempool_api": "정확한 수수료 및 날짜에 대한 Mempool API",
"enable_replace_by_fee": "대체별로 활성화하십시오", "enable_replace_by_fee": "대체별로 활성화하십시오",
"enable_silent_payments_scanning": "팁에 도달 할 때까지 사일런트 지불을 스캔하기 시작합니다.", "enable_silent_payments_scanning": "팁에 도달 할 때까지 사일런트 지불을 스캔하기 시작합니다.",

View file

@ -235,6 +235,7 @@
"edit_token": "တိုကင်ကို တည်းဖြတ်ပါ။", "edit_token": "တိုကင်ကို တည်းဖြတ်ပါ။",
"electrum_address_disclaimer": "သင်အသုံးပြုသည့်အချိန်တိုင်းတွင် ကျွန်ုပ်တို့သည် လိပ်စာအသစ်များကို ထုတ်ပေးသော်လည်း ယခင်လိပ်စာများသည် ဆက်လက်အလုပ်လုပ်နေပါသည်။", "electrum_address_disclaimer": "သင်အသုံးပြုသည့်အချိန်တိုင်းတွင် ကျွန်ုပ်တို့သည် လိပ်စာအသစ်များကို ထုတ်ပေးသော်လည်း ယခင်လိပ်စာများသည် ဆက်လက်အလုပ်လုပ်နေပါသည်။",
"email_address": "အီးမေးလ်လိပ်စာ", "email_address": "အီးမေးလ်လိပ်စာ",
"enable": "စွမ်းဆောင်နိုင်စေ",
"enable_mempool_api": "Mempool API တိကျသောအခကြေးငွေနှင့်ရက်စွဲများအတွက်", "enable_mempool_api": "Mempool API တိကျသောအခကြေးငွေနှင့်ရက်စွဲများအတွက်",
"enable_replace_by_fee": "အစားထိုး - by- အခကြေးငွေ enable", "enable_replace_by_fee": "အစားထိုး - by- အခကြေးငွေ enable",
"enable_silent_payments_scanning": "အစွန်အဖျားသို့ရောက်ရှိသည်အထိအသံတိတ်ငွေပေးချေမှုကိုစကင်ဖတ်စစ်ဆေးပါ", "enable_silent_payments_scanning": "အစွန်အဖျားသို့ရောက်ရှိသည်အထိအသံတိတ်ငွေပေးချေမှုကိုစကင်ဖတ်စစ်ဆေးပါ",

View file

@ -235,6 +235,7 @@
"edit_token": "Token bewerken", "edit_token": "Token bewerken",
"electrum_address_disclaimer": "We genereren nieuwe adressen elke keer dat u er een gebruikt, maar eerdere adressen blijven werken", "electrum_address_disclaimer": "We genereren nieuwe adressen elke keer dat u er een gebruikt, maar eerdere adressen blijven werken",
"email_address": "E-mailadres", "email_address": "E-mailadres",
"enable": "Inschakelen",
"enable_mempool_api": "Mempool API voor nauwkeurige kosten en datums", "enable_mempool_api": "Mempool API voor nauwkeurige kosten en datums",
"enable_replace_by_fee": "Schakel vervangen door een fee", "enable_replace_by_fee": "Schakel vervangen door een fee",
"enable_silent_payments_scanning": "Begin met het scannen van stille betalingen, totdat de tip is bereikt", "enable_silent_payments_scanning": "Begin met het scannen van stille betalingen, totdat de tip is bereikt",

View file

@ -235,6 +235,7 @@
"edit_token": "Edytuj token", "edit_token": "Edytuj token",
"electrum_address_disclaimer": "Za każdym razem, gdy wykorzystasz adres, dla wiekszej prywatności generujemy nowy, ale poprzednie adresy nadal działają, i moga odbierać środki", "electrum_address_disclaimer": "Za każdym razem, gdy wykorzystasz adres, dla wiekszej prywatności generujemy nowy, ale poprzednie adresy nadal działają, i moga odbierać środki",
"email_address": "Adres e-mail", "email_address": "Adres e-mail",
"enable": "Włączać",
"enable_mempool_api": "Mempool API dla dokładnych opłat i dat", "enable_mempool_api": "Mempool API dla dokładnych opłat i dat",
"enable_replace_by_fee": "Włącz wymianę po lewej", "enable_replace_by_fee": "Włącz wymianę po lewej",
"enable_silent_payments_scanning": "Zacznij skanować ciche płatności, aż do osiągnięcia wskazówki", "enable_silent_payments_scanning": "Zacznij skanować ciche płatności, aż do osiągnięcia wskazówki",

View file

@ -235,6 +235,7 @@
"edit_token": "Editar símbolo", "edit_token": "Editar símbolo",
"electrum_address_disclaimer": "Geramos novos endereços cada vez que você usa um, mas os endereços anteriores continuam funcionando", "electrum_address_disclaimer": "Geramos novos endereços cada vez que você usa um, mas os endereços anteriores continuam funcionando",
"email_address": "Endereço de e-mail", "email_address": "Endereço de e-mail",
"enable": "Habilitar",
"enable_mempool_api": "Mempool API para taxas e datas precisas", "enable_mempool_api": "Mempool API para taxas e datas precisas",
"enable_replace_by_fee": "Habilite substituir por taxa", "enable_replace_by_fee": "Habilite substituir por taxa",
"enable_silent_payments_scanning": "Comece a escanear pagamentos silenciosos, até que o topo seja alcançada", "enable_silent_payments_scanning": "Comece a escanear pagamentos silenciosos, até que o topo seja alcançada",

View file

@ -235,6 +235,7 @@
"edit_token": "Изменить токен", "edit_token": "Изменить токен",
"electrum_address_disclaimer": "Мы генерируем новые адреса каждый раз, когда вы их используете, но предыдущие адреса продолжают работать.", "electrum_address_disclaimer": "Мы генерируем новые адреса каждый раз, когда вы их используете, но предыдущие адреса продолжают работать.",
"email_address": "Адрес электронной почты", "email_address": "Адрес электронной почты",
"enable": "Давать возможность",
"enable_mempool_api": "Mempool API за точные сборы и даты", "enable_mempool_api": "Mempool API за точные сборы и даты",
"enable_replace_by_fee": "Включить замену за пикой", "enable_replace_by_fee": "Включить замену за пикой",
"enable_silent_payments_scanning": "Начните сканировать безмолвные платежи, пока не будет достигнут наконечник", "enable_silent_payments_scanning": "Начните сканировать безмолвные платежи, пока не будет достигнут наконечник",

View file

@ -235,6 +235,7 @@
"edit_token": "แก้ไขโทเค็น", "edit_token": "แก้ไขโทเค็น",
"electrum_address_disclaimer": "เราสร้างที่อยู่ใหม่ทุกครั้งที่คุณใช้หนึ่งอย่าง แต่ที่อยู่เก่ายังสามารถใช้ได้ต่อไป", "electrum_address_disclaimer": "เราสร้างที่อยู่ใหม่ทุกครั้งที่คุณใช้หนึ่งอย่าง แต่ที่อยู่เก่ายังสามารถใช้ได้ต่อไป",
"email_address": "ที่อยู่อีเมล", "email_address": "ที่อยู่อีเมล",
"enable": "เปิดใช้งาน",
"enable_mempool_api": "Mempool API สำหรับค่าธรรมเนียมและวันที่ที่ถูกต้อง", "enable_mempool_api": "Mempool API สำหรับค่าธรรมเนียมและวันที่ที่ถูกต้อง",
"enable_replace_by_fee": "เปิดใช้งานการเปลี่ยนโดยค่าธรรมเนียม", "enable_replace_by_fee": "เปิดใช้งานการเปลี่ยนโดยค่าธรรมเนียม",
"enable_silent_payments_scanning": "เริ่มสแกนการชำระเงินแบบเงียบจนกว่าจะถึงปลาย", "enable_silent_payments_scanning": "เริ่มสแกนการชำระเงินแบบเงียบจนกว่าจะถึงปลาย",

View file

@ -235,6 +235,7 @@
"edit_token": "I-edit ang token", "edit_token": "I-edit ang token",
"electrum_address_disclaimer": "Bumubuo kami ng mga bagong address sa tuwing gagamit ka ng isa, ngunit ang mga nakaraang address ay patuloy na gumagana", "electrum_address_disclaimer": "Bumubuo kami ng mga bagong address sa tuwing gagamit ka ng isa, ngunit ang mga nakaraang address ay patuloy na gumagana",
"email_address": "Email Address", "email_address": "Email Address",
"enable": "Paganahin",
"enable_mempool_api": "Mempool API para sa tumpak na bayad at mga petsa", "enable_mempool_api": "Mempool API para sa tumpak na bayad at mga petsa",
"enable_replace_by_fee": "Paganahin ang Replace-By-Fee", "enable_replace_by_fee": "Paganahin ang Replace-By-Fee",
"enable_silent_payments_scanning": "Simulan ang pag -scan ng tahimik na pagbabayad, hanggang sa maabot ang tip", "enable_silent_payments_scanning": "Simulan ang pag -scan ng tahimik na pagbabayad, hanggang sa maabot ang tip",

View file

@ -235,6 +235,7 @@
"edit_token": "Belirteci düzenle", "edit_token": "Belirteci düzenle",
"electrum_address_disclaimer": "Adresini her kullandığında yeni adres oluşturuyoruz, ancak önceki adresler de çalışmaya devam eder", "electrum_address_disclaimer": "Adresini her kullandığında yeni adres oluşturuyoruz, ancak önceki adresler de çalışmaya devam eder",
"email_address": "E-posta Adresi", "email_address": "E-posta Adresi",
"enable": "Olanak vermek",
"enable_mempool_api": "Doğru ücretler ve tarihler için Mempool API'si", "enable_mempool_api": "Doğru ücretler ve tarihler için Mempool API'si",
"enable_replace_by_fee": "Farklı Değiştir'i Etkinleştir", "enable_replace_by_fee": "Farklı Değiştir'i Etkinleştir",
"enable_silent_payments_scanning": "Bahşiş ulaşılıncaya kadar sessiz ödemeleri taramaya başlayın", "enable_silent_payments_scanning": "Bahşiş ulaşılıncaya kadar sessiz ödemeleri taramaya başlayın",

View file

@ -235,6 +235,7 @@
"edit_token": "Редагувати маркер", "edit_token": "Редагувати маркер",
"electrum_address_disclaimer": "Ми створюємо нові адреси щоразу, коли ви використовуєте їх, але попередні адреси продовжують працювати", "electrum_address_disclaimer": "Ми створюємо нові адреси щоразу, коли ви використовуєте їх, але попередні адреси продовжують працювати",
"email_address": "Адреса електронної пошти", "email_address": "Адреса електронної пошти",
"enable": "Ввімкнути",
"enable_mempool_api": "API Mempool для точних зборів та дат", "enable_mempool_api": "API Mempool для точних зборів та дат",
"enable_replace_by_fee": "Увімкнути заміну з комісією", "enable_replace_by_fee": "Увімкнути заміну з комісією",
"enable_silent_payments_scanning": "Почніть сканувати мовчазні платежі, поки не буде досягнуто наконечника", "enable_silent_payments_scanning": "Почніть сканувати мовчазні платежі, поки не буде досягнуто наконечника",

View file

@ -235,6 +235,7 @@
"edit_token": "ٹوکن میں ترمیم کریں۔", "edit_token": "ٹوکن میں ترمیم کریں۔",
"electrum_address_disclaimer": "جب بھی آپ ایک کا استعمال کرتے ہیں تو ہم نئے پتے تیار کرتے ہیں، لیکن پچھلے پتے کام کرتے رہتے ہیں۔", "electrum_address_disclaimer": "جب بھی آپ ایک کا استعمال کرتے ہیں تو ہم نئے پتے تیار کرتے ہیں، لیکن پچھلے پتے کام کرتے رہتے ہیں۔",
"email_address": "ای میل اڈریس", "email_address": "ای میل اڈریس",
"enable": "قابل بنائیں",
"enable_mempool_api": "درست فیسوں اور تاریخوں کے لئے میمپول API", "enable_mempool_api": "درست فیسوں اور تاریخوں کے لئے میمپول API",
"enable_replace_by_fee": "فی فیس کو تبدیل کریں", "enable_replace_by_fee": "فی فیس کو تبدیل کریں",
"enable_silent_payments_scanning": "خاموش ادائیگیوں کو اسکین کرنا شروع کریں ، جب تک کہ نوک نہ پہنچ جائے", "enable_silent_payments_scanning": "خاموش ادائیگیوں کو اسکین کرنا شروع کریں ، جب تک کہ نوک نہ پہنچ جائے",

View file

@ -236,6 +236,7 @@
"edit_token": "Chỉnh sửa token", "edit_token": "Chỉnh sửa token",
"electrum_address_disclaimer": "Chúng tôi tạo địa chỉ mới mỗi khi bạn sử dụng, nhưng các địa chỉ cũ vẫn tiếp tục hoạt động", "electrum_address_disclaimer": "Chúng tôi tạo địa chỉ mới mỗi khi bạn sử dụng, nhưng các địa chỉ cũ vẫn tiếp tục hoạt động",
"email_address": "Địa chỉ Email", "email_address": "Địa chỉ Email",
"enable": "Cho phép",
"enable_mempool_api": "API Mempool cho các khoản phí và ngày chính xác", "enable_mempool_api": "API Mempool cho các khoản phí và ngày chính xác",
"enable_replace_by_fee": "Bật Thay thế Bằng Phí", "enable_replace_by_fee": "Bật Thay thế Bằng Phí",
"enable_silent_payments_scanning": "Bật quét thanh toán im lặng", "enable_silent_payments_scanning": "Bật quét thanh toán im lặng",

View file

@ -236,6 +236,7 @@
"edit_token": "Ṣatunkọ àmi", "edit_token": "Ṣatunkọ àmi",
"electrum_address_disclaimer": "A dá àwọn àdírẹ́sì títun ní gbogbo àwọn ìgbà t'ẹ́ lo ó kan ṣùgbọ́n ẹ lè tẹ̀síwájú lo àwọn àdírẹ́sì tẹ́lẹ̀tẹ́lẹ̀.", "electrum_address_disclaimer": "A dá àwọn àdírẹ́sì títun ní gbogbo àwọn ìgbà t'ẹ́ lo ó kan ṣùgbọ́n ẹ lè tẹ̀síwájú lo àwọn àdírẹ́sì tẹ́lẹ̀tẹ́lẹ̀.",
"email_address": "Àdírẹ́sì ímeèlì", "email_address": "Àdírẹ́sì ímeèlì",
"enable": "Mu ṣiṣẹ",
"enable_mempool_api": "Mempool API fun awọn owo deede ati awọn ọjọ", "enable_mempool_api": "Mempool API fun awọn owo deede ati awọn ọjọ",
"enable_replace_by_fee": "Mu ki o rọpo", "enable_replace_by_fee": "Mu ki o rọpo",
"enable_silent_payments_scanning": "Bẹrẹ awọn sisanwo ipalọlọ, titi ti o fi de opin", "enable_silent_payments_scanning": "Bẹrẹ awọn sisanwo ipalọlọ, titi ti o fi de opin",

View file

@ -235,6 +235,7 @@
"edit_token": "编辑令牌", "edit_token": "编辑令牌",
"electrum_address_disclaimer": "每次您使用一个地址时,我们都会生成新地址,但之前的地址仍然有效", "electrum_address_disclaimer": "每次您使用一个地址时,我们都会生成新地址,但之前的地址仍然有效",
"email_address": "电子邮件地址", "email_address": "电子邮件地址",
"enable": "使能够",
"enable_mempool_api": "Mempool API获得准确的费用和日期", "enable_mempool_api": "Mempool API获得准确的费用和日期",
"enable_replace_by_fee": "启用by-Fee替换", "enable_replace_by_fee": "启用by-Fee替换",
"enable_silent_payments_scanning": "开始扫描无声付款,直到达到提示", "enable_silent_payments_scanning": "开始扫描无声付款,直到达到提示",

View file

@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
APP_ANDROID_TYPE=$1 APP_ANDROID_TYPE=$1
MONERO_COM_NAME="Monero.com" MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.16.5" MONERO_COM_VERSION="1.17.0"
MONERO_COM_BUILD_NUMBER=100 MONERO_COM_BUILD_NUMBER=102
MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_BUNDLE_ID="com.monero.app"
MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_PACKAGE="com.monero.app"
MONERO_COM_SCHEME="monero.com" MONERO_COM_SCHEME="monero.com"
CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="4.19.5" CAKEWALLET_VERSION="4.20.0"
CAKEWALLET_BUILD_NUMBER=227 CAKEWALLET_BUILD_NUMBER=230
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
CAKEWALLET_SCHEME="cakewallet" CAKEWALLET_SCHEME="cakewallet"

View file

@ -13,7 +13,7 @@ fi
# build mwebd: # build mwebd:
git clone https://github.com/ltcmweb/mwebd git clone https://github.com/ltcmweb/mwebd
cd mwebd cd mwebd
git reset --hard f6ea8a9e3d348b01bb44f03a1cc4ad65b0abe935 git reset --hard 555349415f76a42ec5c76152b64c4ab9aabc448f
gomobile bind -target=android -androidapi 21 . gomobile bind -target=android -androidapi 21 .
mkdir -p ../../../cw_mweb/android/libs/ mkdir -p ../../../cw_mweb/android/libs/
mv ./mwebd.aar $_ mv ./mwebd.aar $_

View file

@ -22,7 +22,7 @@ cp -rf ./ios/Runner/InfoBase.plist ./ios/Runner/Info.plist
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:1:CFBundleURLName string ${APP_IOS_TYPE}" ./ios/Runner/Info.plist /usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:1:CFBundleURLName string ${APP_IOS_TYPE}" ./ios/Runner/Info.plist
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:1:CFBundleURLSchemes array" ./ios/Runner/Info.plist /usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:1:CFBundleURLSchemes array" ./ios/Runner/Info.plist
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:1:CFBundleURLSchemes: string ${APP_IOS_TYPE}" ./ios/Runner/Info.plist /usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:1:CFBundleURLSchemes: string ${APP_IOS_TYPE}" ./ios/Runner/Info.plist
sed -i '' "s/\${PRODUCT_BUNDLE_IDENTIFIER}/${APP_IOS_BUNDLE_ID}/g" ./ios/Runner.xcodeproj/project.pbxproj sed -i '' "s/PRODUCT_BUNDLE_IDENTIFIER = .*;/PRODUCT_BUNDLE_IDENTIFIER = $APP_IOS_BUNDLE_ID;/g" ./ios/Runner.xcodeproj/project.pbxproj
CONFIG_ARGS="" CONFIG_ARGS=""

View file

@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
APP_IOS_TYPE=$1 APP_IOS_TYPE=$1
MONERO_COM_NAME="Monero.com" MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.16.5" MONERO_COM_VERSION="1.17.0"
MONERO_COM_BUILD_NUMBER=98 MONERO_COM_BUILD_NUMBER=100
MONERO_COM_BUNDLE_ID="com.cakewallet.monero" MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="4.19.5" CAKEWALLET_VERSION="4.20.0"
CAKEWALLET_BUILD_NUMBER=266 CAKEWALLET_BUILD_NUMBER=269
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
HAVEN_NAME="Haven" HAVEN_NAME="Haven"

View file

@ -12,7 +12,7 @@ fi
# build mwebd: # build mwebd:
git clone https://github.com/ltcmweb/mwebd git clone https://github.com/ltcmweb/mwebd
cd mwebd cd mwebd
git reset --hard f6ea8a9e3d348b01bb44f03a1cc4ad65b0abe935 git reset --hard 555349415f76a42ec5c76152b64c4ab9aabc448f
gomobile bind -target=ios . gomobile bind -target=ios .
mv -fn ./Mwebd.xcframework ../../../ios/ mv -fn ./Mwebd.xcframework ../../../ios/
# cleanup: # cleanup:

View file

@ -14,8 +14,8 @@ if [ -n "$1" ]; then
fi fi
CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="1.9.5" CAKEWALLET_VERSION="1.10.0"
CAKEWALLET_BUILD_NUMBER=33 CAKEWALLET_BUILD_NUMBER=35
if ! [[ " ${TYPES[*]} " =~ " ${APP_LINUX_TYPE} " ]]; then if ! [[ " ${TYPES[*]} " =~ " ${APP_LINUX_TYPE} " ]]; then
echo "Wrong app type." echo "Wrong app type."

View file

@ -28,7 +28,7 @@ sed -i '' "s/\${BUNDLE_ID}/${APP_MACOS_BUNDLE_ID}/g" ./macos/Runner/DebugProfile
sed -i '' "s/\${BUNDLE_ID}/${APP_MACOS_BUNDLE_ID}/g" ./macos/Runner/Release.entitlements sed -i '' "s/\${BUNDLE_ID}/${APP_MACOS_BUNDLE_ID}/g" ./macos/Runner/Release.entitlements
sed -i '' "s/\${BUNDLE_ID}/${APP_MACOS_BUNDLE_ID}/g" ./macos/Runner/Runner.entitlements sed -i '' "s/\${BUNDLE_ID}/${APP_MACOS_BUNDLE_ID}/g" ./macos/Runner/Runner.entitlements
sed -i '' "s/\${PRODUCT_NAME}/${APP_MACOS_NAME}/g" ./macos/Runner/Configs/AppInfo.xcconfig sed -i '' "s/\${PRODUCT_NAME}/${APP_MACOS_NAME}/g" ./macos/Runner/Configs/AppInfo.xcconfig
sed -i '' "s/\${PRODUCT_BUNDLE_IDENTIFIER}/${APP_MACOS_BUNDLE_ID}/g" ./macos/Runner/Configs/AppInfo.xcconfig sed -i '' "s/PRODUCT_BUNDLE_IDENTIFIER = .*;/PRODUCT_BUNDLE_IDENTIFIER = $APP_MACOS_BUNDLE_ID;/g" ./macos/Runner/Configs/AppInfo.xcconfig
CONFIG_ARGS="" CONFIG_ARGS=""
case $APP_MACOS_TYPE in case $APP_MACOS_TYPE in

View file

@ -16,13 +16,13 @@ if [ -n "$1" ]; then
fi fi
MONERO_COM_NAME="Monero.com" MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.6.5" MONERO_COM_VERSION="1.7.0"
MONERO_COM_BUILD_NUMBER=31 MONERO_COM_BUILD_NUMBER=33
MONERO_COM_BUNDLE_ID="com.cakewallet.monero" MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="1.12.5" CAKEWALLET_VERSION="1.13.0"
CAKEWALLET_BUILD_NUMBER=88 CAKEWALLET_BUILD_NUMBER=90
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then

View file

@ -1,5 +1,5 @@
#define MyAppName "Cake Wallet" #define MyAppName "Cake Wallet"
#define MyAppVersion "0.0.6" #define MyAppVersion "0.1.0"
#define MyAppPublisher "Cake Labs LLC" #define MyAppPublisher "Cake Labs LLC"
#define MyAppURL "https://cakewallet.com/" #define MyAppURL "https://cakewallet.com/"
#define MyAppExeName "CakeWallet.exe" #define MyAppExeName "CakeWallet.exe"

View file

@ -75,6 +75,7 @@ Future<void> main(List<String> args) async {
Future<void> generateBitcoin(bool hasImplementation) async { Future<void> generateBitcoin(bool hasImplementation) async {
final outputFile = File(bitcoinOutputPath); final outputFile = File(bitcoinOutputPath);
const bitcoinCommonHeaders = """ const bitcoinCommonHeaders = """
import 'dart:io' show Platform;
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart'; import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart';