Skip to content

Commit

Permalink
fix: subscribing for external wallets (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex-A4 authored Dec 6, 2023
1 parent 276f0c7 commit 077a776
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,15 @@ abstract class TonWalletRepository {
/// To update subscriptions after transport changed,
/// use [updateTransportSubscriptions].
///
/// The second value is [KeyAccount.isExternal] that allows to identify if
/// we should use [subscribe] or [subscribeByAddress].
///
/// This is a heavy operation that interacts with network, so this method
/// should not be called often.
///
/// !!! This method must be called from app side because repository does not
/// track current active accounts.
Future<void> updateSubscriptions(List<TonWalletAsset> assets);
Future<void> updateSubscriptions(List<(TonWalletAsset, bool)> assets);

/// Update subscriptions when transport changed.
/// To get new transport, [TransportRepository.currentTransport] should be
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ mixin TonWalletRepositoryImpl implements TonWalletRepository {
/// assets could be reused.
@protected
@visibleForTesting
List<TonWalletAsset>? lastUpdatedAssets;
List<(TonWalletAsset, bool)>? lastUpdatedAssets;

/// Subject that allows listening for wallets subscribing/unsubscribing
final _walletsSubject =
Expand Down Expand Up @@ -127,7 +127,7 @@ mixin TonWalletRepositoryImpl implements TonWalletRepository {
@override
Future<void> retrySubscriptions(Address address) async {
final asset =
lastUpdatedAssets?.firstWhereOrNull((e) => e.address == address);
lastUpdatedAssets?.firstWhereOrNull((e) => e.$1.address == address);

if (asset == null) {
walletsMap[address] = TonWalletState.error(
Expand Down Expand Up @@ -201,8 +201,8 @@ mixin TonWalletRepositoryImpl implements TonWalletRepository {
CancelableOperationAwaited<void>? _lastOperation;

@override
Future<void> updateSubscriptions(List<TonWalletAsset> assets) async {
final toSubscribe = <TonWalletAsset>[];
Future<void> updateSubscriptions(List<(TonWalletAsset, bool)> assets) async {
final toSubscribe = <(TonWalletAsset, bool)>[];
final toUnsubscribe = <TonWalletState>[];

// Stop last created operation if possible
Expand All @@ -214,11 +214,11 @@ mixin TonWalletRepositoryImpl implements TonWalletRepository {

toUnsubscribe.addAll(
// pick all elements from old list, which is not contains in a new list
wallets.where((w) => !assets.any((a) => a.address == w.address)),
wallets.where((w) => !assets.any((a) => a.$1.address == w.address)),
);
toSubscribe.addAll(
// pick all elements from new list, which is not contains in old list
assets.where((a) => !wallets.any((w) => w.address == a.address)),
assets.where((a) => !wallets.any((w) => w.address == a.$1.address)),
);

for (final asset in toUnsubscribe) {
Expand Down Expand Up @@ -251,16 +251,18 @@ mixin TonWalletRepositoryImpl implements TonWalletRepository {
await operation.valueOrCancellation();
}

Future<void> _subscribeAsset(TonWalletAsset asset) async {
Future<void> _subscribeAsset((TonWalletAsset, bool) asset) async {
if (currentTransport.transport.disposed) return;

try {
await subscribe(asset);
asset.$2
? await subscribeByAddress(asset.$1.address)
: await subscribe(asset.$1);
} catch (e, t) {
_logger.severe('_subscribeAsset', e, t);

// Save error state of wallet
final address = asset.address;
final address = asset.$1.address;
final res = TonWalletState.error(err: e, address: address);
walletsMap[address] = res;
_walletsSubject.add(walletsMap);
Expand Down
51 changes: 45 additions & 6 deletions test/src/ton_wallet_repository_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1254,7 +1254,46 @@ void main() {
mockTonWallet(tonWrapper1, asset1);
mockTonWallet(tonWrapper2, asset2);

await repository.updateSubscriptions([asset1, asset2]);
await repository.updateSubscriptions([(asset1, false), (asset2, false)]);

expect(repository.wallets.length, 2);
});

test('updateSubscriptions without side effects by address metod', () async {
mockWrapper(bridge);
when(() => wallet.onMessageExpiredStream)
.thenAnswer((_) => expiredStream);
when(() => wallet.onMessageSentStream)
.thenAnswer((_) => messageSentStream);
when(() => wallet.onTransactionsFoundStream)
.thenAnswer((_) => transactionsFoundStream);
when(() => wallet.onStateChangedStream).thenAnswer((_) => stateStream);

when(() => transport.transport).thenReturn(proto);
when(() => proto.disposed).thenReturn(false);
when(() => wallet.address).thenReturn(multisigAddress);
when(() => proto.transportBox).thenReturn(box);

when(
() => bridge.subscribeStaticMethodTonWalletDartWrapper(
publicKey: any(named: 'publicKey'),
instanceHash: any(named: 'instanceHash'),
transport: any(named: 'transport'),
walletType: any(named: 'walletType'),
workchainId: any(named: 'workchainId'),
),
).thenAnswer((_) => Future.value(tonWrapper2));
when(
() => bridge.subscribeByAddressStaticMethodTonWalletDartWrapper(
address: any(named: 'address'),
instanceHash: any(named: 'instanceHash'),
transport: any(named: 'transport'),
),
).thenAnswer((_) => Future.value(tonWrapper1));
mockTonWallet(tonWrapper1, asset1);
mockTonWallet(tonWrapper2, asset2);

await repository.updateSubscriptions([(asset1, true), (asset2, false)]);

expect(repository.wallets.length, 2);
});
Expand Down Expand Up @@ -1292,7 +1331,7 @@ void main() {
mockTonWallet(tonWrapper1, asset1);
mockTonWallet(tonWrapper2, asset2);

await repository.updateSubscriptions([asset1, asset2]);
await repository.updateSubscriptions([(asset1, false), (asset2, false)]);

final wallets = repository.wallets;

Expand Down Expand Up @@ -1327,7 +1366,7 @@ void main() {
).thenAnswer((_) => throwError());
mockTonWallet(tonWrapper1, asset1);

await repository.updateSubscriptions([asset1]);
await repository.updateSubscriptions([(asset1, false)]);

var wallets = repository.wallets;

Expand Down Expand Up @@ -1422,9 +1461,9 @@ void main() {
mockTonWallet(tonWrapper1, asset1);
mockTonWallet(tonWrapper2, asset2);

unawaited(repository.updateSubscriptions([asset1]));
unawaited(repository.updateSubscriptions([(asset1, false)]));
await Future<void>.delayed(const Duration(milliseconds: 300));
await repository.updateSubscriptions([asset1, asset2]);
await repository.updateSubscriptions([(asset1, false), (asset2, false)]);

expect(repository.wallets.length, 2);
verify(
Expand Down Expand Up @@ -1490,7 +1529,7 @@ void main() {

repository.walletsMap[asset1.address] = state;
repository.walletsMap[asset2.address] = state;
repository.lastUpdatedAssets = [asset1, asset2];
repository.lastUpdatedAssets = [(asset1, false), (asset2, false)];
await repository.updateTransportSubscriptions();

verify(wallet.dispose).called(2);
Expand Down

0 comments on commit 077a776

Please sign in to comment.