use database contract data and contract management updates

This commit is contained in:
julian 2023-03-02 18:40:12 -06:00
parent a5d8fdde79
commit babbd75da3
23 changed files with 504 additions and 256 deletions

View file

@ -358,4 +358,20 @@ class MainDB {
throw MainDBException("failed addNewTransactionData", e); throw MainDBException("failed addNewTransactionData", e);
} }
} }
// ========== Ethereum =======================================================
// eth contracts
QueryBuilder<EthContract, EthContract, QWhere> getEthContracts() =>
isar.ethContracts.where();
Future<void> putEthContract(EthContract contract) => isar.writeTxn(() async {
await isar.ethContracts.put(contract);
});
Future<void> putEthContracts(List<EthContract> contracts) =>
isar.writeTxn(() async {
await isar.ethContracts.putAll(contracts);
});
} }

View file

@ -1,11 +1,11 @@
import 'package:stackwallet/models/add_wallet_list_entity/add_wallet_list_entity.dart'; import 'package:stackwallet/models/add_wallet_list_entity/add_wallet_list_entity.dart';
import 'package:stackwallet/models/ethereum/eth_token.dart'; import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart';
class EthTokenEntity extends AddWalletListEntity { class EthTokenEntity extends AddWalletListEntity {
EthTokenEntity(this.token); EthTokenEntity(this.token);
final EthContractInfo token; final EthContract token;
@override @override
Coin get coin => Coin.ethereum; Coin get coin => Coin.ethereum;
@ -17,5 +17,5 @@ class EthTokenEntity extends AddWalletListEntity {
String get ticker => token.symbol; String get ticker => token.symbol;
@override @override
List<Object?> get props => [coin, name, ticker, token.contractAddress]; List<Object?> get props => [coin, name, ticker, token.address];
} }

View file

@ -1,10 +0,0 @@
import 'package:stackwallet/models/ethereum/eth_token.dart';
class Erc20ContractInfo extends EthContractInfo {
const Erc20ContractInfo({
required super.contractAddress,
required super.name,
required super.symbol,
required super.decimals,
});
}

View file

@ -1,10 +0,0 @@
import 'package:stackwallet/models/ethereum/eth_token.dart';
class Erc721ContractInfo extends EthContractInfo {
const Erc721ContractInfo({
required super.contractAddress,
required super.name,
required super.symbol,
required super.decimals,
});
}

View file

@ -1,62 +0,0 @@
import 'dart:convert';
import 'package:equatable/equatable.dart';
import 'package:stackwallet/models/ethereum/erc20_token.dart';
import 'package:stackwallet/models/ethereum/erc721_token.dart';
abstract class EthContractInfo extends Equatable {
const EthContractInfo({
required this.contractAddress,
required this.name,
required this.symbol,
required this.decimals,
});
final String contractAddress;
final String name;
final String symbol;
final int decimals;
static EthContractInfo? fromMap(Map<String, dynamic> map) {
switch (map["runtimeType"]) {
case "Erc20ContractInfo":
return Erc20ContractInfo(
contractAddress: map["contractAddress"] as String,
name: map["name"] as String,
symbol: map["symbol"] as String,
decimals: map["decimals"] as int,
);
case "Erc721ContractInfo":
return Erc721ContractInfo(
contractAddress: map["contractAddress"] as String,
name: map["name"] as String,
symbol: map["symbol"] as String,
decimals: map["decimals"] as int,
);
default:
return null;
}
}
static EthContractInfo? fromJson(String json) => fromMap(
Map<String, dynamic>.from(
jsonDecode(json) as Map,
),
);
Map<String, dynamic> toMap() => {
"runtimeType": "$runtimeType",
"contractAddress": contractAddress,
"name": name,
"symbol": symbol,
"decimals": decimals,
};
String toJson() => jsonEncode(toMap());
@override
String toString() => toMap().toString();
@override
List<Object?> get props => [contractAddress];
}

View file

@ -11,6 +11,7 @@ class EthContract extends Contract {
required this.symbol, required this.symbol,
required this.decimals, required this.decimals,
required this.type, required this.type,
required this.walletIds,
this.abi, this.abi,
this.otherData, this.otherData,
}); });
@ -28,10 +29,34 @@ class EthContract extends Contract {
late final String? abi; late final String? abi;
late final List<String> walletIds;
@enumerated @enumerated
late final EthContractType type; late final EthContractType type;
late final String? otherData; late final String? otherData;
EthContract copyWith({
Id? id,
String? address,
String? name,
String? symbol,
int? decimals,
EthContractType? type,
List<String>? walletIds,
String? abi,
String? otherData,
}) =>
EthContract(
address: address ?? this.address,
name: name ?? this.name,
symbol: symbol ?? this.symbol,
decimals: decimals ?? this.decimals,
type: type ?? this.type,
walletIds: walletIds ?? this.walletIds,
abi: abi ?? this.abi,
otherData: otherData ?? this.otherData,
)..id = id ?? this.id;
} }
// Used in Isar db and stored there as int indexes so adding/removing values // Used in Isar db and stored there as int indexes so adding/removing values

View file

