Remove Next Address button and logic for electrum wallets. Add disclaimer for electrum wallets on address screen. Change way for generation of current receive and change addresses.

wownero
M 2 years ago
parent 2bbd413b12
commit 63a0395c2d

@ -116,7 +116,9 @@ class ElectrumTransactionInfo extends TransactionInfo {
factory ElectrumTransactionInfo.fromElectrumBundle(
ElectrumTransactionBundle bundle, WalletType type,
{@required Set<String> addresses, int height}) {
final date = DateTime.fromMillisecondsSinceEpoch(bundle.time * 1000);
final date = bundle.time != null
? DateTime.fromMillisecondsSinceEpoch(bundle.time * 1000)
: DateTime.now();
var direction = TransactionDirection.incoming;
var amount = 0;
var inputAmount = 0;

@ -484,7 +484,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
final original = bitcoin.Transaction.fromHex(transactionHex);
final ins = <bitcoin.Transaction>[];
final time = verboseTransaction['time'] as int;
final confirmations = verboseTransaction['time'] as int;
final confirmations = verboseTransaction['confirmations'] as int ?? 0;
for (final vin in original.ins) {
final id = HEX.encode(vin.hash.reversed.toList());
@ -510,13 +510,35 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
@override
Future<Map<String, ElectrumTransactionInfo>> fetchTransactions() async {
final addressHashes = <String, BitcoinAddressRecord>{};
final normalizedHistories = <Map<String, dynamic>>[];
walletAddresses.addresses.forEach((addressRecord) {
if (addressRecord.isHidden) {
return;
}
final sh = scriptHash(addressRecord.address, networkType: networkType);
addressHashes[sh] = addressRecord;
});
final histories =
publicScriptHashes.map((scriptHash) => electrumClient.getHistory(scriptHash));
final _historiesWithDetails = await Future.wait(histories)
.then((histories) => histories.expand((i) => i).toList())
.then((histories) => histories.map((tx) => fetchTransactionInfo(
hash: tx['tx_hash'] as String, height: tx['height'] as int)));
final historiesWithDetails = await Future.wait(_historiesWithDetails);
addressHashes.keys.map((scriptHash) => electrumClient
.getHistory(scriptHash)
.then((history) => {scriptHash: history}));
final historyResults = await Future.wait(histories);
historyResults.forEach((history) {
history.entries.forEach((historyItem) {
if (historyItem.value.isNotEmpty) {
final address = addressHashes[historyItem.key];
address.setAsUsed();
normalizedHistories.addAll(historyItem.value);
}
});
});
final historiesWithDetails = await Future.wait(
normalizedHistories
.map((transaction) => fetchTransactionInfo(
hash: transaction['tx_hash'] as String,
height: transaction['height'] as int)));
return historiesWithDetails.fold<Map<String, ElectrumTransactionInfo>>(
<String, ElectrumTransactionInfo>{}, (acc, tx) {
@ -534,6 +556,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
_isTransactionUpdating = true;
final transactions = await fetchTransactions();
transactionHistory.addMany(transactions);
walletAddresses.updateReceiveAddresses();
await transactionHistory.save();
_isTransactionUpdating = false;
} catch (e) {

@ -6,7 +6,6 @@ import 'package:cw_core/wallet_addresses.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:flutter/foundation.dart';
import 'package:mobx/mobx.dart';
import 'dart:math';
part 'electrum_wallet_addresses.g.dart';
@ -22,44 +21,60 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
this.sideHd,
this.electrumClient,
this.networkType})
: super(walletInfo) {
: addresses = ObservableList<BitcoinAddressRecord>.of(
(initialAddresses ?? []).toSet()),
receiveAddresses = ObservableList<BitcoinAddressRecord>.of(
(initialAddresses ?? [])
.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed)
.toSet()),
changeAddresses = ObservableList<BitcoinAddressRecord>.of(
(initialAddresses ?? [])
.where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed)
.toSet()),
super(walletInfo) {
currentReceiveAddressIndex = initialRegularAddressIndex;
currentChangeAddressIndex = initialChangeAddressIndex;
addresses = ObservableList<BitcoinAddressRecord>.of(
(initialAddresses ?? []).toSet());
}
static const defaultReceiveAddressesCount = 22;
static const defaultChangeAddressesCount = 17;
static const gap = 20;
final ObservableList<BitcoinAddressRecord> addresses;
final ObservableList<BitcoinAddressRecord> receiveAddresses;
final ObservableList<BitcoinAddressRecord> changeAddresses;
final ElectrumClient electrumClient;
final bitcoin.NetworkType networkType;
final bitcoin.HDWallet mainHd;
final bitcoin.HDWallet sideHd;
@override
@computed
String get address => receiveAddresses.first.address;
@override
@observable
String address;
set address(String addr) => null;
int currentReceiveAddressIndex;
int currentChangeAddressIndex;
ElectrumClient electrumClient;
bitcoin.NetworkType networkType;
bitcoin.HDWallet mainHd;
bitcoin.HDWallet sideHd;
ObservableList<BitcoinAddressRecord> addresses;
List<BitcoinAddressRecord> get receiveAddresses => addresses
.where((addr) => !addr.isHidden && !addr.isUsed)
.toList();
List<BitcoinAddressRecord> get changeAddresses => addresses
.where((addr) => addr.isHidden && !addr.isUsed)
.toList();
List<BitcoinAddressRecord> get totalReceiveAddresses => addresses
.where((addr) => !addr.isHidden)
.toList();
@computed
int get totalCountOfReceiveAddresses =>
addresses.fold(0, (acc, addressRecord) {
if (!addressRecord.isHidden) {
return acc + 1;
}
return acc;
});
List<BitcoinAddressRecord> get totalChangeAddresses => addresses
.where((addr) => addr.isHidden)
.toList();
@computed
int get totalCountOfChangeAddresses =>
addresses.fold(0, (acc, addressRecord) {
if (addressRecord.isHidden) {
return acc + 1;
}
return acc;
});
Future<void> discoverAddresses() async {
await _discoverAddresses(mainHd, false);
@ -70,60 +85,39 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
@override
Future<void> init() async {
await _generateInitialAddresses();
if (receiveAddresses.isEmpty) {
final newAddresses = await _createNewAddresses(
gap,
hd: mainHd,
startIndex: totalReceiveAddresses.length > 0
? totalReceiveAddresses.length - 1
: 0,
isHidden: false);
_addAddresses(newAddresses);
} else if (currentReceiveAddressIndex >= receiveAddresses.length) {
currentReceiveAddressIndex = 0;
}
address = receiveAddresses[currentReceiveAddressIndex].address;
updateReceiveAddresses();
updateChangeAddresses();
await updateAddressesInBox();
}
@action
Future<void> nextReceiveAddress() async {
if (receiveAddresses.isEmpty) {
final newAddresses = await _createNewAddresses(
gap,
hd: mainHd,
startIndex: totalReceiveAddresses.length > 0
? totalReceiveAddresses.length - 1
: 0,
isHidden: false);
_addAddresses(newAddresses);
} else if (currentReceiveAddressIndex >= receiveAddresses.length) {
if (currentReceiveAddressIndex >= receiveAddresses.length) {
currentReceiveAddressIndex = 0;
}
address = receiveAddresses[currentReceiveAddressIndex].address;
currentReceiveAddressIndex += 1;
await updateAddressesInBox();
if (currentChangeAddressIndex >= changeAddresses.length) {
currentChangeAddressIndex = 0;
}
}
@action
Future<String> getChangeAddress() async {
updateChangeAddresses();
if (changeAddresses.isEmpty) {
final newAddresses = await _createNewAddresses(
gap,
hd: sideHd,
startIndex: totalChangeAddresses.length > 0
? totalChangeAddresses.length - 1
startIndex: totalCountOfChangeAddresses > 0
? totalCountOfChangeAddresses - 1
: 0,
isHidden: true);
_addAddresses(newAddresses);
} else if (currentChangeAddressIndex >= changeAddresses.length) {
}
if (currentChangeAddressIndex >= changeAddresses.length) {
currentChangeAddressIndex = 0;
}
updateChangeAddresses();
final address = changeAddresses[currentChangeAddressIndex].address;
currentChangeAddressIndex += 1;
return address;
@ -153,18 +147,20 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
}
}
void randomizeAddress() {
const minCountOfVisibleAddresses = 5;
final random = Random();
var availableAddresses = addresses
.where((addr) => !addr.isHidden)
.toList();
if (availableAddresses.length < minCountOfVisibleAddresses) {
availableAddresses = addresses;
}
@action
void updateReceiveAddresses() {
receiveAddresses.removeRange(0, receiveAddresses.length);
final newAdresses = addresses
.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed);
receiveAddresses.addAll(newAdresses);
}
address = availableAddresses[random.nextInt(availableAddresses.length)].address;
@action
void updateChangeAddresses() {
changeAddresses.removeRange(0, changeAddresses.length);
final newAdresses = addresses
.where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed);
changeAddresses.addAll(newAdresses);
}
Future<void> _discoverAddresses(bitcoin.HDWallet hd, bool isHidden) async {
@ -187,12 +183,12 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
while(hasAddrUse) {
final addr = addrs.last.address;
hasAddrUse = await _validateAddressUsing(addr);
hasAddrUse = await _hasAddressUsed(addr);
if (!hasAddrUse) {
break;
}
final start = addrs.length;
final count = start + gap;
final batch = await _createNewAddresses(
@ -264,9 +260,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
this.addresses.addAll(addressesSet);
}
Future<bool> _validateAddressUsing(String address) async {
Future<bool> _hasAddressUsed(String address) async {
final sh = scriptHash(address, networkType: networkType);
final balance = await electrumClient.getBalance(sh);
return balance.isEmpty;
final transactionHistory = await electrumClient.getHistory(sh);
return transactionHistory.isNotEmpty;
}
}

@ -53,18 +53,6 @@ class CWBitcoin extends Bitcoin {
final bitcoinWallet = wallet as ElectrumWallet;
await bitcoinWallet.walletAddresses.generateNewAddress();
}
@override
Future<void> nextAddress(Object wallet) {
final bitcoinWallet = wallet as ElectrumWallet;
bitcoinWallet.walletAddresses.nextReceiveAddress();
}
@override
Future<void> randomAddress(Object wallet) {
final bitcoinWallet = wallet as ElectrumWallet;
bitcoinWallet.walletAddresses.randomizeAddress();
}
@override
Object createBitcoinTransactionCredentials(List<Output> outputs, TransactionPriority priority)

@ -125,14 +125,15 @@ class AddressPage extends StatelessWidget {
),
),
)
: PrimaryButton(
onPressed: () => addressListViewModel.nextAddress(),
text: 'Next address',
color: Theme.of(context).buttonColor,
textColor: Theme.of(context)
.accentTextTheme
.display3
.backgroundColor);
: Text(
S.of(context).electrum_address_disclaimer,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
color: Theme.of(context)
.accentTextTheme
.display2
.backgroundColor));
})
],
),

