mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-23 06:38:35 +02:00
Merge branch 'release-4.2.4' into CAKE-334-unspent-coins-control-application-logic
This commit is contained in:
@@ -3,12 +3,12 @@ import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||
import 'package:cake_wallet/bitcoin/utils.dart';
|
||||
import 'package:cake_wallet/bitcoin/electrum_wallet_snapshot.dart';
|
||||
import 'package:cake_wallet/bitcoin/electrum_wallet.dart';
|
||||
import 'package:cake_wallet/entities/wallet_info.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart';
|
||||
import 'package:cake_wallet/bitcoin/electrum_balance.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_wallet_addresses.dart';
|
||||
|
||||
part 'bitcoin_wallet.g.dart';
|
||||
|
||||
@@ -30,8 +30,14 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||
unspentCoinsInfo: unspentCoinsInfo,
|
||||
networkType: bitcoin.bitcoin,
|
||||
initialAddresses: initialAddresses,
|
||||
initialBalance: initialBalance,
|
||||
accountIndex: accountIndex);
|
||||
initialBalance: initialBalance) {
|
||||
walletAddresses = BitcoinWalletAddresses(
|
||||
walletInfo,
|
||||
initialAddresses: initialAddresses,
|
||||
accountIndex: accountIndex,
|
||||
hd: hd,
|
||||
networkType: networkType);
|
||||
}
|
||||
|
||||
static Future<BitcoinWallet> open({
|
||||
@required String name,
|
||||
@@ -50,8 +56,4 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||
initialBalance: snp.balance,
|
||||
accountIndex: snp.accountIndex);
|
||||
}
|
||||
|
||||
@override
|
||||
String getAddress({@required int index, @required bitcoin.HDWallet hd}) =>
|
||||
generateP2WPKHAddress(hd: hd, index: index, networkType: networkType);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||
import 'package:cake_wallet/bitcoin/utils.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart';
|
||||
import 'package:cake_wallet/bitcoin/electrum_wallet_addresses.dart';
|
||||
import 'package:cake_wallet/entities/wallet_info.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'bitcoin_wallet_addresses.g.dart';
|
||||
|
||||
class BitcoinWalletAddresses = BitcoinWalletAddressesBase
|
||||
with _$BitcoinWalletAddresses;
|
||||
|
||||
abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses
|
||||
with Store {
|
||||
BitcoinWalletAddressesBase(
|
||||
WalletInfo walletInfo,
|
||||
{@required List<BitcoinAddressRecord> initialAddresses,
|
||||
int accountIndex = 0,
|
||||
@required bitcoin.HDWallet hd,
|
||||
@required this.networkType})
|
||||
: super(
|
||||
walletInfo,
|
||||
initialAddresses: initialAddresses,
|
||||
accountIndex: accountIndex,
|
||||
hd: hd);
|
||||
|
||||
bitcoin.NetworkType networkType;
|
||||
|
||||
@override
|
||||
String getAddress({@required int index, @required bitcoin.HDWallet hd}) =>
|
||||
generateP2WPKHAddress(hd: hd, index: index, networkType: networkType);
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:cake_wallet/bitcoin/unspent_coins_info.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:cake_wallet/bitcoin/electrum_wallet_addresses.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:rxdart/subjects.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@@ -45,18 +46,14 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
|
||||
@required this.networkType,
|
||||
@required this.mnemonic,
|
||||
ElectrumClient electrumClient,
|
||||
int accountIndex = 0,
|
||||
ElectrumBalance initialBalance})
|
||||
: balance = initialBalance ??
|
||||
const ElectrumBalance(confirmed: 0, unconfirmed: 0),
|
||||
hd = bitcoin.HDWallet.fromSeed(mnemonicToSeedBytes(mnemonic),
|
||||
network: networkType)
|
||||
.derivePath("m/0'/0"),
|
||||
addresses = ObservableList<BitcoinAddressRecord>.of(
|
||||
(initialAddresses ?? []).toSet()),
|
||||
syncStatus = NotConnectedSyncStatus(),
|
||||
_password = password,
|
||||
_accountIndex = accountIndex,
|
||||
_feeRates = <int>[],
|
||||
_isTransactionUpdating = false,
|
||||
super(walletInfo) {
|
||||
@@ -79,8 +76,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
|
||||
Box<UnspentCoinsInfo> unspentCoinsInfo;
|
||||
|
||||
@override
|
||||
@observable
|
||||
String address;
|
||||
ElectrumWalletAddresses walletAddresses;
|
||||
|
||||
@override
|
||||
@observable
|
||||
@@ -90,9 +86,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
|
||||
@observable
|
||||
SyncStatus syncStatus;
|
||||
|
||||
ObservableList<BitcoinAddressRecord> addresses;
|
||||
|
||||
List<String> get scriptHashes => addresses
|
||||
List<String> get scriptHashes => walletAddresses.addresses
|
||||
.map((addr) => scriptHash(addr.address, networkType: networkType))
|
||||
.toList();
|
||||
|
||||
@@ -110,74 +104,15 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
|
||||
final String _password;
|
||||
List<BitcoinUnspent> unspentCoins;
|
||||
List<int> _feeRates;
|
||||
int _accountIndex;
|
||||
Map<String, BehaviorSubject<Object>> _scripthashesUpdateSubject;
|
||||
bool _isTransactionUpdating;
|
||||
|
||||
Future<void> init() async {
|
||||
await generateAddresses();
|
||||
address = addresses[_accountIndex].address;
|
||||
await walletAddresses.init();
|
||||
await transactionHistory.init();
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> nextAddress() async {
|
||||
_accountIndex += 1;
|
||||
|
||||
if (_accountIndex >= addresses.length) {
|
||||
_accountIndex = 0;
|
||||
}
|
||||
|
||||
address = addresses[_accountIndex].address;
|
||||
|
||||
await save();
|
||||
}
|
||||
|
||||
Future<void> generateAddresses() async {
|
||||
if (addresses.length < 33) {
|
||||
final addressesCount = 33 - addresses.length;
|
||||
await generateNewAddresses(addressesCount,
|
||||
startIndex: addresses.length, hd: hd);
|
||||
}
|
||||
}
|
||||
|
||||
Future<BitcoinAddressRecord> generateNewAddress(
|
||||
{bool isHidden = false, bitcoin.HDWallet hd}) async {
|
||||
_accountIndex += 1;
|
||||
final _hd = hd ?? this.hd;
|
||||
final address = BitcoinAddressRecord(
|
||||
getAddress(index: _accountIndex, hd: _hd),
|
||||
index: _accountIndex,
|
||||
isHidden: isHidden);
|
||||
addresses.add(address);
|
||||
await save();
|
||||
return address;
|
||||
}
|
||||
|
||||
Future<List<BitcoinAddressRecord>> generateNewAddresses(int count,
|
||||
{int startIndex = 0, bitcoin.HDWallet hd, bool isHidden = false}) async {
|
||||
final list = <BitcoinAddressRecord>[];
|
||||
|
||||
for (var i = startIndex; i < count + startIndex; i++) {
|
||||
final address = BitcoinAddressRecord(getAddress(index: i, hd: hd),
|
||||
index: i, isHidden: isHidden);
|
||||
list.add(address);
|
||||
}
|
||||
|
||||
addresses.addAll(list);
|
||||
await save();
|
||||
return list;
|
||||
}
|
||||
|
||||
Future<void> updateAddress(String address) async {
|
||||
for (final addr in addresses) {
|
||||
if (addr.address == address) {
|
||||
await save();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
@override
|
||||
Future<void> startSync() async {
|
||||
@@ -266,8 +201,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
|
||||
}
|
||||
|
||||
final txb = bitcoin.TransactionBuilder(network: networkType);
|
||||
final changeAddress = address;
|
||||
|
||||
final changeAddress = walletAddresses.address;
|
||||
var leftAmount = totalAmount;
|
||||
var totalInputAmount = 0;
|
||||
|
||||
@@ -340,8 +274,8 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
|
||||
|
||||
String toJSON() => json.encode({
|
||||
'mnemonic': mnemonic,
|
||||
'account_index': _accountIndex.toString(),
|
||||
'addresses': addresses.map((addr) => addr.toJSON()).toList(),
|
||||
'account_index': walletAddresses.accountIndex.toString(),
|
||||
'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(),
|
||||
'balance': balance?.toJSON()
|
||||
});
|
||||
|
||||
@@ -413,13 +347,12 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
String getAddress({@required int index, @required bitcoin.HDWallet hd}) => '';
|
||||
|
||||
Future<String> makePath() async =>
|
||||
pathForWallet(name: walletInfo.name, type: walletInfo.type);
|
||||
|
||||
Future<void> updateUnspent() async {
|
||||
final unspent = await Future.wait(addresses.map((address) => electrumClient
|
||||
final unspent = await Future.wait(walletAddresses
|
||||
.addresses.map((address) => electrumClient
|
||||
.getListUnspentWithAddress(address.address, networkType)
|
||||
.then((unspent) => unspent
|
||||
.map((unspent) => BitcoinUnspent.fromJSON(address, unspent)))));
|
||||
@@ -491,7 +424,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
|
||||
{@required String hash, @required int height}) async {
|
||||
final tx = await electrumClient.getTransactionExpanded(hash: hash);
|
||||
return ElectrumTransactionInfo.fromElectrumVerbose(tx, walletInfo.type,
|
||||
height: height, addresses: addresses);
|
||||
height: height, addresses: walletAddresses.addresses);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart';
|
||||
import 'package:cake_wallet/entities/wallet_addresses.dart';
|
||||
import 'package:cake_wallet/entities/wallet_info.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'electrum_wallet_addresses.g.dart';
|
||||
|
||||
class ElectrumWalletAddresses = ElectrumWalletAddressesBase
|
||||
with _$ElectrumWalletAddresses;
|
||||
|
||||
abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||
ElectrumWalletAddressesBase(WalletInfo walletInfo,
|
||||
{@required List<BitcoinAddressRecord> initialAddresses,
|
||||
int accountIndex = 0,
|
||||
@required bitcoin.HDWallet hd})
|
||||
: super(walletInfo) {
|
||||
this.hd = hd;
|
||||
this.accountIndex = accountIndex;
|
||||
addresses = ObservableList<BitcoinAddressRecord>.of(
|
||||
(initialAddresses ?? []).toSet());
|
||||
}
|
||||
|
||||
@override
|
||||
@observable
|
||||
String address;
|
||||
|
||||
bitcoin.HDWallet hd;
|
||||
|
||||
ObservableList<BitcoinAddressRecord> addresses;
|
||||
|
||||
int accountIndex;
|
||||
|
||||
@override
|
||||
Future<void> init() async {
|
||||
await generateAddresses();
|
||||
address = addresses[accountIndex].address;
|
||||
await updateAddressesInBox();
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> nextAddress() async {
|
||||
accountIndex += 1;
|
||||
|
||||
if (accountIndex >= addresses.length) {
|
||||
accountIndex = 0;
|
||||
}
|
||||
|
||||
address = addresses[accountIndex].address;
|
||||
|
||||
await updateAddressesInBox();
|
||||
}
|
||||
|
||||
Future<void> generateAddresses() async {
|
||||
if (addresses.length < 33) {
|
||||
final addressesCount = 33 - addresses.length;
|
||||
await generateNewAddresses(addressesCount,
|
||||
startIndex: addresses.length, hd: hd);
|
||||
}
|
||||
}
|
||||
|
||||
Future<BitcoinAddressRecord> generateNewAddress(
|
||||
{bool isHidden = false, bitcoin.HDWallet hd}) async {
|
||||
accountIndex += 1;
|
||||
final _hd = hd ?? this.hd;
|
||||
final address = BitcoinAddressRecord(
|
||||
getAddress(index: accountIndex, hd: _hd),
|
||||
index: accountIndex,
|
||||
isHidden: isHidden);
|
||||
addresses.add(address);
|
||||
return address;
|
||||
}
|
||||
|
||||
Future<List<BitcoinAddressRecord>> generateNewAddresses(int count,
|
||||
{int startIndex = 0, bitcoin.HDWallet hd, bool isHidden = false}) async {
|
||||
final list = <BitcoinAddressRecord>[];
|
||||
|
||||
for (var i = startIndex; i < count + startIndex; i++) {
|
||||
final address = BitcoinAddressRecord(getAddress(index: i, hd: hd),
|
||||
index: i, isHidden: isHidden);
|
||||
list.add(address);
|
||||
}
|
||||
|
||||
addresses.addAll(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
/*Future<void> updateAddress(String address) async {
|
||||
for (final addr in addresses) {
|
||||
if (addr.address == address) {
|
||||
await save();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
String getAddress({@required int index, @required bitcoin.HDWallet hd}) => '';
|
||||
|
||||
@override
|
||||
Future<void> updateAddressesInBox() async {
|
||||
try {
|
||||
addressesMap.clear();
|
||||
addressesMap[address] = '';
|
||||
|
||||
await saveAddressesInBox();
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_mnemonic.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_transaction_priority.dart';
|
||||
import 'package:cake_wallet/bitcoin/unspent_coins_info.dart';
|
||||
import 'package:cake_wallet/bitcoin/litecoin_wallet_addresses.dart';
|
||||
import 'package:cake_wallet/entities/transaction_priority.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
@@ -12,7 +11,6 @@ import 'package:cake_wallet/bitcoin/electrum_wallet.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart';
|
||||
import 'package:cake_wallet/bitcoin/electrum_balance.dart';
|
||||
import 'package:cake_wallet/bitcoin/litecoin_network.dart';
|
||||
import 'package:cake_wallet/bitcoin/utils.dart';
|
||||
|
||||
part 'litecoin_wallet.g.dart';
|
||||
|
||||
@@ -34,8 +32,15 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||
unspentCoinsInfo: unspentCoinsInfo,
|
||||
networkType: litecoinNetwork,
|
||||
initialAddresses: initialAddresses,
|
||||
initialBalance: initialBalance,
|
||||
accountIndex: accountIndex);
|
||||
initialBalance: initialBalance) {
|
||||
walletAddresses = LitecoinWalletAddresses(
|
||||
walletInfo,
|
||||
initialAddresses: initialAddresses,
|
||||
accountIndex: accountIndex,
|
||||
hd: hd,
|
||||
networkType: networkType,
|
||||
mnemonic: mnemonic);
|
||||
}
|
||||
|
||||
static Future<LitecoinWallet> open({
|
||||
@required String name,
|
||||
@@ -55,27 +60,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||
accountIndex: snp.accountIndex);
|
||||
}
|
||||
|
||||
@override
|
||||
String getAddress({@required int index, @required bitcoin.HDWallet hd}) =>
|
||||
generateP2WPKHAddress(hd: hd, index: index, networkType: networkType);
|
||||
|
||||
@override
|
||||
Future<void> generateAddresses() async {
|
||||
if (addresses.length < 33) {
|
||||
final addressesCount = 22 - addresses.length;
|
||||
await generateNewAddresses(addressesCount,
|
||||
hd: hd, startIndex: addresses.length);
|
||||
|
||||
final changeRoot = bitcoin.HDWallet.fromSeed(
|
||||
mnemonicToSeedBytes(mnemonic),
|
||||
network: networkType)
|
||||
.derivePath("m/0'/1");
|
||||
|
||||
await generateNewAddresses(11,
|
||||
startIndex: 0, hd: changeRoot, isHidden: true);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
int feeRate(TransactionPriority priority) {
|
||||
if (priority is LitecoinTransactionPriority) {
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_mnemonic.dart';
|
||||
import 'package:cake_wallet/bitcoin/utils.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart';
|
||||
import 'package:cake_wallet/bitcoin/electrum_wallet_addresses.dart';
|
||||
import 'package:cake_wallet/entities/wallet_info.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'litecoin_wallet_addresses.g.dart';
|
||||
|
||||
class LitecoinWalletAddresses = LitecoinWalletAddressesBase
|
||||
with _$LitecoinWalletAddresses;
|
||||
|
||||
abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses
|
||||
with Store {
|
||||
LitecoinWalletAddressesBase(
|
||||
WalletInfo walletInfo,
|
||||
{@required List<BitcoinAddressRecord> initialAddresses,
|
||||
int accountIndex = 0,
|
||||
@required bitcoin.HDWallet hd,
|
||||
@required this.networkType,
|
||||
@required this.mnemonic})
|
||||
: super(
|
||||
walletInfo,
|
||||
initialAddresses: initialAddresses,
|
||||
accountIndex: accountIndex,
|
||||
hd: hd);
|
||||
|
||||
bitcoin.NetworkType networkType;
|
||||
|
||||
final String mnemonic;
|
||||
|
||||
@override
|
||||
String getAddress({@required int index, @required bitcoin.HDWallet hd}) =>
|
||||
generateP2WPKHAddress(hd: hd, index: index, networkType: networkType);
|
||||
|
||||
@override
|
||||
Future<void> generateAddresses() async {
|
||||
if (addresses.length < 33) {
|
||||
final addressesCount = 22 - addresses.length;
|
||||
await generateNewAddresses(addressesCount,
|
||||
hd: hd, startIndex: addresses.length);
|
||||
|
||||
final changeRoot = bitcoin.HDWallet.fromSeed(
|
||||
mnemonicToSeedBytes(mnemonic),
|
||||
network: networkType)
|
||||
.derivePath("m/0'/1");
|
||||
|
||||
await generateNewAddresses(11,
|
||||
startIndex: 0, hd: changeRoot, isHidden: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user