@ -52,6 +52,11 @@ const EthContractSchema = CollectionSchema(
name: r'type', name: r'type',
type: IsarType.byte, type: IsarType.byte,
enumMap: _EthContracttypeEnumValueMap, enumMap: _EthContracttypeEnumValueMap,
),
r'walletIds': PropertySchema(
id: 7,
name: r'walletIds',
type: IsarType.stringList,
) )
}, },
estimateSize: _ethContractEstimateSize, estimateSize: _ethContractEstimateSize,
@ -103,6 +108,13 @@ int _ethContractEstimateSize(
} }
} }
bytesCount += 3 + object.symbol.length * 3; bytesCount += 3 + object.symbol.length * 3;
bytesCount += 3 + object.walletIds.length * 3;
{
for (var i = 0; i < object.walletIds.length; i++) {
final value = object.walletIds[i];
bytesCount += value.length * 3;
}
}
return bytesCount; return bytesCount;
} }
@ -119,6 +131,7 @@ void _ethContractSerialize(
writer.writeString(offsets[4], object.otherData); writer.writeString(offsets[4], object.otherData);
writer.writeString(offsets[5], object.symbol); writer.writeString(offsets[5], object.symbol);
writer.writeByte(offsets[6], object.type.index); writer.writeByte(offsets[6], object.type.index);
writer.writeStringList(offsets[7], object.walletIds);
} }
EthContract _ethContractDeserialize( EthContract _ethContractDeserialize(
@ -136,6 +149,7 @@ EthContract _ethContractDeserialize(
symbol: reader.readString(offsets[5]), symbol: reader.readString(offsets[5]),
type: _EthContracttypeValueEnumMap[reader.readByteOrNull(offsets[6])] ?? type: _EthContracttypeValueEnumMap[reader.readByteOrNull(offsets[6])] ??
EthContractType.erc20, EthContractType.erc20,
walletIds: reader.readStringList(offsets[7]) ?? [],
); );
object.id = id; object.id = id;
return object; return object;
@ -163,6 +177,8 @@ P _ethContractDeserializeProp<P>(
case 6: case 6:
return (_EthContracttypeValueEnumMap[reader.readByteOrNull(offset)] ?? return (_EthContracttypeValueEnumMap[reader.readByteOrNull(offset)] ??
EthContractType.erc20) as P; EthContractType.erc20) as P;
case 7:
return (reader.readStringList(offset) ?? []) as P;
default: default:
throw IsarError('Unknown property with id $propertyId'); throw IsarError('Unknown property with id $propertyId');
} }
@ -1230,6 +1246,231 @@ extension EthContractQueryFilter
)); ));
}); });
} }
QueryBuilder<EthContract, EthContract, QAfterFilterCondition>
walletIdsElementEqualTo(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'walletIds',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<EthContract, EthContract, QAfterFilterCondition>
walletIdsElementGreaterThan(
String value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
include: include,
property: r'walletIds',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<EthContract, EthContract, QAfterFilterCondition>
walletIdsElementLessThan(
String value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.lessThan(
include: include,
property: r'walletIds',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<EthContract, EthContract, QAfterFilterCondition>
walletIdsElementBetween(
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'walletIds',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<EthContract, EthContract, QAfterFilterCondition>
walletIdsElementStartsWith(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.startsWith(
property: r'walletIds',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<EthContract, EthContract, QAfterFilterCondition>
walletIdsElementEndsWith(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.endsWith(
property: r'walletIds',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<EthContract, EthContract, QAfterFilterCondition>
walletIdsElementContains(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.contains(
property: r'walletIds',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<EthContract, EthContract, QAfterFilterCondition>
walletIdsElementMatches(String pattern, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.matches(
property: r'walletIds',
wildcard: pattern,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<EthContract, EthContract, QAfterFilterCondition>
walletIdsElementIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'walletIds',
value: '',
));
});
}
QueryBuilder<EthContract, EthContract, QAfterFilterCondition>
walletIdsElementIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
property: r'walletIds',
value: '',
));
});
}
QueryBuilder<EthContract, EthContract, QAfterFilterCondition>
walletIdsLengthEqualTo(int length) {
return QueryBuilder.apply(this, (query) {
return query.listLength(
r'walletIds',
length,
true,
length,
true,
);
});
}
QueryBuilder<EthContract, EthContract, QAfterFilterCondition>
walletIdsIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.listLength(
r'walletIds',
0,
true,
0,
true,
);
});
}
QueryBuilder<EthContract, EthContract, QAfterFilterCondition>
walletIdsIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.listLength(
r'walletIds',
0,
false,
999999,
true,
);
});
}
QueryBuilder<EthContract, EthContract, QAfterFilterCondition>
walletIdsLengthLessThan(
int length, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
return query.listLength(
r'walletIds',
0,
true,
length,
include,
);
});
}
QueryBuilder<EthContract, EthContract, QAfterFilterCondition>
walletIdsLengthGreaterThan(
int length, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
return query.listLength(
r'walletIds',
length,
include,
999999,
true,
);
});
}
QueryBuilder<EthContract, EthContract, QAfterFilterCondition>
walletIdsLengthBetween(
int lower,
int upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.listLength(
r'walletIds',
lower,
includeLower,
upper,
includeUpper,
);
});
}
} }
extension EthContractQueryObject extension EthContractQueryObject
@ -1472,6 +1713,12 @@ extension EthContractQueryWhereDistinct
return query.addDistinctBy(r'type'); return query.addDistinctBy(r'type');
}); });
} }
QueryBuilder<EthContract, EthContract, QDistinct> distinctByWalletIds() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'walletIds');
});
}
} }
extension EthContractQueryProperty extension EthContractQueryProperty
@ -1523,4 +1770,11 @@ extension EthContractQueryProperty
return query.addPropertyName(r'type'); return query.addPropertyName(r'type');
}); });
} }
QueryBuilder<EthContract, List<String>, QQueryOperations>
walletIdsProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'walletIds');
});
}
} }

View file