@ -212,26 +212,4 @@ abstract class WalletAddressListViewModelBase with Store {
_baseItems.add(WalletAddressListHeader());
}
@action
void nextAddress() {
final wallet = _wallet;
if (wallet.type == WalletType.bitcoin
|| wallet.type == WalletType.litecoin) {
bitcoin.nextAddress(wallet);
wallet.save();
}
}
@action
void generateRandomAddress() {
final wallet = _wallet;
if (wallet.type == WalletType.bitcoin
|| wallet.type == WalletType.litecoin) {
bitcoin.randomAddress(wallet);
wallet.save();
}
}
}

@ -522,5 +522,6 @@
"third_intro_content" : "Yats leben auch außerhalb von Cake Wallet. Jede Wallet-Adresse auf der Welt kann durch ein Yat ersetzt werden!",
"learn_more" : "Erfahren Sie mehr",
"new_template" : "neue Vorlage"
"new_template" : "neue Vorlage",
"electrum_address_disclaimer": "Wir generieren jedes Mal neue Adressen, wenn Sie eine verwenden, aber vorherige Adressen funktionieren weiterhin"
}

@ -523,5 +523,6 @@
"third_intro_content" : "Yats live outside of Cake Wallet, too. Any wallet address on earth can be replaced with a Yat!",
"learn_more" : "Learn More",
"new_template" : "New Template"
"new_template" : "New Template",
"electrum_address_disclaimer": "We generate new addresses each time you use one, but previous addresses continue to work"
}

