mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-18 16:44:32 +00:00
dirty
This commit is contained in:
parent
44fbab715a
commit
fec5f5883f
2 changed files with 117 additions and 39 deletions
|
@ -490,7 +490,15 @@ class ElectrumXClient {
|
||||||
command: 'server.ping',
|
command: 'server.ping',
|
||||||
requestTimeout: const Duration(seconds: 2),
|
requestTimeout: const Duration(seconds: 2),
|
||||||
retries: retryCount,
|
retries: retryCount,
|
||||||
).timeout(const Duration(seconds: 2)) as bool;
|
).timeout(
|
||||||
|
const Duration(seconds: 2),
|
||||||
|
onTimeout: () {
|
||||||
|
Logging.instance.log(
|
||||||
|
"ElectrumxClient.ping timed out with retryCount=$retryCount, host=$_host",
|
||||||
|
level: LogLevel.Debug,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
) as bool;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
|
|
|
@ -487,113 +487,9 @@ abstract class Wallet<T extends CryptoCurrency> {
|
||||||
|
|
||||||
// Should fire events
|
// Should fire events
|
||||||
Future<void> refresh() async {
|
Future<void> refresh() async {
|
||||||
// Awaiting this lock could be dangerous.
|
final refreshCompleter = Completer<void>();
|
||||||
// Since refresh is periodic (generally)
|
final future = refreshCompleter.future.then(
|
||||||
if (refreshMutex.isLocked) {
|
(_) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
final start = DateTime.now();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// this acquire should be almost instant due to above check.
|
|
||||||
// Slight possibility of race but should be irrelevant
|
|
||||||
await refreshMutex.acquire();
|
|
||||||
|
|
||||||
GlobalEventBus.instance.fire(
|
|
||||||
WalletSyncStatusChangedEvent(
|
|
||||||
WalletSyncStatus.syncing,
|
|
||||||
walletId,
|
|
||||||
cryptoCurrency,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// add some small buffer before making calls.
|
|
||||||
// this can probably be removed in the future but was added as a
|
|
||||||
// debugging feature
|
|
||||||
await Future<void>.delayed(const Duration(milliseconds: 300));
|
|
||||||
|
|
||||||
// TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided.
|
|
||||||
final Set<String> codesToCheck = {};
|
|
||||||
if (this is PaynymInterface) {
|
|
||||||
// isSegwit does not matter here at all
|
|
||||||
final myCode =
|
|
||||||
await (this as PaynymInterface).getPaymentCode(isSegwit: false);
|
|
||||||
|
|
||||||
final nym = await PaynymIsApi().nym(myCode.toString());
|
|
||||||
if (nym.value != null) {
|
|
||||||
for (final follower in nym.value!.followers) {
|
|
||||||
codesToCheck.add(follower.code);
|
|
||||||
}
|
|
||||||
for (final following in nym.value!.following) {
|
|
||||||
codesToCheck.add(following.code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.0, walletId));
|
|
||||||
await updateChainHeight();
|
|
||||||
|
|
||||||
if (this is BitcoinFrostWallet) {
|
|
||||||
await (this as BitcoinFrostWallet).lookAhead();
|
|
||||||
}
|
|
||||||
|
|
||||||
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.1, walletId));
|
|
||||||
|
|
||||||
// TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided.
|
|
||||||
if (this is MultiAddressInterface) {
|
|
||||||
if (info.otherData[WalletInfoKeys.reuseAddress] != true) {
|
|
||||||
await (this as MultiAddressInterface)
|
|
||||||
.checkReceivingAddressForTransactions();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.2, walletId));
|
|
||||||
|
|
||||||
// TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided.
|
|
||||||
if (this is MultiAddressInterface) {
|
|
||||||
await (this as MultiAddressInterface)
|
|
||||||
.checkChangeAddressForTransactions();
|
|
||||||
}
|
|
||||||
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.3, walletId));
|
|
||||||
if (this is SparkInterface) {
|
|
||||||
// this should be called before updateTransactions()
|
|
||||||
await (this as SparkInterface).refreshSparkData();
|
|
||||||
}
|
|
||||||
|
|
||||||
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.50, walletId));
|
|
||||||
final fetchFuture = updateTransactions();
|
|
||||||
final utxosRefreshFuture = updateUTXOs();
|
|
||||||
// if (currentHeight != storedHeight) {
|
|
||||||
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.60, walletId));
|
|
||||||
|
|
||||||
await utxosRefreshFuture;
|
|
||||||
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.70, walletId));
|
|
||||||
|
|
||||||
await fetchFuture;
|
|
||||||
|
|
||||||
// TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided.
|
|
||||||
if (this is PaynymInterface && codesToCheck.isNotEmpty) {
|
|
||||||
await (this as PaynymInterface)
|
|
||||||
.checkForNotificationTransactionsTo(codesToCheck);
|
|
||||||
// check utxos again for notification outputs
|
|
||||||
await updateUTXOs();
|
|
||||||
}
|
|
||||||
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.80, walletId));
|
|
||||||
|
|
||||||
// await getAllTxsToWatch();
|
|
||||||
|
|
||||||
// TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided.
|
|
||||||
if (this is LelantusInterface) {
|
|
||||||
if (info.otherData[WalletInfoKeys.enableLelantusScanning] as bool? ??
|
|
||||||
false) {
|
|
||||||
await (this as LelantusInterface).refreshLelantusData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.90, walletId));
|
|
||||||
|
|
||||||
await updateBalance();
|
|
||||||
|
|
||||||
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(1.0, walletId));
|
|
||||||
GlobalEventBus.instance.fire(
|
GlobalEventBus.instance.fire(
|
||||||
WalletSyncStatusChangedEvent(
|
WalletSyncStatusChangedEvent(
|
||||||
WalletSyncStatus.synced,
|
WalletSyncStatus.synced,
|
||||||
|
@ -616,7 +512,8 @@ abstract class Wallet<T extends CryptoCurrency> {
|
||||||
// }
|
// }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error, strace) {
|
},
|
||||||
|
onError: (Object error, StackTrace strace) {
|
||||||
GlobalEventBus.instance.fire(
|
GlobalEventBus.instance.fire(
|
||||||
NodeConnectionStatusChangedEvent(
|
NodeConnectionStatusChangedEvent(
|
||||||
NodeConnectionStatus.disconnected,
|
NodeConnectionStatus.disconnected,
|
||||||
|
@ -635,8 +532,181 @@ abstract class Wallet<T extends CryptoCurrency> {
|
||||||
"Caught exception in refreshWalletData(): $error\n$strace",
|
"Caught exception in refreshWalletData(): $error\n$strace",
|
||||||
level: LogLevel.Error,
|
level: LogLevel.Error,
|
||||||
);
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
unawaited(_refresh(refreshCompleter));
|
||||||
|
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should fire events
|
||||||
|
Future<void> _refresh(Completer<void> completer) async {
|
||||||
|
// Awaiting this lock could be dangerous.
|
||||||
|
// Since refresh is periodic (generally)
|
||||||
|
if (refreshMutex.isLocked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final start = DateTime.now();
|
||||||
|
|
||||||
|
bool tAlive = true;
|
||||||
|
final t = Timer.periodic(const Duration(seconds: 1), (timer) async {
|
||||||
|
if (tAlive) {
|
||||||
|
final pingSuccess = await pingCheck();
|
||||||
|
if (!pingSuccess) {
|
||||||
|
tAlive = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
timer.cancel();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
void _checkAlive() {
|
||||||
|
if (!tAlive) throw Exception("refresh alive ping failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// this acquire should be almost instant due to above check.
|
||||||
|
// Slight possibility of race but should be irrelevant
|
||||||
|
await refreshMutex.acquire();
|
||||||
|
|
||||||
|
GlobalEventBus.instance.fire(
|
||||||
|
WalletSyncStatusChangedEvent(
|
||||||
|
WalletSyncStatus.syncing,
|
||||||
|
walletId,
|
||||||
|
cryptoCurrency,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
_checkAlive();
|
||||||
|
|
||||||
|
// add some small buffer before making calls.
|
||||||
|
// this can probably be removed in the future but was added as a
|
||||||
|
// debugging feature
|
||||||
|
await Future<void>.delayed(const Duration(milliseconds: 300));
|
||||||
|
_checkAlive();
|
||||||
|
|
||||||
|
// TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided.
|
||||||
|
final Set<String> codesToCheck = {};
|
||||||
|
_checkAlive();
|
||||||
|
if (this is PaynymInterface) {
|
||||||
|
// isSegwit does not matter here at all
|
||||||
|
final myCode =
|
||||||
|
await (this as PaynymInterface).getPaymentCode(isSegwit: false);
|
||||||
|
_checkAlive();
|
||||||
|
|
||||||
|
final nym = await PaynymIsApi().nym(myCode.toString());
|
||||||
|
_checkAlive();
|
||||||
|
if (nym.value != null) {
|
||||||
|
for (final follower in nym.value!.followers) {
|
||||||
|
codesToCheck.add(follower.code);
|
||||||
|
}
|
||||||
|
_checkAlive();
|
||||||
|
for (final following in nym.value!.following) {
|
||||||
|
codesToCheck.add(following.code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_checkAlive();
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.0, walletId));
|
||||||
|
_checkAlive();
|
||||||
|
await updateChainHeight();
|
||||||
|
|
||||||
|
_checkAlive();
|
||||||
|
if (this is BitcoinFrostWallet) {
|
||||||
|
await (this as BitcoinFrostWallet).lookAhead();
|
||||||
|
}
|
||||||
|
_checkAlive();
|
||||||
|
|
||||||
|
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.1, walletId));
|
||||||
|
|
||||||
|
_checkAlive();
|
||||||
|
// TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided.
|
||||||
|
if (this is MultiAddressInterface) {
|
||||||
|
if (info.otherData[WalletInfoKeys.reuseAddress] != true) {
|
||||||
|
await (this as MultiAddressInterface)
|
||||||
|
.checkReceivingAddressForTransactions();
|
||||||
|
}
|
||||||
|
_checkAlive();
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.2, walletId));
|
||||||
|
_checkAlive();
|
||||||
|
|
||||||
|
// TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided.
|
||||||
|
if (this is MultiAddressInterface) {
|
||||||
|
await (this as MultiAddressInterface)
|
||||||
|
.checkChangeAddressForTransactions();
|
||||||
|
}
|
||||||
|
_checkAlive();
|
||||||
|
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.3, walletId));
|
||||||
|
if (this is SparkInterface) {
|
||||||
|
// this should be called before updateTransactions()
|
||||||
|
await (this as SparkInterface).refreshSparkData();
|
||||||
|
}
|
||||||
|
_checkAlive();
|
||||||
|
|
||||||
|
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.50, walletId));
|
||||||
|
_checkAlive();
|
||||||
|
final fetchFuture = updateTransactions();
|
||||||
|
_checkAlive();
|
||||||
|
final utxosRefreshFuture = updateUTXOs();
|
||||||
|
// if (currentHeight != storedHeight) {
|
||||||
|
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.60, walletId));
|
||||||
|
|
||||||
|
_checkAlive();
|
||||||
|
await utxosRefreshFuture;
|
||||||
|
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.70, walletId));
|
||||||
|
|
||||||
|
_checkAlive();
|
||||||
|
await fetchFuture;
|
||||||
|
|
||||||
|
// TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided.
|
||||||
|
if (this is PaynymInterface && codesToCheck.isNotEmpty) {
|
||||||
|
_checkAlive();
|
||||||
|
await (this as PaynymInterface)
|
||||||
|
.checkForNotificationTransactionsTo(codesToCheck);
|
||||||
|
// check utxos again for notification outputs
|
||||||
|
_checkAlive();
|
||||||
|
await updateUTXOs();
|
||||||
|
}
|
||||||
|
_checkAlive();
|
||||||
|
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.80, walletId));
|
||||||
|
|
||||||
|
// await getAllTxsToWatch();
|
||||||
|
_checkAlive();
|
||||||
|
|
||||||
|
// TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided.
|
||||||
|
if (this is LelantusInterface) {
|
||||||
|
if (info.otherData[WalletInfoKeys.enableLelantusScanning] as bool? ??
|
||||||
|
false) {
|
||||||
|
await (this as LelantusInterface).refreshLelantusData();
|
||||||
|
_checkAlive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.90, walletId));
|
||||||
|
|
||||||
|
_checkAlive();
|
||||||
|
await updateBalance();
|
||||||
|
|
||||||
|
_checkAlive();
|
||||||
|
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(1.0, walletId));
|
||||||
|
|
||||||
|
tAlive = false; // interrupt timer as its not needed anymore
|
||||||
|
|
||||||
|
completer.complete();
|
||||||
|
} catch (error, strace) {
|
||||||
|
completer.completeError(error, strace);
|
||||||
} finally {
|
} finally {
|
||||||
|
t.cancel();
|
||||||
refreshMutex.release();
|
refreshMutex.release();
|
||||||
|
if (!completer.isCompleted) {
|
||||||
|
completer.completeError(
|
||||||
|
"finally block hit before completer completed",
|
||||||
|
StackTrace.current,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Logging.instance.log(
|
Logging.instance.log(
|
||||||
"Refresh for "
|
"Refresh for "
|
||||||
|
|
Loading…
Reference in a new issue