@ -3,7 +3,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/ethereum/eth_token.dart'; import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
import 'package:stackwallet/services/ethereum/ethereum_api.dart'; import 'package:stackwallet/services/ethereum/ethereum_api.dart';
import 'package:stackwallet/utilities/show_loading.dart'; import 'package:stackwallet/utilities/show_loading.dart';
import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/text_styles.dart';
@ -39,7 +39,7 @@ class _AddCustomTokenViewState extends ConsumerState<AddCustomTokenView> {
bool enableSubFields = false; bool enableSubFields = false;
bool addTokenButtonEnabled = false; bool addTokenButtonEnabled = false;
EthContractInfo? currentToken; EthContract? currentToken;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -96,6 +96,7 @@ class _AddCustomTokenViewState extends ConsumerState<AddCustomTokenView> {
nameController.text = currentToken!.name; nameController.text = currentToken!.name;
symbolController.text = currentToken!.symbol; symbolController.text = currentToken!.symbol;
decimalsController.text = currentToken!.decimals.toString(); decimalsController.text = currentToken!.decimals.toString();
currentToken!.walletIds.add(widget.walletId);
} else { } else {
nameController.text = ""; nameController.text = "";
symbolController.text = ""; symbolController.text = "";

View file

@ -1,7 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/models/ethereum/eth_token.dart'; import 'package:isar/isar.dart';
import 'package:stackwallet/db/isar/main_db.dart';
import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
import 'package:stackwallet/pages/add_wallet_views/add_token_view/add_custom_token_view.dart'; import 'package:stackwallet/pages/add_wallet_views/add_token_view/add_custom_token_view.dart';
import 'package:stackwallet/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list.dart'; import 'package:stackwallet/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list.dart';
import 'package:stackwallet/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart'; import 'package:stackwallet/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart';
@ -60,7 +62,7 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
(e) => (e) =>
e.token.name.toLowerCase().contains(lowercaseTerm) || e.token.name.toLowerCase().contains(lowercaseTerm) ||
e.token.symbol.toLowerCase().contains(lowercaseTerm) || e.token.symbol.toLowerCase().contains(lowercaseTerm) ||
e.token.contractAddress.toLowerCase().contains(lowercaseTerm), e.token.address.toLowerCase().contains(lowercaseTerm),
); );
} }
@ -69,16 +71,16 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
Future<void> onNextPressed() async { Future<void> onNextPressed() async {
final selectedTokens = final selectedTokens =
tokenEntities.where((e) => e.selected).map((e) => e.token).toSet(); tokenEntities.where((e) => e.selected).map((e) => e.token).toList();
final ethWallet = ref final ethWallet = ref
.read(walletsChangeNotifierProvider) .read(walletsChangeNotifierProvider)
.getManager(widget.walletId) .getManager(widget.walletId)
.wallet as EthereumWallet; .wallet as EthereumWallet;
await ethWallet.addTokenContract(selectedTokens); await ethWallet.addTokenContracts(selectedTokens);
if (mounted) { if (mounted) {
Navigator.of(context).pop(); Navigator.of(context).pop(42);
} }
} }
@ -87,15 +89,18 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
AddCustomTokenView.routeName, AddCustomTokenView.routeName,
arguments: widget.walletId, arguments: widget.walletId,
); );
if (token is EthContractInfo) { if (token is EthContract) {
setState(() { await MainDB.instance.putEthContract(token);
if (tokenEntities if (mounted) {
.where((e) => e.token.contractAddress == token.contractAddress) setState(() {
.isEmpty) { if (tokenEntities
tokenEntities.add(AddTokenListElementData(token)..selected = true); .where((e) => e.token.address == token.address)
tokenEntities.sort((a, b) => a.token.name.compareTo(b.token.name)); .isEmpty) {
} tokenEntities.add(AddTokenListElementData(token)..selected = true);
}); tokenEntities.sort((a, b) => a.token.name.compareTo(b.token.name));
}
});
}
} }
} }
@ -104,9 +109,15 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
_searchFieldController = TextEditingController(); _searchFieldController = TextEditingController();
_searchFocusNode = FocusNode(); _searchFocusNode = FocusNode();
tokenEntities final contracts =
.addAll(DefaultTokens.list.map((e) => AddTokenListElementData(e))); MainDB.instance.getEthContracts().sortByName().findAllSync();
tokenEntities.sort((a, b) => a.token.name.compareTo(b.token.name));
if (contracts.isEmpty) {
contracts.addAll(DefaultTokens.list);
MainDB.instance.putEthContracts(contracts);
}
tokenEntities.addAll(contracts.map((e) => AddTokenListElementData(e)));
super.initState(); super.initState();
} }

View file

