mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-23 11:59:30 +00:00
nano clean up and optimisations
This commit is contained in:
parent
91d330e57b
commit
3275039d01
1 changed files with 126 additions and 66 deletions
|
@ -8,41 +8,35 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:nanodart/nanodart.dart';
|
import 'package:nanodart/nanodart.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:stackwallet/db/isar/main_db.dart';
|
||||||
|
|
||||||
import 'package:stackwallet/models/balance.dart';
|
import 'package:stackwallet/models/balance.dart';
|
||||||
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
|
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||||
import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart';
|
import 'package:stackwallet/models/node_model.dart';
|
||||||
import 'package:stackwallet/models/paymint/fee_object_model.dart';
|
import 'package:stackwallet/models/paymint/fee_object_model.dart';
|
||||||
import 'package:stackwallet/services/coins/coin_service.dart';
|
import 'package:stackwallet/services/coins/coin_service.dart';
|
||||||
|
import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart';
|
||||||
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
|
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
|
||||||
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
|
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
|
||||||
import 'package:stackwallet/services/mixins/coin_control_interface.dart';
|
import 'package:stackwallet/services/mixins/coin_control_interface.dart';
|
||||||
import 'package:stackwallet/services/mixins/wallet_cache.dart';
|
import 'package:stackwallet/services/mixins/wallet_cache.dart';
|
||||||
import 'package:stackwallet/services/mixins/wallet_db.dart';
|
import 'package:stackwallet/services/mixins/wallet_db.dart';
|
||||||
|
import 'package:stackwallet/services/node_service.dart';
|
||||||
|
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||||
|
import 'package:stackwallet/utilities/constants.dart';
|
||||||
|
import 'package:stackwallet/utilities/default_nodes.dart';
|
||||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
import 'package:stackwallet/utilities/enums/log_level_enum.dart';
|
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
|
||||||
import 'package:stackwallet/utilities/logger.dart';
|
import 'package:stackwallet/utilities/logger.dart';
|
||||||
|
import 'package:stackwallet/utilities/prefs.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
|
|
||||||
import '../../../db/isar/main_db.dart';
|
|
||||||
import '../../../models/isar/models/blockchain_data/address.dart';
|
|
||||||
import '../../../models/node_model.dart';
|
|
||||||
import '../../../utilities/default_nodes.dart';
|
|
||||||
import '../../../utilities/flutter_secure_storage_interface.dart';
|
|
||||||
import '../../../utilities/prefs.dart';
|
|
||||||
import '../../node_service.dart';
|
|
||||||
import '../../transaction_notification_tracker.dart';
|
|
||||||
|
|
||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
|
||||||
|
|
||||||
const int MINIMUM_CONFIRMATIONS = 1;
|
const int MINIMUM_CONFIRMATIONS = 1;
|
||||||
const String DEFAULT_REPRESENTATIVE =
|
const String DEFAULT_REPRESENTATIVE =
|
||||||
"nano_38713x95zyjsqzx6nm1dsom1jmm668owkeb9913ax6nfgj15az3nu8xkx579";
|
"nano_38713x95zyjsqzx6nm1dsom1jmm668owkeb9913ax6nfgj15az3nu8xkx579";
|
||||||
|
@ -135,13 +129,26 @@ class NanoWallet extends CoinServiceAPI
|
||||||
late final TransactionNotificationTracker txTracker;
|
late final TransactionNotificationTracker txTracker;
|
||||||
final _prefs = Prefs.instance;
|
final _prefs = Prefs.instance;
|
||||||
|
|
||||||
|
Timer? timer;
|
||||||
bool _shouldAutoSync = false;
|
bool _shouldAutoSync = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool get shouldAutoSync => _shouldAutoSync;
|
bool get shouldAutoSync => _shouldAutoSync;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
set shouldAutoSync(bool shouldAutoSync) => _shouldAutoSync = shouldAutoSync;
|
set shouldAutoSync(bool shouldAutoSync) {
|
||||||
|
if (_shouldAutoSync != shouldAutoSync) {
|
||||||
|
_shouldAutoSync = shouldAutoSync;
|
||||||
|
if (!shouldAutoSync) {
|
||||||
|
timer?.cancel();
|
||||||
|
timer = null;
|
||||||
|
stopNetworkAlivePinging();
|
||||||
|
} else {
|
||||||
|
startNetworkAlivePinging();
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Balance get balance => _balance ??= getCachedBalance();
|
Balance get balance => _balance ??= getCachedBalance();
|
||||||
|
@ -177,7 +184,7 @@ class NanoWallet extends CoinServiceAPI
|
||||||
Future<String> confirmSend({required Map<String, dynamic> txData}) async {
|
Future<String> confirmSend({required Map<String, dynamic> txData}) async {
|
||||||
try {
|
try {
|
||||||
// our address:
|
// our address:
|
||||||
final String publicAddress = await getAddressFromMnemonic();
|
final String publicAddress = await currentReceivingAddress;
|
||||||
|
|
||||||
// first get the account balance:
|
// first get the account balance:
|
||||||
final balanceBody = jsonEncode({
|
final balanceBody = jsonEncode({
|
||||||
|
@ -279,8 +286,18 @@ class NanoWallet extends CoinServiceAPI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Address?> get _currentReceivingAddress => db
|
||||||
|
.getAddresses(walletId)
|
||||||
|
.filter()
|
||||||
|
.typeEqualTo(AddressType.nano)
|
||||||
|
.and()
|
||||||
|
.subTypeEqualTo(AddressSubType.receiving)
|
||||||
|
.sortByDerivationIndexDesc()
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String> get currentReceivingAddress => getAddressFromMnemonic();
|
Future<String> get currentReceivingAddress async =>
|
||||||
|
(await _currentReceivingAddress)?.value ?? await getAddressFromMnemonic();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Amount> estimateFeeFor(Amount amount, int feeRate) {
|
Future<Amount> estimateFeeFor(Amount amount, int feeRate) {
|
||||||
|
@ -295,13 +312,13 @@ class NanoWallet extends CoinServiceAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
// TODO: implement fees
|
// Nano has no fees
|
||||||
Future<FeeObject> get fees => throw UnimplementedError();
|
Future<FeeObject> get fees => throw UnimplementedError();
|
||||||
|
|
||||||
Future<void> updateBalance() async {
|
Future<void> updateBalance() async {
|
||||||
final body = jsonEncode({
|
final body = jsonEncode({
|
||||||
"action": "account_balance",
|
"action": "account_balance",
|
||||||
"account": await getAddressFromMnemonic(),
|
"account": await currentReceivingAddress,
|
||||||
});
|
});
|
||||||
final headers = {
|
final headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
@ -336,7 +353,7 @@ class NanoWallet extends CoinServiceAPI
|
||||||
};
|
};
|
||||||
|
|
||||||
// our address:
|
// our address:
|
||||||
final String publicAddress = await getAddressFromMnemonic();
|
final String publicAddress = await currentReceivingAddress;
|
||||||
|
|
||||||
// first check if the account is open:
|
// first check if the account is open:
|
||||||
// get the account info (we need the frontier and representative):
|
// get the account info (we need the frontier and representative):
|
||||||
|
@ -455,7 +472,7 @@ class NanoWallet extends CoinServiceAPI
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
"action": "receivable",
|
"action": "receivable",
|
||||||
"source": "true",
|
"source": "true",
|
||||||
"account": await getAddressFromMnemonic(),
|
"account": await currentReceivingAddress,
|
||||||
"count": "-1",
|
"count": "-1",
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -477,7 +494,8 @@ class NanoWallet extends CoinServiceAPI
|
||||||
|
|
||||||
Future<void> updateTransactions() async {
|
Future<void> updateTransactions() async {
|
||||||
await confirmAllReceivable();
|
await confirmAllReceivable();
|
||||||
final String publicAddress = await getAddressFromMnemonic();
|
final receivingAddress = (await _currentReceivingAddress)!;
|
||||||
|
final String publicAddress = receivingAddress.value;
|
||||||
final response = await http.post(Uri.parse(getCurrentNode().host),
|
final response = await http.post(Uri.parse(getCurrentNode().host),
|
||||||
headers: {"Content-Type": "application/json"},
|
headers: {"Content-Type": "application/json"},
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
|
@ -521,22 +539,19 @@ class NanoWallet extends CoinServiceAPI
|
||||||
inputs: [],
|
inputs: [],
|
||||||
outputs: [],
|
outputs: [],
|
||||||
nonce: 0,
|
nonce: 0,
|
||||||
|
numberOfMessages: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
Address address = Address(
|
Address address = transactionType == TransactionType.incoming
|
||||||
|
? receivingAddress
|
||||||
|
: Address(
|
||||||
walletId: walletId,
|
walletId: walletId,
|
||||||
publicKey: [],
|
publicKey: [],
|
||||||
value: transactionType == TransactionType.incoming
|
value: tx["account"].toString(),
|
||||||
? publicAddress
|
|
||||||
: tx["account"].toString(),
|
|
||||||
derivationIndex: 0,
|
derivationIndex: 0,
|
||||||
derivationPath: null,
|
derivationPath: null,
|
||||||
type: transactionType == TransactionType.incoming
|
type: AddressType.nano,
|
||||||
? AddressType.nonWallet
|
subType: AddressSubType.nonWallet,
|
||||||
: AddressType.nano,
|
|
||||||
subType: transactionType == TransactionType.incoming
|
|
||||||
? AddressSubType.receiving
|
|
||||||
: AddressSubType.nonWallet,
|
|
||||||
);
|
);
|
||||||
Tuple2<Transaction, Address> tuple = Tuple2(transaction, address);
|
Tuple2<Transaction, Address> tuple = Tuple2(transaction, address);
|
||||||
transactionList.add(tuple);
|
transactionList.add(tuple);
|
||||||
|
@ -550,7 +565,9 @@ class NanoWallet extends CoinServiceAPI
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> fullRescan(
|
Future<void> fullRescan(
|
||||||
int maxUnusedAddressGap, int maxNumberOfIndexesToCheck) async {
|
int maxUnusedAddressGap,
|
||||||
|
int maxNumberOfIndexesToCheck,
|
||||||
|
) async {
|
||||||
await _prefs.init();
|
await _prefs.init();
|
||||||
await updateTransactions();
|
await updateTransactions();
|
||||||
await updateBalance();
|
await updateBalance();
|
||||||
|
@ -592,23 +609,27 @@ class NanoWallet extends CoinServiceAPI
|
||||||
);
|
);
|
||||||
String privateKey = NanoKeys.seedToPrivate(seed, 0);
|
String privateKey = NanoKeys.seedToPrivate(seed, 0);
|
||||||
String publicKey = NanoKeys.createPublicKey(privateKey);
|
String publicKey = NanoKeys.createPublicKey(privateKey);
|
||||||
String publicAddress =
|
String publicAddress = NanoAccounts.createAccount(
|
||||||
NanoAccounts.createAccount(NanoAccountType.NANO, publicKey);
|
NanoAccountType.NANO,
|
||||||
|
publicKey,
|
||||||
|
);
|
||||||
|
|
||||||
final address = Address(
|
final address = Address(
|
||||||
walletId: walletId,
|
walletId: walletId,
|
||||||
value: publicAddress,
|
value: publicAddress,
|
||||||
publicKey: [], // TODO: add public key
|
publicKey: [],
|
||||||
derivationIndex: 0,
|
derivationIndex: 0,
|
||||||
derivationPath: null,
|
derivationPath: null,
|
||||||
type: AddressType.unknown,
|
type: AddressType.nano,
|
||||||
subType: AddressSubType.receiving,
|
subType: AddressSubType.receiving,
|
||||||
);
|
);
|
||||||
|
|
||||||
await db.putAddress(address);
|
await db.putAddress(address);
|
||||||
|
|
||||||
await Future.wait(
|
await Future.wait([
|
||||||
[updateCachedId(walletId), updateCachedIsFavorite(false)]);
|
updateCachedId(walletId),
|
||||||
|
updateCachedIsFavorite(false),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -643,20 +664,14 @@ class NanoWallet extends CoinServiceAPI
|
||||||
Map<String, dynamic>? args,
|
Map<String, dynamic>? args,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
int satAmount = amount.raw.toInt();
|
if (amount.decimals != coin.decimals) {
|
||||||
int realfee = 0;
|
throw ArgumentError("Nano prepareSend attempted with invalid Amount");
|
||||||
|
|
||||||
if (balance.spendable == amount) {
|
|
||||||
satAmount = balance.spendable.raw.toInt() - realfee;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> txData = {
|
Map<String, dynamic> txData = {
|
||||||
"fee": realfee,
|
"fee": 0,
|
||||||
"addresss": address,
|
"addresss": address,
|
||||||
"recipientAmt": Amount(
|
"recipientAmt": amount,
|
||||||
rawValue: BigInt.from(satAmount),
|
|
||||||
fractionDigits: coin.decimals,
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Logging.instance.log("prepare send: $txData", level: LogLevel.Info);
|
Logging.instance.log("prepare send: $txData", level: LogLevel.Info);
|
||||||
|
@ -696,17 +711,19 @@ class NanoWallet extends CoinServiceAPI
|
||||||
final address = Address(
|
final address = Address(
|
||||||
walletId: walletId,
|
walletId: walletId,
|
||||||
value: publicAddress,
|
value: publicAddress,
|
||||||
publicKey: [], // TODO: add public key
|
publicKey: [],
|
||||||
derivationIndex: 0,
|
derivationIndex: 0,
|
||||||
derivationPath: null,
|
derivationPath: null,
|
||||||
type: AddressType.unknown,
|
type: AddressType.nano,
|
||||||
subType: AddressSubType.receiving,
|
subType: AddressSubType.receiving,
|
||||||
);
|
);
|
||||||
|
|
||||||
await db.putAddress(address);
|
await db.putAddress(address);
|
||||||
|
|
||||||
await Future.wait(
|
await Future.wait([
|
||||||
[updateCachedId(walletId), updateCachedIsFavorite(false)]);
|
updateCachedId(walletId),
|
||||||
|
updateCachedIsFavorite(false),
|
||||||
|
]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
|
@ -769,6 +786,49 @@ class NanoWallet extends CoinServiceAPI
|
||||||
return Future.value(false);
|
return Future.value(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Timer? _networkAliveTimer;
|
||||||
|
|
||||||
|
void startNetworkAlivePinging() {
|
||||||
|
// call once on start right away
|
||||||
|
_periodicPingCheck();
|
||||||
|
|
||||||
|
// then periodically check
|
||||||
|
_networkAliveTimer = Timer.periodic(
|
||||||
|
Constants.networkAliveTimerDuration,
|
||||||
|
(_) async {
|
||||||
|
_periodicPingCheck();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _periodicPingCheck() async {
|
||||||
|
bool hasNetwork = await testNetworkConnection();
|
||||||
|
|
||||||
|
if (_isConnected != hasNetwork) {
|
||||||
|
NodeConnectionStatus status = hasNetwork
|
||||||
|
? NodeConnectionStatus.connected
|
||||||
|
: NodeConnectionStatus.disconnected;
|
||||||
|
|
||||||
|
GlobalEventBus.instance.fire(
|
||||||
|
NodeConnectionStatusChangedEvent(
|
||||||
|
status,
|
||||||
|
walletId,
|
||||||
|
coin,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
_isConnected = hasNetwork;
|
||||||
|
if (hasNetwork) {
|
||||||
|
unawaited(refresh());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopNetworkAlivePinging() {
|
||||||
|
_networkAliveTimer?.cancel();
|
||||||
|
_networkAliveTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<Transaction>> get transactions =>
|
Future<List<Transaction>> get transactions =>
|
||||||
db.getTransactions(walletId).findAll();
|
db.getTransactions(walletId).findAll();
|
||||||
|
@ -785,9 +845,9 @@ class NanoWallet extends CoinServiceAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> updateSentCachedTxData(Map<String, dynamic> txData) {
|
Future<void> updateSentCachedTxData(Map<String, dynamic> txData) async {
|
||||||
// TODO: implement updateSentCachedTxData
|
// not currently used for nano
|
||||||
throw UnimplementedError();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -800,7 +860,7 @@ class NanoWallet extends CoinServiceAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateChainHeight() async {
|
Future<void> updateChainHeight() async {
|
||||||
final String publicAddress = await getAddressFromMnemonic();
|
final String publicAddress = await currentReceivingAddress;
|
||||||
// first get the account balance:
|
// first get the account balance:
|
||||||
final infoBody = jsonEncode({
|
final infoBody = jsonEncode({
|
||||||
"action": "account_info",
|
"action": "account_info",
|
||||||
|
|
Loading…
Reference in a new issue