From 61e687585ef2816181bdfdf335c6efd6bc0aced5 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 10 Jan 2024 11:58:22 -0600 Subject: [PATCH 1/2] token wallet info cache refactor from hive to isar --- lib/db/isar/main_db.dart | 2 + .../isar/models/token_wallet_info.dart | 93 ++ .../isar/models/token_wallet_info.g.dart | 1162 +++++++++++++++++ 3 files changed, 1257 insertions(+) create mode 100644 lib/wallets/isar/models/token_wallet_info.dart create mode 100644 lib/wallets/isar/models/token_wallet_info.g.dart diff --git a/lib/db/isar/main_db.dart b/lib/db/isar/main_db.dart index 560cac003..c6eceea80 100644 --- a/lib/db/isar/main_db.dart +++ b/lib/db/isar/main_db.dart @@ -22,6 +22,7 @@ import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/stack_file_system.dart'; import 'package:stackwallet/wallets/isar/models/spark_coin.dart'; +import 'package:stackwallet/wallets/isar/models/token_wallet_info.dart'; import 'package:stackwallet/wallets/isar/models/wallet_info.dart'; import 'package:stackwallet/wallets/isar/models/wallet_info_meta.dart'; import 'package:tuple/tuple.dart'; @@ -65,6 +66,7 @@ class MainDB { TransactionV2Schema, SparkCoinSchema, WalletInfoMetaSchema, + TokenWalletInfoSchema, ], directory: (await StackFileSystem.applicationIsarDirectory()).path, // inspector: kDebugMode, diff --git a/lib/wallets/isar/models/token_wallet_info.dart b/lib/wallets/isar/models/token_wallet_info.dart new file mode 100644 index 000000000..78378db41 --- /dev/null +++ b/lib/wallets/isar/models/token_wallet_info.dart @@ -0,0 +1,93 @@ +import 'package:isar/isar.dart'; +import 'package:stackwallet/models/balance.dart'; +import 'package:stackwallet/models/isar/models/isar_models.dart'; +import 'package:stackwallet/utilities/amount/amount.dart'; +import 'package:stackwallet/wallets/isar/isar_id_interface.dart'; + +part 'token_wallet_info.g.dart'; + +@Collection(accessor: "tokenWalletInfo", inheritance: false) +class TokenWalletInfo implements IsarId { + @override + Id id = Isar.autoIncrement; + + @Index( + unique: true, + replace: false, + composite: [ + CompositeIndex("tokenAddress"), + ], + ) + final String walletId; + + final String tokenAddress; + + final int tokenFractionDigits; + + final String? cachedBalanceJsonString; + + TokenWalletInfo({ + required this.walletId, + required this.tokenAddress, + required this.tokenFractionDigits, + this.cachedBalanceJsonString, + }); + + EthContract getContract(Isar isar) => + isar.ethContracts.where().addressEqualTo(tokenAddress).findFirstSync()!; + + // token balance cache + Balance getCachedBalance() { + if (cachedBalanceJsonString == null) { + return Balance( + total: Amount.zeroWith( + fractionDigits: tokenFractionDigits, + ), + spendable: Amount.zeroWith( + fractionDigits: tokenFractionDigits, + ), + blockedTotal: Amount.zeroWith( + fractionDigits: tokenFractionDigits, + ), + pendingSpendable: Amount.zeroWith( + fractionDigits: tokenFractionDigits, + ), + ); + } + return Balance.fromJson( + cachedBalanceJsonString!, + tokenFractionDigits, + ); + } + + Future updateCachedBalance( + Balance balance, { + required Isar isar, + }) async { + // // ensure we are updating using the latest entry of this in the db + final thisEntry = await isar.tokenWalletInfo + .where() + .walletIdEqualToTokenAddressNotEqualTo(walletId, tokenAddress) + .findFirst(); + if (thisEntry == null) { + throw Exception( + "Attempted to update cached token balance before object was saved in db", + ); + } else { + await isar.writeTxn(() async { + await isar.tokenWalletInfo.deleteByWalletIdTokenAddress( + walletId, + tokenAddress, + ); + await isar.tokenWalletInfo.put( + TokenWalletInfo( + walletId: walletId, + tokenAddress: tokenAddress, + tokenFractionDigits: tokenFractionDigits, + cachedBalanceJsonString: balance.toJsonIgnoreCoin(), + ), + ); + }); + } + } +} diff --git a/lib/wallets/isar/models/token_wallet_info.g.dart b/lib/wallets/isar/models/token_wallet_info.g.dart new file mode 100644 index 000000000..bdf6a060a --- /dev/null +++ b/lib/wallets/isar/models/token_wallet_info.g.dart @@ -0,0 +1,1162 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'token_wallet_info.dart'; + +// ************************************************************************** +// IsarCollectionGenerator +// ************************************************************************** + +// coverage:ignore-file +// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters + +extension GetTokenWalletInfoCollection on Isar { + IsarCollection get tokenWalletInfo => this.collection(); +} + +const TokenWalletInfoSchema = CollectionSchema( + name: r'TokenWalletInfo', + id: -2566407308847951136, + properties: { + r'cachedBalanceJsonString': PropertySchema( + id: 0, + name: r'cachedBalanceJsonString', + type: IsarType.string, + ), + r'tokenAddress': PropertySchema( + id: 1, + name: r'tokenAddress', + type: IsarType.string, + ), + r'tokenFractionDigits': PropertySchema( + id: 2, + name: r'tokenFractionDigits', + type: IsarType.long, + ), + r'walletId': PropertySchema( + id: 3, + name: r'walletId', + type: IsarType.string, + ) + }, + estimateSize: _tokenWalletInfoEstimateSize, + serialize: _tokenWalletInfoSerialize, + deserialize: _tokenWalletInfoDeserialize, + deserializeProp: _tokenWalletInfoDeserializeProp, + idName: r'id', + indexes: { + r'walletId_tokenAddress': IndexSchema( + id: -7747794843092592407, + name: r'walletId_tokenAddress', + unique: true, + replace: false, + properties: [ + IndexPropertySchema( + name: r'walletId', + type: IndexType.hash, + caseSensitive: true, + ), + IndexPropertySchema( + name: r'tokenAddress', + type: IndexType.hash, + caseSensitive: true, + ) + ], + ) + }, + links: {}, + embeddedSchemas: {}, + getId: _tokenWalletInfoGetId, + getLinks: _tokenWalletInfoGetLinks, + attach: _tokenWalletInfoAttach, + version: '3.0.5', +); + +int _tokenWalletInfoEstimateSize( + TokenWalletInfo object, + List offsets, + Map> allOffsets, +) { + var bytesCount = offsets.last; + { + final value = object.cachedBalanceJsonString; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } + bytesCount += 3 + object.tokenAddress.length * 3; + bytesCount += 3 + object.walletId.length * 3; + return bytesCount; +} + +void _tokenWalletInfoSerialize( + TokenWalletInfo object, + IsarWriter writer, + List offsets, + Map> allOffsets, +) { + writer.writeString(offsets[0], object.cachedBalanceJsonString); + writer.writeString(offsets[1], object.tokenAddress); + writer.writeLong(offsets[2], object.tokenFractionDigits); + writer.writeString(offsets[3], object.walletId); +} + +TokenWalletInfo _tokenWalletInfoDeserialize( + Id id, + IsarReader reader, + List offsets, + Map> allOffsets, +) { + final object = TokenWalletInfo( + cachedBalanceJsonString: reader.readStringOrNull(offsets[0]), + tokenAddress: reader.readString(offsets[1]), + tokenFractionDigits: reader.readLong(offsets[2]), + walletId: reader.readString(offsets[3]), + ); + object.id = id; + return object; +} + +P _tokenWalletInfoDeserializeProp