@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
import 'package:stackwallet/models/ethereum/eth_token.dart';
import 'package:stackwallet/models/isar/exchange_cache/currency.dart'; import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart'; import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart';
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart'; import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/assets.dart';
@ -13,7 +13,7 @@ import 'package:stackwallet/widgets/rounded_white_container.dart';
class AddTokenListElementData { class AddTokenListElementData {
AddTokenListElementData(this.token); AddTokenListElementData(this.token);
final EthContractInfo token; final EthContract token;
bool selected = false; bool selected = false;
} }
@ -34,7 +34,7 @@ class _AddTokenListElementState extends State<AddTokenListElement> {
.exchangeNameEqualTo(ChangeNowExchange.exchangeName) .exchangeNameEqualTo(ChangeNowExchange.exchangeName)
.filter() .filter()
.tokenContractEqualTo( .tokenContractEqualTo(
widget.data.token.contractAddress, widget.data.token.address,
caseSensitive: false, caseSensitive: false,
) )
.and() .and()

View file

@ -3,9 +3,12 @@ import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/db/isar/main_db.dart';
import 'package:stackwallet/models/add_wallet_list_entity/add_wallet_list_entity.dart'; import 'package:stackwallet/models/add_wallet_list_entity/add_wallet_list_entity.dart';
import 'package:stackwallet/models/add_wallet_list_entity/sub_classes/coin_entity.dart'; import 'package:stackwallet/models/add_wallet_list_entity/sub_classes/coin_entity.dart';
import 'package:stackwallet/models/add_wallet_list_entity/sub_classes/eth_token_entity.dart'; import 'package:stackwallet/models/add_wallet_list_entity/sub_classes/eth_token_entity.dart';
import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/sub_widgets/add_wallet_text.dart'; import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/sub_widgets/add_wallet_text.dart';
import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/sub_widgets/expanding_sub_list_item.dart'; import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/sub_widgets/expanding_sub_list_item.dart';
import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/sub_widgets/next_button.dart'; import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/sub_widgets/next_button.dart';
@ -67,7 +70,7 @@ class _AddWalletViewState extends ConsumerState<AddWalletView> {
e.name.toLowerCase().contains(lowercaseTerm) || e.name.toLowerCase().contains(lowercaseTerm) ||
e.coin.name.toLowerCase().contains(lowercaseTerm) || e.coin.name.toLowerCase().contains(lowercaseTerm) ||
(e is EthTokenEntity && (e is EthTokenEntity &&
e.token.contractAddress.toLowerCase().contains(lowercaseTerm)), e.token.address.toLowerCase().contains(lowercaseTerm)),
); );
} }
@ -92,8 +95,15 @@ class _AddWalletViewState extends ConsumerState<AddWalletView> {
coinEntities.addAll(_coinsTestnet.map((e) => CoinEntity(e))); coinEntities.addAll(_coinsTestnet.map((e) => CoinEntity(e)));
} }
tokenEntities.addAll(DefaultTokens.list.map((e) => EthTokenEntity(e))); final contracts =
tokenEntities.sort((a, b) => a.name.compareTo(b.name)); MainDB.instance.getEthContracts().sortByName().findAllSync();
if (contracts.isEmpty) {
contracts.addAll(DefaultTokens.list);
MainDB.instance.putEthContracts(contracts);
}
tokenEntities.addAll(contracts.map((e) => EthTokenEntity(e)));
super.initState(); super.initState();
} }

View file

