mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-10 21:04:53 +00:00
feat: fix rescan & stop, new card
This commit is contained in:
parent
b7ff9ab32b
commit
e16a2180c4
41 changed files with 406 additions and 178 deletions
|
@ -35,6 +35,13 @@ part 'bitcoin_wallet.g.dart';
|
||||||
class BitcoinWallet = BitcoinWalletBase with _$BitcoinWallet;
|
class BitcoinWallet = BitcoinWalletBase with _$BitcoinWallet;
|
||||||
|
|
||||||
abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
|
@observable
|
||||||
|
bool nodeSupportsSilentPayments = true;
|
||||||
|
@observable
|
||||||
|
bool silentPaymentsScanningActive = false;
|
||||||
|
@observable
|
||||||
|
bool allowedToSwitchNodesForScanning = false;
|
||||||
|
|
||||||
BitcoinWalletBase({
|
BitcoinWalletBase({
|
||||||
required String password,
|
required String password,
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
|
@ -307,10 +314,21 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> getNodeIsElectrs() async {
|
Future<bool> getNodeIsElectrs() async {
|
||||||
if (node?.uri.host.contains("electrs") ?? false) {
|
if (node?.isElectrs != null) {
|
||||||
return true;
|
return node!.isElectrs!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final isNamedElectrs = node?.uri.host.contains("electrs") ?? false;
|
||||||
|
if (isNamedElectrs) {
|
||||||
|
node!.isElectrs = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final isNamedFulcrum = node!.uri.host.contains("fulcrum");
|
||||||
|
if (isNamedFulcrum) {
|
||||||
|
node!.isElectrs = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node!.isElectrs == null) {
|
||||||
final version = await sendWorker(ElectrumWorkerGetVersionRequest());
|
final version = await sendWorker(ElectrumWorkerGetVersionRequest());
|
||||||
|
|
||||||
if (version is List<String> && version.isNotEmpty) {
|
if (version is List<String> && version.isNotEmpty) {
|
||||||
|
@ -318,37 +336,30 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
|
|
||||||
if (server.toLowerCase().contains('electrs')) {
|
if (server.toLowerCase().contains('electrs')) {
|
||||||
node!.isElectrs = true;
|
node!.isElectrs = true;
|
||||||
node!.save();
|
|
||||||
return node!.isElectrs!;
|
|
||||||
}
|
}
|
||||||
} else if (version is String && version.toLowerCase().contains('electrs')) {
|
} else if (version is String && version.toLowerCase().contains('electrs')) {
|
||||||
node!.isElectrs = true;
|
node!.isElectrs = true;
|
||||||
node!.save();
|
} else {
|
||||||
return node!.isElectrs!;
|
node!.isElectrs = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node!.isElectrs = false;
|
|
||||||
node!.save();
|
node!.save();
|
||||||
return node!.isElectrs!;
|
return node!.isElectrs!;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> getNodeSupportsSilentPayments() async {
|
Future<bool> getNodeSupportsSilentPayments() async {
|
||||||
// TODO: handle disconnection on check
|
if (node?.supportsSilentPayments != null) {
|
||||||
// TODO: use cached values
|
return node!.supportsSilentPayments!;
|
||||||
if (node == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final isFulcrum = node!.uri.host.contains("fulcrum");
|
|
||||||
if (isFulcrum) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// As of today (august 2024), only ElectrumRS supports silent payments
|
// As of today (august 2024), only ElectrumRS supports silent payments
|
||||||
if (!(await getNodeIsElectrs())) {
|
final isElectrs = await getNodeIsElectrs();
|
||||||
return false;
|
if (!isElectrs) {
|
||||||
|
node!.supportsSilentPayments = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node!.supportsSilentPayments == null) {
|
||||||
try {
|
try {
|
||||||
final workerResponse = (await sendWorker(ElectrumWorkerCheckTweaksRequest())) as String;
|
final workerResponse = (await sendWorker(ElectrumWorkerCheckTweaksRequest())) as String;
|
||||||
final tweaksResponse = ElectrumWorkerCheckTweaksResponse.fromJson(
|
final tweaksResponse = ElectrumWorkerCheckTweaksResponse.fromJson(
|
||||||
|
@ -358,12 +369,13 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
|
|
||||||
if (supportsScanning) {
|
if (supportsScanning) {
|
||||||
node!.supportsSilentPayments = true;
|
node!.supportsSilentPayments = true;
|
||||||
node!.save();
|
} else {
|
||||||
return node!.supportsSilentPayments!;
|
|
||||||
}
|
|
||||||
} catch (_) {}
|
|
||||||
|
|
||||||
node!.supportsSilentPayments = false;
|
node!.supportsSilentPayments = false;
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
node!.supportsSilentPayments = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
node!.save();
|
node!.save();
|
||||||
return node!.supportsSilentPayments!;
|
return node!.supportsSilentPayments!;
|
||||||
}
|
}
|
||||||
|
@ -437,8 +449,10 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
@action
|
@action
|
||||||
Future<void> setSilentPaymentsScanning(bool active) async {
|
Future<void> setSilentPaymentsScanning(bool active) async {
|
||||||
silentPaymentsScanningActive = active;
|
silentPaymentsScanningActive = active;
|
||||||
|
final nodeSupportsSilentPayments = await getNodeSupportsSilentPayments();
|
||||||
|
final isAllowedToScan = nodeSupportsSilentPayments || allowedToSwitchNodesForScanning;
|
||||||
|
|
||||||
if (active) {
|
if (active && isAllowedToScan) {
|
||||||
syncStatus = AttemptingScanSyncStatus();
|
syncStatus = AttemptingScanSyncStatus();
|
||||||
|
|
||||||
final tip = currentChainTip!;
|
final tip = currentChainTip!;
|
||||||
|
@ -730,8 +744,6 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
await walletInfo.updateRestoreHeight(height);
|
await walletInfo.updateRestoreHeight(height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
@ -765,6 +777,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
.map((addr) => addr.labelIndex)
|
.map((addr) => addr.labelIndex)
|
||||||
.toList(),
|
.toList(),
|
||||||
isSingleScan: doSingleScan ?? false,
|
isSingleScan: doSingleScan ?? false,
|
||||||
|
shouldSwitchNodes:
|
||||||
|
!(await getNodeSupportsSilentPayments()) && allowedToSwitchNodesForScanning,
|
||||||
),
|
),
|
||||||
).toJson(),
|
).toJson(),
|
||||||
);
|
);
|
||||||
|
|
|
@ -276,11 +276,6 @@ abstract class ElectrumWalletBase
|
||||||
@override
|
@override
|
||||||
bool isTestnet;
|
bool isTestnet;
|
||||||
|
|
||||||
@observable
|
|
||||||
bool nodeSupportsSilentPayments = true;
|
|
||||||
@observable
|
|
||||||
bool silentPaymentsScanningActive = false;
|
|
||||||
|
|
||||||
bool _isTryingToConnect = false;
|
bool _isTryingToConnect = false;
|
||||||
|
|
||||||
Completer<SharedPreferences> sharedPrefs = Completer();
|
Completer<SharedPreferences> sharedPrefs = Completer();
|
||||||
|
|
|
@ -14,17 +14,15 @@ import 'package:cw_bitcoin/electrum_worker/electrum_worker_methods.dart';
|
||||||
import 'package:cw_bitcoin/electrum_worker/electrum_worker_params.dart';
|
import 'package:cw_bitcoin/electrum_worker/electrum_worker_params.dart';
|
||||||
import 'package:cw_bitcoin/electrum_worker/methods/methods.dart';
|
import 'package:cw_bitcoin/electrum_worker/methods/methods.dart';
|
||||||
import 'package:cw_core/sync_status.dart';
|
import 'package:cw_core/sync_status.dart';
|
||||||
import 'package:cw_core/transaction_direction.dart';
|
|
||||||
import 'package:cw_core/wallet_type.dart';
|
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:rxdart/rxdart.dart';
|
||||||
import 'package:sp_scanner/sp_scanner.dart';
|
import 'package:sp_scanner/sp_scanner.dart';
|
||||||
|
|
||||||
class ElectrumWorker {
|
class ElectrumWorker {
|
||||||
final SendPort sendPort;
|
final SendPort sendPort;
|
||||||
ElectrumApiProvider? _electrumClient;
|
ElectrumApiProvider? _electrumClient;
|
||||||
BasedUtxoNetwork? _network;
|
BasedUtxoNetwork? _network;
|
||||||
bool _isScanning = false;
|
BehaviorSubject<Map<String, dynamic>>? _scanningStream;
|
||||||
bool _stopScanRequested = false;
|
|
||||||
|
|
||||||
ElectrumWorker._(this.sendPort, {ElectrumApiProvider? electrumClient})
|
ElectrumWorker._(this.sendPort, {ElectrumApiProvider? electrumClient})
|
||||||
: _electrumClient = electrumClient;
|
: _electrumClient = electrumClient;
|
||||||
|
@ -47,7 +45,7 @@ class ElectrumWorker {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleMessage(dynamic message) async {
|
void handleMessage(dynamic message) async {
|
||||||
print("Worker received message: $message");
|
print("Worker: received message: $message");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Map<String, dynamic> messageJson;
|
Map<String, dynamic> messageJson;
|
||||||
|
@ -105,27 +103,15 @@ class ElectrumWorker {
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case ElectrumWorkerMethods.stopScanningMethod:
|
case ElectrumWorkerMethods.stopScanningMethod:
|
||||||
|
print("Worker: received message: $message");
|
||||||
await _handleStopScanning(
|
await _handleStopScanning(
|
||||||
ElectrumWorkerStopScanningRequest.fromJson(messageJson),
|
ElectrumWorkerStopScanningRequest.fromJson(messageJson),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case ElectrumRequestMethods.tweaksSubscribeMethod:
|
case ElectrumRequestMethods.tweaksSubscribeMethod:
|
||||||
if (_isScanning) {
|
|
||||||
_stopScanRequested = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_stopScanRequested) {
|
|
||||||
await _handleScanSilentPayments(
|
await _handleScanSilentPayments(
|
||||||
ElectrumWorkerTweaksSubscribeRequest.fromJson(messageJson),
|
ElectrumWorkerTweaksSubscribeRequest.fromJson(messageJson),
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
_stopScanRequested = false;
|
|
||||||
_sendResponse(
|
|
||||||
ElectrumWorkerTweaksSubscribeResponse(
|
|
||||||
result: TweaksSyncResponse(syncStatus: SyncedSyncStatus()),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ElectrumRequestMethods.estimateFeeMethod:
|
case ElectrumRequestMethods.estimateFeeMethod:
|
||||||
|
@ -550,28 +536,25 @@ class ElectrumWorker {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _handleStopScanning(ElectrumWorkerStopScanningRequest request) async {
|
Future<void> _handleStopScanning(ElectrumWorkerStopScanningRequest request) async {
|
||||||
_stopScanRequested = true;
|
_scanningStream?.close();
|
||||||
|
_scanningStream = null;
|
||||||
_sendResponse(
|
_sendResponse(
|
||||||
ElectrumWorkerStopScanningResponse(result: true, id: request.id),
|
ElectrumWorkerStopScanningResponse(result: true, id: request.id),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _handleScanSilentPayments(ElectrumWorkerTweaksSubscribeRequest request) async {
|
Future<void> _handleScanSilentPayments(ElectrumWorkerTweaksSubscribeRequest request) async {
|
||||||
_isScanning = true;
|
|
||||||
final scanData = request.scanData;
|
final scanData = request.scanData;
|
||||||
|
|
||||||
// TODO: confirmedSwitch use new connection
|
var scanningClient = _electrumClient;
|
||||||
// final _electrumClient = await ElectrumApiProvider.connect(
|
|
||||||
// ElectrumTCPService.connect(
|
|
||||||
// Uri.parse("tcp://electrs.cakewallet.com:50001"),
|
|
||||||
// onConnectionStatusChange: (status) {
|
|
||||||
// _sendResponse(
|
|
||||||
// ElectrumWorkerConnectionResponse(status: status, id: request.id),
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
|
|
||||||
|
if (scanData.shouldSwitchNodes) {
|
||||||
|
scanningClient = await ElectrumApiProvider.connect(
|
||||||
|
ElectrumTCPService.connect(
|
||||||
|
Uri.parse("tcp://electrs.cakewallet.com:50001"),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
int syncHeight = scanData.height;
|
int syncHeight = scanData.height;
|
||||||
int initialSyncHeight = syncHeight;
|
int initialSyncHeight = syncHeight;
|
||||||
|
|
||||||
|
@ -587,6 +570,15 @@ class ElectrumWorker {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
int getCountPerRequest(int syncHeight) {
|
||||||
|
if (scanData.isSingleScan) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
final amountLeft = scanData.chainTip - syncHeight + 1;
|
||||||
|
return amountLeft;
|
||||||
|
}
|
||||||
|
|
||||||
// Initial status UI update, send how many blocks in total to scan
|
// Initial status UI update, send how many blocks in total to scan
|
||||||
_sendResponse(ElectrumWorkerTweaksSubscribeResponse(
|
_sendResponse(ElectrumWorkerTweaksSubscribeResponse(
|
||||||
result: TweaksSyncResponse(
|
result: TweaksSyncResponse(
|
||||||
|
@ -597,17 +589,16 @@ class ElectrumWorker {
|
||||||
|
|
||||||
final req = ElectrumTweaksSubscribe(
|
final req = ElectrumTweaksSubscribe(
|
||||||
height: syncHeight,
|
height: syncHeight,
|
||||||
count: 1,
|
count: getCountPerRequest(syncHeight),
|
||||||
historicalMode: false,
|
historicalMode: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
final stream = await _electrumClient!.subscribe(req);
|
_scanningStream = await scanningClient!.subscribe(req);
|
||||||
|
|
||||||
void listenFn(Map<String, dynamic> event, ElectrumTweaksSubscribe req) {
|
void listenFn(Map<String, dynamic> event, ElectrumTweaksSubscribe req) {
|
||||||
final response = req.onResponse(event);
|
final response = req.onResponse(event);
|
||||||
if (_stopScanRequested || response == null) {
|
|
||||||
_stopScanRequested = false;
|
if (response == null || _scanningStream == null) {
|
||||||
_isScanning = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,10 +614,10 @@ class ElectrumWorker {
|
||||||
final nextHeight = syncHeight + 1;
|
final nextHeight = syncHeight + 1;
|
||||||
|
|
||||||
if (nextHeight <= scanData.chainTip) {
|
if (nextHeight <= scanData.chainTip) {
|
||||||
final nextStream = _electrumClient!.subscribe(
|
final nextStream = scanningClient!.subscribe(
|
||||||
ElectrumTweaksSubscribe(
|
ElectrumTweaksSubscribe(
|
||||||
height: nextHeight,
|
height: nextHeight,
|
||||||
count: 1,
|
count: getCountPerRequest(nextHeight),
|
||||||
historicalMode: false,
|
historicalMode: false,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -710,6 +701,7 @@ class ElectrumWorker {
|
||||||
receivingOutputAddress,
|
receivingOutputAddress,
|
||||||
labelIndex: 1, // TODO: get actual index/label
|
labelIndex: 1, // TODO: get actual index/label
|
||||||
isUsed: true,
|
isUsed: true,
|
||||||
|
// TODO: use right wallet
|
||||||
spendKey: scanData.silentPaymentsWallets.first.b_spend.tweakAdd(
|
spendKey: scanData.silentPaymentsWallets.first.b_spend.tweakAdd(
|
||||||
BigintUtils.fromBytes(BytesUtils.fromHexString(t_k)),
|
BigintUtils.fromBytes(BytesUtils.fromHexString(t_k)),
|
||||||
),
|
),
|
||||||
|
@ -753,24 +745,27 @@ class ElectrumWorker {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
stream?.close();
|
_scanningStream?.close();
|
||||||
|
_scanningStream = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stream?.listen((event) => listenFn(event, req));
|
_scanningStream?.listen((event) => listenFn(event, req));
|
||||||
_isScanning = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _handleGetVersion(ElectrumWorkerGetVersionRequest request) async {
|
Future<void> _handleGetVersion(ElectrumWorkerGetVersionRequest request) async {
|
||||||
_sendResponse(ElectrumWorkerGetVersionResponse(
|
_sendResponse(
|
||||||
result: (await _electrumClient!.request(
|
ElectrumWorkerGetVersionResponse(
|
||||||
|
result: await _electrumClient!.request(
|
||||||
ElectrumVersion(
|
ElectrumVersion(
|
||||||
clientName: "",
|
clientName: "",
|
||||||
protocolVersion: ["1.4"],
|
protocolVersion: "1.4",
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
id: request.id));
|
id: request.id,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ class ScanData {
|
||||||
final Map<String, String> labels;
|
final Map<String, String> labels;
|
||||||
final List<int> labelIndexes;
|
final List<int> labelIndexes;
|
||||||
final bool isSingleScan;
|
final bool isSingleScan;
|
||||||
|
final bool shouldSwitchNodes;
|
||||||
|
|
||||||
ScanData({
|
ScanData({
|
||||||
required this.silentPaymentsWallets,
|
required this.silentPaymentsWallets,
|
||||||
|
@ -19,6 +20,7 @@ class ScanData {
|
||||||
required this.labels,
|
required this.labels,
|
||||||
required this.labelIndexes,
|
required this.labelIndexes,
|
||||||
required this.isSingleScan,
|
required this.isSingleScan,
|
||||||
|
required this.shouldSwitchNodes,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory ScanData.fromHeight(ScanData scanData, int newHeight) {
|
factory ScanData.fromHeight(ScanData scanData, int newHeight) {
|
||||||
|
@ -31,6 +33,7 @@ class ScanData {
|
||||||
labels: scanData.labels,
|
labels: scanData.labels,
|
||||||
labelIndexes: scanData.labelIndexes,
|
labelIndexes: scanData.labelIndexes,
|
||||||
isSingleScan: scanData.isSingleScan,
|
isSingleScan: scanData.isSingleScan,
|
||||||
|
shouldSwitchNodes: scanData.shouldSwitchNodes,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +47,7 @@ class ScanData {
|
||||||
'labels': labels,
|
'labels': labels,
|
||||||
'labelIndexes': labelIndexes,
|
'labelIndexes': labelIndexes,
|
||||||
'isSingleScan': isSingleScan,
|
'isSingleScan': isSingleScan,
|
||||||
|
'shouldSwitchNodes': shouldSwitchNodes,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +64,7 @@ class ScanData {
|
||||||
labels: json['labels'] as Map<String, String>,
|
labels: json['labels'] as Map<String, String>,
|
||||||
labelIndexes: (json['labelIndexes'] as List).map((e) => e as int).toList(),
|
labelIndexes: (json['labelIndexes'] as List).map((e) => e as int).toList(),
|
||||||
isSingleScan: json['isSingleScan'] as bool,
|
isSingleScan: json['isSingleScan'] as bool,
|
||||||
|
shouldSwitchNodes: json['shouldSwitchNodes'] as bool,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,6 +288,11 @@ class CWBitcoin extends Bitcoin {
|
||||||
return BitcoinReceivePageOption.fromType(bitcoinWallet.walletAddresses.addressPageType);
|
return BitcoinReceivePageOption.fromType(bitcoinWallet.walletAddresses.addressPageType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool isReceiveOptionSP(ReceivePageOption option) {
|
||||||
|
return option.value == BitcoinReceivePageOption.silent_payments.value;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool hasSelectedSilentPayments(Object wallet) {
|
bool hasSelectedSilentPayments(Object wallet) {
|
||||||
final bitcoinWallet = wallet as ElectrumWallet;
|
final bitcoinWallet = wallet as ElectrumWallet;
|
||||||
|
@ -610,7 +615,7 @@ class CWBitcoin extends Bitcoin {
|
||||||
@override
|
@override
|
||||||
@computed
|
@computed
|
||||||
bool getScanningActive(Object wallet) {
|
bool getScanningActive(Object wallet) {
|
||||||
final bitcoinWallet = wallet as ElectrumWallet;
|
final bitcoinWallet = wallet as BitcoinWallet;
|
||||||
return bitcoinWallet.silentPaymentsScanningActive;
|
return bitcoinWallet.silentPaymentsScanningActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -620,6 +625,12 @@ class CWBitcoin extends Bitcoin {
|
||||||
bitcoinWallet.setSilentPaymentsScanning(active);
|
bitcoinWallet.setSilentPaymentsScanning(active);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> allowToSwitchNodesForScanning(Object wallet, bool allow) async {
|
||||||
|
final bitcoinWallet = wallet as BitcoinWallet;
|
||||||
|
bitcoinWallet.allowedToSwitchNodesForScanning = allow;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool isTestnet(Object wallet) {
|
bool isTestnet(Object wallet) {
|
||||||
final bitcoinWallet = wallet as ElectrumWallet;
|
final bitcoinWallet = wallet as ElectrumWallet;
|
||||||
|
|
50
lib/di.dart
50
lib/di.dart
|
@ -472,10 +472,14 @@ Future<void> setup({
|
||||||
getIt.get<SeedSettingsViewModel>(),
|
getIt.get<SeedSettingsViewModel>(),
|
||||||
type: type));
|
type: type));
|
||||||
|
|
||||||
getIt.registerFactory<WalletAddressListViewModel>(() => WalletAddressListViewModel(
|
getIt.registerFactoryParam<WalletAddressListViewModel, ReceivePageOption?, void>(
|
||||||
|
(ReceivePageOption? addressType, _) => WalletAddressListViewModel(
|
||||||
appStore: getIt.get<AppStore>(),
|
appStore: getIt.get<AppStore>(),
|
||||||
yatStore: getIt.get<YatStore>(),
|
yatStore: getIt.get<YatStore>(),
|
||||||
fiatConversionStore: getIt.get<FiatConversionStore>()));
|
fiatConversionStore: getIt.get<FiatConversionStore>(),
|
||||||
|
addressType: addressType,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
getIt.registerFactory(() => BalanceViewModel(
|
getIt.registerFactory(() => BalanceViewModel(
|
||||||
appStore: getIt.get<AppStore>(),
|
appStore: getIt.get<AppStore>(),
|
||||||
|
@ -704,12 +708,26 @@ Future<void> setup({
|
||||||
getIt.get<ReceiveOptionViewModel>(param1: pageOption));
|
getIt.get<ReceiveOptionViewModel>(param1: pageOption));
|
||||||
});
|
});
|
||||||
|
|
||||||
getIt.registerFactory<ReceivePage>(
|
getIt.registerFactoryParam<ReceivePage, ReceivePageOption?, void>(
|
||||||
() => ReceivePage(addressListViewModel: getIt.get<WalletAddressListViewModel>()));
|
(ReceivePageOption? addressType, _) => ReceivePage(
|
||||||
getIt.registerFactory<AddressPage>(() => AddressPage(
|
addressListViewModel: getIt.get<WalletAddressListViewModel>(
|
||||||
addressListViewModel: getIt.get<WalletAddressListViewModel>(),
|
param1: addressType,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
getIt.registerFactoryParam<AddressPage, ReceivePageOption?, void>(
|
||||||
|
(ReceivePageOption? addressType, _) => AddressPage(
|
||||||
|
addressListViewModel: getIt.get<WalletAddressListViewModel>(
|
||||||
|
param1: addressType,
|
||||||
|
),
|
||||||
dashboardViewModel: getIt.get<DashboardViewModel>(),
|
dashboardViewModel: getIt.get<DashboardViewModel>(),
|
||||||
receiveOptionViewModel: getIt.get<ReceiveOptionViewModel>()));
|
receiveOptionViewModel: getIt.get<ReceiveOptionViewModel>(
|
||||||
|
param1: addressType,
|
||||||
|
),
|
||||||
|
addressType: addressType,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
getIt.registerFactoryParam<WalletAddressEditOrCreateViewModel, WalletAddressListItem?, void>(
|
getIt.registerFactoryParam<WalletAddressEditOrCreateViewModel, WalletAddressListItem?, void>(
|
||||||
(WalletAddressListItem? item, _) =>
|
(WalletAddressListItem? item, _) =>
|
||||||
|
@ -907,8 +925,8 @@ Future<void> setup({
|
||||||
|
|
||||||
getIt.registerFactory(() => AnimatedURModel(getIt.get<AppStore>()));
|
getIt.registerFactory(() => AnimatedURModel(getIt.get<AppStore>()));
|
||||||
|
|
||||||
getIt.registerFactoryParam<AnimatedURPage, String, void>((String urQr, _) =>
|
getIt.registerFactoryParam<AnimatedURPage, String, void>(
|
||||||
AnimatedURPage(getIt.get<AnimatedURModel>(), urQr: urQr));
|
(String urQr, _) => AnimatedURPage(getIt.get<AnimatedURModel>(), urQr: urQr));
|
||||||
|
|
||||||
getIt.registerFactoryParam<ContactViewModel, ContactRecord?, void>(
|
getIt.registerFactoryParam<ContactViewModel, ContactRecord?, void>(
|
||||||
(ContactRecord? contact, _) => ContactViewModel(_contactSource, contact: contact));
|
(ContactRecord? contact, _) => ContactViewModel(_contactSource, contact: contact));
|
||||||
|
@ -1207,16 +1225,15 @@ Future<void> setup({
|
||||||
final items = args.first as List<SelectableItem>;
|
final items = args.first as List<SelectableItem>;
|
||||||
final pickAnOption = args[1] as void Function(SelectableOption option)?;
|
final pickAnOption = args[1] as void Function(SelectableOption option)?;
|
||||||
final confirmOption = args[2] as void Function(BuildContext contex)?;
|
final confirmOption = args[2] as void Function(BuildContext contex)?;
|
||||||
return BuyOptionsPage(
|
return BuyOptionsPage(items: items, pickAnOption: pickAnOption, confirmOption: confirmOption);
|
||||||
items: items, pickAnOption: pickAnOption, confirmOption: confirmOption);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
getIt.registerFactoryParam<PaymentMethodOptionsPage, List<dynamic>, void>((List<dynamic> args, _) {
|
getIt
|
||||||
|
.registerFactoryParam<PaymentMethodOptionsPage, List<dynamic>, void>((List<dynamic> args, _) {
|
||||||
final items = args.first as List<SelectableOption>;
|
final items = args.first as List<SelectableOption>;
|
||||||
final pickAnOption = args[1] as void Function(SelectableOption option)?;
|
final pickAnOption = args[1] as void Function(SelectableOption option)?;
|
||||||
|
|
||||||
return PaymentMethodOptionsPage(
|
return PaymentMethodOptionsPage(items: items, pickAnOption: pickAnOption);
|
||||||
items: items, pickAnOption: pickAnOption);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
getIt.registerFactory(() {
|
getIt.registerFactory(() {
|
||||||
|
@ -1300,9 +1317,8 @@ Future<void> setup({
|
||||||
getIt.registerFactory<CakePayService>(
|
getIt.registerFactory<CakePayService>(
|
||||||
() => CakePayService(getIt.get<SecureStorage>(), getIt.get<CakePayApi>()));
|
() => CakePayService(getIt.get<SecureStorage>(), getIt.get<CakePayApi>()));
|
||||||
|
|
||||||
getIt.registerFactory(
|
getIt.registerFactory(() => CakePayCardsListViewModel(
|
||||||
() => CakePayCardsListViewModel(cakePayService: getIt.get<CakePayService>(),
|
cakePayService: getIt.get<CakePayService>(), settingsStore: getIt.get<SettingsStore>()));
|
||||||
settingsStore: getIt.get<SettingsStore>()));
|
|
||||||
|
|
||||||
getIt.registerFactory(() => CakePayAuthViewModel(cakePayService: getIt.get<CakePayService>()));
|
getIt.registerFactory(() => CakePayAuthViewModel(cakePayService: getIt.get<CakePayService>()));
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,7 @@ import 'package:cake_wallet/wallet_types.g.dart';
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
import 'package:cw_core/nano_account.dart';
|
import 'package:cw_core/nano_account.dart';
|
||||||
import 'package:cw_core/node.dart';
|
import 'package:cw_core/node.dart';
|
||||||
|
import 'package:cw_core/receive_page_option.dart';
|
||||||
import 'package:cw_core/transaction_info.dart';
|
import 'package:cw_core/transaction_info.dart';
|
||||||
import 'package:cw_core/unspent_coin_type.dart';
|
import 'package:cw_core/unspent_coin_type.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
|
@ -376,11 +377,21 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
fullscreenDialog: true, builder: (_) => getIt.get<SendTemplatePage>());
|
fullscreenDialog: true, builder: (_) => getIt.get<SendTemplatePage>());
|
||||||
|
|
||||||
case Routes.receive:
|
case Routes.receive:
|
||||||
return CupertinoPageRoute<void>(builder: (_) => getIt.get<ReceivePage>());
|
final args = settings.arguments as Map<String, dynamic>?;
|
||||||
|
final addressType = args?['addressType'] as ReceivePageOption?;
|
||||||
|
|
||||||
|
return CupertinoPageRoute<void>(
|
||||||
|
builder: (_) => getIt.get<ReceivePage>(param1: addressType),
|
||||||
|
);
|
||||||
|
|
||||||
case Routes.addressPage:
|
case Routes.addressPage:
|
||||||
|
final args = settings.arguments as Map<String, dynamic>?;
|
||||||
|
final addressType = args?['addressType'] as ReceivePageOption?;
|
||||||
|
|
||||||
return CupertinoPageRoute<void>(
|
return CupertinoPageRoute<void>(
|
||||||
fullscreenDialog: true, builder: (_) => getIt.get<AddressPage>());
|
fullscreenDialog: true,
|
||||||
|
builder: (_) => getIt.get<AddressPage>(param1: addressType),
|
||||||
|
);
|
||||||
|
|
||||||
case Routes.transactionDetails:
|
case Routes.transactionDetails:
|
||||||
return CupertinoPageRoute<void>(
|
return CupertinoPageRoute<void>(
|
||||||
|
@ -588,7 +599,8 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
|
|
||||||
case Routes.paymentMethodOptionsPage:
|
case Routes.paymentMethodOptionsPage:
|
||||||
final args = settings.arguments as List;
|
final args = settings.arguments as List;
|
||||||
return MaterialPageRoute<void>(builder: (_) => getIt.get<PaymentMethodOptionsPage>(param1: args));
|
return MaterialPageRoute<void>(
|
||||||
|
builder: (_) => getIt.get<PaymentMethodOptionsPage>(param1: args));
|
||||||
|
|
||||||
case Routes.buyWebView:
|
case Routes.buyWebView:
|
||||||
final args = settings.arguments as List;
|
final args = settings.arguments as List;
|
||||||
|
@ -751,7 +763,8 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
return MaterialPageRoute<void>(builder: (_) => getIt.get<Setup2FAInfoPage>());
|
return MaterialPageRoute<void>(builder: (_) => getIt.get<Setup2FAInfoPage>());
|
||||||
|
|
||||||
case Routes.urqrAnimatedPage:
|
case Routes.urqrAnimatedPage:
|
||||||
return MaterialPageRoute<void>(builder: (_) => getIt.get<AnimatedURPage>(param1: settings.arguments));
|
return MaterialPageRoute<void>(
|
||||||
|
builder: (_) => getIt.get<AnimatedURPage>(param1: settings.arguments));
|
||||||
|
|
||||||
case Routes.homeSettings:
|
case Routes.homeSettings:
|
||||||
return CupertinoPageRoute<void>(
|
return CupertinoPageRoute<void>(
|
||||||
|
|
|
@ -32,9 +32,11 @@ class AddressPage extends BasePage {
|
||||||
required this.addressListViewModel,
|
required this.addressListViewModel,
|
||||||
required this.dashboardViewModel,
|
required this.dashboardViewModel,
|
||||||
required this.receiveOptionViewModel,
|
required this.receiveOptionViewModel,
|
||||||
|
ReceivePageOption? addressType,
|
||||||
}) : _cryptoAmountFocus = FocusNode(),
|
}) : _cryptoAmountFocus = FocusNode(),
|
||||||
_formKey = GlobalKey<FormState>(),
|
_formKey = GlobalKey<FormState>(),
|
||||||
_amountController = TextEditingController() {
|
_amountController = TextEditingController(),
|
||||||
|
_addressType = addressType {
|
||||||
_amountController.addListener(() {
|
_amountController.addListener(() {
|
||||||
if (_formKey.currentState!.validate()) {
|
if (_formKey.currentState!.validate()) {
|
||||||
addressListViewModel.changeAmount(
|
addressListViewModel.changeAmount(
|
||||||
|
@ -49,6 +51,7 @@ class AddressPage extends BasePage {
|
||||||
final ReceiveOptionViewModel receiveOptionViewModel;
|
final ReceiveOptionViewModel receiveOptionViewModel;
|
||||||
final TextEditingController _amountController;
|
final TextEditingController _amountController;
|
||||||
final GlobalKey<FormState> _formKey;
|
final GlobalKey<FormState> _formKey;
|
||||||
|
ReceivePageOption? _addressType;
|
||||||
|
|
||||||
final FocusNode _cryptoAmountFocus;
|
final FocusNode _cryptoAmountFocus;
|
||||||
|
|
||||||
|
@ -190,7 +193,11 @@ class AddressPage extends BasePage {
|
||||||
if (addressListViewModel.hasAddressList) {
|
if (addressListViewModel.hasAddressList) {
|
||||||
return SelectButton(
|
return SelectButton(
|
||||||
text: addressListViewModel.buttonTitle,
|
text: addressListViewModel.buttonTitle,
|
||||||
onTap: () => Navigator.of(context).pushNamed(Routes.receive),
|
onTap: () => Navigator.pushNamed(
|
||||||
|
context,
|
||||||
|
Routes.receive,
|
||||||
|
arguments: {'addressType': _addressType},
|
||||||
|
),
|
||||||
textColor: Theme.of(context).extension<SyncIndicatorTheme>()!.textColor,
|
textColor: Theme.of(context).extension<SyncIndicatorTheme>()!.textColor,
|
||||||
color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor,
|
color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor,
|
||||||
borderColor: Theme.of(context).extension<BalancePageTheme>()!.cardBorderColor,
|
borderColor: Theme.of(context).extension<BalancePageTheme>()!.cardBorderColor,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'dart:async';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:auto_size_text/auto_size_text.dart';
|
import 'package:auto_size_text/auto_size_text.dart';
|
||||||
|
@ -354,12 +355,108 @@ class CryptoBalanceWidget extends StatelessWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 8),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Semantics(
|
||||||
|
label: S.of(context).receive,
|
||||||
|
child: OutlinedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pushNamed(
|
||||||
|
context,
|
||||||
|
Routes.addressPage,
|
||||||
|
arguments: {
|
||||||
|
'addressType': bitcoin!
|
||||||
|
.getBitcoinReceivePageOptions()
|
||||||
|
.where(
|
||||||
|
(option) => option.value == "Silent Payments",
|
||||||
|
)
|
||||||
|
.first
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
style: OutlinedButton.styleFrom(
|
||||||
|
backgroundColor: Colors.grey.shade400.withAlpha(50),
|
||||||
|
side: BorderSide(
|
||||||
|
color: Colors.grey.shade400.withAlpha(50), width: 0),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 12),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
height: 30,
|
||||||
|
width: 30,
|
||||||
|
'assets/images/received.png',
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<BalancePageTheme>()!
|
||||||
|
.balanceAmountColor,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Text(
|
||||||
|
S.of(context).receive,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<BalancePageTheme>()!
|
||||||
|
.textColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 24),
|
||||||
|
Expanded(
|
||||||
|
child: Semantics(
|
||||||
|
label: S.of(context).scan,
|
||||||
|
child: OutlinedButton(
|
||||||
|
onPressed: () => _toggleSilentPaymentsScanning(context),
|
||||||
|
style: OutlinedButton.styleFrom(
|
||||||
|
backgroundColor: Colors.grey.shade400.withAlpha(50),
|
||||||
|
side: BorderSide(
|
||||||
|
color: Colors.grey.shade400.withAlpha(50), width: 0),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 12),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
Observer(
|
Observer(
|
||||||
builder: (_) => StandardSwitch(
|
builder: (_) => StandardSwitch(
|
||||||
value: dashboardViewModel.silentPaymentsScanningActive,
|
value:
|
||||||
onTaped: () => _toggleSilentPaymentsScanning(context),
|
dashboardViewModel.silentPaymentsScanningActive,
|
||||||
|
onTaped: () =>
|
||||||
|
_toggleSilentPaymentsScanning(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text(
|
||||||
|
S.of(context).scan,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<BalancePageTheme>()!
|
||||||
|
.textColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -466,12 +563,20 @@ class CryptoBalanceWidget extends StatelessWidget {
|
||||||
Future<void> _toggleSilentPaymentsScanning(BuildContext context) async {
|
Future<void> _toggleSilentPaymentsScanning(BuildContext context) async {
|
||||||
final isSilentPaymentsScanningActive = dashboardViewModel.silentPaymentsScanningActive;
|
final isSilentPaymentsScanningActive = dashboardViewModel.silentPaymentsScanningActive;
|
||||||
final newValue = !isSilentPaymentsScanningActive;
|
final newValue = !isSilentPaymentsScanningActive;
|
||||||
|
final willScan = newValue == true;
|
||||||
dashboardViewModel.silentPaymentsScanningActive = newValue;
|
dashboardViewModel.silentPaymentsScanningActive = newValue;
|
||||||
|
|
||||||
final needsToSwitch = !isSilentPaymentsScanningActive &&
|
if (willScan) {
|
||||||
await bitcoin!.getNodeIsElectrsSPEnabled(dashboardViewModel.wallet) == false;
|
late bool isElectrsSPEnabled;
|
||||||
|
try {
|
||||||
|
isElectrsSPEnabled = await bitcoin!
|
||||||
|
.getNodeIsElectrsSPEnabled(dashboardViewModel.wallet)
|
||||||
|
.timeout(const Duration(seconds: 3));
|
||||||
|
} on TimeoutException {
|
||||||
|
isElectrsSPEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final needsToSwitch = isElectrsSPEnabled == false;
|
||||||
if (needsToSwitch) {
|
if (needsToSwitch) {
|
||||||
return showPopUp<void>(
|
return showPopUp<void>(
|
||||||
context: context,
|
context: context,
|
||||||
|
@ -481,14 +586,17 @@ class CryptoBalanceWidget extends StatelessWidget {
|
||||||
rightButtonText: S.of(context).confirm,
|
rightButtonText: S.of(context).confirm,
|
||||||
leftButtonText: S.of(context).cancel,
|
leftButtonText: S.of(context).cancel,
|
||||||
actionRightButton: () {
|
actionRightButton: () {
|
||||||
dashboardViewModel.setSilentPaymentsScanning(newValue);
|
dashboardViewModel.allowSilentPaymentsScanning(true);
|
||||||
|
dashboardViewModel.setSilentPaymentsScanning(true);
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
actionLeftButton: () {
|
actionLeftButton: () {
|
||||||
dashboardViewModel.silentPaymentsScanningActive = isSilentPaymentsScanningActive;
|
dashboardViewModel.silentPaymentsScanningActive = isSilentPaymentsScanningActive;
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
));
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dashboardViewModel.setSilentPaymentsScanning(newValue);
|
return dashboardViewModel.setSilentPaymentsScanning(newValue);
|
||||||
|
@ -1045,10 +1153,9 @@ class BalanceRowWidget extends StatelessWidget {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
style: OutlinedButton.styleFrom(
|
style: OutlinedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey.shade400
|
backgroundColor: Colors.grey.shade400.withAlpha(50),
|
||||||
.withAlpha(50),
|
side:
|
||||||
side: BorderSide(color: Colors.grey.shade400
|
BorderSide(color: Colors.grey.shade400.withAlpha(50), width: 0),
|
||||||
.withAlpha(50), width: 0),
|
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
),
|
),
|
||||||
|
@ -1104,10 +1211,9 @@ class BalanceRowWidget extends StatelessWidget {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
style: OutlinedButton.styleFrom(
|
style: OutlinedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey.shade400
|
backgroundColor: Colors.grey.shade400.withAlpha(50),
|
||||||
.withAlpha(50),
|
side:
|
||||||
side: BorderSide(color: Colors.grey.shade400
|
BorderSide(color: Colors.grey.shade400.withAlpha(50), width: 0),
|
||||||
.withAlpha(50), width: 0),
|
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||||
import 'package:cake_wallet/main.dart';
|
|
||||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -35,7 +36,8 @@ class RescanPage extends BasePage {
|
||||||
isSilentPaymentsScan: _rescanViewModel.isSilentPaymentsScan,
|
isSilentPaymentsScan: _rescanViewModel.isSilentPaymentsScan,
|
||||||
isMwebScan: _rescanViewModel.isMwebScan,
|
isMwebScan: _rescanViewModel.isMwebScan,
|
||||||
doSingleScan: _rescanViewModel.doSingleScan,
|
doSingleScan: _rescanViewModel.doSingleScan,
|
||||||
hasDatePicker: !_rescanViewModel.isMwebScan,// disable date picker for mweb for now
|
hasDatePicker:
|
||||||
|
!_rescanViewModel.isMwebScan, // disable date picker for mweb for now
|
||||||
toggleSingleScan: () =>
|
toggleSingleScan: () =>
|
||||||
_rescanViewModel.doSingleScan = !_rescanViewModel.doSingleScan,
|
_rescanViewModel.doSingleScan = !_rescanViewModel.doSingleScan,
|
||||||
walletType: _rescanViewModel.wallet.type,
|
walletType: _rescanViewModel.wallet.type,
|
||||||
|
@ -69,12 +71,19 @@ class RescanPage extends BasePage {
|
||||||
|
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
|
||||||
final needsToSwitch =
|
late bool isElectrsSPEnabled;
|
||||||
await bitcoin!.getNodeIsElectrsSPEnabled(_rescanViewModel.wallet) == false;
|
try {
|
||||||
|
isElectrsSPEnabled = await bitcoin!
|
||||||
|
.getNodeIsElectrsSPEnabled(_rescanViewModel.wallet)
|
||||||
|
.timeout(const Duration(seconds: 3));
|
||||||
|
} on TimeoutException {
|
||||||
|
isElectrsSPEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final needsToSwitch = isElectrsSPEnabled == false;
|
||||||
if (needsToSwitch) {
|
if (needsToSwitch) {
|
||||||
return showPopUp<void>(
|
return showPopUp<void>(
|
||||||
context: navigatorKey.currentState!.context,
|
context: context,
|
||||||
builder: (BuildContext _dialogContext) => AlertWithTwoActions(
|
builder: (BuildContext _dialogContext) => AlertWithTwoActions(
|
||||||
alertTitle: S.of(_dialogContext).change_current_node_title,
|
alertTitle: S.of(_dialogContext).change_current_node_title,
|
||||||
alertContent: S.of(_dialogContext).confirm_silent_payments_switch_node,
|
alertContent: S.of(_dialogContext).confirm_silent_payments_switch_node,
|
||||||
|
@ -86,7 +95,8 @@ class RescanPage extends BasePage {
|
||||||
_rescanViewModel.rescanCurrentWallet(restoreHeight: height);
|
_rescanViewModel.rescanCurrentWallet(restoreHeight: height);
|
||||||
},
|
},
|
||||||
actionLeftButton: () => Navigator.of(_dialogContext).pop(),
|
actionLeftButton: () => Navigator.of(_dialogContext).pop(),
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_rescanViewModel.rescanCurrentWallet(restoreHeight: height);
|
_rescanViewModel.rescanCurrentWallet(restoreHeight: height);
|
||||||
|
|
|
@ -428,7 +428,8 @@ abstract class DashboardViewModelBase with Store {
|
||||||
// to not cause work duplication, this will do the job as well, it will be slightly less precise
|
// to not cause work duplication, this will do the job as well, it will be slightly less precise
|
||||||
// about what happened - but still enough.
|
// about what happened - but still enough.
|
||||||
// if (keys['privateSpendKey'] == List.generate(64, (index) => "0").join("")) "Private spend key is 0",
|
// if (keys['privateSpendKey'] == List.generate(64, (index) => "0").join("")) "Private spend key is 0",
|
||||||
if (keys['privateViewKey'] == List.generate(64, (index) => "0").join("") && !wallet.isHardwareWallet)
|
if (keys['privateViewKey'] == List.generate(64, (index) => "0").join("") &&
|
||||||
|
!wallet.isHardwareWallet)
|
||||||
"private view key is 0",
|
"private view key is 0",
|
||||||
// if (keys['publicSpendKey'] == List.generate(64, (index) => "0").join("")) "public spend key is 0",
|
// if (keys['publicSpendKey'] == List.generate(64, (index) => "0").join("")) "public spend key is 0",
|
||||||
if (keys['publicViewKey'] == List.generate(64, (index) => "0").join(""))
|
if (keys['publicViewKey'] == List.generate(64, (index) => "0").join(""))
|
||||||
|
@ -454,6 +455,13 @@ abstract class DashboardViewModelBase with Store {
|
||||||
@observable
|
@observable
|
||||||
bool silentPaymentsScanningActive = false;
|
bool silentPaymentsScanningActive = false;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void allowSilentPaymentsScanning(bool allow) {
|
||||||
|
if (hasSilentPayments) {
|
||||||
|
bitcoin!.allowToSwitchNodesForScanning(wallet, allow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
void setSilentPaymentsScanning(bool active) {
|
void setSilentPaymentsScanning(bool active) {
|
||||||
silentPaymentsScanningActive = active;
|
silentPaymentsScanningActive = active;
|
||||||
|
|
|
@ -25,6 +25,7 @@ import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_i
|
||||||
import 'package:cake_wallet/wownero/wownero.dart';
|
import 'package:cake_wallet/wownero/wownero.dart';
|
||||||
import 'package:cw_core/amount_converter.dart';
|
import 'package:cw_core/amount_converter.dart';
|
||||||
import 'package:cw_core/currency.dart';
|
import 'package:cw_core/currency.dart';
|
||||||
|
import 'package:cw_core/receive_page_option.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
|
@ -209,6 +210,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
|
||||||
required AppStore appStore,
|
required AppStore appStore,
|
||||||
required this.yatStore,
|
required this.yatStore,
|
||||||
required this.fiatConversionStore,
|
required this.fiatConversionStore,
|
||||||
|
ReceivePageOption? addressType,
|
||||||
}) : _baseItems = <ListItem>[],
|
}) : _baseItems = <ListItem>[],
|
||||||
selectedCurrency = walletTypeToCryptoCurrency(appStore.wallet!.type),
|
selectedCurrency = walletTypeToCryptoCurrency(appStore.wallet!.type),
|
||||||
_cryptoNumberFormat = NumberFormat(_cryptoNumberPattern),
|
_cryptoNumberFormat = NumberFormat(_cryptoNumberPattern),
|
||||||
|
@ -216,6 +218,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
|
||||||
.contains(appStore.wallet!.type),
|
.contains(appStore.wallet!.type),
|
||||||
amount = '',
|
amount = '',
|
||||||
_settingsStore = appStore.settingsStore,
|
_settingsStore = appStore.settingsStore,
|
||||||
|
_addressType = addressType,
|
||||||
super(appStore: appStore) {
|
super(appStore: appStore) {
|
||||||
_init();
|
_init();
|
||||||
}
|
}
|
||||||
|
@ -234,6 +237,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
|
||||||
|
|
||||||
final FiatConversionStore fiatConversionStore;
|
final FiatConversionStore fiatConversionStore;
|
||||||
final SettingsStore _settingsStore;
|
final SettingsStore _settingsStore;
|
||||||
|
final ReceivePageOption? _addressType;
|
||||||
|
|
||||||
double? _fiatRate;
|
double? _fiatRate;
|
||||||
String _rawAmount = '';
|
String _rawAmount = '';
|
||||||
|
@ -264,8 +268,19 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
|
||||||
WalletType get type => wallet.type;
|
WalletType get type => wallet.type;
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
WalletAddressListItem get address =>
|
WalletAddressListItem get address {
|
||||||
WalletAddressListItem(address: wallet.walletAddresses.address, isPrimary: false);
|
if (_addressType != null) {
|
||||||
|
final shouldForceSP = _addressType != null && bitcoin!.isReceiveOptionSP(_addressType!);
|
||||||
|
if (shouldForceSP) {
|
||||||
|
return WalletAddressListItem(
|
||||||
|
address: bitcoin!.getSilentPaymentAddresses(wallet).first.address,
|
||||||
|
isPrimary: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return WalletAddressListItem(address: wallet.walletAddresses.address, isPrimary: false);
|
||||||
|
}
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
PaymentURI get uri {
|
PaymentURI get uri {
|
||||||
|
@ -354,7 +369,10 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isElectrumWallet) {
|
if (isElectrumWallet) {
|
||||||
if (bitcoin!.hasSelectedSilentPayments(wallet)) {
|
final hasSelectedSP = bitcoin!.hasSelectedSilentPayments(wallet);
|
||||||
|
final shouldForceSP = _addressType != null && bitcoin!.isReceiveOptionSP(_addressType!);
|
||||||
|
|
||||||
|
if (hasSelectedSP || shouldForceSP) {
|
||||||
final addressItems = bitcoin!.getSilentPaymentAddresses(wallet).map((address) {
|
final addressItems = bitcoin!.getSilentPaymentAddresses(wallet).map((address) {
|
||||||
final isPrimary = address.id == 0;
|
final isPrimary = address.id == 0;
|
||||||
|
|
||||||
|
|
|
@ -594,6 +594,7 @@
|
||||||
"save_backup_password_alert": "حفظ كلمة المرور الاحتياطية",
|
"save_backup_password_alert": "حفظ كلمة المرور الاحتياطية",
|
||||||
"save_to_downloads": "ﺕﻼﻳﺰﻨﺘﻟﺍ ﻲﻓ ﻆﻔﺣ",
|
"save_to_downloads": "ﺕﻼﻳﺰﻨﺘﻟﺍ ﻲﻓ ﻆﻔﺣ",
|
||||||
"saved_the_trade_id": "لقد تم حفظ معرف العملية",
|
"saved_the_trade_id": "لقد تم حفظ معرف العملية",
|
||||||
|
"scan": "مسح",
|
||||||
"scan_one_block": "مسح كتلة واحدة",
|
"scan_one_block": "مسح كتلة واحدة",
|
||||||
"scan_qr_code": "امسح رمز QR ضوئيًا",
|
"scan_qr_code": "امسح رمز QR ضوئيًا",
|
||||||
"scan_qr_code_to_get_address": "امسح ال QR للحصول على العنوان",
|
"scan_qr_code_to_get_address": "امسح ال QR للحصول على العنوان",
|
||||||
|
|
|
@ -594,6 +594,7 @@
|
||||||
"save_backup_password_alert": "Запазване на паролата за възстановяване",
|
"save_backup_password_alert": "Запазване на паролата за възстановяване",
|
||||||
"save_to_downloads": "Запазване в Изтегляния",
|
"save_to_downloads": "Запазване в Изтегляния",
|
||||||
"saved_the_trade_id": "Запазих trade ID-то",
|
"saved_the_trade_id": "Запазих trade ID-то",
|
||||||
|
"scan": "Сканиране",
|
||||||
"scan_one_block": "Сканирайте един блок",
|
"scan_one_block": "Сканирайте един блок",
|
||||||
"scan_qr_code": "Сканирайте QR кода, за да получите адреса",
|
"scan_qr_code": "Сканирайте QR кода, за да получите адреса",
|
||||||
"scan_qr_code_to_get_address": "Сканирайте QR кода, за да получите адреса",
|
"scan_qr_code_to_get_address": "Сканирайте QR кода, за да получите адреса",
|
||||||
|
|
|
@ -594,6 +594,7 @@
|
||||||
"save_backup_password_alert": "Uložit heslo pro zálohy",
|
"save_backup_password_alert": "Uložit heslo pro zálohy",
|
||||||
"save_to_downloads": "Uložit do Stažených souborů",
|
"save_to_downloads": "Uložit do Stažených souborů",
|
||||||
"saved_the_trade_id": "Uložil jsem si ID transakce (trade ID)",
|
"saved_the_trade_id": "Uložil jsem si ID transakce (trade ID)",
|
||||||
|
"scan": "Skenovat",
|
||||||
"scan_one_block": "Prohledejte jeden blok",
|
"scan_one_block": "Prohledejte jeden blok",
|
||||||
"scan_qr_code": "Naskenujte QR kód pro získání adresy",
|
"scan_qr_code": "Naskenujte QR kód pro získání adresy",
|
||||||
"scan_qr_code_to_get_address": "Prohledejte QR kód a získejte adresu",
|
"scan_qr_code_to_get_address": "Prohledejte QR kód a získejte adresu",
|
||||||
|
|
|
@ -595,6 +595,7 @@
|
||||||
"save_backup_password_alert": "Sicherungskennwort speichern",
|
"save_backup_password_alert": "Sicherungskennwort speichern",
|
||||||
"save_to_downloads": "Unter „Downloads“ speichern",
|
"save_to_downloads": "Unter „Downloads“ speichern",
|
||||||
"saved_the_trade_id": "Ich habe die Handels-ID gespeichert",
|
"saved_the_trade_id": "Ich habe die Handels-ID gespeichert",
|
||||||
|
"scan": "Scan",
|
||||||
"scan_one_block": "Einen Block scannen",
|
"scan_one_block": "Einen Block scannen",
|
||||||
"scan_qr_code": "QR-Code scannen",
|
"scan_qr_code": "QR-Code scannen",
|
||||||
"scan_qr_code_to_get_address": "Scannen Sie den QR-Code, um die Adresse zu erhalten",
|
"scan_qr_code_to_get_address": "Scannen Sie den QR-Code, um die Adresse zu erhalten",
|
||||||
|
|
|
@ -594,6 +594,7 @@
|
||||||
"save_backup_password_alert": "Save backup password",
|
"save_backup_password_alert": "Save backup password",
|
||||||
"save_to_downloads": "Save to Downloads",
|
"save_to_downloads": "Save to Downloads",
|
||||||
"saved_the_trade_id": "I've saved the trade ID",
|
"saved_the_trade_id": "I've saved the trade ID",
|
||||||
|
"scan": "Scan",
|
||||||
"scan_one_block": "Scan one block",
|
"scan_one_block": "Scan one block",
|
||||||
"scan_qr_code": "Scan QR code",
|
"scan_qr_code": "Scan QR code",
|
||||||
"scan_qr_code_to_get_address": "Scan the QR code to get the address",
|
"scan_qr_code_to_get_address": "Scan the QR code to get the address",
|
||||||
|
|
|
@ -595,6 +595,7 @@
|
||||||
"save_backup_password_alert": "Guardar contraseña de respaldo",
|
"save_backup_password_alert": "Guardar contraseña de respaldo",
|
||||||
"save_to_downloads": "Guardar en Descargas",
|
"save_to_downloads": "Guardar en Descargas",
|
||||||
"saved_the_trade_id": "He salvado comercial ID",
|
"saved_the_trade_id": "He salvado comercial ID",
|
||||||
|
"scan": "Escanear",
|
||||||
"scan_one_block": "Escanear un bloque",
|
"scan_one_block": "Escanear un bloque",
|
||||||
"scan_qr_code": "Escanear código QR",
|
"scan_qr_code": "Escanear código QR",
|
||||||
"scan_qr_code_to_get_address": "Escanea el código QR para obtener la dirección",
|
"scan_qr_code_to_get_address": "Escanea el código QR para obtener la dirección",
|
||||||
|
|
|
@ -594,6 +594,7 @@
|
||||||
"save_backup_password_alert": "Enregistrer le mot de passe de sauvegarde",
|
"save_backup_password_alert": "Enregistrer le mot de passe de sauvegarde",
|
||||||
"save_to_downloads": "Enregistrer dans les téléchargements",
|
"save_to_downloads": "Enregistrer dans les téléchargements",
|
||||||
"saved_the_trade_id": "J'ai sauvegardé l'ID d'échange",
|
"saved_the_trade_id": "J'ai sauvegardé l'ID d'échange",
|
||||||
|
"scan": "Balayage",
|
||||||
"scan_one_block": "Scanner un bloc",
|
"scan_one_block": "Scanner un bloc",
|
||||||
"scan_qr_code": "Scannez le QR code",
|
"scan_qr_code": "Scannez le QR code",
|
||||||
"scan_qr_code_to_get_address": "Scannez le QR code pour obtenir l'adresse",
|
"scan_qr_code_to_get_address": "Scannez le QR code pour obtenir l'adresse",
|
||||||
|
|
|
@ -596,6 +596,7 @@
|
||||||
"save_backup_password_alert": "Ajiye kalmar sirri ta ajiya",
|
"save_backup_password_alert": "Ajiye kalmar sirri ta ajiya",
|
||||||
"save_to_downloads": "Ajiye zuwa Zazzagewa",
|
"save_to_downloads": "Ajiye zuwa Zazzagewa",
|
||||||
"saved_the_trade_id": "Na ajiye ID na ciniki",
|
"saved_the_trade_id": "Na ajiye ID na ciniki",
|
||||||
|
"scan": "Scan",
|
||||||
"scan_one_block": "Duba toshe daya",
|
"scan_one_block": "Duba toshe daya",
|
||||||
"scan_qr_code": "Gani QR kodin",
|
"scan_qr_code": "Gani QR kodin",
|
||||||
"scan_qr_code_to_get_address": "Duba lambar QR don samun adireshin",
|
"scan_qr_code_to_get_address": "Duba lambar QR don samun adireshin",
|
||||||
|
|
|
@ -596,6 +596,7 @@
|
||||||
"save_backup_password_alert": "बैकअप पासवर्ड सेव करें",
|
"save_backup_password_alert": "बैकअप पासवर्ड सेव करें",
|
||||||
"save_to_downloads": "डाउनलोड में सहेजें",
|
"save_to_downloads": "डाउनलोड में सहेजें",
|
||||||
"saved_the_trade_id": "मैंने व्यापार बचा लिया है ID",
|
"saved_the_trade_id": "मैंने व्यापार बचा लिया है ID",
|
||||||
|
"scan": "स्कैन",
|
||||||
"scan_one_block": "एक ब्लॉक को स्कैन करना",
|
"scan_one_block": "एक ब्लॉक को स्कैन करना",
|
||||||
"scan_qr_code": "स्कैन क्यू आर कोड",
|
"scan_qr_code": "स्कैन क्यू आर कोड",
|
||||||
"scan_qr_code_to_get_address": "पता प्राप्त करने के लिए QR कोड स्कैन करें",
|
"scan_qr_code_to_get_address": "पता प्राप्त करने के लिए QR कोड स्कैन करें",
|
||||||
|
|
|
@ -594,6 +594,7 @@
|
||||||
"save_backup_password_alert": "Spremi lozinku za sigurnosnu kopiju",
|
"save_backup_password_alert": "Spremi lozinku za sigurnosnu kopiju",
|
||||||
"save_to_downloads": "Spremi u Preuzimanja",
|
"save_to_downloads": "Spremi u Preuzimanja",
|
||||||
"saved_the_trade_id": "Spremio/la sam transakcijski ID",
|
"saved_the_trade_id": "Spremio/la sam transakcijski ID",
|
||||||
|
"scan": "Skenirati",
|
||||||
"scan_one_block": "Skenirajte jedan blok",
|
"scan_one_block": "Skenirajte jedan blok",
|
||||||
"scan_qr_code": "Skenirajte QR kod",
|
"scan_qr_code": "Skenirajte QR kod",
|
||||||
"scan_qr_code_to_get_address": "Skeniraj QR kod za dobivanje adrese",
|
"scan_qr_code_to_get_address": "Skeniraj QR kod za dobivanje adrese",
|
||||||
|
|
|
@ -594,6 +594,7 @@
|
||||||
"save_backup_password_alert": "Պահպանել կրկնօրինակի գաղտնաբառը",
|
"save_backup_password_alert": "Պահպանել կրկնօրինակի գաղտնաբառը",
|
||||||
"save_to_downloads": "Պահպանել ներբեռնումներում",
|
"save_to_downloads": "Պահպանել ներբեռնումներում",
|
||||||
"saved_the_trade_id": "Ես պահպանել եմ առևտրի ID-ն",
|
"saved_the_trade_id": "Ես պահպանել եմ առևտրի ID-ն",
|
||||||
|
"scan": "Սկանավորել",
|
||||||
"scan_one_block": "Սկանավորել մեկ բլոկ",
|
"scan_one_block": "Սկանավորել մեկ բլոկ",
|
||||||
"scan_qr_code": "Սկանավորել QR կոդ",
|
"scan_qr_code": "Սկանավորել QR կոդ",
|
||||||
"scan_qr_code_to_get_address": "Սկանավորել QR կոդը հասցեն ստանալու համար",
|
"scan_qr_code_to_get_address": "Սկանավորել QR կոդը հասցեն ստանալու համար",
|
||||||
|
|
|
@ -597,6 +597,7 @@
|
||||||
"save_backup_password_alert": "Simpan kata sandi cadangan",
|
"save_backup_password_alert": "Simpan kata sandi cadangan",
|
||||||
"save_to_downloads": "Simpan ke Unduhan",
|
"save_to_downloads": "Simpan ke Unduhan",
|
||||||
"saved_the_trade_id": "Saya telah menyimpan ID perdagangan",
|
"saved_the_trade_id": "Saya telah menyimpan ID perdagangan",
|
||||||
|
"scan": "Pindai",
|
||||||
"scan_one_block": "Pindai satu blok",
|
"scan_one_block": "Pindai satu blok",
|
||||||
"scan_qr_code": "Scan kode QR untuk mendapatkan alamat",
|
"scan_qr_code": "Scan kode QR untuk mendapatkan alamat",
|
||||||
"scan_qr_code_to_get_address": "Pindai kode QR untuk mendapatkan alamat",
|
"scan_qr_code_to_get_address": "Pindai kode QR untuk mendapatkan alamat",
|
||||||
|
|
|
@ -596,6 +596,7 @@
|
||||||
"save_backup_password_alert": "Salva password Backup",
|
"save_backup_password_alert": "Salva password Backup",
|
||||||
"save_to_downloads": "Salva in Download",
|
"save_to_downloads": "Salva in Download",
|
||||||
"saved_the_trade_id": "Ho salvato l'ID dello scambio",
|
"saved_the_trade_id": "Ho salvato l'ID dello scambio",
|
||||||
|
"scan": "Scansione",
|
||||||
"scan_one_block": "Scansionare un blocco",
|
"scan_one_block": "Scansionare un blocco",
|
||||||
"scan_qr_code": "Scansiona il codice QR",
|
"scan_qr_code": "Scansiona il codice QR",
|
||||||
"scan_qr_code_to_get_address": "Scansiona il codice QR per ottenere l'indirizzo",
|
"scan_qr_code_to_get_address": "Scansiona il codice QR per ottenere l'indirizzo",
|
||||||
|
|
|
@ -595,6 +595,7 @@
|
||||||
"save_backup_password_alert": "バックアップパスワードを保存する",
|
"save_backup_password_alert": "バックアップパスワードを保存する",
|
||||||
"save_to_downloads": "ダウンロードに保存",
|
"save_to_downloads": "ダウンロードに保存",
|
||||||
"saved_the_trade_id": "取引IDを保存しました",
|
"saved_the_trade_id": "取引IDを保存しました",
|
||||||
|
"scan": "スキャン",
|
||||||
"scan_one_block": "1つのブロックをスキャンします",
|
"scan_one_block": "1つのブロックをスキャンします",
|
||||||
"scan_qr_code": "QRコードをスキャン",
|
"scan_qr_code": "QRコードをスキャン",
|
||||||
"scan_qr_code_to_get_address": "QRコードをスキャンして住所を取得します",
|
"scan_qr_code_to_get_address": "QRコードをスキャンして住所を取得します",
|
||||||
|
|
|
@ -595,6 +595,7 @@
|
||||||
"save_backup_password_alert": "백업 비밀번호 저장",
|
"save_backup_password_alert": "백업 비밀번호 저장",
|
||||||
"save_to_downloads": "다운로드에 저장",
|
"save_to_downloads": "다운로드에 저장",
|
||||||
"saved_the_trade_id": "거래 ID를 저장했습니다",
|
"saved_the_trade_id": "거래 ID를 저장했습니다",
|
||||||
|
"scan": "주사",
|
||||||
"scan_one_block": "하나의 블록을 스캔하십시오",
|
"scan_one_block": "하나의 블록을 스캔하십시오",
|
||||||
"scan_qr_code": "QR 코드 스캔",
|
"scan_qr_code": "QR 코드 스캔",
|
||||||
"scan_qr_code_to_get_address": "QR 코드를 스캔하여 주소를 얻습니다.",
|
"scan_qr_code_to_get_address": "QR 코드를 스캔하여 주소를 얻습니다.",
|
||||||
|
|
|
@ -594,6 +594,7 @@
|
||||||
"save_backup_password_alert": "အရန်စကားဝှက်ကို သိမ်းဆည်းပါ။",
|
"save_backup_password_alert": "အရန်စကားဝှက်ကို သိမ်းဆည်းပါ။",
|
||||||
"save_to_downloads": "ဒေါင်းလုဒ်များထံ သိမ်းဆည်းပါ။",
|
"save_to_downloads": "ဒေါင်းလုဒ်များထံ သိမ်းဆည်းပါ။",
|
||||||
"saved_the_trade_id": "ကုန်သွယ်မှု ID ကို သိမ်းဆည်းပြီးပါပြီ။",
|
"saved_the_trade_id": "ကုန်သွယ်မှု ID ကို သိမ်းဆည်းပြီးပါပြီ။",
|
||||||
|
"scan": "စကင်ဖတ်",
|
||||||
"scan_one_block": "တစ်ကွက်ကိုစကင်ဖတ်စစ်ဆေးပါ",
|
"scan_one_block": "တစ်ကွက်ကိုစကင်ဖတ်စစ်ဆေးပါ",
|
||||||
"scan_qr_code": "QR ကုဒ်ကို စကင်န်ဖတ်ပါ။",
|
"scan_qr_code": "QR ကုဒ်ကို စကင်န်ဖတ်ပါ။",
|
||||||
"scan_qr_code_to_get_address": "လိပ်စာရယူရန် QR ကုဒ်ကို စကင်န်ဖတ်ပါ။",
|
"scan_qr_code_to_get_address": "လိပ်စာရယူရန် QR ကုဒ်ကို စကင်န်ဖတ်ပါ။",
|
||||||
|
|
|
@ -594,6 +594,7 @@
|
||||||
"save_backup_password_alert": "Bewaar back-upwachtwoord",
|
"save_backup_password_alert": "Bewaar back-upwachtwoord",
|
||||||
"save_to_downloads": "Opslaan in downloads",
|
"save_to_downloads": "Opslaan in downloads",
|
||||||
"saved_the_trade_id": "Ik heb de ruil-ID opgeslagen",
|
"saved_the_trade_id": "Ik heb de ruil-ID opgeslagen",
|
||||||
|
"scan": "Scannen",
|
||||||
"scan_one_block": "Scan een blok",
|
"scan_one_block": "Scan een blok",
|
||||||
"scan_qr_code": "Scan QR-code",
|
"scan_qr_code": "Scan QR-code",
|
||||||
"scan_qr_code_to_get_address": "Scan de QR-code om het adres te krijgen",
|
"scan_qr_code_to_get_address": "Scan de QR-code om het adres te krijgen",
|
||||||
|
|
|
@ -594,6 +594,7 @@
|
||||||
"save_backup_password_alert": "Zapisz hasło kopii zapasowej",
|
"save_backup_password_alert": "Zapisz hasło kopii zapasowej",
|
||||||
"save_to_downloads": "Zapisz w Pobranych",
|
"save_to_downloads": "Zapisz w Pobranych",
|
||||||
"saved_the_trade_id": "Zapisałem ID",
|
"saved_the_trade_id": "Zapisałem ID",
|
||||||
|
"scan": "Skandować",
|
||||||
"scan_one_block": "Zeskanuj jeden blok",
|
"scan_one_block": "Zeskanuj jeden blok",
|
||||||
"scan_qr_code": "Skanowania QR code",
|
"scan_qr_code": "Skanowania QR code",
|
||||||
"scan_qr_code_to_get_address": "Zeskanuj kod QR, aby uzyskać adres",
|
"scan_qr_code_to_get_address": "Zeskanuj kod QR, aby uzyskać adres",
|
||||||
|
|
|
@ -596,6 +596,7 @@
|
||||||
"save_backup_password_alert": "Salvar senha de backup",
|
"save_backup_password_alert": "Salvar senha de backup",
|
||||||
"save_to_downloads": "Salvar em Downloads",
|
"save_to_downloads": "Salvar em Downloads",
|
||||||
"saved_the_trade_id": "ID da troca salvo",
|
"saved_the_trade_id": "ID da troca salvo",
|
||||||
|
"scan": "Scan",
|
||||||
"scan_one_block": "Escanear um bloco",
|
"scan_one_block": "Escanear um bloco",
|
||||||
"scan_qr_code": "Escanear código QR",
|
"scan_qr_code": "Escanear código QR",
|
||||||
"scan_qr_code_to_get_address": "Digitalize o código QR para obter o endereço",
|
"scan_qr_code_to_get_address": "Digitalize o código QR para obter o endereço",
|
||||||
|
|
|
@ -595,6 +595,7 @@
|
||||||
"save_backup_password_alert": "Сохранить пароль резервной копии",
|
"save_backup_password_alert": "Сохранить пароль резервной копии",
|
||||||
"save_to_downloads": "Сохранить в загрузках",
|
"save_to_downloads": "Сохранить в загрузках",
|
||||||
"saved_the_trade_id": "Я сохранил ID сделки",
|
"saved_the_trade_id": "Я сохранил ID сделки",
|
||||||
|
"scan": "Сканирование",
|
||||||
"scan_one_block": "Сканируйте один блок",
|
"scan_one_block": "Сканируйте один блок",
|
||||||
"scan_qr_code": "Сканировать QR-код",
|
"scan_qr_code": "Сканировать QR-код",
|
||||||
"scan_qr_code_to_get_address": "Отсканируйте QR-код для получения адреса",
|
"scan_qr_code_to_get_address": "Отсканируйте QR-код для получения адреса",
|
||||||
|
|
|
@ -594,6 +594,7 @@
|
||||||
"save_backup_password_alert": "บันทึกรหัสผ่านสำรอง",
|
"save_backup_password_alert": "บันทึกรหัสผ่านสำรอง",
|
||||||
"save_to_downloads": "บันทึกลงดาวน์โหลด",
|
"save_to_downloads": "บันทึกลงดาวน์โหลด",
|
||||||
"saved_the_trade_id": "ฉันได้บันทึก ID ของการซื้อขายแล้ว",
|
"saved_the_trade_id": "ฉันได้บันทึก ID ของการซื้อขายแล้ว",
|
||||||
|
"scan": "สแกน",
|
||||||
"scan_one_block": "สแกนหนึ่งบล็อก",
|
"scan_one_block": "สแกนหนึ่งบล็อก",
|
||||||
"scan_qr_code": "สแกนรหัส QR",
|
"scan_qr_code": "สแกนรหัส QR",
|
||||||
"scan_qr_code_to_get_address": "สแกน QR code เพื่อรับที่อยู่",
|
"scan_qr_code_to_get_address": "สแกน QR code เพื่อรับที่อยู่",
|
||||||
|
|
|
@ -594,6 +594,7 @@
|
||||||
"save_backup_password_alert": "I-save ang backup na password",
|
"save_backup_password_alert": "I-save ang backup na password",
|
||||||
"save_to_downloads": "I-save sa mga Pag-download",
|
"save_to_downloads": "I-save sa mga Pag-download",
|
||||||
"saved_the_trade_id": "Nai-save ko na ang trade ID",
|
"saved_the_trade_id": "Nai-save ko na ang trade ID",
|
||||||
|
"scan": "I -scan",
|
||||||
"scan_one_block": "I-scan ang isang bloke",
|
"scan_one_block": "I-scan ang isang bloke",
|
||||||
"scan_qr_code": "I-scan ang QR code",
|
"scan_qr_code": "I-scan ang QR code",
|
||||||
"scan_qr_code_to_get_address": "I-scan ang QR code upang makuha ang address",
|
"scan_qr_code_to_get_address": "I-scan ang QR code upang makuha ang address",
|
||||||
|
|
|
@ -594,6 +594,7 @@
|
||||||
"save_backup_password_alert": "Yedek parolasını kaydet",
|
"save_backup_password_alert": "Yedek parolasını kaydet",
|
||||||
"save_to_downloads": "İndirilenlere Kaydet",
|
"save_to_downloads": "İndirilenlere Kaydet",
|
||||||
"saved_the_trade_id": "Takas ID'imi kaydettim",
|
"saved_the_trade_id": "Takas ID'imi kaydettim",
|
||||||
|
"scan": "Taramak",
|
||||||
"scan_one_block": "Bir bloğu tara",
|
"scan_one_block": "Bir bloğu tara",
|
||||||
"scan_qr_code": "QR kodunu tarayın",
|
"scan_qr_code": "QR kodunu tarayın",
|
||||||
"scan_qr_code_to_get_address": "Adresi getirmek için QR kodunu tara",
|
"scan_qr_code_to_get_address": "Adresi getirmek için QR kodunu tara",
|
||||||
|
|
|
@ -595,6 +595,7 @@
|
||||||
"save_backup_password_alert": "Зберегти пароль резервної копії",
|
"save_backup_password_alert": "Зберегти пароль резервної копії",
|
||||||
"save_to_downloads": "Зберегти до завантажень",
|
"save_to_downloads": "Зберегти до завантажень",
|
||||||
"saved_the_trade_id": "Я зберіг ID операції",
|
"saved_the_trade_id": "Я зберіг ID операції",
|
||||||
|
"scan": "Сканувати",
|
||||||
"scan_one_block": "Сканувати один блок",
|
"scan_one_block": "Сканувати один блок",
|
||||||
"scan_qr_code": "Відскануйте QR-код",
|
"scan_qr_code": "Відскануйте QR-код",
|
||||||
"scan_qr_code_to_get_address": "Скануйте QR-код для одержання адреси",
|
"scan_qr_code_to_get_address": "Скануйте QR-код для одержання адреси",
|
||||||
|
|
|
@ -596,6 +596,7 @@
|
||||||
"save_backup_password_alert": "بیک اپ پاس ورڈ محفوظ کریں۔",
|
"save_backup_password_alert": "بیک اپ پاس ورڈ محفوظ کریں۔",
|
||||||
"save_to_downloads": "۔ﮟﯾﺮﮐ ﻅﻮﻔﺤﻣ ﮟﯿﻣ ﺯﮈﻮﻟ ﻥﺅﺍﮈ",
|
"save_to_downloads": "۔ﮟﯾﺮﮐ ﻅﻮﻔﺤﻣ ﮟﯿﻣ ﺯﮈﻮﻟ ﻥﺅﺍﮈ",
|
||||||
"saved_the_trade_id": "میں نے تجارتی ID محفوظ کر لی ہے۔",
|
"saved_the_trade_id": "میں نے تجارتی ID محفوظ کر لی ہے۔",
|
||||||
|
"scan": "اسکین",
|
||||||
"scan_one_block": "ایک بلاک اسکین کریں",
|
"scan_one_block": "ایک بلاک اسکین کریں",
|
||||||
"scan_qr_code": "پتہ حاصل کرنے کے لیے QR کوڈ اسکین کریں۔",
|
"scan_qr_code": "پتہ حاصل کرنے کے لیے QR کوڈ اسکین کریں۔",
|
||||||
"scan_qr_code_to_get_address": "پتہ حاصل کرنے کے لئے QR کوڈ کو اسکین کریں",
|
"scan_qr_code_to_get_address": "پتہ حاصل کرنے کے لئے QR کوڈ کو اسکین کریں",
|
||||||
|
|
|
@ -593,6 +593,7 @@
|
||||||
"save_backup_password_alert": "Lưu mật khẩu sao lưu",
|
"save_backup_password_alert": "Lưu mật khẩu sao lưu",
|
||||||
"save_to_downloads": "Lưu vào Tải xuống",
|
"save_to_downloads": "Lưu vào Tải xuống",
|
||||||
"saved_the_trade_id": "Tôi đã lưu ID giao dịch",
|
"saved_the_trade_id": "Tôi đã lưu ID giao dịch",
|
||||||
|
"scan": "Quét",
|
||||||
"scan_one_block": "Quét một khối",
|
"scan_one_block": "Quét một khối",
|
||||||
"scan_qr_code": "Quét mã QR",
|
"scan_qr_code": "Quét mã QR",
|
||||||
"scan_qr_code_to_get_address": "Quét mã QR để nhận địa chỉ",
|
"scan_qr_code_to_get_address": "Quét mã QR để nhận địa chỉ",
|
||||||
|
|
|
@ -595,6 +595,7 @@
|
||||||
"save_backup_password_alert": "Pamọ́ ọ̀rọ̀ aṣínà ti ẹ̀dà",
|
"save_backup_password_alert": "Pamọ́ ọ̀rọ̀ aṣínà ti ẹ̀dà",
|
||||||
"save_to_downloads": "Fipamọ si Awọn igbasilẹ",
|
"save_to_downloads": "Fipamọ si Awọn igbasilẹ",
|
||||||
"saved_the_trade_id": "Mo ti pamọ́ àmì ìdánimọ̀ pàṣípààrọ̀",
|
"saved_the_trade_id": "Mo ti pamọ́ àmì ìdánimọ̀ pàṣípààrọ̀",
|
||||||
|
"scan": "Ọlọjẹ",
|
||||||
"scan_one_block": "Ọlọjẹ ọkan bulọki",
|
"scan_one_block": "Ọlọjẹ ọkan bulọki",
|
||||||
"scan_qr_code": "Yan QR koodu",
|
"scan_qr_code": "Yan QR koodu",
|
||||||
"scan_qr_code_to_get_address": "Ṣayẹwo koodu QR naa lati gba adirẹsi naa",
|
"scan_qr_code_to_get_address": "Ṣayẹwo koodu QR naa lati gba adirẹsi naa",
|
||||||
|
|
|
@ -594,6 +594,7 @@
|
||||||
"save_backup_password_alert": "保存备份密码",
|
"save_backup_password_alert": "保存备份密码",
|
||||||
"save_to_downloads": "保存到下载",
|
"save_to_downloads": "保存到下载",
|
||||||
"saved_the_trade_id": "我已经保存了交易编号",
|
"saved_the_trade_id": "我已经保存了交易编号",
|
||||||
|
"scan": "扫描",
|
||||||
"scan_one_block": "扫描一个街区",
|
"scan_one_block": "扫描一个街区",
|
||||||
"scan_qr_code": "扫描二维码",
|
"scan_qr_code": "扫描二维码",
|
||||||
"scan_qr_code_to_get_address": "扫描二维码获取地址",
|
"scan_qr_code_to_get_address": "扫描二维码获取地址",
|
||||||
|
|
|
@ -227,11 +227,13 @@ abstract class Bitcoin {
|
||||||
List<ReceivePageOption> getBitcoinReceivePageOptions();
|
List<ReceivePageOption> getBitcoinReceivePageOptions();
|
||||||
List<ReceivePageOption> getLitecoinReceivePageOptions();
|
List<ReceivePageOption> getLitecoinReceivePageOptions();
|
||||||
BitcoinAddressType getBitcoinAddressType(ReceivePageOption option);
|
BitcoinAddressType getBitcoinAddressType(ReceivePageOption option);
|
||||||
|
bool isReceiveOptionSP(ReceivePageOption option);
|
||||||
bool hasSelectedSilentPayments(Object wallet);
|
bool hasSelectedSilentPayments(Object wallet);
|
||||||
bool isBitcoinReceivePageOption(ReceivePageOption option);
|
bool isBitcoinReceivePageOption(ReceivePageOption option);
|
||||||
BitcoinAddressType getOptionToType(ReceivePageOption option);
|
BitcoinAddressType getOptionToType(ReceivePageOption option);
|
||||||
bool hasTaprootInput(PendingTransaction pendingTransaction);
|
bool hasTaprootInput(PendingTransaction pendingTransaction);
|
||||||
bool getScanningActive(Object wallet);
|
bool getScanningActive(Object wallet);
|
||||||
|
Future<void> allowToSwitchNodesForScanning(Object wallet, bool allow);
|
||||||
Future<void> setScanningActive(Object wallet, bool active);
|
Future<void> setScanningActive(Object wallet, bool active);
|
||||||
bool isTestnet(Object wallet);
|
bool isTestnet(Object wallet);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue