mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-22 19:39:22 +00:00
Merge branch 'staging' into flutter3.3.4
This commit is contained in:
commit
b8d304f9a3
18 changed files with 163 additions and 68 deletions
|
@ -454,7 +454,7 @@
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 78;
|
CURRENT_PROJECT_VERSION = 79;
|
||||||
DEVELOPMENT_TEAM = 4DQKUWSG6C;
|
DEVELOPMENT_TEAM = 4DQKUWSG6C;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
@ -508,7 +508,7 @@
|
||||||
"$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**",
|
"$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**",
|
||||||
"$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs",
|
"$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.5.8;
|
MARKETING_VERSION = 1.5.9;
|
||||||
ONLY_ACTIVE_ARCH = NO;
|
ONLY_ACTIVE_ARCH = NO;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet;
|
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
@ -641,7 +641,7 @@
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 78;
|
CURRENT_PROJECT_VERSION = 79;
|
||||||
DEVELOPMENT_TEAM = 4DQKUWSG6C;
|
DEVELOPMENT_TEAM = 4DQKUWSG6C;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
@ -695,7 +695,7 @@
|
||||||
"$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**",
|
"$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**",
|
||||||
"$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs",
|
"$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.5.8;
|
MARKETING_VERSION = 1.5.9;
|
||||||
ONLY_ACTIVE_ARCH = NO;
|
ONLY_ACTIVE_ARCH = NO;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet;
|
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
@ -720,7 +720,7 @@
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 78;
|
CURRENT_PROJECT_VERSION = 79;
|
||||||
DEVELOPMENT_TEAM = 4DQKUWSG6C;
|
DEVELOPMENT_TEAM = 4DQKUWSG6C;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
@ -774,7 +774,7 @@
|
||||||
"$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**",
|
"$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**",
|
||||||
"$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs",
|
"$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.5.8;
|
MARKETING_VERSION = 1.5.9;
|
||||||
ONLY_ACTIVE_ARCH = NO;
|
ONLY_ACTIVE_ARCH = NO;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet;
|
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
|
|
@ -143,7 +143,12 @@ void main() async {
|
||||||
boxName: DB.boxNameDBInfo, key: "hive_data_version") as int? ??
|
boxName: DB.boxNameDBInfo, key: "hive_data_version") as int? ??
|
||||||
0;
|
0;
|
||||||
if (dbVersion < Constants.currentHiveDbVersion) {
|
if (dbVersion < Constants.currentHiveDbVersion) {
|
||||||
await DbVersionMigrator().migrate(dbVersion);
|
try {
|
||||||
|
await DbVersionMigrator().migrate(dbVersion);
|
||||||
|
} catch (e, s) {
|
||||||
|
Logging.instance.log("Cannot migrate database\n$e $s",
|
||||||
|
level: LogLevel.Error, printFullLength: true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
monero.onStartup();
|
monero.onStartup();
|
||||||
|
@ -231,7 +236,9 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
|
||||||
// unawaited(_nodeService.updateCommunityNodes());
|
// unawaited(_nodeService.updateCommunityNodes());
|
||||||
|
|
||||||
// run without awaiting
|
// run without awaiting
|
||||||
if (Constants.enableExchange && _prefs.externalCalls) {
|
if (Constants.enableExchange &&
|
||||||
|
_prefs.externalCalls &&
|
||||||
|
await _prefs.isExternalCallsSet()) {
|
||||||
unawaited(ExchangeDataLoadingService().loadAll(ref));
|
unawaited(ExchangeDataLoadingService().loadAll(ref));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -276,6 +276,12 @@ class ExchangeFormState extends ChangeNotifier {
|
||||||
|
|
||||||
void _onExchangeRateTypeChanged() {
|
void _onExchangeRateTypeChanged() {
|
||||||
print("_onExchangeRateTypeChanged");
|
print("_onExchangeRateTypeChanged");
|
||||||
|
updateRanges(shouldNotifyListeners: true).then(
|
||||||
|
(_) => updateEstimate(
|
||||||
|
shouldNotifyListeners: true,
|
||||||
|
reversed: reversed,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onExchangeTypeChanged() {
|
void _onExchangeTypeChanged() {
|
||||||
|
|
|
@ -144,6 +144,8 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
|
||||||
|
|
||||||
Future<void> chooseDate() async {
|
Future<void> chooseDate() async {
|
||||||
final height = MediaQuery.of(context).size.height;
|
final height = MediaQuery.of(context).size.height;
|
||||||
|
final fetchedColor =
|
||||||
|
Theme.of(context).extension<StackColors>()!.accentColorDark;
|
||||||
// check and hide keyboard
|
// check and hide keyboard
|
||||||
if (FocusScope.of(context).hasFocus) {
|
if (FocusScope.of(context).hasFocus) {
|
||||||
FocusScope.of(context).unfocus();
|
FocusScope.of(context).unfocus();
|
||||||
|
@ -155,8 +157,7 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
|
||||||
initialDate: DateTime.now(),
|
initialDate: DateTime.now(),
|
||||||
height: height * 0.5,
|
height: height * 0.5,
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
primarySwatch: Util.createMaterialColor(
|
primarySwatch: Util.createMaterialColor(fetchedColor),
|
||||||
Theme.of(context).extension<StackColors>()!.accentColorDark),
|
|
||||||
),
|
),
|
||||||
//TODO pick a better initial date
|
//TODO pick a better initial date
|
||||||
// 2007 chosen as that is just before bitcoin launched
|
// 2007 chosen as that is just before bitcoin launched
|
||||||
|
@ -272,6 +273,7 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
|
||||||
// if (!isDesktop)
|
// if (!isDesktop)
|
||||||
RestoreFromDatePicker(
|
RestoreFromDatePicker(
|
||||||
onTap: chooseDate,
|
onTap: chooseDate,
|
||||||
|
controller: _dateController,
|
||||||
),
|
),
|
||||||
|
|
||||||
// if (isDesktop)
|
// if (isDesktop)
|
||||||
|
|
|
@ -5,10 +5,14 @@ import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||||
|
|
||||||
class RestoreFromDatePicker extends StatefulWidget {
|
class RestoreFromDatePicker extends StatefulWidget {
|
||||||
const RestoreFromDatePicker({Key? key, required this.onTap})
|
const RestoreFromDatePicker({
|
||||||
: super(key: key);
|
Key? key,
|
||||||
|
required this.onTap,
|
||||||
|
required this.controller,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
|
final TextEditingController controller;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<RestoreFromDatePicker> createState() => _RestoreFromDatePickerState();
|
State<RestoreFromDatePicker> createState() => _RestoreFromDatePickerState();
|
||||||
|
@ -21,17 +25,11 @@ class _RestoreFromDatePickerState extends State<RestoreFromDatePicker> {
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
onTap = widget.onTap;
|
onTap = widget.onTap;
|
||||||
_dateController = TextEditingController();
|
_dateController = widget.controller;
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_dateController.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
|
|
|
@ -43,7 +43,7 @@ import 'package:stackwallet/utilities/prefs.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
const int MINIMUM_CONFIRMATIONS = 3;
|
const int MINIMUM_CONFIRMATIONS = 1;
|
||||||
const int DUST_LIMIT = 546;
|
const int DUST_LIMIT = 546;
|
||||||
|
|
||||||
const String GENESIS_HASH_MAINNET =
|
const String GENESIS_HASH_MAINNET =
|
||||||
|
@ -265,6 +265,11 @@ class BitcoinCashWallet extends CoinServiceAPI {
|
||||||
DerivePathType addressType({required String address}) {
|
DerivePathType addressType({required String address}) {
|
||||||
Uint8List? decodeBase58;
|
Uint8List? decodeBase58;
|
||||||
Segwit? decodeBech32;
|
Segwit? decodeBech32;
|
||||||
|
try {
|
||||||
|
if (Bitbox.Address.detectFormat(address) == 0) {
|
||||||
|
address = Bitbox.Address.toLegacyAddress(address);
|
||||||
|
}
|
||||||
|
} catch (e, s) {}
|
||||||
try {
|
try {
|
||||||
decodeBase58 = bs58check.decode(address);
|
decodeBase58 = bs58check.decode(address);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -825,9 +830,6 @@ class BitcoinCashWallet extends CoinServiceAPI {
|
||||||
/// Refreshes display data for the wallet
|
/// Refreshes display data for the wallet
|
||||||
@override
|
@override
|
||||||
Future<void> refresh() async {
|
Future<void> refresh() async {
|
||||||
final bchaddr = Bitbox.Address.toCashAddress(await currentReceivingAddress);
|
|
||||||
print("bchaddr: $bchaddr ${await currentReceivingAddress}");
|
|
||||||
|
|
||||||
if (refreshMutex) {
|
if (refreshMutex) {
|
||||||
Logging.instance.log("$walletId $walletName refreshMutex denied",
|
Logging.instance.log("$walletId $walletName refreshMutex denied",
|
||||||
level: LogLevel.Info);
|
level: LogLevel.Info);
|
||||||
|
@ -1384,7 +1386,9 @@ class BitcoinCashWallet extends CoinServiceAPI {
|
||||||
initialChangeAddressP2SH, 1, DerivePathType.bip49);
|
initialChangeAddressP2SH, 1, DerivePathType.bip49);
|
||||||
|
|
||||||
// this._currentReceivingAddress = Future(() => initialReceivingAddress);
|
// this._currentReceivingAddress = Future(() => initialReceivingAddress);
|
||||||
_currentReceivingAddressP2PKH = Future(() => initialReceivingAddressP2PKH);
|
|
||||||
|
var newaddr = await _getCurrentAddressForChain(0, DerivePathType.bip44);
|
||||||
|
_currentReceivingAddressP2PKH = Future(() => newaddr);
|
||||||
_currentReceivingAddressP2SH = Future(() => initialReceivingAddressP2SH);
|
_currentReceivingAddressP2SH = Future(() => initialReceivingAddressP2SH);
|
||||||
|
|
||||||
Logging.instance.log("_generateNewWalletFinished", level: LogLevel.Info);
|
Logging.instance.log("_generateNewWalletFinished", level: LogLevel.Info);
|
||||||
|
@ -1521,6 +1525,11 @@ class BitcoinCashWallet extends CoinServiceAPI {
|
||||||
print("Array key is ${jsonEncode(arrayKey)}");
|
print("Array key is ${jsonEncode(arrayKey)}");
|
||||||
final internalChainArray =
|
final internalChainArray =
|
||||||
DB.instance.get<dynamic>(boxName: walletId, key: arrayKey);
|
DB.instance.get<dynamic>(boxName: walletId, key: arrayKey);
|
||||||
|
if (derivePathType == DerivePathType.bip44) {
|
||||||
|
if (Bitbox.Address.detectFormat(internalChainArray.last as String) == 1) {
|
||||||
|
return Bitbox.Address.toCashAddress(internalChainArray.last as String);
|
||||||
|
}
|
||||||
|
}
|
||||||
return internalChainArray.last as String;
|
return internalChainArray.last as String;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1986,6 +1995,9 @@ class BitcoinCashWallet extends CoinServiceAPI {
|
||||||
/// Returns the scripthash or throws an exception on invalid bch address
|
/// Returns the scripthash or throws an exception on invalid bch address
|
||||||
String _convertToScriptHash(String bchAddress, NetworkType network) {
|
String _convertToScriptHash(String bchAddress, NetworkType network) {
|
||||||
try {
|
try {
|
||||||
|
if (Bitbox.Address.detectFormat(bchAddress) == 0) {
|
||||||
|
bchAddress = Bitbox.Address.toLegacyAddress(bchAddress);
|
||||||
|
}
|
||||||
final output = Address.addressToOutputScript(bchAddress, network);
|
final output = Address.addressToOutputScript(bchAddress, network);
|
||||||
final hash = sha256.convert(output.toList(growable: false)).toString();
|
final hash = sha256.convert(output.toList(growable: false)).toString();
|
||||||
|
|
||||||
|
@ -2058,11 +2070,27 @@ class BitcoinCashWallet extends CoinServiceAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<TransactionData> _fetchTransactionData() async {
|
Future<TransactionData> _fetchTransactionData() async {
|
||||||
final List<String> allAddresses = await _fetchAllOwnAddresses();
|
List<String> allAddressesOld = await _fetchAllOwnAddresses();
|
||||||
|
List<String> allAddresses = [];
|
||||||
|
for (String address in allAddressesOld) {
|
||||||
|
if (Bitbox.Address.detectFormat(address) == 1) {
|
||||||
|
allAddresses.add(Bitbox.Address.toCashAddress(address));
|
||||||
|
} else {
|
||||||
|
allAddresses.add(address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final changeAddressesP2PKH =
|
var changeAddressesP2PKHOld =
|
||||||
DB.instance.get<dynamic>(boxName: walletId, key: 'changeAddressesP2PKH')
|
DB.instance.get<dynamic>(boxName: walletId, key: 'changeAddressesP2PKH')
|
||||||
as List<dynamic>;
|
as List<dynamic>;
|
||||||
|
List<dynamic> changeAddressesP2PKH = [];
|
||||||
|
for (var address in changeAddressesP2PKHOld) {
|
||||||
|
if (Bitbox.Address.detectFormat(address as String) == 1) {
|
||||||
|
changeAddressesP2PKH.add(Bitbox.Address.toCashAddress(address));
|
||||||
|
} else {
|
||||||
|
changeAddressesP2PKH.add(address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final List<Map<String, dynamic>> allTxHashes =
|
final List<Map<String, dynamic>> allTxHashes =
|
||||||
await _fetchHistory(allAddresses);
|
await _fetchHistory(allAddresses);
|
||||||
|
@ -2087,7 +2115,16 @@ class BitcoinCashWallet extends CoinServiceAPI {
|
||||||
if (txHeight > 0 &&
|
if (txHeight > 0 &&
|
||||||
txHeight < latestTxnBlockHeight - MINIMUM_CONFIRMATIONS) {
|
txHeight < latestTxnBlockHeight - MINIMUM_CONFIRMATIONS) {
|
||||||
if (unconfirmedCachedTransactions[tx["tx_hash"] as String] == null) {
|
if (unconfirmedCachedTransactions[tx["tx_hash"] as String] == null) {
|
||||||
allTxHashes.remove(tx);
|
print(cachedTransactions.findTransaction(tx["tx_hash"] as String));
|
||||||
|
print(unconfirmedCachedTransactions[tx["tx_hash"] as String]);
|
||||||
|
final cachedTx =
|
||||||
|
cachedTransactions.findTransaction(tx["tx_hash"] as String);
|
||||||
|
if (!(cachedTx != null &&
|
||||||
|
addressType(address: cachedTx.address) ==
|
||||||
|
DerivePathType.bip44 &&
|
||||||
|
Bitbox.Address.detectFormat(cachedTx.address) == 1)) {
|
||||||
|
allTxHashes.remove(tx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2096,7 +2133,6 @@ class BitcoinCashWallet extends CoinServiceAPI {
|
||||||
List<Map<String, dynamic>> allTransactions = [];
|
List<Map<String, dynamic>> allTransactions = [];
|
||||||
|
|
||||||
for (final txHash in allTxHashes) {
|
for (final txHash in allTxHashes) {
|
||||||
Logging.instance.log("bch: $txHash", level: LogLevel.Info);
|
|
||||||
final tx = await cachedElectrumXClient.getTransaction(
|
final tx = await cachedElectrumXClient.getTransaction(
|
||||||
txHash: txHash["tx_hash"] as String,
|
txHash: txHash["tx_hash"] as String,
|
||||||
verbose: true,
|
verbose: true,
|
||||||
|
@ -2166,7 +2202,8 @@ class BitcoinCashWallet extends CoinServiceAPI {
|
||||||
.log("recipientsArray: $recipientsArray", level: LogLevel.Info);
|
.log("recipientsArray: $recipientsArray", level: LogLevel.Info);
|
||||||
|
|
||||||
final foundInSenders =
|
final foundInSenders =
|
||||||
allAddresses.any((element) => sendersArray.contains(element));
|
allAddresses.any((element) => sendersArray.contains(element)) ||
|
||||||
|
allAddressesOld.any((element) => sendersArray.contains(element));
|
||||||
Logging.instance
|
Logging.instance
|
||||||
.log("foundInSenders: $foundInSenders", level: LogLevel.Info);
|
.log("foundInSenders: $foundInSenders", level: LogLevel.Info);
|
||||||
|
|
||||||
|
@ -2228,7 +2265,8 @@ class BitcoinCashWallet extends CoinServiceAPI {
|
||||||
.toBigInt()
|
.toBigInt()
|
||||||
.toInt();
|
.toInt();
|
||||||
totalOut += value;
|
totalOut += value;
|
||||||
if (allAddresses.contains(address)) {
|
if (allAddresses.contains(address) ||
|
||||||
|
allAddressesOld.contains(address)) {
|
||||||
outputAmtAddressedToWallet += value;
|
outputAmtAddressedToWallet += value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2743,7 +2781,10 @@ class BitcoinCashWallet extends CoinServiceAPI {
|
||||||
for (final output in tx["vout"] as List) {
|
for (final output in tx["vout"] as List) {
|
||||||
final n = output["n"];
|
final n = output["n"];
|
||||||
if (n != null && n == utxosToUse[i].vout) {
|
if (n != null && n == utxosToUse[i].vout) {
|
||||||
final address = output["scriptPubKey"]["addresses"][0] as String;
|
String address = output["scriptPubKey"]["addresses"][0] as String;
|
||||||
|
if (Bitbox.Address.detectFormat(address) == 0) {
|
||||||
|
address = Bitbox.Address.toLegacyAddress(address);
|
||||||
|
}
|
||||||
if (!addressTxid.containsKey(address)) {
|
if (!addressTxid.containsKey(address)) {
|
||||||
addressTxid[address] = <String>[];
|
addressTxid[address] = <String>[];
|
||||||
}
|
}
|
||||||
|
@ -2772,8 +2813,13 @@ class BitcoinCashWallet extends CoinServiceAPI {
|
||||||
derivePathType: DerivePathType.bip44,
|
derivePathType: DerivePathType.bip44,
|
||||||
);
|
);
|
||||||
for (int i = 0; i < p2pkhLength; i++) {
|
for (int i = 0; i < p2pkhLength; i++) {
|
||||||
|
String address = addressesP2PKH[i];
|
||||||
|
if (Bitbox.Address.detectFormat(address) == 0) {
|
||||||
|
address = Bitbox.Address.toLegacyAddress(address);
|
||||||
|
}
|
||||||
|
|
||||||
// receives
|
// receives
|
||||||
final receiveDerivation = receiveDerivations[addressesP2PKH[i]];
|
final receiveDerivation = receiveDerivations[address];
|
||||||
// if a match exists it will not be null
|
// if a match exists it will not be null
|
||||||
if (receiveDerivation != null) {
|
if (receiveDerivation != null) {
|
||||||
final data = P2PKH(
|
final data = P2PKH(
|
||||||
|
@ -2783,7 +2829,7 @@ class BitcoinCashWallet extends CoinServiceAPI {
|
||||||
network: _network,
|
network: _network,
|
||||||
).data;
|
).data;
|
||||||
|
|
||||||
for (String tx in addressTxid[addressesP2PKH[i]]!) {
|
for (String tx in addressTxid[address]!) {
|
||||||
results[tx] = {
|
results[tx] = {
|
||||||
"output": data.output,
|
"output": data.output,
|
||||||
"keyPair": ECPair.fromWIF(
|
"keyPair": ECPair.fromWIF(
|
||||||
|
@ -2794,7 +2840,7 @@ class BitcoinCashWallet extends CoinServiceAPI {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if its not a receive, check change
|
// if its not a receive, check change
|
||||||
final changeDerivation = changeDerivations[addressesP2PKH[i]];
|
final changeDerivation = changeDerivations[address];
|
||||||
// if a match exists it will not be null
|
// if a match exists it will not be null
|
||||||
if (changeDerivation != null) {
|
if (changeDerivation != null) {
|
||||||
final data = P2PKH(
|
final data = P2PKH(
|
||||||
|
@ -2804,7 +2850,7 @@ class BitcoinCashWallet extends CoinServiceAPI {
|
||||||
network: _network,
|
network: _network,
|
||||||
).data;
|
).data;
|
||||||
|
|
||||||
for (String tx in addressTxid[addressesP2PKH[i]]!) {
|
for (String tx in addressTxid[address]!) {
|
||||||
results[tx] = {
|
results[tx] = {
|
||||||
"output": data.output,
|
"output": data.output,
|
||||||
"keyPair": ECPair.fromWIF(
|
"keyPair": ECPair.fromWIF(
|
||||||
|
@ -3377,8 +3423,9 @@ class BitcoinCashWallet extends CoinServiceAPI {
|
||||||
0,
|
0,
|
||||||
DerivePathType
|
DerivePathType
|
||||||
.bip44); // Add that new receiving address to the array of receiving addresses
|
.bip44); // Add that new receiving address to the array of receiving addresses
|
||||||
_currentReceivingAddressP2PKH = Future(() =>
|
var newaddr = await _getCurrentAddressForChain(0, DerivePathType.bip44);
|
||||||
newReceivingAddress); // Set the new receiving address that the service
|
_currentReceivingAddressP2PKH = Future(
|
||||||
|
() => newaddr); // Set the new receiving address that the service
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
|
|
|
@ -1990,7 +1990,6 @@ class EpicCashWallet extends CoinServiceAPI {
|
||||||
|
|
||||||
Future<bool> refreshIfThereIsNewData() async {
|
Future<bool> refreshIfThereIsNewData() async {
|
||||||
if (_hasCalledExit) return false;
|
if (_hasCalledExit) return false;
|
||||||
Logging.instance.log("Can we do this here?", level: LogLevel.Fatal);
|
|
||||||
// TODO returning true here signals this class to call refresh() after which it will fire an event that notifies the UI that new data has been fetched/found for this wallet
|
// TODO returning true here signals this class to call refresh() after which it will fire an event that notifies the UI that new data has been fetched/found for this wallet
|
||||||
return true;
|
return true;
|
||||||
// TODO: do a quick check to see if there is any new data that would require a refresh
|
// TODO: do a quick check to see if there is any new data that would require a refresh
|
||||||
|
|
|
@ -39,6 +39,19 @@ class NodeService extends ChangeNotifier {
|
||||||
key: savedNode.id,
|
key: savedNode.id,
|
||||||
value: defaultNode.copyWith(enabled: savedNode.enabled));
|
value: defaultNode.copyWith(enabled: savedNode.enabled));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if a default node is the primary node for the crypto currency
|
||||||
|
// and update it if needed
|
||||||
|
final coin = coinFromPrettyName(defaultNode.coinName);
|
||||||
|
final primaryNode = getPrimaryNodeFor(coin: coin);
|
||||||
|
if (primaryNode != null && primaryNode.id == defaultNode.id) {
|
||||||
|
await setPrimaryNodeFor(
|
||||||
|
coin: coin,
|
||||||
|
node: defaultNode.copyWith(
|
||||||
|
enabled: primaryNode.enabled,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,12 +78,12 @@ class PriceAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
final externalCalls = Prefs.instance.externalCalls;
|
final externalCalls = Prefs.instance.externalCalls;
|
||||||
if (!Logger.isTestEnv && !externalCalls) {
|
if ((!Logger.isTestEnv && !externalCalls) ||
|
||||||
|
!(await Prefs.instance.isExternalCallsSet())) {
|
||||||
Logging.instance.log("User does not want to use external calls",
|
Logging.instance.log("User does not want to use external calls",
|
||||||
level: LogLevel.Info);
|
level: LogLevel.Info);
|
||||||
return _cachedPrices;
|
return _cachedPrices;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Coin, Tuple2<Decimal, double>> result = {};
|
Map<Coin, Tuple2<Decimal, double>> result = {};
|
||||||
try {
|
try {
|
||||||
final uri = Uri.parse(
|
final uri = Uri.parse(
|
||||||
|
@ -123,7 +123,8 @@ class PriceAPI {
|
||||||
|
|
||||||
static Future<List<String>?> availableBaseCurrencies() async {
|
static Future<List<String>?> availableBaseCurrencies() async {
|
||||||
final externalCalls = Prefs.instance.externalCalls;
|
final externalCalls = Prefs.instance.externalCalls;
|
||||||
if (!Logger.isTestEnv && !externalCalls) {
|
if ((!Logger.isTestEnv && !externalCalls) ||
|
||||||
|
!(await Prefs.instance.isExternalCallsSet())) {
|
||||||
Logging.instance.log("User does not want to use external calls",
|
Logging.instance.log("User does not want to use external calls",
|
||||||
level: LogLevel.Info);
|
level: LogLevel.Info);
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -36,7 +36,7 @@ abstract class Constants {
|
||||||
// Enable Logger.print statements
|
// Enable Logger.print statements
|
||||||
static const bool disableLogger = false;
|
static const bool disableLogger = false;
|
||||||
|
|
||||||
static const int currentHiveDbVersion = 2;
|
static const int currentHiveDbVersion = 3;
|
||||||
|
|
||||||
static List<int> possibleLengthsForCoin(Coin coin) {
|
static List<int> possibleLengthsForCoin(Coin coin) {
|
||||||
final List<int> values = [];
|
final List<int> values = [];
|
||||||
|
|
|
@ -143,6 +143,18 @@ class DbVersionMigrator {
|
||||||
|
|
||||||
// try to continue migrating
|
// try to continue migrating
|
||||||
return await migrate(2);
|
return await migrate(2);
|
||||||
|
case 2:
|
||||||
|
await Hive.openBox<dynamic>(DB.boxNamePrefs);
|
||||||
|
final prefs = Prefs.instance;
|
||||||
|
await prefs.init();
|
||||||
|
if (!(await prefs.isExternalCallsSet())) {
|
||||||
|
prefs.externalCalls = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update version
|
||||||
|
await DB.instance.put<dynamic>(
|
||||||
|
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 3);
|
||||||
|
return await migrate(3);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// finally return
|
// finally return
|
||||||
|
|
|
@ -70,28 +70,24 @@ abstract class DefaultNodes {
|
||||||
isDown: false,
|
isDown: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: eventually enable ssl and set scheme to https
|
|
||||||
// currently get certificate failure
|
|
||||||
static NodeModel get monero => NodeModel(
|
static NodeModel get monero => NodeModel(
|
||||||
host: "http://monero.stackwallet.com",
|
host: "https://monero.stackwallet.com",
|
||||||
port: 18081,
|
port: 18081,
|
||||||
name: defaultName,
|
name: defaultName,
|
||||||
id: _nodeId(Coin.monero),
|
id: _nodeId(Coin.monero),
|
||||||
useSSL: false,
|
useSSL: true,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
coinName: Coin.monero.name,
|
coinName: Coin.monero.name,
|
||||||
isFailover: true,
|
isFailover: true,
|
||||||
isDown: false,
|
isDown: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: eventually enable ssl and set scheme to https
|
|
||||||
// currently get certificate failure
|
|
||||||
static NodeModel get wownero => NodeModel(
|
static NodeModel get wownero => NodeModel(
|
||||||
host: "http://eu-west-2.wow.xmr.pm",
|
host: "https://wownero.stackwallet.com",
|
||||||
port: 34568,
|
port: 34568,
|
||||||
name: defaultName,
|
name: defaultName,
|
||||||
id: _nodeId(Coin.wownero),
|
id: _nodeId(Coin.wownero),
|
||||||
useSSL: false,
|
useSSL: true,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
coinName: Coin.wownero.name,
|
coinName: Coin.wownero.name,
|
||||||
isFailover: true,
|
isFailover: true,
|
||||||
|
|
|
@ -181,25 +181,32 @@ Coin coinFromPrettyName(String name) {
|
||||||
case "Bitcoin":
|
case "Bitcoin":
|
||||||
case "bitcoin":
|
case "bitcoin":
|
||||||
return Coin.bitcoin;
|
return Coin.bitcoin;
|
||||||
|
|
||||||
case "Bitcoincash":
|
case "Bitcoincash":
|
||||||
case "bitcoincash":
|
case "bitcoincash":
|
||||||
case "Bitcoin Cash":
|
case "Bitcoin Cash":
|
||||||
return Coin.bitcoincash;
|
return Coin.bitcoincash;
|
||||||
|
|
||||||
case "Dogecoin":
|
case "Dogecoin":
|
||||||
case "dogecoin":
|
case "dogecoin":
|
||||||
return Coin.dogecoin;
|
return Coin.dogecoin;
|
||||||
|
|
||||||
case "Epic Cash":
|
case "Epic Cash":
|
||||||
case "epicCash":
|
case "epicCash":
|
||||||
return Coin.epicCash;
|
return Coin.epicCash;
|
||||||
|
|
||||||
case "Firo":
|
case "Firo":
|
||||||
case "firo":
|
case "firo":
|
||||||
return Coin.firo;
|
return Coin.firo;
|
||||||
|
|
||||||
case "Monero":
|
case "Monero":
|
||||||
case "monero":
|
case "monero":
|
||||||
return Coin.monero;
|
return Coin.monero;
|
||||||
|
|
||||||
case "Namecoin":
|
case "Namecoin":
|
||||||
case "namecoin":
|
case "namecoin":
|
||||||
return Coin.namecoin;
|
return Coin.namecoin;
|
||||||
|
|
||||||
case "Bitcoin Testnet":
|
case "Bitcoin Testnet":
|
||||||
case "tBitcoin":
|
case "tBitcoin":
|
||||||
case "bitcoinTestNet":
|
case "bitcoinTestNet":
|
||||||
|
@ -208,19 +215,24 @@ Coin coinFromPrettyName(String name) {
|
||||||
case "Bitcoincash Testnet":
|
case "Bitcoincash Testnet":
|
||||||
case "tBitcoin Cash":
|
case "tBitcoin Cash":
|
||||||
case "Bitcoin Cash Testnet":
|
case "Bitcoin Cash Testnet":
|
||||||
|
case "bitcoincashTestnet":
|
||||||
return Coin.bitcoincashTestnet;
|
return Coin.bitcoincashTestnet;
|
||||||
|
|
||||||
case "Firo Testnet":
|
case "Firo Testnet":
|
||||||
case "tFiro":
|
case "tFiro":
|
||||||
case "firoTestNet":
|
case "firoTestNet":
|
||||||
return Coin.firoTestNet;
|
return Coin.firoTestNet;
|
||||||
|
|
||||||
case "Dogecoin Testnet":
|
case "Dogecoin Testnet":
|
||||||
case "tDogecoin":
|
case "tDogecoin":
|
||||||
case "dogecoinTestNet":
|
case "dogecoinTestNet":
|
||||||
return Coin.dogecoinTestNet;
|
return Coin.dogecoinTestNet;
|
||||||
|
|
||||||
case "Wownero":
|
case "Wownero":
|
||||||
case "tWownero":
|
case "tWownero":
|
||||||
case "wownero":
|
case "wownero":
|
||||||
return Coin.wownero;
|
return Coin.wownero;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw ArgumentError.value(
|
throw ArgumentError.value(
|
||||||
name, "name", "No Coin enum value with that prettyName");
|
name, "name", "No Coin enum value with that prettyName");
|
||||||
|
|
|
@ -571,4 +571,13 @@ class Prefs extends ChangeNotifier {
|
||||||
boxName: DB.boxNamePrefs, key: "externalCalls") as bool? ??
|
boxName: DB.boxNamePrefs, key: "externalCalls") as bool? ??
|
||||||
true;
|
true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> isExternalCallsSet() async {
|
||||||
|
if (await DB.instance
|
||||||
|
.get<dynamic>(boxName: DB.boxNamePrefs, key: "externalCalls") ==
|
||||||
|
null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -306,10 +306,10 @@ class NodeOptionsSheet extends ConsumerWidget {
|
||||||
style: status == "Connected"
|
style: status == "Connected"
|
||||||
? Theme.of(context)
|
? Theme.of(context)
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
.getPrimaryEnabledButtonColor(context)
|
.getPrimaryDisabledButtonColor(context)
|
||||||
: Theme.of(context)
|
: Theme.of(context)
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
.getPrimaryDisabledButtonColor(context),
|
.getPrimaryEnabledButtonColor(context),
|
||||||
onPressed: status == "Connected"
|
onPressed: status == "Connected"
|
||||||
? null
|
? null
|
||||||
: () async {
|
: () async {
|
||||||
|
|
|
@ -11,7 +11,7 @@ description: Stack Wallet
|
||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 1.5.8+78
|
version: 1.5.9+79
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.17.0 <3.0.0"
|
sdk: ">=2.17.0 <3.0.0"
|
||||||
|
|
|
@ -16,6 +16,9 @@ void main() {
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
await setUpTestHive();
|
await setUpTestHive();
|
||||||
await Hive.openBox<dynamic>(DB.boxNamePriceCache);
|
await Hive.openBox<dynamic>(DB.boxNamePriceCache);
|
||||||
|
await Hive.openBox<dynamic>(DB.boxNamePrefs);
|
||||||
|
await DB.instance.put<dynamic>(
|
||||||
|
boxName: DB.boxNamePrefs, key: "externalCalls", value: true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("getPricesAnd24hChange fetch", () async {
|
test("getPricesAnd24hChange fetch", () async {
|
||||||
|
|
|
@ -26,7 +26,7 @@ import 'bitcoincash_wallet_test_parameters.dart';
|
||||||
void main() {
|
void main() {
|
||||||
group("bitcoincash constants", () {
|
group("bitcoincash constants", () {
|
||||||
test("bitcoincash minimum confirmations", () async {
|
test("bitcoincash minimum confirmations", () async {
|
||||||
expect(MINIMUM_CONFIRMATIONS, 3);
|
expect(MINIMUM_CONFIRMATIONS, 1);
|
||||||
});
|
});
|
||||||
test("bitcoincash dust limit", () async {
|
test("bitcoincash dust limit", () async {
|
||||||
expect(DUST_LIMIT, 546);
|
expect(DUST_LIMIT, 546);
|
||||||
|
@ -831,18 +831,9 @@ void main() {
|
||||||
|
|
||||||
await bch?.initializeNew();
|
await bch?.initializeNew();
|
||||||
await bch?.initializeExisting();
|
await bch?.initializeExisting();
|
||||||
expect(
|
expect(bch?.validateAddress(await bch!.currentReceivingAddress), true);
|
||||||
Address.validateAddress(
|
expect(bch?.validateAddress(await bch!.currentReceivingAddress), true);
|
||||||
await bch!.currentReceivingAddress, bitcoincashtestnet),
|
expect(bch?.validateAddress(await bch!.currentReceivingAddress), true);
|
||||||
true);
|
|
||||||
expect(
|
|
||||||
Address.validateAddress(
|
|
||||||
await bch!.currentReceivingAddress, bitcoincashtestnet),
|
|
||||||
true);
|
|
||||||
expect(
|
|
||||||
Address.validateAddress(
|
|
||||||
await bch!.currentReceivingAddress, bitcoincashtestnet),
|
|
||||||
true);
|
|
||||||
|
|
||||||
verifyNever(client?.ping()).called(0);
|
verifyNever(client?.ping()).called(0);
|
||||||
verify(client?.getServerFeatures()).called(1);
|
verify(client?.getServerFeatures()).called(1);
|
||||||
|
@ -884,8 +875,7 @@ void main() {
|
||||||
expect(addresses?.length, 2);
|
expect(addresses?.length, 2);
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
expect(
|
expect(bch?.validateAddress(addresses![i]), true);
|
||||||
Address.validateAddress(addresses![i], bitcoincashtestnet), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
verifyNever(client?.ping()).called(0);
|
verifyNever(client?.ping()).called(0);
|
||||||
|
|
Loading…
Reference in a new issue