@ -2,7 +2,6 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/ethereum/eth_token.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/providers/global/debug_service_provider.dart'; import 'package:stackwallet/providers/global/debug_service_provider.dart';
import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/providers.dart';
@ -13,8 +12,6 @@ import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart';
import '../../../models/ethereum/erc20_token.dart';
class HiddenSettings extends StatelessWidget { class HiddenSettings extends StatelessWidget {
const HiddenSettings({Key? key}) : super(key: key); const HiddenSettings({Key? key}) : super(key: key);
@ -192,20 +189,20 @@ class HiddenSettings extends StatelessWidget {
Consumer(builder: (_, ref, __) { Consumer(builder: (_, ref, __) {
return GestureDetector( return GestureDetector(
onTap: () async { onTap: () async {
final erc20 = Erc20ContractInfo( // final erc20 = Erc20ContractInfo(
contractAddress: 'some con', // contractAddress: 'some con',
name: "loonamsn", // name: "loonamsn",
symbol: "DD", // symbol: "DD",
decimals: 19, // decimals: 19,
); // );
//
final json = erc20.toJson(); // final json = erc20.toJson();
//
print(json); // print(json);
//
final ee = EthContractInfo.fromJson(json); // final ee = EthContractInfo.fromJson(json);
//
print(ee); // print(ee);
}, },
child: RoundedWhiteContainer( child: RoundedWhiteContainer(
child: Text( child: Text(

View file

@ -3,11 +3,12 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/models/ethereum/eth_token.dart'; import 'package:isar/isar.dart';
import 'package:stackwallet/db/isar/main_db.dart';
import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
import 'package:stackwallet/pages/add_wallet_views/add_token_view/add_token_view.dart'; import 'package:stackwallet/pages/add_wallet_views/add_token_view/add_token_view.dart';
import 'package:stackwallet/pages/token_view/sub_widgets/my_tokens_list.dart'; import 'package:stackwallet/pages/token_view/sub_widgets/my_tokens_list.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart'; import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/services/coins/ethereum/ethereum_wallet.dart';
import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/text_styles.dart';
@ -38,6 +39,34 @@ class _TokenDetailsViewState extends ConsumerState<MyTokensView> {
late final String walletAddress; late final String walletAddress;
late final TextEditingController _searchController; late final TextEditingController _searchController;
final searchFieldFocusNode = FocusNode(); final searchFieldFocusNode = FocusNode();
String _searchString = "";
List<EthContract> _filter(String searchTerm) {
if (searchTerm.isNotEmpty) {
final term = searchTerm.toLowerCase();
return MainDB.instance
.getEthContracts()
.filter()
.walletIdsElementEqualTo(widget.walletId)
.and()
.group(
(q) => q
.nameContains(term, caseSensitive: false)
.or()
.symbolContains(term, caseSensitive: false)
.or()
.addressContains(term, caseSensitive: false),
)
.findAllSync();
// return tokens.toList();
}
//implement search/filter
return MainDB.instance
.getEthContracts()
.filter()
.walletIdsElementEqualTo(widget.walletId)
.findAllSync();
}
@override @override
void initState() { void initState() {
@ -53,26 +82,10 @@ class _TokenDetailsViewState extends ConsumerState<MyTokensView> {
super.dispose(); super.dispose();
} }
String _searchString = "";
List<EthContractInfo> _filter(
Set<EthContractInfo> tokens, String searchTerm) {
if (searchTerm.isEmpty) {
return tokens.toList();
}
//implement search/filter
return tokens.toList();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isDesktop = Util.isDesktop; final isDesktop = Util.isDesktop;
final tokens = (ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(widget.walletId).wallet))
as EthereumWallet)
.contracts;
return MasterScaffold( return MasterScaffold(
background: Theme.of(context).extension<StackColors>()!.background, background: Theme.of(context).extension<StackColors>()!.background,
isDesktop: isDesktop, isDesktop: isDesktop,
@ -160,11 +173,15 @@ class _TokenDetailsViewState extends ConsumerState<MyTokensView> {
width: 20, width: 20,
height: 20, height: 20,
), ),
onPressed: () { onPressed: () async {
Navigator.of(context).pushNamed( final result = await Navigator.of(context).pushNamed(
AddTokenView.routeName, AddTokenView.routeName,
arguments: widget.walletId, arguments: widget.walletId,
); );
if (mounted && result == 42) {
setState(() {});
}
}, },
), ),
), ),
@ -273,7 +290,7 @@ class _TokenDetailsViewState extends ConsumerState<MyTokensView> {
Expanded( Expanded(
child: MyTokensList( child: MyTokensList(
walletId: widget.walletId, walletId: widget.walletId,
tokens: _filter(tokens, _searchString), tokens: _filter(_searchString),
), ),
), ),
], ],

View file

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/models/ethereum/eth_token.dart'; import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
import 'package:stackwallet/pages/token_view/token_view.dart'; import 'package:stackwallet/pages/token_view/token_view.dart';
import 'package:stackwallet/providers/global/secure_store_provider.dart'; import 'package:stackwallet/providers/global/secure_store_provider.dart';
import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/providers.dart';
@ -24,7 +24,7 @@ class MyTokenSelectItem extends ConsumerStatefulWidget {
}) : super(key: key); }) : super(key: key);
final String walletId; final String walletId;
final EthContractInfo token; final EthContract token;
@override @override
ConsumerState<MyTokenSelectItem> createState() => _MyTokenSelectItemState(); ConsumerState<MyTokenSelectItem> createState() => _MyTokenSelectItemState();
@ -133,7 +133,7 @@ class _MyTokenSelectItemState extends ConsumerState<MyTokenSelectItem> {
Text("${ref.watch( Text("${ref.watch(
priceAnd24hChangeNotifierProvider.select( priceAnd24hChangeNotifierProvider.select(
(value) => value (value) => value
.getTokenPrice(widget.token.contractAddress) .getTokenPrice(widget.token.address)
.item1 .item1
.toStringAsFixed(2), .toStringAsFixed(2),
), ),

View file

@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/ethereum/eth_token.dart'; import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
import 'package:stackwallet/pages/token_view/sub_widgets/my_token_select_item.dart'; import 'package:stackwallet/pages/token_view/sub_widgets/my_token_select_item.dart';
class MyTokensList extends StatelessWidget { class MyTokensList extends StatelessWidget {
@ -11,7 +11,7 @@ class MyTokensList extends StatelessWidget {
}) : super(key: key); }) : super(key: key);
final String walletId; final String walletId;
final List<EthContractInfo> tokens; final List<EthContract> tokens;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -22,7 +22,7 @@ class MyTokensList extends StatelessWidget {
itemBuilder: (ctx, index) { itemBuilder: (ctx, index) {
final token = tokens[index]; final token = tokens[index];
return Padding( return Padding(
key: Key(token.contractAddress), key: Key(token.address),
padding: const EdgeInsets.all(4), padding: const EdgeInsets.all(4),
child: MyTokenSelectItem( child: MyTokenSelectItem(
walletId: walletId, walletId: walletId,

View file

@ -78,7 +78,7 @@ class _TokenViewState extends ConsumerState<TokenView> {
SvgPicture.asset( SvgPicture.asset(
Assets.svg.iconForToken( Assets.svg.iconForToken(
contractAddress: ref.watch(tokenServiceProvider contractAddress: ref.watch(tokenServiceProvider
.select((value) => value!.token.contractAddress))), .select((value) => value!.token.address))),
width: 24, width: 24,
height: 24, height: 24,
), ),
@ -118,7 +118,7 @@ class _TokenViewState extends ConsumerState<TokenView> {
walletId: widget.walletId, walletId: widget.walletId,
initialSyncStatus: initialSyncStatus, initialSyncStatus: initialSyncStatus,
tokenContractAddress: ref.watch(tokenServiceProvider tokenContractAddress: ref.watch(tokenServiceProvider
.select((value) => value!.token.contractAddress)), .select((value) => value!.token.address)),
), ),
), ),
), ),

View file

@ -7,7 +7,6 @@ import 'package:http/http.dart';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
import 'package:stackwallet/db/isar/main_db.dart'; import 'package:stackwallet/db/isar/main_db.dart';
import 'package:stackwallet/models/balance.dart'; import 'package:stackwallet/models/balance.dart';
import 'package:stackwallet/models/ethereum/eth_token.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/models/node_model.dart'; import 'package:stackwallet/models/node_model.dart';
import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/models/paymint/fee_object_model.dart';
@ -18,7 +17,6 @@ import 'package:stackwallet/services/event_bus/events/global/refresh_percent_cha
import 'package:stackwallet/services/event_bus/events/global/updated_in_background_event.dart'; import 'package:stackwallet/services/event_bus/events/global/updated_in_background_event.dart';
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/mixins/eth_extras_wallet_cache.dart';
import 'package:stackwallet/services/mixins/wallet_cache.dart'; import 'package:stackwallet/services/mixins/wallet_cache.dart';
import 'package:stackwallet/services/mixins/wallet_db.dart'; import 'package:stackwallet/services/mixins/wallet_db.dart';
import 'package:stackwallet/services/node_service.dart'; import 'package:stackwallet/services/node_service.dart';
@ -39,8 +37,7 @@ import 'package:web3dart/web3dart.dart' as web3;
const int MINIMUM_CONFIRMATIONS = 3; const int MINIMUM_CONFIRMATIONS = 3;
class EthereumWallet extends CoinServiceAPI class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB {
with WalletCache, WalletDB, EthExtrasWalletCache {
EthereumWallet({ EthereumWallet({
required String walletId, required String walletId,
required String walletName, required String walletName,
@ -55,7 +52,6 @@ class EthereumWallet extends CoinServiceAPI
_coin = coin; _coin = coin;
_secureStore = secureStore; _secureStore = secureStore;
initCache(walletId, coin); initCache(walletId, coin);
initEthExtrasCache(walletId);
initWalletDB(mockableOverride: mockableOverride); initWalletDB(mockableOverride: mockableOverride);
} }
@ -66,29 +62,47 @@ class EthereumWallet extends CoinServiceAPI
Timer? timer; Timer? timer;
Timer? _networkAliveTimer; Timer? _networkAliveTimer;
Set<EthContractInfo> get contracts => getCachedTokenContracts(); Future<void> addTokenContracts(List<EthContract> contracts) async {
List<EthContract> updatedContracts = [];
for (final contract in contracts) {
final updatedWalletIds = contract.walletIds.toList();
if (!updatedWalletIds.contains(walletId)) {
updatedWalletIds.add(walletId);
updatedContracts.add(contract.copyWith(walletIds: updatedWalletIds));
} else {
updatedContracts.add(contract);
}
}
await db.putEthContracts(updatedContracts);
Future<void> addTokenContract(Set<EthContractInfo> contractInfo) => GlobalEventBus.instance.fire(
updateCachedTokenContracts(contracts..addAll(contractInfo)).then( UpdatedInBackgroundEvent(
(value) => GlobalEventBus.instance.fire( "$contracts updated/added for: $walletId $walletName",
UpdatedInBackgroundEvent( walletId,
"$contractInfo updated/added for: $walletId $walletName", ),
walletId, );
), }
),
);
Future<void> removeTokenContract(String contractAddress) => Future<void> removeTokenContract(String contractAddress) async {
updateCachedTokenContracts(contracts final contract =
..removeWhere((e) => e.contractAddress == contractAddress)) await db.getEthContracts().addressEqualTo(contractAddress).findFirst();
.then(
(value) => GlobalEventBus.instance.fire( if (contract == null) {
UpdatedInBackgroundEvent( return; // todo some error?
"$contractAddress removed for: $walletId $walletName", }
walletId,
), final updatedWalletIds = contract.walletIds.toList();
), updatedWalletIds.removeWhere((e) => e == contractAddress);
);
await db.putEthContract(contract.copyWith(walletIds: updatedWalletIds));
GlobalEventBus.instance.fire(
UpdatedInBackgroundEvent(
"$contractAddress removed for: $walletId $walletName",
walletId,
),
);
}
@override @override
String get walletId => _walletId; String get walletId => _walletId;

View file

@ -1,4 +1,4 @@
import 'package:stackwallet/models/ethereum/eth_token.dart'; import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
import 'package:stackwallet/models/token_balance.dart'; import 'package:stackwallet/models/token_balance.dart';
import 'package:stackwallet/services/ethereum/ethereum_api.dart'; import 'package:stackwallet/services/ethereum/ethereum_api.dart';
import 'package:stackwallet/services/mixins/eth_token_cache.dart'; import 'package:stackwallet/services/mixins/eth_token_cache.dart';
@ -6,7 +6,7 @@ import 'package:stackwallet/utilities/logger.dart';
class CachedEthTokenBalance with EthTokenCache { class CachedEthTokenBalance with EthTokenCache {
final String walletId; final String walletId;
final EthContractInfo token; final EthContract token;
CachedEthTokenBalance(this.walletId, this.token) { CachedEthTokenBalance(this.walletId, this.token) {
initCache(walletId, token); initCache(walletId, token);
@ -15,13 +15,13 @@ class CachedEthTokenBalance with EthTokenCache {
Future<void> fetchAndUpdateCachedBalance(String address) async { Future<void> fetchAndUpdateCachedBalance(String address) async {
final response = await EthereumAPI.getWalletTokenBalance( final response = await EthereumAPI.getWalletTokenBalance(
address: address, address: address,
contractAddress: token.contractAddress, contractAddress: token.address,
); );
if (response.value != null) { if (response.value != null) {
await updateCachedBalance( await updateCachedBalance(
TokenBalance( TokenBalance(
contractAddress: token.contractAddress, contractAddress: token.address,
decimalPlaces: token.decimals, decimalPlaces: token.decimals,
total: response.value!, total: response.value!,
spendable: response.value!, spendable: response.value!,

View file

@ -5,9 +5,7 @@ import 'package:decimal/decimal.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:stackwallet/dto/ethereum/eth_token_tx_dto.dart'; import 'package:stackwallet/dto/ethereum/eth_token_tx_dto.dart';
import 'package:stackwallet/dto/ethereum/eth_tx_dto.dart'; import 'package:stackwallet/dto/ethereum/eth_tx_dto.dart';
import 'package:stackwallet/models/ethereum/erc20_token.dart'; import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
import 'package:stackwallet/models/ethereum/erc721_token.dart';
import 'package:stackwallet/models/ethereum/eth_token.dart';
import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/utilities/default_nodes.dart'; import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/eth_commons.dart'; import 'package:stackwallet/utilities/eth_commons.dart';
@ -64,7 +62,10 @@ abstract class EthereumAPI {
final List<EthTxDTO> txns = []; final List<EthTxDTO> txns = [];
for (final map in list!) { for (final map in list!) {
txns.add(EthTxDTO.fromMap(Map<String, dynamic>.from(map as Map))); final txn = EthTxDTO.fromMap(Map<String, dynamic>.from(map as Map));
if (txn.hasToken == 0) {
txns.add(txn);
}
} }
return EthereumResponse( return EthereumResponse(
txns, txns,
@ -311,7 +312,7 @@ abstract class EthereumAPI {
slow: feesSlow.toInt()); slow: feesSlow.toInt());
} }
static Future<EthereumResponse<EthContractInfo>> getTokenByContractAddress( static Future<EthereumResponse<EthContract>> getTokenByContractAddress(
String contractAddress) async { String contractAddress) async {
try { try {
final response = await get(Uri.parse( final response = await get(Uri.parse(
@ -322,20 +323,24 @@ abstract class EthereumAPI {
final json = jsonDecode(response.body); final json = jsonDecode(response.body);
if (json["message"] == "OK") { if (json["message"] == "OK") {
final map = Map<String, dynamic>.from(json["result"] as Map); final map = Map<String, dynamic>.from(json["result"] as Map);
EthContractInfo? token; EthContract? token;
if (map["type"] == "ERC-20") { if (map["type"] == "ERC-20") {
token = Erc20ContractInfo( token = EthContract(
contractAddress: map["contractAddress"] as String, address: map["contractAddress"] as String,
decimals: int.parse(map["decimals"] as String), decimals: int.parse(map["decimals"] as String),
name: map["name"] as String, name: map["name"] as String,
symbol: map["symbol"] as String, symbol: map["symbol"] as String,
type: EthContractType.erc20,
walletIds: [],
); );
} else if (map["type"] == "ERC-721") { } else if (map["type"] == "ERC-721") {
token = Erc721ContractInfo( token = EthContract(
contractAddress: map["contractAddress"] as String, address: map["contractAddress"] as String,
decimals: int.parse(map["decimals"] as String), decimals: int.parse(map["decimals"] as String),
name: map["name"] as String, name: map["name"] as String,
symbol: map["symbol"] as String, symbol: map["symbol"] as String,
type: EthContractType.erc721,
walletIds: [],
); );
} else { } else {
throw EthApiException( throw EthApiException(

View file

@ -5,9 +5,7 @@ import 'package:ethereum_addresses/ethereum_addresses.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
import 'package:stackwallet/models/ethereum/eth_token.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/address.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
import 'package:stackwallet/models/node_model.dart'; import 'package:stackwallet/models/node_model.dart';
import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/models/token_balance.dart'; import 'package:stackwallet/models/token_balance.dart';
@ -30,7 +28,7 @@ import 'package:tuple/tuple.dart';
import 'package:web3dart/web3dart.dart' as web3dart; import 'package:web3dart/web3dart.dart' as web3dart;
class EthereumTokenService extends ChangeNotifier with EthTokenCache { class EthereumTokenService extends ChangeNotifier with EthTokenCache {
final EthContractInfo token; final EthContract token;
final EthereumWallet ethWallet; final EthereumWallet ethWallet;
final TransactionNotificationTracker tracker; final TransactionNotificationTracker tracker;
final SecureStorageInterface _secureStore; final SecureStorageInterface _secureStore;
@ -51,7 +49,7 @@ class EthereumTokenService extends ChangeNotifier with EthTokenCache {
required SecureStorageInterface secureStore, required SecureStorageInterface secureStore,
required this.tracker, required this.tracker,
}) : _secureStore = secureStore { }) : _secureStore = secureStore {
_contractAddress = web3dart.EthereumAddress.fromHex(token.contractAddress); _contractAddress = web3dart.EthereumAddress.fromHex(token.address);
initCache(ethWallet.walletId, token); initCache(ethWallet.walletId, token);
} }
@ -220,7 +218,7 @@ class EthereumTokenService extends ChangeNotifier with EthTokenCache {
GlobalEventBus.instance.fire( GlobalEventBus.instance.fire(
WalletSyncStatusChangedEvent( WalletSyncStatusChangedEvent(
WalletSyncStatus.syncing, WalletSyncStatus.syncing,
ethWallet.walletId + token.contractAddress, ethWallet.walletId + token.address,
coin, coin,
), ),
); );
@ -237,7 +235,7 @@ class EthereumTokenService extends ChangeNotifier with EthTokenCache {
GlobalEventBus.instance.fire( GlobalEventBus.instance.fire(
WalletSyncStatusChangedEvent( WalletSyncStatusChangedEvent(
WalletSyncStatus.synced, WalletSyncStatus.synced,
ethWallet.walletId + token.contractAddress, ethWallet.walletId + token.address,
coin, coin,
), ),
); );
@ -256,7 +254,7 @@ class EthereumTokenService extends ChangeNotifier with EthTokenCache {
String _balance = balanceRequest.first.toString(); String _balance = balanceRequest.first.toString();
final newBalance = TokenBalance( final newBalance = TokenBalance(
contractAddress: token.contractAddress, contractAddress: token.address,
total: int.parse(_balance), total: int.parse(_balance),
spendable: int.parse(_balance), spendable: int.parse(_balance),
blockedTotal: 0, blockedTotal: 0,
@ -270,7 +268,7 @@ class EthereumTokenService extends ChangeNotifier with EthTokenCache {
Future<List<Transaction>> get transactions => ethWallet.db Future<List<Transaction>> get transactions => ethWallet.db
.getTransactions(ethWallet.walletId) .getTransactions(ethWallet.walletId)
.filter() .filter()
.otherDataEqualTo(token.contractAddress) .otherDataEqualTo(token.address)
.sortByTimestampDesc() .sortByTimestampDesc()
.findAll(); .findAll();
@ -279,7 +277,7 @@ class EthereumTokenService extends ChangeNotifier with EthTokenCache {
final response = await EthereumAPI.getTokenTransactions( final response = await EthereumAPI.getTokenTransactions(
address: addressString, address: addressString,
contractAddress: token.contractAddress, contractAddress: token.address,
); );
if (response.value == null) { if (response.value == null) {

View file

@ -1,29 +0,0 @@
import 'package:stackwallet/db/hive/db.dart';
import 'package:stackwallet/models/ethereum/eth_token.dart';
mixin EthExtrasWalletCache {
late final String _walletId;
void initEthExtrasCache(String walletId) {
_walletId = walletId;
}
// cached list of user added token contracts
Set<EthContractInfo> getCachedTokenContracts() {
final list = DB.instance.get<dynamic>(
boxName: _walletId,
key: "ethTokenContracts",
) as List<String>? ??
[];
return list.map((e) => EthContractInfo.fromJson(e)!).toSet();
}
Future<void> updateCachedTokenContracts(
Set<EthContractInfo> contracts) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "ethTokenContracts",
value: contracts.map((e) => e.toJson()).toList(),
);
}
}

View file

@ -1,5 +1,5 @@
import 'package:stackwallet/db/hive/db.dart'; import 'package:stackwallet/db/hive/db.dart';
import 'package:stackwallet/models/ethereum/eth_token.dart'; import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
import 'package:stackwallet/models/token_balance.dart'; import 'package:stackwallet/models/token_balance.dart';
abstract class _Keys { abstract class _Keys {
@ -10,9 +10,9 @@ abstract class _Keys {
mixin EthTokenCache { mixin EthTokenCache {
late final String _walletId; late final String _walletId;
late final EthContractInfo _token; late final EthContract _token;
void initCache(String walletId, EthContractInfo token) { void initCache(String walletId, EthContract token) {
_walletId = walletId; _walletId = walletId;
_token = token; _token = token;
} }
@ -21,11 +21,11 @@ mixin EthTokenCache {
TokenBalance getCachedBalance() { TokenBalance getCachedBalance() {
final jsonString = DB.instance.get<dynamic>( final jsonString = DB.instance.get<dynamic>(
boxName: _walletId, boxName: _walletId,
key: _Keys.tokenBalance(_token.contractAddress), key: _Keys.tokenBalance(_token.address),
) as String?; ) as String?;
if (jsonString == null) { if (jsonString == null) {
return TokenBalance( return TokenBalance(
contractAddress: _token.contractAddress, contractAddress: _token.address,
decimalPlaces: _token.decimals, decimalPlaces: _token.decimals,
total: 0, total: 0,
spendable: 0, spendable: 0,
@ -41,7 +41,7 @@ mixin EthTokenCache {
Future<void> updateCachedBalance(TokenBalance balance) async { Future<void> updateCachedBalance(TokenBalance balance) async {
await DB.instance.put<dynamic>( await DB.instance.put<dynamic>(
boxName: _walletId, boxName: _walletId,
key: _Keys.tokenBalance(_token.contractAddress), key: _Keys.tokenBalance(_token.address),
value: balance.toJsonIgnoreCoin(), value: balance.toJsonIgnoreCoin(),
); );
} }

View file

@ -1,43 +1,54 @@
import 'package:stackwallet/models/ethereum/erc20_token.dart'; import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
import 'package:stackwallet/models/ethereum/eth_token.dart';
abstract class DefaultTokens { abstract class DefaultTokens {
static const List<EthContractInfo> list = [ static List<EthContract> list = [
Erc20ContractInfo( EthContract(
contractAddress: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", address: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
name: "USD Coin", name: "USD Coin",
symbol: "USDC", symbol: "USDC",
decimals: 6, decimals: 6,
type: EthContractType.erc20,
walletIds: [],
), ),
Erc20ContractInfo( EthContract(
contractAddress: "0xdac17f958d2ee523a2206206994597c13d831ec7", address: "0xdac17f958d2ee523a2206206994597c13d831ec7",
name: "Tether", name: "Tether",
symbol: "USDT", symbol: "USDT",
decimals: 6, decimals: 6,
type: EthContractType.erc20,
walletIds: [],
), ),
Erc20ContractInfo( EthContract(
contractAddress: "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce", address: "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce",
name: "Shiba Inu", name: "Shiba Inu",
symbol: "SHIB", symbol: "SHIB",
decimals: 18, decimals: 18,
type: EthContractType.erc20,
walletIds: [],
), ),
Erc20ContractInfo( EthContract(
contractAddress: "0xB8c77482e45F1F44dE1745F52C74426C631bDD52", address: "0xB8c77482e45F1F44dE1745F52C74426C631bDD52",
name: "BNB Token", name: "BNB Token",
symbol: "BNB", symbol: "BNB",
decimals: 18, decimals: 18,
type: EthContractType.erc20,
walletIds: [],
), ),
Erc20ContractInfo( EthContract(
contractAddress: "0x4Fabb145d64652a948d72533023f6E7A623C7C53", address: "0x4Fabb145d64652a948d72533023f6E7A623C7C53",
name: "BUSD", name: "BUSD",
symbol: "BUSD", symbol: "BUSD",
decimals: 18, decimals: 18,
type: EthContractType.erc20,
walletIds: [],
), ),
Erc20ContractInfo( EthContract(
contractAddress: "0x514910771af9ca656af840dff83e8264ecf986ca", address: "0x514910771af9ca656af840dff83e8264ecf986ca",
name: "Chainlink", name: "Chainlink",
symbol: "LINK", symbol: "LINK",
decimals: 18, decimals: 18,
type: EthContractType.erc20,
walletIds: [],
), ),
]; ];
} }