get token transactions refactor

This commit is contained in:
julian 2023-02-24 10:22:25 -06:00
parent 58280010f8
commit 057066950e

View file

@ -1,16 +1,14 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:math'; import 'dart:math';
import 'package:ethereum_addresses/ethereum_addresses.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:stackwallet/models/ethereum/erc20_token.dart';
import 'package:stackwallet/models/ethereum/erc721_token.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/eth_commons.dart'; import 'package:stackwallet/utilities/eth_commons.dart';
import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/logger.dart';
import '../../models/ethereum/erc20_token.dart';
import '../../models/ethereum/eth_token.dart';
class AbiRequestResponse { class AbiRequestResponse {
final String message; final String message;
final String result; final String result;
@ -31,6 +29,87 @@ class AbiRequestResponse {
} }
} }
class EthTokenTx {
final String blockHash;
final int blockNumber;
final int confirmations;
final String contractAddress;
final int cumulativeGasUsed;
final String from;
final int gas;
final BigInt gasPrice;
final int gasUsed;
final String hash;
final String input;
final int logIndex;
final int nonce;
final int timeStamp;
final String to;
final int tokenDecimal;
final String tokenName;
final String tokenSymbol;
final int transactionIndex;
final BigInt value;
EthTokenTx({
required this.blockHash,
required this.blockNumber,
required this.confirmations,
required this.contractAddress,
required this.cumulativeGasUsed,
required this.from,
required this.gas,
required this.gasPrice,
required this.gasUsed,
required this.hash,
required this.input,
required this.logIndex,
required this.nonce,
required this.timeStamp,
required this.to,
required this.tokenDecimal,
required this.tokenName,
required this.tokenSymbol,
required this.transactionIndex,
required this.value,
});
factory EthTokenTx.fromMap({
required Map<String, dynamic> map,
}) {
try {
return EthTokenTx(
blockHash: map["blockHash"] as String,
blockNumber: int.parse(map["blockNumber"] as String),
confirmations: int.parse(map["confirmations"] as String),
contractAddress: map["contractAddress"] as String,
cumulativeGasUsed: int.parse(map["cumulativeGasUsed"] as String),
from: map["from"] as String,
gas: int.parse(map["gas"] as String),
gasPrice: BigInt.parse(map["gasPrice"] as String),
gasUsed: int.parse(map["gasUsed"] as String),
hash: map["hash"] as String,
input: map["input"] as String,
logIndex: int.parse(map["logIndex"] as String),
nonce: int.parse(map["nonce"] as String),
timeStamp: int.parse(map["timeStamp"] as String),
to: map["to"] as String,
tokenDecimal: int.parse(map["tokenDecimal"] as String),
tokenName: map["tokenName"] as String,
tokenSymbol: map["tokenSymbol"] as String,
transactionIndex: int.parse(map["transactionIndex"] as String),
value: BigInt.parse(map["value"] as String),
);
} catch (e, s) {
Logging.instance.log(
"EthTokenTx.fromMap() failed: $e\n$s",
level: LogLevel.Fatal,
);
rethrow;
}
}
}
class EthereumResponse<T> { class EthereumResponse<T> {
final T? value; final T? value;
final Exception? exception; final Exception? exception;
@ -63,6 +142,53 @@ abstract class EthereumAPI {
} }
} }
static Future<EthereumResponse<List<EthTokenTx>>> getTokenTransactions({
required String address,
int? startBlock,
int? endBlock,
// todo add more params?
}) async {
try {
final uri = Uri.parse(
"$blockExplorer?module=account&action=tokentx&address=$address",
);
final response = await get(uri);
if (response.statusCode == 200) {
final json = jsonDecode(response.body);
if (json["message"] == "OK") {
final result =
List<Map<String, dynamic>>.from(json["result"] as List);
final List<EthTokenTx> tokenTxns = [];
for (final map in result) {
tokenTxns.add(EthTokenTx.fromMap(map: map));
}
return EthereumResponse(
tokenTxns,
null,
);
} else {
throw Exception(json["message"] as String);
}
} else {
throw Exception(
"getWalletTokens($address) failed with status code: "
"${response.statusCode}",
);
}
} catch (e, s) {
Logging.instance.log(
"getWalletTokens(): $e\n$s",
level: LogLevel.Error,
);
return EthereumResponse(
null,
Exception(e.toString()),
);
}
}
static Future<EthereumResponse<List<EthToken>>> getWalletTokens({ static Future<EthereumResponse<List<EthToken>>> getWalletTokens({
required String address, required String address,
}) async { }) async {
@ -129,45 +255,6 @@ abstract class EthereumAPI {
} }
} }
static Future<List<dynamic>> getWalletTokenTransactions(
String address) async {
AddressTransaction tokens =
await fetchAddressTransactions(address, "tokentx");
List<dynamic> tokensList = [];
var tokenMap = {};
if (tokens.message == "OK") {
final allTxs = tokens.result;
allTxs.forEach((element) {
print("=========================================================");
print("THING: $element");
print("=========================================================");
String key = element["tokenSymbol"] as String;
tokenMap[key] = {};
tokenMap[key]["balance"] = 0;
if (tokenMap.containsKey(key)) {
tokenMap[key]["contractAddress"] =
element["contractAddress"] as String;
tokenMap[key]["decimals"] = element["tokenDecimal"];
tokenMap[key]["name"] = element["tokenName"];
tokenMap[key]["symbol"] = element["tokenSymbol"];
if (checksumEthereumAddress(address) == address) {
tokenMap[key]["balance"] += int.parse(element["value"] as String);
} else {
tokenMap[key]["balance"] -= int.parse(element["value"] as String);
}
}
});
tokenMap.forEach((key, value) {
tokensList.add(value as Map<dynamic, dynamic>);
});
return tokensList;
}
return <dynamic>[];
}
static Future<GasTracker> getGasOracle() async { static Future<GasTracker> getGasOracle() async {
final response = await get(Uri.parse(gasTrackerUrl)); final response = await get(Uri.parse(gasTrackerUrl));
if (response.statusCode == 200) { if (response.statusCode == 200) {