@ -522,5 +522,6 @@
"third_intro_content" : "Los Yats también viven fuera de Cake Wallet. Cualquier dirección de billetera en la tierra se puede reemplazar con un Yat!",
"learn_more" : "Aprende más",
"new_template" : "Nueva plantilla"
"new_template" : "Nueva plantilla",
"electrum_address_disclaimer": "Generamos nuevas direcciones cada vez que usa una, pero las direcciones anteriores siguen funcionando"
}

@ -522,5 +522,6 @@
"third_intro_content" : "Yats Cake Wallet के बाहर भी रहता है। धरती पर किसी भी वॉलेट पते को Yat से बदला जा सकता है!",
"learn_more" : "और अधिक जानें",
"new_template" : "नया टेम्पलेट"
"new_template" : "नया टेम्पलेट",
"electrum_address_disclaimer": "हर बार जब आप एक का उपयोग करते हैं तो हम नए पते उत्पन्न करते हैं, लेकिन पिछले पते काम करना जारी रखते हैं"
}

@ -522,5 +522,6 @@
"third_intro_content" : "Yats žive i izvan Cake Wallet -a. Bilo koja adresa novčanika na svijetu može se zamijeniti Yat!",
"learn_more" : "Saznajte više",
"new_template" : "novi predložak"
"new_template" : "novi predložak",
"electrum_address_disclaimer": "Minden egyes alkalommal új címeket generálunk, de a korábbi címek továbbra is működnek"
}

