Add validation for custom addresses and clean up

This commit is contained in:
likho 2023-01-30 15:44:30 +02:00
parent d53709c7b0
commit f7e2568e6a
4 changed files with 65 additions and 99 deletions

View file

@ -741,45 +741,7 @@ class EthereumWallet extends CoinServiceAPI {
@override @override
Future<void> updateSentCachedTxData(Map<String, dynamic> txData) async { Future<void> updateSentCachedTxData(Map<String, dynamic> txData) async {
final priceData = //Only used for Electrumx coins
await _priceAPI.getPricesAnd24hChange(baseCurrency: _prefs.currency);
Decimal currentPrice = priceData[coin]?.item1 ?? Decimal.zero;
final locale = await Devicelocale.currentLocale;
final String worthNow = Format.localizedStringAsFixed(
value:
((currentPrice * Decimal.fromInt(txData["recipientAmt"] as int)) /
Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2),
decimalPlaces: 2,
locale: locale!);
final tx = models.Transaction(
txid: txData["txid"] as String,
confirmedStatus: false,
timestamp: DateTime.now().millisecondsSinceEpoch ~/ 1000,
txType: "Sent",
amount: txData["recipientAmt"] as int,
worthNow: worthNow,
worthAtBlockTimestamp: worthNow,
fees: txData["fee"] as int,
inputSize: 0,
outputSize: 0,
inputs: [],
outputs: [],
address: txData["address"] as String,
height: -1,
confirmations: 0,
);
if (cachedTxData == null) {
final data = await _fetchTransactionData();
_transactionData = Future(() => data);
} else {
final transactions = cachedTxData!.getAllTransactions();
transactions[tx.txid] = tx;
cachedTxData = models.TransactionData.fromMap(transactions);
_transactionData = Future(() => cachedTxData!);
}
} }
@override @override

View file

@ -1,6 +1,5 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:math'; import 'dart:math';
import 'package:devicelocale/devicelocale.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:decimal/decimal.dart'; import 'package:decimal/decimal.dart';
import 'package:stackwallet/utilities/eth_commons.dart'; import 'package:stackwallet/utilities/eth_commons.dart';
@ -42,6 +41,26 @@ class AbiRequestResponse {
} }
} }
class TokenData {
final String message;
final Map<String, dynamic> result;
final String status;
const TokenData({
required this.message,
required this.result,
required this.status,
});
factory TokenData.fromJson(Map<String, dynamic> json) {
return TokenData(
message: json['message'] as String,
result: json['result'] as Map<String, dynamic>,
status: json['status'] as String,
);
}
}
const int MINIMUM_CONFIRMATIONS = 3; const int MINIMUM_CONFIRMATIONS = 3;
class EthereumToken extends TokenServiceAPI { class EthereumToken extends TokenServiceAPI {
@ -81,7 +100,7 @@ class EthereumToken extends TokenServiceAPI {
return AbiRequestResponse.fromJson( return AbiRequestResponse.fromJson(
json.decode(response.body) as Map<String, dynamic>); json.decode(response.body) as Map<String, dynamic>);
} else { } else {
throw Exception('Failed to load token abi'); throw Exception("ERROR GETTING TOKENABI ${response.reasonPhrase}");
} }
} }
@ -185,6 +204,8 @@ class EthereumToken extends TokenServiceAPI {
_balanceFunction = _contract.function('balanceOf'); _balanceFunction = _contract.function('balanceOf');
_sendFunction = _contract.function('transfer'); _sendFunction = _contract.function('transfer');
_client = await getEthClient(); _client = await getEthClient();
// print(_credentials.p)
} }
@override @override
@ -294,47 +315,6 @@ class EthereumToken extends TokenServiceAPI {
_transactionData ??= _fetchTransactionData(); _transactionData ??= _fetchTransactionData();
Future<TransactionData>? _transactionData; Future<TransactionData>? _transactionData;
@override
Future<void> updateSentCachedTxData(Map<String, dynamic> txData) async {
Decimal currentPrice = Decimal.zero;
final locale = await Devicelocale.currentLocale;
final String worthNow = Format.localizedStringAsFixed(
value:
((currentPrice * Decimal.fromInt(txData["recipientAmt"] as int)) /
Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2),
decimalPlaces: 2,
locale: locale!);
final tx = models.Transaction(
txid: txData["txid"] as String,
confirmedStatus: false,
timestamp: DateTime.now().millisecondsSinceEpoch ~/ 1000,
txType: "Sent",
amount: txData["recipientAmt"] as int,
worthNow: worthNow,
worthAtBlockTimestamp: worthNow,
fees: txData["fee"] as int,
inputSize: 0,
outputSize: 0,
inputs: [],
outputs: [],
address: txData["address"] as String,
height: -1,
confirmations: 0,
);
if (cachedTxData == null) {
final data = await _fetchTransactionData();
_transactionData = Future(() => data);
} else {
final transactions = cachedTxData!.getAllTransactions();
transactions[tx.txid] = tx;
cachedTxData = models.TransactionData.fromMap(transactions);
_transactionData = Future(() => cachedTxData!);
}
}
Future<TransactionData> _fetchTransactionData() async { Future<TransactionData> _fetchTransactionData() async {
String thisAddress = await currentReceivingAddress; String thisAddress = await currentReceivingAddress;
// final cachedTransactions = {} as TransactionData?; // final cachedTransactions = {} as TransactionData?;
@ -440,9 +420,6 @@ class EthereumToken extends TokenServiceAPI {
} }
} }
// final transactionsMap = {} as Map<String, models.Transaction>;
// transactionsMap
// .addAll(TransactionData.fromJson(result).getAllTransactions());
final txModel = TransactionData.fromMap( final txModel = TransactionData.fromMap(
TransactionData.fromJson(result).getAllTransactions()); TransactionData.fromJson(result).getAllTransactions());
@ -455,6 +432,34 @@ class EthereumToken extends TokenServiceAPI {
return isValidEthereumAddress(address); return isValidEthereumAddress(address);
} }
//Validate that a custom token is valid and is ERC-20, a token will be valid
@override
Future<TokenData> getTokenByContractAddress(String contractAddress) async {
final response = await get(Uri.parse(
"$blockExplorer?module=token&action=getToken&contractaddress=$contractAddress"));
if (response.statusCode == 200) {
return TokenData.fromJson(
json.decode(response.body) as Map<String, dynamic>);
} else {
throw Exception("ERROR GETTING TOKEN ${response.reasonPhrase}");
}
}
//Validate that a custom token is valid and is ERC-20
@override
Future<bool> isValidToken(String contractAddress) async {
TokenData tokenData = await getTokenByContractAddress(contractAddress);
if (tokenData.message == "OK") {
final result = tokenData.result;
if (result["type"] == "ERC-20") {
return true;
}
return false;
}
return false;
}
Future<NodeModel> getCurrentNode() async { Future<NodeModel> getCurrentNode() async {
return NodeService(secureStorageInterface: _secureStore) return NodeService(secureStorageInterface: _secureStore)
.getPrimaryNodeFor(coin: coin) ?? .getPrimaryNodeFor(coin: coin) ??

View file

@ -41,7 +41,6 @@ abstract class TokenServiceAPI {
Future<int> get maxFee; Future<int> get maxFee;
Future<String> get currentReceivingAddress; Future<String> get currentReceivingAddress;
// Future<String> get currentLegacyReceivingAddress;
Future<Decimal> get availableBalance; Future<Decimal> get availableBalance;
Future<Decimal> get totalBalance; Future<Decimal> get totalBalance;
@ -52,9 +51,6 @@ abstract class TokenServiceAPI {
Future<void> refresh(); Future<void> refresh();
// String get walletName;
// String get walletId;
bool validateAddress(String address); bool validateAddress(String address);
Future<void> initializeNew(); Future<void> initializeNew();
@ -62,6 +58,5 @@ abstract class TokenServiceAPI {
Future<int> estimateFeeFor(int satoshiAmount, int feeRate); Future<int> estimateFeeFor(int satoshiAmount, int feeRate);
// used for electrumx coins Future<bool> isValidToken(String contractAddress);
Future<void> updateSentCachedTxData(Map<String, dynamic> txData);
} }

View file

@ -58,14 +58,18 @@ const _gasTrackerUrl =
Future<AddressTransaction> fetchAddressTransactions( Future<AddressTransaction> fetchAddressTransactions(
String address, String action) async { String address, String action) async {
try {
final response = await get(Uri.parse( final response = await get(Uri.parse(
"$blockExplorer?module=account&action=$action&address=$address")); "$blockExplorer?module=account&action=$action&address=$address"));
if (response.statusCode == 200) { if (response.statusCode == 200) {
return AddressTransaction.fromJson( return AddressTransaction.fromJson(
json.decode(response.body) as Map<String, dynamic>); json.decode(response.body) as Map<String, dynamic>);
} else { } else {
throw Exception('Failed to load transactions'); throw Exception(
'ERROR GETTING TRANSACTIONS WITH STATUS ${response.statusCode}');
}
} catch (e, s) {
throw Exception('ERROR GETTING TRANSACTIONS ${e.toString()}');
} }
} }