( + IsarReader reader, + int propertyId, + int offset, + Map> allOffsets, +) { + switch (propertyId) { + case 0: + return (reader.readStringOrNull(offset)) as P; + case 1: + return (reader.readString(offset)) as P; + case 2: + return (reader.readLong(offset)) as P; + case 3: + return (reader.readString(offset)) as P; + default: + throw IsarError('Unknown property with id $propertyId'); + } +} + +Id _tokenWalletInfoGetId(TokenWalletInfo object) { + return object.id; +} + +List> _tokenWalletInfoGetLinks(TokenWalletInfo object) { + return []; +} + +void _tokenWalletInfoAttach( + IsarCollection col, Id id, TokenWalletInfo object) { + object.id = id; +} + +extension TokenWalletInfoByIndex on IsarCollection { + Future getByWalletIdTokenAddress( + String walletId, String tokenAddress) { + return getByIndex(r'walletId_tokenAddress', [walletId, tokenAddress]); + } + + TokenWalletInfo? getByWalletIdTokenAddressSync( + String walletId, String tokenAddress) { + return getByIndexSync(r'walletId_tokenAddress', [walletId, tokenAddress]); + } + + Future deleteByWalletIdTokenAddress( + String walletId, String tokenAddress) { + return deleteByIndex(r'walletId_tokenAddress', [walletId, tokenAddress]); + } + + bool deleteByWalletIdTokenAddressSync(String walletId, String tokenAddress) { + return deleteByIndexSync( + r'walletId_tokenAddress', [walletId, tokenAddress]); + } + + Future> getAllByWalletIdTokenAddress( + List walletIdValues, List tokenAddressValues) { + final len = walletIdValues.length; + assert(tokenAddressValues.length == len, + 'All index values must have the same length'); + final values = >[]; + for (var i = 0; i < len; i++) { + values.add([walletIdValues[i], tokenAddressValues[i]]); + } + + return getAllByIndex(r'walletId_tokenAddress', values); + } + + List getAllByWalletIdTokenAddressSync( + List walletIdValues, List tokenAddressValues) { + final len = walletIdValues.length; + assert(tokenAddressValues.length == len, + 'All index values must have the same length'); + final values = >[]; + for (var i = 0; i < len; i++) { + values.add([walletIdValues[i], tokenAddressValues[i]]); + } + + return getAllByIndexSync(r'walletId_tokenAddress', values); + } + + Future deleteAllByWalletIdTokenAddress( + List walletIdValues, List tokenAddressValues) { + final len = walletIdValues.length; + assert(tokenAddressValues.length == len, + 'All index values must have the same length'); + final values = >[]; + for (var i = 0; i < len; i++) { + values.add([walletIdValues[i], tokenAddressValues[i]]); + } + + return deleteAllByIndex(r'walletId_tokenAddress', values); + } + + int deleteAllByWalletIdTokenAddressSync( + List walletIdValues, List tokenAddressValues) { + final len = walletIdValues.length; + assert(tokenAddressValues.length == len, + 'All index values must have the same length'); + final values = >[]; + for (var i = 0; i < len; i++) { + values.add([walletIdValues[i], tokenAddressValues[i]]); + } + + return deleteAllByIndexSync(r'walletId_tokenAddress', values); + } + + Future putByWalletIdTokenAddress(TokenWalletInfo object) { + return putByIndex(r'walletId_tokenAddress', object); + } + + Id putByWalletIdTokenAddressSync(TokenWalletInfo object, + {bool saveLinks = true}) { + return putByIndexSync(r'walletId_tokenAddress', object, + saveLinks: saveLinks); + } + + Future> putAllByWalletIdTokenAddress(List objects) { + return putAllByIndex(r'walletId_tokenAddress', objects); + } + + List putAllByWalletIdTokenAddressSync(List objects, + {bool saveLinks = true}) { + return putAllByIndexSync(r'walletId_tokenAddress', objects, + saveLinks: saveLinks); + } +} + +extension TokenWalletInfoQueryWhereSort + on QueryBuilder { + QueryBuilder anyId() { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(const IdWhereClause.any()); + }); + } +} + +extension TokenWalletInfoQueryWhere + on QueryBuilder { + QueryBuilder idEqualTo( + Id id) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: id, + upper: id, + )); + }); + } + + QueryBuilder + idNotEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ) + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ); + } else { + return query + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ) + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ); + } + }); + } + + QueryBuilder + idGreaterThan(Id id, {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: include), + ); + }); + } + + QueryBuilder idLessThan( + Id id, + {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: include), + ); + }); + } + + QueryBuilder idBetween( + Id lowerId, + Id upperId, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: lowerId, + includeLower: includeLower, + upper: upperId, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + walletIdEqualToAnyTokenAddress(String walletId) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.equalTo( + indexName: r'walletId_tokenAddress', + value: [walletId], + )); + }); + } + + QueryBuilder + walletIdNotEqualToAnyTokenAddress(String walletId) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId_tokenAddress', + lower: [], + upper: [walletId], + includeUpper: false, + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId_tokenAddress', + lower: [walletId], + includeLower: false, + upper: [], + )); + } else { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId_tokenAddress', + lower: [walletId], + includeLower: false, + upper: [], + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId_tokenAddress', + lower: [], + upper: [walletId], + includeUpper: false, + )); + } + }); + } + + QueryBuilder + walletIdTokenAddressEqualTo(String walletId, String tokenAddress) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.equalTo( + indexName: r'walletId_tokenAddress', + value: [walletId, tokenAddress], + )); + }); + } + + QueryBuilder + walletIdEqualToTokenAddressNotEqualTo( + String walletId, String tokenAddress) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId_tokenAddress', + lower: [walletId], + upper: [walletId, tokenAddress], + includeUpper: false, + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId_tokenAddress', + lower: [walletId, tokenAddress], + includeLower: false, + upper: [walletId], + )); + } else { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId_tokenAddress', + lower: [walletId, tokenAddress], + includeLower: false, + upper: [walletId], + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId_tokenAddress', + lower: [walletId], + upper: [walletId, tokenAddress], + includeUpper: false, + )); + } + }); + } +} + +extension TokenWalletInfoQueryFilter + on QueryBuilder { + QueryBuilder + cachedBalanceJsonStringIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'cachedBalanceJsonString', + )); + }); + } + + QueryBuilder + cachedBalanceJsonStringIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'cachedBalanceJsonString', + )); + }); + } + + QueryBuilder + cachedBalanceJsonStringEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'cachedBalanceJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + cachedBalanceJsonStringGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'cachedBalanceJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + cachedBalanceJsonStringLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'cachedBalanceJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + cachedBalanceJsonStringBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'cachedBalanceJsonString', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + cachedBalanceJsonStringStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'cachedBalanceJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + cachedBalanceJsonStringEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'cachedBalanceJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + cachedBalanceJsonStringContains(String value, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'cachedBalanceJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + cachedBalanceJsonStringMatches(String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'cachedBalanceJsonString', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + cachedBalanceJsonStringIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'cachedBalanceJsonString', + value: '', + )); + }); + } + + QueryBuilder + cachedBalanceJsonStringIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'cachedBalanceJsonString', + value: '', + )); + }); + } + + QueryBuilder + idEqualTo(Id value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'id', + value: value, + )); + }); + } + + QueryBuilder + idGreaterThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder + idLessThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder + idBetween( + Id lower, + Id upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'id', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + tokenAddressEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'tokenAddress', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + tokenAddressGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'tokenAddress', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + tokenAddressLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'tokenAddress', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + tokenAddressBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'tokenAddress', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + tokenAddressStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'tokenAddress', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + tokenAddressEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'tokenAddress', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + tokenAddressContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'tokenAddress', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + tokenAddressMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'tokenAddress', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + tokenAddressIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'tokenAddress', + value: '', + )); + }); + } + + QueryBuilder + tokenAddressIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'tokenAddress', + value: '', + )); + }); + } + + QueryBuilder + tokenFractionDigitsEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'tokenFractionDigits', + value: value, + )); + }); + } + + QueryBuilder + tokenFractionDigitsGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'tokenFractionDigits', + value: value, + )); + }); + } + + QueryBuilder + tokenFractionDigitsLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'tokenFractionDigits', + value: value, + )); + }); + } + + QueryBuilder + tokenFractionDigitsBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'tokenFractionDigits', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + walletIdEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'walletId', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'walletId', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'walletId', + value: '', + )); + }); + } + + QueryBuilder + walletIdIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'walletId', + value: '', + )); + }); + } +} + +extension TokenWalletInfoQueryObject + on QueryBuilder {} + +extension TokenWalletInfoQueryLinks + on QueryBuilder {} + +extension TokenWalletInfoQuerySortBy + on QueryBuilder { + QueryBuilder + sortByCachedBalanceJsonString() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'cachedBalanceJsonString', Sort.asc); + }); + } + + QueryBuilder + sortByCachedBalanceJsonStringDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'cachedBalanceJsonString', Sort.desc); + }); + } + + QueryBuilder + sortByTokenAddress() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'tokenAddress', Sort.asc); + }); + } + + QueryBuilder + sortByTokenAddressDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'tokenAddress', Sort.desc); + }); + } + + QueryBuilder + sortByTokenFractionDigits() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'tokenFractionDigits', Sort.asc); + }); + } + + QueryBuilder + sortByTokenFractionDigitsDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'tokenFractionDigits', Sort.desc); + }); + } + + QueryBuilder + sortByWalletId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.asc); + }); + } + + QueryBuilder + sortByWalletIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.desc); + }); + } +} + +extension TokenWalletInfoQuerySortThenBy + on QueryBuilder { + QueryBuilder + thenByCachedBalanceJsonString() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'cachedBalanceJsonString', Sort.asc); + }); + } + + QueryBuilder + thenByCachedBalanceJsonStringDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'cachedBalanceJsonString', Sort.desc); + }); + } + + QueryBuilder thenById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.asc); + }); + } + + QueryBuilder thenByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.desc); + }); + } + + QueryBuilder + thenByTokenAddress() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'tokenAddress', Sort.asc); + }); + } + + QueryBuilder + thenByTokenAddressDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'tokenAddress', Sort.desc); + }); + } + + QueryBuilder + thenByTokenFractionDigits() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'tokenFractionDigits', Sort.asc); + }); + } + + QueryBuilder + thenByTokenFractionDigitsDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'tokenFractionDigits', Sort.desc); + }); + } + + QueryBuilder + thenByWalletId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.asc); + }); + } + + QueryBuilder + thenByWalletIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.desc); + }); + } +} + +extension TokenWalletInfoQueryWhereDistinct + on QueryBuilder { + QueryBuilder + distinctByCachedBalanceJsonString({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'cachedBalanceJsonString', + caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByTokenAddress({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'tokenAddress', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByTokenFractionDigits() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'tokenFractionDigits'); + }); + } + + QueryBuilder distinctByWalletId( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'walletId', caseSensitive: caseSensitive); + }); + } +} + +extension TokenWalletInfoQueryProperty + on QueryBuilder { + QueryBuilder idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'id'); + }); + } + + QueryBuilder + cachedBalanceJsonStringProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'cachedBalanceJsonString'); + }); + } + + QueryBuilder + tokenAddressProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'tokenAddress'); + }); + } + + QueryBuilder + tokenFractionDigitsProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'tokenFractionDigits'); + }); + } + + QueryBuilder walletIdProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'walletId'); + }); + } +} From baea4923dddfe3c8ce88d0f6111058383797c4e4 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 10 Jan 2024 12:21:28 -0600 Subject: [PATCH 2/2] token wallet info cache and contract addresses provider usages --- .../edit_wallet_tokens_view.dart | 5 +- lib/pages/token_view/my_tokens_view.dart | 8 +- .../sub_widgets/my_token_select_item.dart | 20 ++- lib/pages/wallets_view/wallets_overview.dart | 5 +- .../ethereum/cached_eth_token_balance.dart | 25 +++- lib/services/mixins/eth_token_cache.dart | 140 +++++++++--------- .../providers/eth/token_balance_provider.dart | 40 +++++ .../isar/providers/wallet_info_provider.dart | 7 + lib/widgets/master_wallet_card.dart | 40 ++--- 9 files changed, 168 insertions(+), 122 deletions(-) create mode 100644 lib/wallets/isar/providers/eth/token_balance_provider.dart diff --git a/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart b/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart index ca3b776d5..4a5dcae28 100644 --- a/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart +++ b/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart @@ -180,10 +180,7 @@ class _EditWalletTokensViewState extends ConsumerState { tokenEntities.addAll(contracts.map((e) => AddTokenListElementData(e))); - final walletContracts = - (ref.read(pWallets).getWallet(widget.walletId) as EthereumWallet) - .info - .tokenContractAddresses; + final walletContracts = ref.read(pWalletTokenAddresses(widget.walletId)); final shouldMarkAsSelectedContracts = [ ...walletContracts, diff --git a/lib/pages/token_view/my_tokens_view.dart b/lib/pages/token_view/my_tokens_view.dart index 9813e3eff..35168b9f7 100644 --- a/lib/pages/token_view/my_tokens_view.dart +++ b/lib/pages/token_view/my_tokens_view.dart @@ -15,14 +15,12 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart'; import 'package:stackwallet/pages/token_view/sub_widgets/my_tokens_list.dart'; -import 'package:stackwallet/providers/global/wallets_provider.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart'; -import 'package:stackwallet/wallets/wallet/impl/ethereum_wallet.dart'; import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/conditional_parent.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; @@ -233,11 +231,7 @@ class _MyTokensViewState extends ConsumerState { child: MyTokensList( walletId: widget.walletId, searchTerm: _searchString, - tokenContracts: ref - .watch(pWallets.select((value) => - value.getWallet(widget.walletId) as EthereumWallet)) - .info - .tokenContractAddresses, + tokenContracts: ref.watch(pWalletTokenAddresses(widget.walletId)), ), ), ], diff --git a/lib/pages/token_view/sub_widgets/my_token_select_item.dart b/lib/pages/token_view/sub_widgets/my_token_select_item.dart index 0907a4adc..b9316773f 100644 --- a/lib/pages/token_view/sub_widgets/my_token_select_item.dart +++ b/lib/pages/token_view/sub_widgets/my_token_select_item.dart @@ -13,6 +13,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart'; import 'package:stackwallet/pages/token_view/token_view.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart'; +import 'package:stackwallet/providers/db/main_db_provider.dart'; import 'package:stackwallet/providers/global/secure_store_provider.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/services/ethereum/cached_eth_token_balance.dart'; @@ -25,6 +26,7 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/show_loading.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; +import 'package:stackwallet/wallets/isar/providers/eth/token_balance_provider.dart'; import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart'; import 'package:stackwallet/wallets/wallet/impl/ethereum_wallet.dart'; import 'package:stackwallet/widgets/desktop/primary_button.dart'; @@ -116,10 +118,13 @@ class _MyTokenSelectItemState extends ConsumerState { cachedBalance = CachedEthTokenBalance(widget.walletId, widget.token); WidgetsBinding.instance.addPostFrameCallback((_) async { - final address = ref.read(pWalletReceivingAddress(widget.walletId)); - await cachedBalance.fetchAndUpdateCachedBalance(address); if (mounted) { - setState(() {}); + final address = ref.read(pWalletReceivingAddress(widget.walletId)); + await cachedBalance.fetchAndUpdateCachedBalance( + address, ref.read(mainDBProvider)); + if (mounted) { + setState(() {}); + } } }); @@ -172,7 +177,14 @@ class _MyTokenSelectItemState extends ConsumerState { const Spacer(), Text( ref.watch(pAmountFormatter(Coin.ethereum)).format( - cachedBalance.getCachedBalance().total, + ref + .watch(pTokenBalance( + ( + walletId: widget.walletId, + contractAddress: widget.token.address + ), + )) + .total, ethContract: widget.token, ), style: isDesktop diff --git a/lib/pages/wallets_view/wallets_overview.dart b/lib/pages/wallets_view/wallets_overview.dart index 7b05aaf24..0f6cef1a6 100644 --- a/lib/pages/wallets_view/wallets_overview.dart +++ b/lib/pages/wallets_view/wallets_overview.dart @@ -25,7 +25,7 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/wallets/isar/models/wallet_info.dart'; -import 'package:stackwallet/wallets/wallet/impl/ethereum_wallet.dart'; +import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart'; import 'package:stackwallet/wallets/wallet/wallet.dart'; import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/conditional_parent.dart'; @@ -119,9 +119,8 @@ class _EthWalletsOverviewState extends ConsumerState { if (widget.coin == Coin.ethereum) { for (final data in walletsData) { final List contracts = []; - final wallet = ref.read(pWallets).getWallet(data.walletId); final contractAddresses = - (wallet as EthereumWallet).info.tokenContractAddresses; + ref.read(pWalletTokenAddresses(data.walletId)); // fetch each contract for (final contractAddress in contractAddresses) { diff --git a/lib/services/ethereum/cached_eth_token_balance.dart b/lib/services/ethereum/cached_eth_token_balance.dart index aad4b3f68..dbcda1131 100644 --- a/lib/services/ethereum/cached_eth_token_balance.dart +++ b/lib/services/ethereum/cached_eth_token_balance.dart @@ -8,29 +8,37 @@ * */ +import 'package:isar/isar.dart'; +import 'package:stackwallet/db/isar/main_db.dart'; import 'package:stackwallet/models/balance.dart'; import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart'; import 'package:stackwallet/services/ethereum/ethereum_api.dart'; -import 'package:stackwallet/services/mixins/eth_token_cache.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/wallets/isar/models/token_wallet_info.dart'; -class CachedEthTokenBalance with EthTokenCache { +class CachedEthTokenBalance { final String walletId; final EthContract token; - CachedEthTokenBalance(this.walletId, this.token) { - initCache(walletId, token); - } + CachedEthTokenBalance(this.walletId, this.token); - Future fetchAndUpdateCachedBalance(String address) async { + Future fetchAndUpdateCachedBalance( + String address, + MainDB mainDB, + ) async { final response = await EthereumAPI.getWalletTokenBalance( address: address, contractAddress: token.address, ); - if (response.value != null) { - await updateCachedBalance( + final info = await mainDB.isar.tokenWalletInfo + .where() + .walletIdTokenAddressEqualTo(walletId, token.address) + .findFirst(); + + if (response.value != null && info != null) { + await info.updateCachedBalance( Balance( total: response.value!, spendable: response.value!, @@ -43,6 +51,7 @@ class CachedEthTokenBalance with EthTokenCache { fractionDigits: token.decimals, ), ), + isar: mainDB.isar, ); } else { Logging.instance.log( diff --git a/lib/services/mixins/eth_token_cache.dart b/lib/services/mixins/eth_token_cache.dart index fde3cb9e9..d6efa1fd2 100644 --- a/lib/services/mixins/eth_token_cache.dart +++ b/lib/services/mixins/eth_token_cache.dart @@ -1,70 +1,70 @@ -/* - * This file is part of Stack Wallet. - * - * Copyright (c) 2023 Cypher Stack - * All Rights Reserved. - * The code is distributed under GPLv3 license, see LICENSE file for details. - * Generated by Cypher Stack on 2023-05-26 - * - */ - -import 'package:stackwallet/db/hive/db.dart'; -import 'package:stackwallet/models/balance.dart'; -import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart'; -import 'package:stackwallet/utilities/amount/amount.dart'; - -abstract class TokenCacheKeys { - static String tokenBalance(String contractAddress) { - return "tokenBalanceCache_$contractAddress"; - } -} - -mixin EthTokenCache { - late final String _walletId; - late final EthContract _token; - - void initCache(String walletId, EthContract token) { - _walletId = walletId; - _token = token; - } - - // token balance cache - Balance getCachedBalance() { - final jsonString = DB.instance.get( - boxName: _walletId, - key: TokenCacheKeys.tokenBalance(_token.address), - ) as String?; - if (jsonString == null) { - return Balance( - total: Amount( - rawValue: BigInt.zero, - fractionDigits: _token.decimals, - ), - spendable: Amount( - rawValue: BigInt.zero, - fractionDigits: _token.decimals, - ), - blockedTotal: Amount( - rawValue: BigInt.zero, - fractionDigits: _token.decimals, - ), - pendingSpendable: Amount( - rawValue: BigInt.zero, - fractionDigits: _token.decimals, - ), - ); - } - return Balance.fromJson( - jsonString, - _token.decimals, - ); - } - - Future updateCachedBalance(Balance balance) async { - await DB.instance.put( - boxName: _walletId, - key: TokenCacheKeys.tokenBalance(_token.address), - value: balance.toJsonIgnoreCoin(), - ); - } -} +// /* +// * This file is part of Stack Wallet. +// * +// * Copyright (c) 2023 Cypher Stack +// * All Rights Reserved. +// * The code is distributed under GPLv3 license, see LICENSE file for details. +// * Generated by Cypher Stack on 2023-05-26 +// * +// */ +// +// import 'package:stackwallet/db/hive/db.dart'; +// import 'package:stackwallet/models/balance.dart'; +// import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart'; +// import 'package:stackwallet/utilities/amount/amount.dart'; +// +// abstract class TokenCacheKeys { +// static String tokenBalance(String contractAddress) { +// return "tokenBalanceCache_$contractAddress"; +// } +// } +// +// mixin EthTokenCache { +// late final String _walletId; +// late final EthContract _token; +// +// void initCache(String walletId, EthContract token) { +// _walletId = walletId; +// _token = token; +// } +// +// // token balance cache +// Balance getCachedBalance() { +// final jsonString = DB.instance.get( +// boxName: _walletId, +// key: TokenCacheKeys.tokenBalance(_token.address), +// ) as String?; +// if (jsonString == null) { +// return Balance( +// total: Amount( +// rawValue: BigInt.zero, +// fractionDigits: _token.decimals, +// ), +// spendable: Amount( +// rawValue: BigInt.zero, +// fractionDigits: _token.decimals, +// ), +// blockedTotal: Amount( +// rawValue: BigInt.zero, +// fractionDigits: _token.decimals, +// ), +// pendingSpendable: Amount( +// rawValue: BigInt.zero, +// fractionDigits: _token.decimals, +// ), +// ); +// } +// return Balance.fromJson( +// jsonString, +// _token.decimals, +// ); +// } +// +// Future updateCachedBalance(Balance balance) async { +// await DB.instance.put( +// boxName: _walletId, +// key: TokenCacheKeys.tokenBalance(_token.address), +// value: balance.toJsonIgnoreCoin(), +// ); +// } +// } diff --git a/lib/wallets/isar/providers/eth/token_balance_provider.dart b/lib/wallets/isar/providers/eth/token_balance_provider.dart new file mode 100644 index 000000000..70504623b --- /dev/null +++ b/lib/wallets/isar/providers/eth/token_balance_provider.dart @@ -0,0 +1,40 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:isar/isar.dart'; +import 'package:stackwallet/models/balance.dart'; +import 'package:stackwallet/providers/db/main_db_provider.dart'; +import 'package:stackwallet/wallets/isar/models/token_wallet_info.dart'; +import 'package:stackwallet/wallets/isar/providers/util/watcher.dart'; + +final _twiProvider = ChangeNotifierProvider.family( + (ref, data) { + final collection = ref.watch(mainDBProvider).isar.tokenWalletInfo; + + final watcher = Watcher( + collection + .where() + .walletIdTokenAddressEqualTo(data.walletId, data.contractAddress) + .findFirstSync()!, + collection: collection, + ); + + ref.onDispose(() => watcher.dispose()); + + return watcher; + }, +); + +final pTokenWalletInfo = Provider.family( + (ref, data) { + return ref.watch(_twiProvider(data)).value as TokenWalletInfo; + }, +); + +final pTokenBalance = + Provider.family( + (ref, data) { + return ref.watch(_twiProvider(data).select( + (value) => (value.value as TokenWalletInfo).getCachedBalance())); + }, +); diff --git a/lib/wallets/isar/providers/wallet_info_provider.dart b/lib/wallets/isar/providers/wallet_info_provider.dart index 3cfeb1be2..b2c39ec21 100644 --- a/lib/wallets/isar/providers/wallet_info_provider.dart +++ b/lib/wallets/isar/providers/wallet_info_provider.dart @@ -82,3 +82,10 @@ final pWalletReceivingAddress = Provider.family( .select((value) => (value.value as WalletInfo).cachedReceivingAddress)); }, ); + +final pWalletTokenAddresses = Provider.family, String>( + (ref, walletId) { + return ref.watch(_wiProvider(walletId) + .select((value) => (value.value as WalletInfo).tokenContractAddresses)); + }, +); diff --git a/lib/widgets/master_wallet_card.dart b/lib/widgets/master_wallet_card.dart index ec73604d4..f6d37d27a 100644 --- a/lib/widgets/master_wallet_card.dart +++ b/lib/widgets/master_wallet_card.dart @@ -11,12 +11,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/util.dart'; -import 'package:stackwallet/wallets/wallet/impl/ethereum_wallet.dart'; +import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart'; import 'package:stackwallet/widgets/animated_widgets/rotate_icon.dart'; import 'package:stackwallet/widgets/expandable.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; @@ -40,17 +39,6 @@ class MasterWalletCard extends ConsumerStatefulWidget { class _MasterWalletCardState extends ConsumerState { final expandableController = ExpandableController(); final rotateIconController = RotateIconController(); - late final List tokenContractAddresses; - - @override - void initState() { - final ethWallet = - ref.read(pWallets).getWallet(widget.walletId) as EthereumWallet; - - tokenContractAddresses = ethWallet.info.tokenContractAddresses; - - super.initState(); - } @override Widget build(BuildContext context) { @@ -130,20 +118,20 @@ class _MasterWalletCardState extends ConsumerState { popPrevious: true, ), ), - ...tokenContractAddresses.map( - (e) => Padding( - padding: const EdgeInsets.only( - left: 7, - right: 7, - bottom: 7, + ...ref.watch(pWalletTokenAddresses(widget.walletId)).map( + (e) => Padding( + padding: const EdgeInsets.only( + left: 7, + right: 7, + bottom: 7, + ), + child: SimpleWalletCard( + walletId: widget.walletId, + contractAddress: e, + popPrevious: Util.isDesktop, + ), + ), ), - child: SimpleWalletCard( - walletId: widget.walletId, - contractAddress: e, - popPrevious: Util.isDesktop, - ), - ), - ), ], ), ),