@ -522,5 +522,6 @@
"third_intro_content" : "Anche Yats vive fuori da Cake Wallet. Qualsiasi indirizzo di portafoglio sulla terra può essere sostituito con un Yat!",
"learn_more" : "Impara di più",
"new_template" : "Nuovo modello"
"new_template" : "Nuovo modello",
"electrum_address_disclaimer": "Generiamo nuovi indirizzi ogni volta che ne utilizzi uno, ma gli indirizzi precedenti continuano a funzionare"
}

@ -522,5 +522,6 @@
"third_intro_content" : "YatsはCakeWalletの外にも住んでいます。 地球上のどのウォレットアドレスもYatに置き換えることができます",
"learn_more" : "もっと詳しく知る",
"new_template" : "新しいテンプレート"
"new_template" : "新しいテンプレート",
"electrum_address_disclaimer": "使用するたびに新しいアドレスが生成されますが、以前のアドレスは引き続き機能します"
}

@ -522,5 +522,6 @@
"third_intro_content" : "Yats는 Cake Wallet 밖에서도 살고 있습니다. 지구상의 모든 지갑 주소는 Yat!",
"learn_more" : "더 알아보기",
"new_template" : "새 템플릿"
"new_template" : "새 템플릿",
"electrum_address_disclaimer": "사용할 때마다 새 주소가 생성되지만 이전 주소는 계속 작동합니다."
}

@ -522,5 +522,6 @@
"third_intro_content" : "Yats wonen ook buiten Cake Wallet. Elk portemonnee-adres op aarde kan worden vervangen door een Yat!",
"learn_more" : "Kom meer te weten",
"new_template" : "Nieuwe sjabloon"
"new_template" : "Nieuwe sjabloon",
"electrum_address_disclaimer": "We generate new addresses each time you use one, but previous addresses continue to work"
}

@ -522,5 +522,6 @@
"third_intro_content" : "Yats mieszkają również poza Cake Wallet. Każdy adres portfela na ziemi można zastąpić Yat!",
"learn_more" : "Ucz się więcej",
"new_template" : "Nowy szablon"
"new_template" : "Nowy szablon",
"electrum_address_disclaimer": "Za każdym razem, gdy korzystasz z jednego z nich, generujemy nowe adresy, ale poprzednie adresy nadal działają"
}

@ -522,5 +522,6 @@
"third_intro_content" : "Yats também mora fora da Cake Wallet. Qualquer endereço de carteira na Terra pode ser substituído por um Yat!",
"learn_more" : "Saber mais",
"new_template" : "Novo modelo"
"new_template" : "Novo modelo",
"electrum_address_disclaimer": "Geramos novos endereços cada vez que você usa um, mas os endereços anteriores continuam funcionando"
}

@ -522,5 +522,6 @@
"third_intro_content" : "Yat находятся за пределами Cake Wallet. Любой адрес кошелька на земле можно заменить на Yat!",
"learn_more" : "Узнать больше",
"new_template" : "Новый шаблон"
"new_template" : "Новый шаблон",
"electrum_address_disclaimer": "Мы генерируем новые адреса каждый раз, когда вы их используете, но предыдущие адреса продолжают работать."
}

@ -521,5 +521,6 @@
"third_intro_content" : "Yat знаходиться за межами Cake Wallet. Будь-яку адресу гаманця на землі можна замінити на Yat!",
"learn_more" : "Дізнатися більше",
"new_template" : "Новий шаблон"
"new_template" : "Новий шаблон",
"electrum_address_disclaimer": "Ми створюємо нові адреси щоразу, коли ви використовуєте їх, але попередні адреси продовжують працювати"
}

@ -520,5 +520,6 @@
"third_intro_content" : "Yats 也住在 Cake Wallet 之外。 地球上任何一個錢包地址都可以用一個Yat來代替",
"learn_more" : "了解更多",
"new_template" : "新模板"
"new_template" : "新模板",
"electrum_address_disclaimer": "每次您使用一个地址时,我们都会生成新地址,但之前的地址仍然有效"
}

@ -74,8 +74,6 @@ abstract class Bitcoin {
TransactionPriority deserializeBitcoinTransactionPriority(int raw);
int getFeeRate(Object wallet, TransactionPriority priority);
Future<void> generateNewAddress(Object wallet);
Future<void> nextAddress(Object wallet);
Future<void> randomAddress(Object wallet);
Object createBitcoinTransactionCredentials(List<Output> outputs, TransactionPriority priority);
List<String> getAddresses(Object wallet);

Loading…
Cancel
Save