mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-17 09:47:37 +00:00
use database contract data and contract management updates
This commit is contained in:
parent
a5d8fdde79
commit
babbd75da3
23 changed files with 504 additions and 256 deletions
|
@ -358,4 +358,20 @@ class MainDB {
|
|||
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);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
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';
|
||||
|
||||
class EthTokenEntity extends AddWalletListEntity {
|
||||
EthTokenEntity(this.token);
|
||||
|
||||
final EthContractInfo token;
|
||||
final EthContract token;
|
||||
|
||||
@override
|
||||
Coin get coin => Coin.ethereum;
|
||||
|
@ -17,5 +17,5 @@ class EthTokenEntity extends AddWalletListEntity {
|
|||
String get ticker => token.symbol;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [coin, name, ticker, token.contractAddress];
|
||||
List<Object?> get props => [coin, name, ticker, token.address];
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
}
|
|
@ -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,
|
||||
});
|
||||
}
|
|
@ -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];
|
||||
}
|
|
@ -11,6 +11,7 @@ class EthContract extends Contract {
|
|||
required this.symbol,
|
||||
required this.decimals,
|
||||
required this.type,
|
||||
required this.walletIds,
|
||||
this.abi,
|
||||
this.otherData,
|
||||
});
|
||||
|
@ -28,10 +29,34 @@ class EthContract extends Contract {
|
|||
|
||||
late final String? abi;
|
||||
|
||||
late final List<String> walletIds;
|
||||
|
||||
@enumerated
|
||||
late final EthContractType type;
|
||||
|
||||
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
|
||||
|
|
|
@ -52,6 +52,11 @@ const EthContractSchema = CollectionSchema(
|
|||
name: r'type',
|
||||
type: IsarType.byte,
|
||||
enumMap: _EthContracttypeEnumValueMap,
|
||||
),
|
||||
r'walletIds': PropertySchema(
|
||||
id: 7,
|
||||
name: r'walletIds',
|
||||
type: IsarType.stringList,
|
||||
)
|
||||
},
|
||||
estimateSize: _ethContractEstimateSize,
|
||||
|
@ -103,6 +108,13 @@ int _ethContractEstimateSize(
|
|||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -119,6 +131,7 @@ void _ethContractSerialize(
|
|||
writer.writeString(offsets[4], object.otherData);
|
||||
writer.writeString(offsets[5], object.symbol);
|
||||
writer.writeByte(offsets[6], object.type.index);
|
||||
writer.writeStringList(offsets[7], object.walletIds);
|
||||
}
|
||||
|
||||
EthContract _ethContractDeserialize(
|
||||
|
@ -136,6 +149,7 @@ EthContract _ethContractDeserialize(
|
|||
symbol: reader.readString(offsets[5]),
|
||||
type: _EthContracttypeValueEnumMap[reader.readByteOrNull(offsets[6])] ??
|
||||
EthContractType.erc20,
|
||||
walletIds: reader.readStringList(offsets[7]) ?? [],
|
||||
);
|
||||
object.id = id;
|
||||
return object;
|
||||
|
@ -163,6 +177,8 @@ P _ethContractDeserializeProp<P>(
|
|||
case 6:
|
||||
return (_EthContracttypeValueEnumMap[reader.readByteOrNull(offset)] ??
|
||||
EthContractType.erc20) as P;
|
||||
case 7:
|
||||
return (reader.readStringList(offset) ?? []) as P;
|
||||
default:
|
||||
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
|
||||
|
@ -1472,6 +1713,12 @@ extension EthContractQueryWhereDistinct
|
|||
return query.addDistinctBy(r'type');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<EthContract, EthContract, QDistinct> distinctByWalletIds() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addDistinctBy(r'walletIds');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
extension EthContractQueryProperty
|
||||
|
@ -1523,4 +1770,11 @@ extension EthContractQueryProperty
|
|||
return query.addPropertyName(r'type');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<EthContract, List<String>, QQueryOperations>
|
||||
walletIdsProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'walletIds');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'dart:async';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.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/utilities/show_loading.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
|
@ -39,7 +39,7 @@ class _AddCustomTokenViewState extends ConsumerState<AddCustomTokenView> {
|
|||
bool enableSubFields = false;
|
||||
bool addTokenButtonEnabled = false;
|
||||
|
||||
EthContractInfo? currentToken;
|
||||
EthContract? currentToken;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -96,6 +96,7 @@ class _AddCustomTokenViewState extends ConsumerState<AddCustomTokenView> {
|
|||
nameController.text = currentToken!.name;
|
||||
symbolController.text = currentToken!.symbol;
|
||||
decimalsController.text = currentToken!.decimals.toString();
|
||||
currentToken!.walletIds.add(widget.walletId);
|
||||
} else {
|
||||
nameController.text = "";
|
||||
symbolController.text = "";
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.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/sub_widgets/add_token_list.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.token.name.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 {
|
||||
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
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet as EthereumWallet;
|
||||
|
||||
await ethWallet.addTokenContract(selectedTokens);
|
||||
await ethWallet.addTokenContracts(selectedTokens);
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop(42);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,15 +89,18 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
|
|||
AddCustomTokenView.routeName,
|
||||
arguments: widget.walletId,
|
||||
);
|
||||
if (token is EthContractInfo) {
|
||||
setState(() {
|
||||
if (tokenEntities
|
||||
.where((e) => e.token.contractAddress == token.contractAddress)
|
||||
.isEmpty) {
|
||||
tokenEntities.add(AddTokenListElementData(token)..selected = true);
|
||||
tokenEntities.sort((a, b) => a.token.name.compareTo(b.token.name));
|
||||
}
|
||||
});
|
||||
if (token is EthContract) {
|
||||
await MainDB.instance.putEthContract(token);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
if (tokenEntities
|
||||
.where((e) => e.token.address == token.address)
|
||||
.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();
|
||||
_searchFocusNode = FocusNode();
|
||||
|
||||
tokenEntities
|
||||
.addAll(DefaultTokens.list.map((e) => AddTokenListElementData(e)));
|
||||
tokenEntities.sort((a, b) => a.token.name.compareTo(b.token.name));
|
||||
final contracts =
|
||||
MainDB.instance.getEthContracts().sortByName().findAllSync();
|
||||
|
||||
if (contracts.isEmpty) {
|
||||
contracts.addAll(DefaultTokens.list);
|
||||
MainDB.instance.putEthContracts(contracts);
|
||||
}
|
||||
|
||||
tokenEntities.addAll(contracts.map((e) => AddTokenListElementData(e)));
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.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/models/ethereum/eth_contract.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/utilities/assets.dart';
|
||||
|
@ -13,7 +13,7 @@ import 'package:stackwallet/widgets/rounded_white_container.dart';
|
|||
class AddTokenListElementData {
|
||||
AddTokenListElementData(this.token);
|
||||
|
||||
final EthContractInfo token;
|
||||
final EthContract token;
|
||||
bool selected = false;
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ class _AddTokenListElementState extends State<AddTokenListElement> {
|
|||
.exchangeNameEqualTo(ChangeNowExchange.exchangeName)
|
||||
.filter()
|
||||
.tokenContractEqualTo(
|
||||
widget.data.token.contractAddress,
|
||||
widget.data.token.address,
|
||||
caseSensitive: false,
|
||||
)
|
||||
.and()
|
||||
|
|
|
@ -3,9 +3,12 @@ import 'dart:io';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.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/sub_classes/coin_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/expanding_sub_list_item.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.coin.name.toLowerCase().contains(lowercaseTerm) ||
|
||||
(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)));
|
||||
}
|
||||
|
||||
tokenEntities.addAll(DefaultTokens.list.map((e) => EthTokenEntity(e)));
|
||||
tokenEntities.sort((a, b) => a.name.compareTo(b.name));
|
||||
final contracts =
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ import 'dart:async';
|
|||
|
||||
import 'package:flutter/material.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/providers/global/debug_service_provider.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/rounded_white_container.dart';
|
||||
|
||||
import '../../../models/ethereum/erc20_token.dart';
|
||||
|
||||
class HiddenSettings extends StatelessWidget {
|
||||
const HiddenSettings({Key? key}) : super(key: key);
|
||||
|
||||
|
@ -192,20 +189,20 @@ class HiddenSettings extends StatelessWidget {
|
|||
Consumer(builder: (_, ref, __) {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
final erc20 = Erc20ContractInfo(
|
||||
contractAddress: 'some con',
|
||||
name: "loonamsn",
|
||||
symbol: "DD",
|
||||
decimals: 19,
|
||||
);
|
||||
|
||||
final json = erc20.toJson();
|
||||
|
||||
print(json);
|
||||
|
||||
final ee = EthContractInfo.fromJson(json);
|
||||
|
||||
print(ee);
|
||||
// final erc20 = Erc20ContractInfo(
|
||||
// contractAddress: 'some con',
|
||||
// name: "loonamsn",
|
||||
// symbol: "DD",
|
||||
// decimals: 19,
|
||||
// );
|
||||
//
|
||||
// final json = erc20.toJson();
|
||||
//
|
||||
// print(json);
|
||||
//
|
||||
// final ee = EthContractInfo.fromJson(json);
|
||||
//
|
||||
// print(ee);
|
||||
},
|
||||
child: RoundedWhiteContainer(
|
||||
child: Text(
|
||||
|
|
|
@ -3,11 +3,12 @@ import 'dart:async';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.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/token_view/sub_widgets/my_tokens_list.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/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
|
@ -38,6 +39,34 @@ class _TokenDetailsViewState extends ConsumerState<MyTokensView> {
|
|||
late final String walletAddress;
|
||||
late final TextEditingController _searchController;
|
||||
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
|
||||
void initState() {
|
||||
|
@ -53,26 +82,10 @@ class _TokenDetailsViewState extends ConsumerState<MyTokensView> {
|
|||
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
|
||||
Widget build(BuildContext context) {
|
||||
final isDesktop = Util.isDesktop;
|
||||
|
||||
final tokens = (ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(widget.walletId).wallet))
|
||||
as EthereumWallet)
|
||||
.contracts;
|
||||
|
||||
return MasterScaffold(
|
||||
background: Theme.of(context).extension<StackColors>()!.background,
|
||||
isDesktop: isDesktop,
|
||||
|
@ -160,11 +173,15 @@ class _TokenDetailsViewState extends ConsumerState<MyTokensView> {
|
|||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
onPressed: () async {
|
||||
final result = await Navigator.of(context).pushNamed(
|
||||
AddTokenView.routeName,
|
||||
arguments: widget.walletId,
|
||||
);
|
||||
|
||||
if (mounted && result == 42) {
|
||||
setState(() {});
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
|
@ -273,7 +290,7 @@ class _TokenDetailsViewState extends ConsumerState<MyTokensView> {
|
|||
Expanded(
|
||||
child: MyTokensList(
|
||||
walletId: widget.walletId,
|
||||
tokens: _filter(tokens, _searchString),
|
||||
tokens: _filter(_searchString),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.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/providers/global/secure_store_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
|
@ -24,7 +24,7 @@ class MyTokenSelectItem extends ConsumerStatefulWidget {
|
|||
}) : super(key: key);
|
||||
|
||||
final String walletId;
|
||||
final EthContractInfo token;
|
||||
final EthContract token;
|
||||
|
||||
@override
|
||||
ConsumerState<MyTokenSelectItem> createState() => _MyTokenSelectItemState();
|
||||
|
@ -133,7 +133,7 @@ class _MyTokenSelectItemState extends ConsumerState<MyTokenSelectItem> {
|
|||
Text("${ref.watch(
|
||||
priceAnd24hChangeNotifierProvider.select(
|
||||
(value) => value
|
||||
.getTokenPrice(widget.token.contractAddress)
|
||||
.getTokenPrice(widget.token.address)
|
||||
.item1
|
||||
.toStringAsFixed(2),
|
||||
),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:flutter/material.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';
|
||||
|
||||
class MyTokensList extends StatelessWidget {
|
||||
|
@ -11,7 +11,7 @@ class MyTokensList extends StatelessWidget {
|
|||
}) : super(key: key);
|
||||
|
||||
final String walletId;
|
||||
final List<EthContractInfo> tokens;
|
||||
final List<EthContract> tokens;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -22,7 +22,7 @@ class MyTokensList extends StatelessWidget {
|
|||
itemBuilder: (ctx, index) {
|
||||
final token = tokens[index];
|
||||
return Padding(
|
||||
key: Key(token.contractAddress),
|
||||
key: Key(token.address),
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: MyTokenSelectItem(
|
||||
walletId: walletId,
|
||||
|
|
|
@ -78,7 +78,7 @@ class _TokenViewState extends ConsumerState<TokenView> {
|
|||
SvgPicture.asset(
|
||||
Assets.svg.iconForToken(
|
||||
contractAddress: ref.watch(tokenServiceProvider
|
||||
.select((value) => value!.token.contractAddress))),
|
||||
.select((value) => value!.token.address))),
|
||||
width: 24,
|
||||
height: 24,
|
||||
),
|
||||
|
@ -118,7 +118,7 @@ class _TokenViewState extends ConsumerState<TokenView> {
|
|||
walletId: widget.walletId,
|
||||
initialSyncStatus: initialSyncStatus,
|
||||
tokenContractAddress: ref.watch(tokenServiceProvider
|
||||
.select((value) => value!.token.contractAddress)),
|
||||
.select((value) => value!.token.address)),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -7,7 +7,6 @@ import 'package:http/http.dart';
|
|||
import 'package:isar/isar.dart';
|
||||
import 'package:stackwallet/db/isar/main_db.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/node_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/wallet_sync_status_changed_event.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_db.dart';
|
||||
import 'package:stackwallet/services/node_service.dart';
|
||||
|
@ -39,8 +37,7 @@ import 'package:web3dart/web3dart.dart' as web3;
|
|||
|
||||
const int MINIMUM_CONFIRMATIONS = 3;
|
||||
|
||||
class EthereumWallet extends CoinServiceAPI
|
||||
with WalletCache, WalletDB, EthExtrasWalletCache {
|
||||
class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
||||
EthereumWallet({
|
||||
required String walletId,
|
||||
required String walletName,
|
||||
|
@ -55,7 +52,6 @@ class EthereumWallet extends CoinServiceAPI
|
|||
_coin = coin;
|
||||
_secureStore = secureStore;
|
||||
initCache(walletId, coin);
|
||||
initEthExtrasCache(walletId);
|
||||
initWalletDB(mockableOverride: mockableOverride);
|
||||
}
|
||||
|
||||
|
@ -66,29 +62,47 @@ class EthereumWallet extends CoinServiceAPI
|
|||
Timer? timer;
|
||||
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) =>
|
||||
updateCachedTokenContracts(contracts..addAll(contractInfo)).then(
|
||||
(value) => GlobalEventBus.instance.fire(
|
||||
UpdatedInBackgroundEvent(
|
||||
"$contractInfo updated/added for: $walletId $walletName",
|
||||
walletId,
|
||||
),
|
||||
),
|
||||
);
|
||||
GlobalEventBus.instance.fire(
|
||||
UpdatedInBackgroundEvent(
|
||||
"$contracts updated/added for: $walletId $walletName",
|
||||
walletId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> removeTokenContract(String contractAddress) =>
|
||||
updateCachedTokenContracts(contracts
|
||||
..removeWhere((e) => e.contractAddress == contractAddress))
|
||||
.then(
|
||||
(value) => GlobalEventBus.instance.fire(
|
||||
UpdatedInBackgroundEvent(
|
||||
"$contractAddress removed for: $walletId $walletName",
|
||||
walletId,
|
||||
),
|
||||
),
|
||||
);
|
||||
Future<void> removeTokenContract(String contractAddress) async {
|
||||
final contract =
|
||||
await db.getEthContracts().addressEqualTo(contractAddress).findFirst();
|
||||
|
||||
if (contract == null) {
|
||||
return; // todo some error?
|
||||
}
|
||||
|
||||
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
|
||||
String get walletId => _walletId;
|
||||
|
|
|
@ -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/services/ethereum/ethereum_api.dart';
|
||||
import 'package:stackwallet/services/mixins/eth_token_cache.dart';
|
||||
|
@ -6,7 +6,7 @@ import 'package:stackwallet/utilities/logger.dart';
|
|||
|
||||
class CachedEthTokenBalance with EthTokenCache {
|
||||
final String walletId;
|
||||
final EthContractInfo token;
|
||||
final EthContract token;
|
||||
|
||||
CachedEthTokenBalance(this.walletId, this.token) {
|
||||
initCache(walletId, token);
|
||||
|
@ -15,13 +15,13 @@ class CachedEthTokenBalance with EthTokenCache {
|
|||
Future<void> fetchAndUpdateCachedBalance(String address) async {
|
||||
final response = await EthereumAPI.getWalletTokenBalance(
|
||||
address: address,
|
||||
contractAddress: token.contractAddress,
|
||||
contractAddress: token.address,
|
||||
);
|
||||
|
||||
if (response.value != null) {
|
||||
await updateCachedBalance(
|
||||
TokenBalance(
|
||||
contractAddress: token.contractAddress,
|
||||
contractAddress: token.address,
|
||||
decimalPlaces: token.decimals,
|
||||
total: response.value!,
|
||||
spendable: response.value!,
|
||||
|
|
|
@ -5,9 +5,7 @@ import 'package:decimal/decimal.dart';
|
|||
import 'package:http/http.dart';
|
||||
import 'package:stackwallet/dto/ethereum/eth_token_tx_dto.dart';
|
||||
import 'package:stackwallet/dto/ethereum/eth_tx_dto.dart';
|
||||
import 'package:stackwallet/models/ethereum/erc20_token.dart';
|
||||
import 'package:stackwallet/models/ethereum/erc721_token.dart';
|
||||
import 'package:stackwallet/models/ethereum/eth_token.dart';
|
||||
import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
|
||||
import 'package:stackwallet/models/paymint/fee_object_model.dart';
|
||||
import 'package:stackwallet/utilities/default_nodes.dart';
|
||||
import 'package:stackwallet/utilities/eth_commons.dart';
|
||||
|
@ -64,7 +62,10 @@ abstract class EthereumAPI {
|
|||
|
||||
final List<EthTxDTO> txns = [];
|
||||
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(
|
||||
txns,
|
||||
|
@ -311,7 +312,7 @@ abstract class EthereumAPI {
|
|||
slow: feesSlow.toInt());
|
||||
}
|
||||
|
||||
static Future<EthereumResponse<EthContractInfo>> getTokenByContractAddress(
|
||||
static Future<EthereumResponse<EthContract>> getTokenByContractAddress(
|
||||
String contractAddress) async {
|
||||
try {
|
||||
final response = await get(Uri.parse(
|
||||
|
@ -322,20 +323,24 @@ abstract class EthereumAPI {
|
|||
final json = jsonDecode(response.body);
|
||||
if (json["message"] == "OK") {
|
||||
final map = Map<String, dynamic>.from(json["result"] as Map);
|
||||
EthContractInfo? token;
|
||||
EthContract? token;
|
||||
if (map["type"] == "ERC-20") {
|
||||
token = Erc20ContractInfo(
|
||||
contractAddress: map["contractAddress"] as String,
|
||||
token = EthContract(
|
||||
address: map["contractAddress"] as String,
|
||||
decimals: int.parse(map["decimals"] as String),
|
||||
name: map["name"] as String,
|
||||
symbol: map["symbol"] as String,
|
||||
type: EthContractType.erc20,
|
||||
walletIds: [],
|
||||
);
|
||||
} else if (map["type"] == "ERC-721") {
|
||||
token = Erc721ContractInfo(
|
||||
contractAddress: map["contractAddress"] as String,
|
||||
token = EthContract(
|
||||
address: map["contractAddress"] as String,
|
||||
decimals: int.parse(map["decimals"] as String),
|
||||
name: map["name"] as String,
|
||||
symbol: map["symbol"] as String,
|
||||
type: EthContractType.erc721,
|
||||
walletIds: [],
|
||||
);
|
||||
} else {
|
||||
throw EthApiException(
|
||||
|
|
|
@ -5,9 +5,7 @@ import 'package:ethereum_addresses/ethereum_addresses.dart';
|
|||
import 'package:flutter/widgets.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:stackwallet/models/ethereum/eth_token.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/isar/models/isar_models.dart';
|
||||
import 'package:stackwallet/models/node_model.dart';
|
||||
import 'package:stackwallet/models/paymint/fee_object_model.dart';
|
||||
import 'package:stackwallet/models/token_balance.dart';
|
||||
|
@ -30,7 +28,7 @@ import 'package:tuple/tuple.dart';
|
|||
import 'package:web3dart/web3dart.dart' as web3dart;
|
||||
|
||||
class EthereumTokenService extends ChangeNotifier with EthTokenCache {
|
||||
final EthContractInfo token;
|
||||
final EthContract token;
|
||||
final EthereumWallet ethWallet;
|
||||
final TransactionNotificationTracker tracker;
|
||||
final SecureStorageInterface _secureStore;
|
||||
|
@ -51,7 +49,7 @@ class EthereumTokenService extends ChangeNotifier with EthTokenCache {
|
|||
required SecureStorageInterface secureStore,
|
||||
required this.tracker,
|
||||
}) : _secureStore = secureStore {
|
||||
_contractAddress = web3dart.EthereumAddress.fromHex(token.contractAddress);
|
||||
_contractAddress = web3dart.EthereumAddress.fromHex(token.address);
|
||||
initCache(ethWallet.walletId, token);
|
||||
}
|
||||
|
||||
|
@ -220,7 +218,7 @@ class EthereumTokenService extends ChangeNotifier with EthTokenCache {
|
|||
GlobalEventBus.instance.fire(
|
||||
WalletSyncStatusChangedEvent(
|
||||
WalletSyncStatus.syncing,
|
||||
ethWallet.walletId + token.contractAddress,
|
||||
ethWallet.walletId + token.address,
|
||||
coin,
|
||||
),
|
||||
);
|
||||
|
@ -237,7 +235,7 @@ class EthereumTokenService extends ChangeNotifier with EthTokenCache {
|
|||
GlobalEventBus.instance.fire(
|
||||
WalletSyncStatusChangedEvent(
|
||||
WalletSyncStatus.synced,
|
||||
ethWallet.walletId + token.contractAddress,
|
||||
ethWallet.walletId + token.address,
|
||||
coin,
|
||||
),
|
||||
);
|
||||
|
@ -256,7 +254,7 @@ class EthereumTokenService extends ChangeNotifier with EthTokenCache {
|
|||
String _balance = balanceRequest.first.toString();
|
||||
|
||||
final newBalance = TokenBalance(
|
||||
contractAddress: token.contractAddress,
|
||||
contractAddress: token.address,
|
||||
total: int.parse(_balance),
|
||||
spendable: int.parse(_balance),
|
||||
blockedTotal: 0,
|
||||
|
@ -270,7 +268,7 @@ class EthereumTokenService extends ChangeNotifier with EthTokenCache {
|
|||
Future<List<Transaction>> get transactions => ethWallet.db
|
||||
.getTransactions(ethWallet.walletId)
|
||||
.filter()
|
||||
.otherDataEqualTo(token.contractAddress)
|
||||
.otherDataEqualTo(token.address)
|
||||
.sortByTimestampDesc()
|
||||
.findAll();
|
||||
|
||||
|
@ -279,7 +277,7 @@ class EthereumTokenService extends ChangeNotifier with EthTokenCache {
|
|||
|
||||
final response = await EthereumAPI.getTokenTransactions(
|
||||
address: addressString,
|
||||
contractAddress: token.contractAddress,
|
||||
contractAddress: token.address,
|
||||
);
|
||||
|
||||
if (response.value == null) {
|
||||
|
|
|
@ -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(),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
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';
|
||||
|
||||
abstract class _Keys {
|
||||
|
@ -10,9 +10,9 @@ abstract class _Keys {
|
|||
|
||||
mixin EthTokenCache {
|
||||
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;
|
||||
_token = token;
|
||||
}
|
||||
|
@ -21,11 +21,11 @@ mixin EthTokenCache {
|
|||
TokenBalance getCachedBalance() {
|
||||
final jsonString = DB.instance.get<dynamic>(
|
||||
boxName: _walletId,
|
||||
key: _Keys.tokenBalance(_token.contractAddress),
|
||||
key: _Keys.tokenBalance(_token.address),
|
||||
) as String?;
|
||||
if (jsonString == null) {
|
||||
return TokenBalance(
|
||||
contractAddress: _token.contractAddress,
|
||||
contractAddress: _token.address,
|
||||
decimalPlaces: _token.decimals,
|
||||
total: 0,
|
||||
spendable: 0,
|
||||
|
@ -41,7 +41,7 @@ mixin EthTokenCache {
|
|||
Future<void> updateCachedBalance(TokenBalance balance) async {
|
||||
await DB.instance.put<dynamic>(
|
||||
boxName: _walletId,
|
||||
key: _Keys.tokenBalance(_token.contractAddress),
|
||||
key: _Keys.tokenBalance(_token.address),
|
||||
value: balance.toJsonIgnoreCoin(),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,43 +1,54 @@
|
|||
import 'package:stackwallet/models/ethereum/erc20_token.dart';
|
||||
import 'package:stackwallet/models/ethereum/eth_token.dart';
|
||||
import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
|
||||
|
||||
abstract class DefaultTokens {
|
||||
static const List<EthContractInfo> list = [
|
||||
Erc20ContractInfo(
|
||||
contractAddress: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
|
||||
static List<EthContract> list = [
|
||||
EthContract(
|
||||
address: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
|
||||
name: "USD Coin",
|
||||
symbol: "USDC",
|
||||
decimals: 6,
|
||||
type: EthContractType.erc20,
|
||||
walletIds: [],
|
||||
),
|
||||
Erc20ContractInfo(
|
||||
contractAddress: "0xdac17f958d2ee523a2206206994597c13d831ec7",
|
||||
EthContract(
|
||||
address: "0xdac17f958d2ee523a2206206994597c13d831ec7",
|
||||
name: "Tether",
|
||||
symbol: "USDT",
|
||||
decimals: 6,
|
||||
type: EthContractType.erc20,
|
||||
walletIds: [],
|
||||
),
|
||||
Erc20ContractInfo(
|
||||
contractAddress: "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce",
|
||||
EthContract(
|
||||
address: "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce",
|
||||
name: "Shiba Inu",
|
||||
symbol: "SHIB",
|
||||
decimals: 18,
|
||||
type: EthContractType.erc20,
|
||||
walletIds: [],
|
||||
),
|
||||
Erc20ContractInfo(
|
||||
contractAddress: "0xB8c77482e45F1F44dE1745F52C74426C631bDD52",
|
||||
EthContract(
|
||||
address: "0xB8c77482e45F1F44dE1745F52C74426C631bDD52",
|
||||
name: "BNB Token",
|
||||
symbol: "BNB",
|
||||
decimals: 18,
|
||||
type: EthContractType.erc20,
|
||||
walletIds: [],
|
||||
),
|
||||
Erc20ContractInfo(
|
||||
contractAddress: "0x4Fabb145d64652a948d72533023f6E7A623C7C53",
|
||||
EthContract(
|
||||
address: "0x4Fabb145d64652a948d72533023f6E7A623C7C53",
|
||||
name: "BUSD",
|
||||
symbol: "BUSD",
|
||||
decimals: 18,
|
||||
type: EthContractType.erc20,
|
||||
walletIds: [],
|
||||
),
|
||||
Erc20ContractInfo(
|
||||
contractAddress: "0x514910771af9ca656af840dff83e8264ecf986ca",
|
||||
EthContract(
|
||||
address: "0x514910771af9ca656af840dff83e8264ecf986ca",
|
||||
name: "Chainlink",
|
||||
symbol: "LINK",
|
||||
decimals: 18,
|
||||
type: EthContractType.erc20,
|
||||
walletIds: [],
|
||||
),
|
||||
];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue