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

feat: Ton hamster #778

Merged
merged 5 commits into from
Feb 11, 2025
Merged
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
10 changes: 10 additions & 0 deletions assets/configs/connections.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@
"networkName": "TON",
"networkType": "ton",
"networkGroup": "ton",
"defaultActiveAssets": [
{
"address": "0:09f2e59dec406ab26a5259a45d7ff23ef11f3e5c7c21de0b0d2a1cbe52b76b3d"
}
],
"icons": {
"nativeToken": "https://raw.githubusercontent.com/broxus/sparx-networks/master/icons/ton/native_token.svg",
"network": "https://raw.githubusercontent.com/broxus/sparx-networks/master/icons/ton/network.svg",
Expand Down Expand Up @@ -167,6 +172,11 @@
"networkName": "Hamster Network",
"networkType": "tycho",
"networkGroup": "hmstr_mainnet",
"defaultActiveAssets": [
{
"address": "0:fddc005ddffcc9c5cc8e2d684c1338d3fa5548426602b04b2cfd2a1a3504be80"
}
],
"icons": {
"nativeToken": "https://raw.githubusercontent.com/broxus/sparx-networks/master/icons/hamster/native_token.svg",
"network": "https://raw.githubusercontent.com/broxus/sparx-networks/master/icons/hamster/network.svg",
Expand Down
102 changes: 100 additions & 2 deletions lib/app/service/assets_service.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'dart:async';
import 'dart:convert';

import 'package:app/app/service/connection/connection_factory.dart';
import 'package:app/app/service/presets_connection/presets_connection_service.dart';
import 'package:app/app/service/service.dart';
import 'package:app/data/models/models.dart';
import 'package:app/http/repository/ton_repository.dart';
Expand All @@ -17,6 +19,9 @@ import 'package:rxdart/rxdart.dart';
class AssetsService {
AssetsService(
this.nekotonRepository,
this.connectionsStorageService,
this.currentAccountsService,
this.presetsConnectionService,
this.httpService,
this.storage,
this.connectionFactory,
Expand All @@ -26,16 +31,26 @@ class AssetsService {
static final _logger = Logger('AssetsService');

final NekotonRepository nekotonRepository;
final ConnectionsStorageService connectionsStorageService;
final CurrentAccountsService currentAccountsService;
final PresetsConnectionService presetsConnectionService;
final HttpService httpService;
final GeneralStorageService storage;
final ConnectionFactory connectionFactory;
final TonRepository tonRepository;

StreamSubscription<TransportStrategy>? _currentTransportSubscription;
StreamSubscription<KeyAccount?>? _accountsSubscription;
StreamSubscription<String>? _connectionsSubscription;
StreamSubscription<void>? _combineSubscription;

/// Start listening for transport changes and update contracts from manifest
void init() {
nekotonRepository.currentTransportStream.listen(_updateSystemContracts);
_currentTransportSubscription =
nekotonRepository.currentTransportStream.listen(_updateSystemContracts);

nekotonRepository.currentTransportStream.flatMap((transport) {
_combineSubscription =
nekotonRepository.currentTransportStream.flatMap((transport) {
return Rx.combineLatest2<List<TokenContractAsset>,
List<TokenContractAsset>, void>(
storage.systemTokenContractAssetsStream(transport.transport.group),
Expand All @@ -45,6 +60,24 @@ class AssetsService {
// listen needs to enable stream api
// ignore: no-empty-block
}).listen((_) {});

_connectionsSubscription =
connectionsStorageService.currentConnectionIdStream.listen(
(_) => updateDefaultAssets(),
);

_accountsSubscription =
currentAccountsService.currentActiveAccountStream.listen(
(_) => updateDefaultAssets(),
);
}

@disposeMethod
void dispose() {
_currentTransportSubscription?.cancel();
_accountsSubscription?.cancel();
_connectionsSubscription?.cancel();
_combineSubscription?.cancel();
}

/// Get list of contracts (custom and system) that is available for current
Expand Down Expand Up @@ -247,6 +280,17 @@ class AssetsService {
}
}

Future<void> updateDefaultActiveAssets(
String accountAddress,
List<String> address,
) async {
return storage.updateDefaultActiveAssets(accountAddress, address);
}

List<String> getDefaultActiveAssets(String accountAddress) {
return storage.getDefaultActiveAssets(accountAddress);
}

/// Try getting contract of existed token contract from storage.
/// This can be helpful when you know, that token exists, but you do not have
/// direct access to TokenWallet.
Expand All @@ -268,6 +312,60 @@ class AssetsService {
nekotonRepository.currentTransport.transport.group,
);

Future<void> updateDefaultAssets() async {
await Future.delayed(const Duration(seconds: 1), () async {
final presetsDefaultAssets =
presetsConnectionService.getDefaultActiveAsset(
connectionsStorageService.currentConnection.group,
);

if (presetsDefaultAssets.isEmpty) {
return;
}

final accountAddress =
currentAccountsService.currentActiveAccount?.address;

if (accountAddress == null) {
return;
}

final cachedAccount = nekotonRepository.seedList.findAccountByAddress(
accountAddress,
);

if (cachedAccount == null) {
return;
}

final cachedDefaultAssets =
getDefaultActiveAssets(accountAddress.address);

final result = <Address>[];
final skipped = <String>[];

for (final preset in presetsDefaultAssets) {
if (cachedDefaultAssets.contains(preset.address.address)) {
continue;
}
result.add(preset.address);
skipped.add(preset.address.address);
}

if (result.isNotEmpty) {
await cachedAccount.addTokenWallets(result);
}
if (skipped.isNotEmpty) {
unawaited(
updateDefaultActiveAssets(
accountAddress.address,
skipped,
),
);
}
});
}

/// Load manifest specified for transport and update system contracts that
/// user can add to list of its contracts.
Future<void> _updateSystemContracts(TransportStrategy transport) async {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:app/app/service/connection/data/account_explorer/account_explorer_link_type.dart';
import 'package:app/app/service/connection/data/default_active_asset.dart';
import 'package:app/app/service/connection/data/transaction_explorer/transaction_explorer_link_type.dart';
import 'package:app/app/service/connection/data/transport_icons.dart';
import 'package:app/app/service/connection/data/transport_manifest_option/transport_manifest_option.dart';
Expand Down Expand Up @@ -27,7 +28,8 @@ class ConnectionTransportData {
this.stakeInformation,
this.tokenApiBaseUrl,
this.currencyApiBaseUrl,
});
List<DefaultActiveAsset>? defaultActiveAssets,
}) : defaultActiveAssets = defaultActiveAssets ?? [];

factory ConnectionTransportData.custom({
required String networkType,
Expand Down Expand Up @@ -75,6 +77,7 @@ class ConnectionTransportData {
transactionExplorerLinkType: TransactionExplorerLinkType.transactions,
);

final List<DefaultActiveAsset> defaultActiveAssets;
final TransportIcons icons;
final List<WalletType> availableWalletTypes;
final WalletDefaultAccountNames walletDefaultAccountNames;
Expand Down
9 changes: 9 additions & 0 deletions lib/app/service/connection/data/default_active_asset.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import 'package:nekoton_repository/nekoton_repository.dart';

class DefaultActiveAsset {
DefaultActiveAsset({
required this.address,
});

final Address address;
}
19 changes: 19 additions & 0 deletions lib/app/service/connection/mapping/transports_mapper.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:app/app/service/connection/data/account_explorer/account_explorer_link_type.dart';
import 'package:app/app/service/connection/data/connection_transport/connection_transport_data.dart';
import 'package:app/app/service/connection/data/default_active_asset.dart';
import 'package:app/app/service/connection/data/transaction_explorer/transaction_explorer_link_type.dart';
import 'package:app/app/service/connection/data/transport_icons.dart';
import 'package:app/app/service/connection/data/transport_manifest_option/transport_manifest_option.dart';
Expand All @@ -17,6 +18,9 @@ Map<NetworkGroup, ConnectionTransportData>? mapToTransports(

for (final transport in list) {
result[transport['networkGroup'] as String] = ConnectionTransportData(
defaultActiveAssets: _mapToDefaultActiveAssets(
transport['defaultActiveAssets'],
),
icons: _mapToTransportIcons(
transport['icons'] as Map<String, dynamic>,
),
Expand Down Expand Up @@ -187,3 +191,18 @@ WalletDefaultAccountNames _mapRoWalletDefaultAccountNames(
walletV5R1: json['walletV5R1'] as String,
);
}

List<DefaultActiveAsset> _mapToDefaultActiveAssets(dynamic json) {
try {
final list = castJsonList<Map<String, dynamic>>(json);

return [
for (final item in list)
DefaultActiveAsset(
address: Address(address: item['address'] as String),
),
];
} catch (_) {
return [];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:async';
import 'package:app/app/service/connection/data/connection_data/connection_data.dart';
import 'package:app/app/service/connection/data/connection_network/connection_network.dart';
import 'package:app/app/service/connection/data/connection_transport/connection_transport_data.dart';
import 'package:app/app/service/connection/data/default_active_asset.dart';
import 'package:app/app/service/connection/data/transport_icons.dart';
import 'package:app/app/service/connection/default_network.dart';
import 'package:app/app/service/connection/group.dart';
Expand Down Expand Up @@ -59,6 +60,10 @@ class PresetsConnectionService {
return transports[networkGroup]?.icons ?? TransportIcons();
}

List<DefaultActiveAsset> getDefaultActiveAsset(NetworkGroup group) {
return transports[group]?.defaultActiveAssets ?? [];
}

Future<void> fetchConnectionsList() async {
_presetsConnectionsSubj.add(await _configHelper.connections);
}
Expand Down
31 changes: 31 additions & 0 deletions lib/app/service/storage_service/general_storage_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ const _currentAddress = 'current_address';
const _currentKey = 'current_public_key';

const _customContractAssetsKey = 'custom_contract_assets_key';
const _defaultActiveAssetsStorageKey = 'default_active_assets_storage_key';
const _lastSelectedSeedsKey = 'last_selected_seeds_key';
const _migrationKey = 'migration_key';
const _preferencesKey = 'preferences_key';
const _systemContractAssetsKey = 'system_contract_assets_key';
const _wasStEverOpenedKey = 'was_stever_opened_key';
const _alreadyAutoEnabledDefaultActiveAssets =
'already_auto_enabled_default_active_assets';

/// This is a wrapper-class above [GetStorage] that provides methods
/// to interact with general information that is not related to some specified
Expand All @@ -35,23 +38,27 @@ class GeneralStorageService extends AbstractStorageService {
@Named(currenciesContainer) this._currenciesStorage,
@Named(systemContractAssetsContainer) this._systemContractAssetsStorage,
@Named(customContractAssetsContainer) this._customContractAssetsStorage,
@Named(defaultActiveAssetsStorage) this._defaultActiveAssetsStorage,
);

static const prefContainer = _preferencesKey;
static const currenciesContainer = _currenciesKey;
static const systemContractAssetsContainer = _systemContractAssetsKey;
static const customContractAssetsContainer = _customContractAssetsKey;
static const defaultActiveAssetsStorage = _defaultActiveAssetsStorageKey;
static const containers = [
prefContainer,
currenciesContainer,
systemContractAssetsContainer,
customContractAssetsContainer,
defaultActiveAssetsStorage,
];

final GetStorage _prefStorage;
final GetStorage _currenciesStorage;
final GetStorage _systemContractAssetsStorage;
final GetStorage _customContractAssetsStorage;
final GetStorage _defaultActiveAssetsStorage;

/// Subject of public keys names
final _currentKeySubject = BehaviorSubject<PublicKey?>();
Expand Down Expand Up @@ -402,6 +409,30 @@ class GeneralStorageService extends AbstractStorageService {
}
}

void updateDefaultActiveAssets(
String accountAddress,
List<String> addresses,
) {
_defaultActiveAssetsStorage.write(
'$_alreadyAutoEnabledDefaultActiveAssets-$accountAddress',
getDefaultActiveAssets(accountAddress)
..addAll(addresses)
..toSet()
..toList(),
);
}

List<String> getDefaultActiveAssets(String accountAddress) {
return _defaultActiveAssetsStorage
.read<List<dynamic>?>(
'$_alreadyAutoEnabledDefaultActiveAssets-$accountAddress',
)
?.cast<String>()
.toSet()
.toList() ??
[];
}

Future<void> _initAppDirectories() async {
final directory = await getApplicationDocumentsDirectory();
_applicationDocumentsDirectory = directory.path;
Expand Down
Loading
Loading