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
Bug fixes and enhancements
Monero enhancements for sending and address generation
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)
Improve fee calculation for Bitcoin to protect against overpaying or underpaying
Enhance auto-address generation for Monero
Bug fixes and enhancements
Add Litecoin MWEB
Wallet groups (same seed, multiple wallets)
Silent Payments 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 = [
BitcoinReceivePageOption.p2wpkh,
BitcoinReceivePageOption.mweb
BitcoinReceivePageOption.mweb,
];
BitcoinAddressType toType() {

View file

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

View file

@ -4,7 +4,6 @@ import 'dart:io';
import 'dart:isolate';
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:cw_bitcoin/litecoin_wallet_addresses.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:cw_core/encryption_file_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_wallet_addresses.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/utils.dart';
import 'package:cw_core/crypto_currency.dart';
@ -168,7 +166,10 @@ abstract class ElectrumWalletBase
@observable
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
.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_address_index': walletAddresses.currentSilentAddressIndex.toString(),
'mweb_addresses': walletAddresses.mwebAddresses.map((addr) => addr.toJSON()).toList(),
'alwaysScan': alwaysScan,
});
int feeRate(TransactionPriority priority) {
@ -1291,7 +1293,7 @@ abstract class ElectrumWalletBase
}
@override
Future<void> close() async {
Future<void> close({required bool shouldCleanup}) async {
try {
await _receiveStream?.cancel();
await electrumClient.close();
@ -1314,11 +1316,15 @@ abstract class ElectrumWalletBase
}
// 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;
});
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));
}));
@ -1878,6 +1884,7 @@ abstract class ElectrumWalletBase
}
Future<void> updateTransactions() async {
print("updateTransactions() called!");
try {
if (_isTransactionUpdating) {
return;
@ -1903,12 +1910,16 @@ abstract class ElectrumWalletBase
Future<void> subscribeForUpdates() async {
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 {
final sh = address.getScriptHash(network);
await _scripthashesUpdateSubject[sh]?.close();
if (!(_scripthashesUpdateSubject[sh]?.isClosed ?? true)) {
await _scripthashesUpdateSubject[sh]?.close();
}
_scripthashesUpdateSubject[sh] = await electrumClient.scripthashUpdate(sh);
_scripthashesUpdateSubject[sh]?.listen((event) async {
try {
@ -1918,7 +1929,7 @@ abstract class ElectrumWalletBase
await _fetchAddressHistory(address, await getCurrentChainTip());
} catch (e, s) {
print(e.toString());
print("sub error: $e");
_onError?.call(FlutterErrorDetails(
exception: e,
stack: s,
@ -1996,6 +2007,7 @@ abstract class ElectrumWalletBase
}
Future<void> updateBalance() async {
print("updateBalance() called!");
balance[currency] = await fetchBalances();
await save();
}

View file

@ -1,3 +1,5 @@
import 'dart:io' show Platform;
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:blockchain_utils/blockchain_utils.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);
} else if (walletInfo.type == WalletType.litecoin) {
await _generateInitialAddresses(type: SegwitAddresType.p2wpkh);
await _generateInitialAddresses(type: SegwitAddresType.mweb);
if (Platform.isAndroid || Platform.isIOS) {
await _generateInitialAddresses(type: SegwitAddresType.mweb);
}
} else if (walletInfo.type == WalletType.bitcoin) {
await _generateInitialAddresses();
await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);

View file

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

View file

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

View file

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

View file

@ -117,6 +117,8 @@ class PendingBitcoinTransaction with PendingTransaction {
idOverride = resp.txid;
} on GrpcError catch (e) {
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});
void close();
Future<void> close({required bool shouldCleanup});
Future<void> changePassword(String password);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -32,15 +32,26 @@ public static func register(with registrar: FlutterPluginRegistrar) {
stopServer()
result(nil)
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 scanSecret = args["scanSecret"] 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 spendPubData = spendPub.data
result(MwebdAddress(scanSecretData, spendPubData, index))
result(MwebdAddresses(scanSecretData, spendPubData, fromIndex, toIndex))
break
default:
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 'package:grpc/grpc.dart';
@ -10,25 +14,51 @@ class CwMweb {
static ClientChannel? _clientChannel;
static int? _port;
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 {
await stop();
// wait a few seconds to make sure the server is stopped
await Future.delayed(const Duration(seconds: 5));
print("initialize client called!");
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);
if (_port == null || _port == 0) {
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:
await Future.delayed(const Duration(seconds: 5));
_clientChannel = ClientChannel('127.0.0.1', port: _port!, channelShutdownHandler: () {
print("Channel is shutting down!");
_rpcClient = null;
log("Channel is shutting down!");
},
options: const ChannelOptions(
credentials: ChannelCredentials.insecure(),
@ -49,9 +79,15 @@ class CwMweb {
throw Exception("blockTime shouldn't be 0! (this connection is likely broken)");
}
return _rpcClient!;
} catch (e) {
print("Attempt $i failed: $e");
} on GrpcError catch (e) {
log("Attempt $i failed: $e");
log('Caught grpc error: ${e.message}');
_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");
@ -61,22 +97,43 @@ class CwMweb {
try {
await CwMwebPlatform.instance.stop();
await cleanup();
} on GrpcError catch (e) {
log('Caught grpc error: ${e.message}');
} catch (e) {
print("Error stopping server: $e");
log("Error stopping server: $e");
}
}
static Future<String?> address(Uint8List scanSecret, Uint8List spendPub, int index) async {
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) {
print("Error getting address: $e");
return null;
log("Error getting address: $e");
}
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 {
await _clientChannel?.terminate();
try {
await _clientChannel?.terminate();
} catch (_) {}
_rpcClient = null;
_clientChannel = null;
_port = null;
@ -84,51 +141,57 @@ class CwMweb {
// wrappers that handle the connection issues:
static Future<SpentResponse> spent(SpentRequest request) async {
log("mweb.spent() called");
try {
if (_rpcClient == null) {
await _initializeClient();
}
_rpcClient = await stub();
return await _rpcClient!.spent(request, options: CallOptions(timeout: TIMEOUT_DURATION));
} on GrpcError catch (e) {
log('Caught grpc error: ${e.message}');
} catch (e) {
print("Error getting spent: $e");
return SpentResponse();
log("Error getting spent: $e");
}
return SpentResponse();
}
static Future<StatusResponse> status(StatusRequest request) async {
log("mweb.status() called");
try {
if (_rpcClient == null) {
await _initializeClient();
}
_rpcClient = await stub();
return await _rpcClient!.status(request, options: CallOptions(timeout: TIMEOUT_DURATION));
} on GrpcError catch (e) {
log('Caught grpc error: ${e.message}');
} catch (e) {
print("Error getting status: $e");
return StatusResponse();
log("Error getting status: $e");
}
return StatusResponse();
}
static Future<CreateResponse> create(CreateRequest request) async {
log("mweb.create() called");
try {
if (_rpcClient == null) {
await _initializeClient();
}
_rpcClient = await stub();
return await _rpcClient!.create(request, options: CallOptions(timeout: TIMEOUT_DURATION));
} on GrpcError catch (e) {
log('Caught grpc error: ${e.message}');
} catch (e) {
print("Error getting create: $e");
return CreateResponse();
log("Error getting create: $e");
}
return CreateResponse();
}
static Future<ResponseStream<Utxo>?> utxos(UtxosRequest request) async {
log("mweb.utxos() called");
try {
if (_rpcClient == null) {
await _initializeClient();
}
// this is a stream, so we should have an effectively infinite timeout:
return _rpcClient!.utxos(request, options: CallOptions(timeout: const Duration(days: 1000 * 365)));
_rpcClient = await stub();
final resp = _rpcClient!
.utxos(request, options: CallOptions(timeout: const Duration(days: 1000 * 365)));
log("got utxo stream");
return resp;
} on GrpcError catch (e) {
log('Caught grpc error: ${e.message}');
} catch (e) {
print("Error getting utxos: $e");
return null;
log("Error getting utxos: $e");
}
return null;
}
}

View file

@ -1,3 +1,5 @@
import 'dart:io' show Platform;
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
@ -11,6 +13,9 @@ class MethodChannelCwMweb extends CwMwebPlatform {
@override
Future<int?> start(String dataDir, String nodeUri) async {
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
return null;
}
final result =
await methodChannel.invokeMethod<int>('start', {'dataDir': dataDir, 'nodeUri': nodeUri});
return result;
@ -18,11 +23,17 @@ class MethodChannelCwMweb extends CwMwebPlatform {
@override
Future<void> stop() async {
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
return;
}
await methodChannel.invokeMethod<void>('stop');
}
@override
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', {
'scanSecret': scanSecret,
'spendPub': spendPub,
@ -30,4 +41,18 @@ class MethodChannelCwMweb extends CwMwebPlatform {
});
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) {
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");
@override
void close() {
Future<void> close({required bool shouldCleanup}) async {
_client.stop();
_receiveTimer?.cancel();
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -14,12 +14,12 @@
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 */; };
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, ); }; };
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, ); }; };
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 */; };
8B1F4FCAA5EB9F3A83D32D5F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D7CD6B6020744E8FA471915D /* Pods_Runner.framework */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
@ -50,6 +50,7 @@
/* End PBXCopyFilesBuildPhase 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>"; };
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>"; };
@ -57,13 +58,11 @@
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>"; };
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>"; };
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>"; };
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>"; };
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>"; };
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>"; };
@ -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>"; };
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>"; };
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>"; };
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>"; };
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>"; };
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 */
@ -97,8 +97,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
4DFD1BB54A3A50573E19A583 /* Pods_Runner.framework in Frameworks */,
CEAFE4A02C53926F009FF3AD /* libresolv.tbd in Frameworks */,
8B1F4FCAA5EB9F3A83D32D5F /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -111,7 +111,7 @@
CEAFE49D2C539250009FF3AD /* Mwebd.xcframework */,
C58D93382C00FAC6004BCF69 /* libresolv.tbd */,
0C9986A3251A932F00D566FD /* CryptoSwift.framework */,
3C663361C56EBB242598F609 /* Pods_Runner.framework */,
D7CD6B6020744E8FA471915D /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -137,10 +137,10 @@
84389F1A05D5860790D82820 /* Pods */ = {
isa = PBXGroup;
children = (
11F9FC13F9EE2A705B213FA9 /* Pods-Runner.debug.xcconfig */,
1F083F2041D1F553F2AF8B62 /* Pods-Runner.release.xcconfig */,
AD0937B0140D5A4C24E73BEA /* Pods-Runner.profile.xcconfig */,
0B80439B9064C9708DDB0ADA /* breez_sdk-OnDemandResources */,
014D7E4DBCFD76DDE652A4D9 /* Pods-Runner.debug.xcconfig */,
28F61114229803070973270D /* Pods-Runner.release.xcconfig */,
D139E30AEB36740C21C00A9E /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
@ -222,14 +222,14 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
B91154210ADCED81FBF06A85 /* [CP] Check Pods Manifest.lock */,
11278EDF4D5DB437B3FDB787 /* [CP] Check Pods Manifest.lock */,
CE5E8A222BEE19C700608EA1 /* CopyFiles */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
32D0076A9969C0C38D68AF62 /* [CP] Embed Pods Frameworks */,
F6F67323547956BC4F7B67F1 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -305,21 +305,26 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
32D0076A9969C0C38D68AF62 /* [CP] Embed Pods Frameworks */ = {
11278EDF4D5DB437B3FDB787 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
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 = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
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;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
@ -353,26 +358,21 @@
shellPath = /bin/sh;
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;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
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;
};
/* End PBXShellScriptBuildPhase section */

View file

@ -262,7 +262,14 @@ class CWBitcoin extends Bitcoin {
List<ReceivePageOption> getBitcoinReceivePageOptions() => BitcoinReceivePageOption.all;
@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
BitcoinAddressType getBitcoinAddressType(ReceivePageOption option) {
@ -608,7 +615,7 @@ class CWBitcoin extends Bitcoin {
final updatedOutputs = outputs.map((output) {
try {
final pendingOut = pendingTx!.outputs[outputs.indexOf(output)];
final pendingOut = pendingTx.outputs[outputs.indexOf(output)];
final updatedOutput = output;
updatedOutput.stealthAddress = P2trAddress.fromScriptPubkey(script: pendingOut.scriptPubKey)
@ -658,8 +665,8 @@ class CWBitcoin extends Bitcoin {
String? getUnusedMwebAddress(Object wallet) {
try {
final electrumWallet = wallet as ElectrumWallet;
final walletAddresses = electrumWallet.walletAddresses as ElectrumWalletAddresses;
final mwebAddress = walletAddresses.mwebAddresses.firstWhere((element) => !element.isUsed);
final mwebAddress =
electrumWallet.walletAddresses.mwebAddresses.firstWhere((element) => !element.isUsed);
return mwebAddress.address;
} catch (_) {
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/routes.dart';
import 'package:cake_wallet/src/screens/dashboard/pages/nft_listing_page.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/action_button.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/home_screen_account_widget.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
@ -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/sync_indicator_theme.dart';
import 'package:cake_wallet/utils/feature_flag.dart';
import 'package:cake_wallet/utils/payment_request.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart';
import 'package:cw_bitcoin/bitcoin_receive_page_option.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:url_launcher/url_launcher.dart';
@ -382,18 +380,10 @@ class CryptoBalanceWidget extends StatelessWidget {
child: DashBoardRoundedCardWidget(
customBorder: 30,
title: S.of(context).litecoin_mweb,
subTitle: '',
subTitle: S.of(context).litecoin_mweb_description,
hint: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
S.of(context).litecoin_mweb_description,
style: TextStyle(
color: Colors.white,
fontSize: 14,
),
textAlign: TextAlign.center,
),
SizedBox(height: 8),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => launchUrl(
@ -401,53 +391,64 @@ class CryptoBalanceWidget extends StatelessWidget {
"https://guides.cakewallet.com/docs/cryptos/litecoin/#mweb"),
mode: LaunchMode.externalApplication,
),
child: Center(
child: Text(
S.of(context).learn_more,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.labelTextColor,
height: 1,
),
softWrap: true,
child: Text(
S.of(context).learn_more,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.labelTextColor,
height: 1,
),
softWrap: true,
),
),
SizedBox(height: 24),
SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () => _dismissMweb(context),
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).primaryColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
Expanded(
child: ElevatedButton(
onPressed: () => _dismissMweb(context),
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).primaryColor,
),
child: Text(
S.of(context).litecoin_mweb_dismiss,
style: TextStyle(color: Colors.white),
),
),
child: Text(
S.of(context).litecoin_mweb_dismiss,
style: TextStyle(color: Colors.white),
),
),
ElevatedButton(
onPressed: () => _enableMweb(context),
child: Text(S.of(context).litecoin_enable_mweb_sync),
const SizedBox(width: 8),
Expanded(
child: ElevatedButton(
onPressed: () => _enableMweb(context),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
foregroundColor: Colors.black,
),
child: Text(
S.of(context).enable,
maxLines: 1,
),
),
),
],
),
],
),
onTap: () => {},
icon: ImageIcon(
AssetImage('assets/images/mweb_logo.png'),
color:
Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor,
size: 50,
icon: Container(
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: ImageIcon(
AssetImage('assets/images/mweb_logo.png'),
color: Color.fromARGB(255, 11, 70, 129),
size: 40,
),
),
),
),
@ -505,7 +506,7 @@ class CryptoBalanceWidget extends StatelessWidget {
},
));
}
dashboardViewModel.setMwebScanningActive();
dashboardViewModel.setMwebEnabled();
}
Future<void> _dismissMweb(BuildContext context) async {
@ -850,23 +851,15 @@ class BalanceRowWidget extends StatelessWidget {
padding: EdgeInsets.only(right: 16, top: 16),
child: Column(
children: [
CakeImageWidget(
imageUrl: 'assets/images/mweb_logo.png',
height: 40,
width: 40,
displayOnError: Container(
height: 30.0,
width: 30.0,
child: Center(
child: Text(
currency.title.substring(0, min(currency.title.length, 2)),
style: TextStyle(fontSize: 11),
),
),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey.shade400,
),
Container(
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: ImageIcon(
AssetImage('assets/images/mweb_logo.png'),
color: Color.fromARGB(255, 11, 70, 129),
size: 40,
),
),
const SizedBox(height: 10),

View file

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

View file

@ -135,10 +135,6 @@ class RootState extends State<Root> with WidgetsBindingObserver {
setState(() => _setInactive(true));
}
if (widget.appStore.wallet?.type == WalletType.litecoin) {
widget.appStore.wallet?.stopSync();
}
break;
case AppLifecycleState.resumed:
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;
default:
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_switcher_cell.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_mobx/flutter_mobx.dart';
@ -33,9 +32,9 @@ class MwebSettingsPage extends BasePage {
),
SettingsSwitcherCell(
title: S.current.litecoin_mweb_always_scan,
value: _mwebSettingsViewModel.mwebAlwaysScan,
value: _mwebSettingsViewModel.mwebEnabled,
onValueChange: (_, bool value) {
_mwebSettingsViewModel.setMwebAlwaysScan(value);
_mwebSettingsViewModel.setMwebEnabled(value);
},
),
SettingsCellWithArrow(

View file

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

View file

@ -37,7 +37,8 @@ abstract class AppStoreBase with Store {
@action
Future<void> changeCurrentWallet(
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!.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/sort_balance_types.dart';
import 'package:cake_wallet/reactions/wallet_connect.dart';
@ -31,6 +32,7 @@ class BalanceRecord {
required this.fiatSecondAdditionalBalance,
required this.asset,
required this.formattedAssetTitle});
final String fiatAdditionalBalance;
final String fiatAvailableBalance;
final String fiatFrozenBalance;
@ -53,7 +55,22 @@ abstract class BalanceViewModelBase with Store {
: isReversing = false,
isShowCard = appStore.wallet!.walletInfo.isShowIntroCakePayCard,
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;
@ -336,14 +353,19 @@ abstract class BalanceViewModelBase with Store {
});
}
@observable
bool mwebEnabled = false;
@computed
bool get hasAdditionalBalance => _hasAdditionalBalanceForWalletType(wallet.type);
@computed
bool get hasSecondAdditionalBalance => _hasSecondAdditionalBalanceForWalletType(wallet.type);
bool get hasSecondAdditionalBalance =>
mwebEnabled && _hasSecondAdditionalBalanceForWalletType(wallet.type);
@computed
bool get hasSecondAvailableBalance => _hasSecondAvailableBalanceForWalletType(wallet.type);
bool get hasSecondAvailableBalance =>
mwebEnabled && _hasSecondAvailableBalanceForWalletType(wallet.type);
bool _hasAdditionalBalanceForWalletType(WalletType type) {
switch (type) {
@ -358,15 +380,16 @@ abstract class BalanceViewModelBase with Store {
}
bool _hasSecondAdditionalBalanceForWalletType(WalletType type) {
if (wallet.type == WalletType.litecoin && settingsStore.mwebAlwaysScan) {
// if ((wallet.balance[CryptoCurrency.ltc]?.secondAdditional ?? 0) > 0)
return true;
if (wallet.type == WalletType.litecoin) {
if ((wallet.balance[CryptoCurrency.ltc]?.secondAdditional ?? 0) > 0) {
return true;
}
}
return false;
}
bool _hasSecondAvailableBalanceForWalletType(WalletType type) {
if (wallet.type == WalletType.litecoin && settingsStore.mwebAlwaysScan) {
if (wallet.type == WalletType.litecoin) {
return true;
}
return false;

View file

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

View file

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

View file

@ -188,36 +188,38 @@ abstract class WalletCreationVMBase with Store {
}
}
Future<List<DerivationInfo>> getDerivationInfoFromQRCredentials(RestoredWallet restoreWallet) async {
var list = <DerivationInfo>[];
final walletType = restoreWallet.type;
var appStore = getIt.get<AppStore>();
var node = appStore.settingsStore.getCurrentNode(walletType);
Future<List<DerivationInfo>> getDerivationInfoFromQRCredentials(
RestoredWallet restoreWallet) async {
var list = <DerivationInfo>[];
final walletType = restoreWallet.type;
var appStore = getIt.get<AppStore>();
var node = appStore.settingsStore.getCurrentNode(walletType);
switch (walletType) {
case WalletType.bitcoin:
case WalletType.litecoin:
return bitcoin!.getDerivationsFromMnemonic(
mnemonic: restoreWallet.mnemonicSeed!,
node: node,
passphrase: restoreWallet.passphrase,
);
case WalletType.nano:
return nanoUtil!.getDerivationsFromMnemonic(
mnemonic: restoreWallet.mnemonicSeed!,
node: node,
);
default:
break;
}
return list;
switch (walletType) {
case WalletType.bitcoin:
case WalletType.litecoin:
return bitcoin!.getDerivationsFromMnemonic(
mnemonic: restoreWallet.mnemonicSeed!,
node: node,
passphrase: restoreWallet.passphrase,
);
case WalletType.nano:
return nanoUtil!.getDerivationsFromMnemonic(
mnemonic: restoreWallet.mnemonicSeed!,
node: node,
);
default:
break;
}
return list;
}
WalletCredentials getCredentials(dynamic options) => throw UnimplementedError();
Future<WalletBase> process(WalletCredentials credentials) => throw UnimplementedError();
Future<WalletCredentials> getWalletCredentialsFromQRCredentials(RestoredWallet restoreWallet) async =>
Future<WalletCredentials> getWalletCredentialsFromQRCredentials(
RestoredWallet restoreWallet) async =>
throw UnimplementedError();
Future<WalletBase> processFromRestoredWallet(

View file

@ -70,6 +70,8 @@ abstract class WalletListViewModelBase with Store {
@action
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);
await _appStore.changeCurrentWallet(wallet);
}

View file

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

View file

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

View file

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

View file

@ -235,6 +235,7 @@
"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í",
"email_address": "E-mailová adresa",
"enable": "Umožnit",
"enable_mempool_api": "Mempool API pro přesné poplatky a data",
"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",

View file

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

View file

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

View file

@ -235,6 +235,7 @@
"edit_token": "Editar token",
"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",
"enable": "Permitir",
"enable_mempool_api": "API de Mempool para tarifas y fechas precisas",
"enable_replace_by_fee": "Habilitar reemplazar por tarea",
"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",
"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",
"enable": "Activer",
"enable_mempool_api": "API Mempool pour les frais et dates précis",
"enable_replace_by_fee": "Activer Remplace-by-Fee",
"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",
"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",
"enable": "Ba dama",
"enable_mempool_api": "Mampool API don ingantattun kudade da kwanakin",
"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",

View file

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

View file

@ -235,6 +235,7 @@
"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",
"email_address": "Adresa e-pošte",
"enable": "Omogućiti",
"enable_mempool_api": "Mempool API za točne naknade i datume",
"enable_replace_by_fee": "Omogući zamjenu",
"enable_silent_payments_scanning": "Započnite skeniranje tihih plaćanja, dok se ne postigne savjet",

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -235,6 +235,7 @@
"edit_token": "Token bewerken",
"electrum_address_disclaimer": "We genereren nieuwe adressen elke keer dat u er een gebruikt, maar eerdere adressen blijven werken",
"email_address": "E-mailadres",
"enable": "Inschakelen",
"enable_mempool_api": "Mempool API voor nauwkeurige kosten en datums",
"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",

View file

@ -235,6 +235,7 @@
"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",
"email_address": "Adres e-mail",
"enable": "Włączać",
"enable_mempool_api": "Mempool API dla dokładnych opłat i dat",
"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",

View file

@ -235,6 +235,7 @@
"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",
"email_address": "Endereço de e-mail",
"enable": "Habilitar",
"enable_mempool_api": "Mempool API para taxas e datas precisas",
"enable_replace_by_fee": "Habilite substituir por taxa",
"enable_silent_payments_scanning": "Comece a escanear pagamentos silenciosos, até que o topo seja alcançada",

View file

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

View file

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

View file

@ -235,6 +235,7 @@
"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",
"email_address": "Email Address",
"enable": "Paganahin",
"enable_mempool_api": "Mempool API para sa tumpak na bayad at mga petsa",
"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",

View file

@ -235,6 +235,7 @@
"edit_token": "Belirteci düzenle",
"electrum_address_disclaimer": "Adresini her kullandığında yeni adres oluşturuyoruz, ancak önceki adresler de çalışmaya devam eder",
"email_address": "E-posta Adresi",
"enable": "Olanak vermek",
"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_silent_payments_scanning": "Bahşiş ulaşılıncaya kadar sessiz ödemeleri taramaya başlayın",

View file

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

View file

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

View file

@ -236,6 +236,7 @@
"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",
"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_replace_by_fee": "Bật Thay thế Bằng Phí",
"enable_silent_payments_scanning": "Bật quét thanh toán im lặng",

View file

@ -236,6 +236,7 @@
"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ẹ̀.",
"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_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",

View file

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

View file

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

View file

@ -13,7 +13,7 @@ fi
# build mwebd:
git clone https://github.com/ltcmweb/mwebd
cd mwebd
git reset --hard f6ea8a9e3d348b01bb44f03a1cc4ad65b0abe935
git reset --hard 555349415f76a42ec5c76152b64c4ab9aabc448f
gomobile bind -target=android -androidapi 21 .
mkdir -p ../../../cw_mweb/android/libs/
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:CFBundleURLSchemes array" ./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=""

View file

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

View file

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

View file

@ -14,8 +14,8 @@ if [ -n "$1" ]; then
fi
CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="1.9.5"
CAKEWALLET_BUILD_NUMBER=33
CAKEWALLET_VERSION="1.10.0"
CAKEWALLET_BUILD_NUMBER=35
if ! [[ " ${TYPES[*]} " =~ " ${APP_LINUX_TYPE} " ]]; then
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/Runner.entitlements
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=""
case $APP_MACOS_TYPE in

View file

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

View file

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

View file

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