Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Performance improvements #627

Draft
wants to merge 9 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 82 additions & 52 deletions integration_test/migration_test.dart

Large diffs are not rendered by default.

42 changes: 18 additions & 24 deletions lib/app/service/assets_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -148,31 +148,25 @@ class AssetsService {
/// This stream listens for contracts from storage and load contracts if
/// needed or return it from storage.
Stream<List<TokenContractAsset>> contractsForAccount(Address address) {
return nekotonRepository.currentTransportStream.flatMap((transport) {
return Rx.combineLatest2<List<TokenContractAsset>, KeyAccount?,
KeyAccount?>(
return nekotonRepository.currentTransportStream.switchMap((transport) {
return Rx.combineLatest2(
contractsStream,
nekotonRepository.seedListStream
.map((list) => list.findAccountByAddress(address)),
nekotonRepository.seedListStream.map(
(list) => list.findAccountByAddress(address),
),
// we ignore result of contracts, this needed just to trigger updating
(a, c) => c,
).asyncExpand((account) {
final wallets =
account?.additionalAssets[transport.transport.group]?.tokenWallets;
final group = transport.transport.group;
final wallets = account?.additionalAssets[group]?.tokenWallets;
if (wallets == null) return Stream.value([]);

return Stream.fromFuture(
Future.value(
() async {
return (await Future.wait(
wallets.map(
(e) => getTokenContractAsset(e.rootTokenContract, transport),
),
))
.whereNotNull()
.toList();
}(),
),
Future.wait(
wallets.map(
(e) => getTokenContractAsset(e.rootTokenContract, transport),
),
).then((e) => e.whereNotNull().toList()),
);
});
});
Expand Down Expand Up @@ -213,7 +207,7 @@ class AssetsService {
isCustom: true,
);

await storage.addCustomTokenContractAsset(asset);
storage.addCustomTokenContractAsset(asset);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Без await ошибка пройдет мимо catch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Функция синхронная


return asset;
} catch (e, st) {
Expand Down Expand Up @@ -263,30 +257,30 @@ class AssetsService {

final manifest = TonAssetsManifest.fromJson(decoded);

await storage.updateSystemTokenContractAssets(manifest.tokens);
storage.updateSystemTokenContractAssets(manifest.tokens);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

И тут.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

И тут

} catch (e, st) {
_logger.severe('_updateSystemContracts', e, st);
}
}

/// Listen for changing contracts and remove old tokens and remove duplicated
/// tokens that could be moved from custom to system.
Future<void> _contractsUpdateListener(
void _contractsUpdateListener(
List<TokenContractAsset> systemAssets,
List<TokenContractAsset> customAssets,
) async {
) {
final duplicatedAssets = customAssets
.where((e) => systemAssets.any((el) => e.address == el.address));

for (final asset in duplicatedAssets) {
await storage.removeCustomTokenContractAsset(asset);
storage.removeCustomTokenContractAsset(asset);
}

final oldAssets =
customAssets.where((e) => e.version == TokenWalletVersion.oldTip3v4);

for (final asset in oldAssets) {
await storage.removeCustomTokenContractAsset(asset);
storage.removeCustomTokenContractAsset(asset);
}
}
}
102 changes: 54 additions & 48 deletions lib/app/service/balance_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -128,37 +128,40 @@ class BalanceService {
/// To listen TokenWallet, use [tokenWalletBalanceStream].
Stream<Fixed> tonWalletBalanceStream(Address address) {
return Rx.combineLatest2<TonWalletState?, TransportStrategy,
(TonWalletState?, TransportStrategy)>(
(TonWalletState?, TransportStrategy)>(
// subscribe for wallet appearing, because it can happens later
nekotonRepository.walletsStream
.map((list) => list.firstWhereOrNull((w) => w.address == address)),
nekotonRepository.currentTransportStream, (a, b) => (a, b),
).flatMap((value) {
final wallet = value.$1?.wallet;
final transport = value.$2;

if (wallet == null) return Stream.value(Fixed.zero);

return Rx.combineLatest2<BigInt, CustomCurrency?, Fixed>(
wallet.fieldUpdatesStream.map((_) => wallet.contractState.balance),
currenciesService.currenciesStream(transport.networkType).map(
(curs) => curs.firstWhereOrNull(
(cur) => cur.address == transport.nativeTokenAddress,
),
),
(a, b) => b != null
? Fixed.fromBigInt(
a,
scale: transport.defaultNativeCurrencyDecimal,
) *
Fixed.parse(b.price)
: Fixed.zero,
);
}).onErrorReturnWith((e, st) {
_logger.severe('tonWalletBalanceStream', e, st);
)
.switchMap((value) {
final wallet = value.$1?.wallet;
final transport = value.$2;

if (wallet == null) return Stream.value(null);

return Rx.combineLatest2<BigInt, CustomCurrency?, Fixed>(
wallet.fieldUpdatesStream.map((_) => wallet.contractState.balance),
currenciesService.currenciesStream(transport.networkType).map(
(curs) => curs.firstWhereOrNull(
(cur) => cur.address == transport.nativeTokenAddress,
),
),
(a, b) => b != null
? Fixed.fromBigInt(
a,
scale: transport.defaultNativeCurrencyDecimal,
) *
Fixed.parse(b.price)
: Fixed.zero,
);
})
.whereNotNull()
.onErrorReturnWith((e, st) {
_logger.severe('tonWalletBalanceStream', e, st);

return Fixed.zero;
});
return Fixed.zero;
});
}

/// Returns stream which emits balance of TokenWallet with [owner] and
Expand All @@ -171,7 +174,7 @@ class BalanceService {
required Address rootTokenContract,
}) {
return Rx.combineLatest2<TokenWalletState?, TransportStrategy,
(TokenWalletState?, TransportStrategy)>(
(TokenWalletState?, TransportStrategy)>(
// subscribe for wallet appearing, because it can happens later
nekotonRepository.tokenWalletsStream.map(
(list) => list.firstWhereOrNull(
Expand All @@ -180,28 +183,31 @@ class BalanceService {
),
nekotonRepository.currentTransportStream,
(a, b) => (a, b),
).flatMap((value) {
final wallet = value.$1?.wallet;
final transport = value.$2;

if (wallet == null) return Stream.value(Fixed.zero);

return Rx.combineLatest2<Money?, CustomCurrency?, Fixed>(
wallet.onMoneyBalanceChangedStream,
currenciesService.currenciesStream(transport.networkType).map(
(curs) => curs.firstWhereOrNull(
(cur) => cur.address == rootTokenContract,
),
),
(a, b) => b != null && a != null
? a.amount * Fixed.parse(b.price)
: Fixed.zero,
);
}).onErrorReturnWith((e, st) {
_logger.severe('tokenWalletBalanceStream', e, st);
)
.switchMap((value) {
final wallet = value.$1?.wallet;
final transport = value.$2;

if (wallet == null) return Stream.value(null);

return Rx.combineLatest2<Money?, CustomCurrency?, Fixed>(
wallet.onMoneyBalanceChangedStream,
currenciesService.currenciesStream(transport.networkType).map(
(curs) => curs.firstWhereOrNull(
(cur) => cur.address == rootTokenContract,
),
),
(a, b) => b != null && a != null
? a.amount * Fixed.parse(b.price)
: Fixed.zero,
);
})
.whereNotNull()
.onErrorReturnWith((e, st) {
_logger.severe('tokenWalletBalanceStream', e, st);

return Fixed.zero;
});
return Fixed.zero;
});
}

/// Get balance of public key and all related Ton/Token wallets of it without
Expand Down
15 changes: 9 additions & 6 deletions lib/app/service/biometry_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ class BiometryPasswordNotStoredException implements Exception {}
/// Service that helps reading/updating biometry settings.
@singleton
class BiometryService {
BiometryService(this.storage, this.appLifecycleService);
BiometryService(this.storage, this.secureStorage, this.appLifecycleService);

final GeneralStorageService storage;
final SecureStorageService secureStorage;
final AppLifecycleService appLifecycleService;

final _localAuth = LocalAuthentication();
Expand Down Expand Up @@ -66,7 +67,9 @@ class BiometryService {
.listen((e) => storage.setIsBiometryEnabled(isEnabled: e));

// clear all passwords if biometry was disabled
enabledStream.where((e) => !e).listen((e) => storage.clearKeyPasswords());
enabledStream
.where((e) => !e)
.listen((e) => secureStorage.clearKeyPasswords());
}

/// On iOS checks face id permission and opens system setting if permission
Expand Down Expand Up @@ -109,7 +112,7 @@ class BiometryService {
// if user want enable biometry - ask auth.
try {
if (!isEnabled || isEnabled && await _authenticate(localizedReason)) {
await storage.setIsBiometryEnabled(isEnabled: isEnabled);
storage.setIsBiometryEnabled(isEnabled: isEnabled);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

И тут тоже

}
} catch (_) {}
}
Expand All @@ -123,7 +126,7 @@ class BiometryService {
required String password,
}) async {
if (available) {
return storage.setKeyPassword(
return secureStorage.setKeyPassword(
publicKey: publicKey,
password: password,
);
Expand All @@ -137,7 +140,7 @@ class BiometryService {
required String localizedReason,
required PublicKey publicKey,
}) async {
final password = await storage.getKeyPassword(publicKey);
final password = await secureStorage.getKeyPassword(publicKey);

if (password != null) {
if (await _authenticate(localizedReason)) {
Expand All @@ -153,7 +156,7 @@ class BiometryService {
/// Check if password of [publicKey] was stored before.
Future<bool> hasKeyPassword(PublicKey publicKey) async {
try {
final password = await storage.getKeyPassword(publicKey);
final password = await secureStorage.getKeyPassword(publicKey);
return password != null;
} catch (_) {
return false;
Expand Down
Loading
Loading