mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-22 10:34:32 +00:00
WIP eth token abi fetch and parsing
This commit is contained in:
parent
85c416fb50
commit
b27b90c08a
2 changed files with 161 additions and 61 deletions
|
@ -468,46 +468,89 @@ abstract class EthereumAPI {
|
|||
}
|
||||
}
|
||||
|
||||
/// Fetch the underlying contract address that a proxy contract points to
|
||||
static Future<EthereumResponse<String>> getProxyTokenImplementation(
|
||||
String contractAddress) async {
|
||||
try {
|
||||
final response = await get(Uri.parse(
|
||||
// "$stackURI?module=contract&action=getsourcecode&address=$contractAddress"));
|
||||
"$etherscanApi?module=contract&action=getsourcecode&address=$contractAddress&apikey=EG6J7RJIQVSTP2BS59D3TY2G55YHS5F2HP"));
|
||||
if (response.statusCode == 200) {
|
||||
final json = jsonDecode(response.body);
|
||||
if (json["message"] == "OK") {
|
||||
final list = json["result"] as List;
|
||||
final map = Map<String, dynamic>.from(list.first as Map);
|
||||
// static Future<EthereumResponse<String>> getTokenAbi22(
|
||||
// String contractAddress) async {
|
||||
// try {
|
||||
// final response = await get(
|
||||
// Uri.parse(
|
||||
// "https://api.etherscan.io/api?module=contract&action=getabi&address=$contractAddress&apikey=EG6J7RJIQVSTP2BS59D3TY2G55YHS5F2HP",
|
||||
// ),
|
||||
// );
|
||||
//
|
||||
// if (response.statusCode == 200) {
|
||||
// final json = jsonDecode(response.body) as Map;
|
||||
// print("========================== 222222222222222 ================");
|
||||
// dev.log((jsonDecode(json["result"] as String)).toString());
|
||||
// print(
|
||||
// "============================ 2222222222222222222 ==============");
|
||||
//
|
||||
// return EthereumResponse(
|
||||
// json["result"] as String,
|
||||
// null,
|
||||
// );
|
||||
// } else {
|
||||
// throw EthApiException(
|
||||
// "getTokenAbi($contractAddress) failed with status code: "
|
||||
// "${response.statusCode}",
|
||||
// );
|
||||
// }
|
||||
// } on EthApiException catch (e) {
|
||||
// return EthereumResponse(
|
||||
// null,
|
||||
// e,
|
||||
// );
|
||||
// } catch (e, s) {
|
||||
// Logging.instance.log(
|
||||
// "getTokenAbi(): $e\n$s",
|
||||
// level: LogLevel.Error,
|
||||
// );
|
||||
// return EthereumResponse(
|
||||
// null,
|
||||
// EthApiException(e.toString()),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
return EthereumResponse(
|
||||
map["Implementation"] as String,
|
||||
null,
|
||||
);
|
||||
} else {
|
||||
throw EthApiException(json["message"] as String);
|
||||
}
|
||||
} else {
|
||||
throw EthApiException(
|
||||
"fetchProxyTokenImplementation($contractAddress) failed with status code: "
|
||||
"${response.statusCode}",
|
||||
);
|
||||
}
|
||||
} on EthApiException catch (e) {
|
||||
return EthereumResponse(
|
||||
null,
|
||||
e,
|
||||
);
|
||||
} catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"fetchProxyTokenImplementation(): $e\n$s",
|
||||
level: LogLevel.Error,
|
||||
);
|
||||
return EthereumResponse(
|
||||
null,
|
||||
EthApiException(e.toString()),
|
||||
);
|
||||
}
|
||||
}
|
||||
// /// Fetch the underlying contract address that a proxy contract points to
|
||||
// static Future<EthereumResponse<String>> getProxyTokenImplementation(
|
||||
// String contractAddress) async {
|
||||
// try {
|
||||
// final response = await get(Uri.parse(
|
||||
// "$stackURI?module=contract&action=getsourcecode&address=$contractAddress"));
|
||||
// // "$etherscanApi?module=contract&action=getsourcecode&address=$contractAddress&apikey=EG6J7RJIQVSTP2BS59D3TY2G55YHS5F2HP"));
|
||||
// if (response.statusCode == 200) {
|
||||
// final json = jsonDecode(response.body);
|
||||
// if (json["message"] == "OK") {
|
||||
// final list = json["result"] as List;
|
||||
// final map = Map<String, dynamic>.from(list.first as Map);
|
||||
//
|
||||
// return EthereumResponse(
|
||||
// map["Implementation"] as String,
|
||||
// null,
|
||||
// );
|
||||
// } else {
|
||||
// throw EthApiException(json["message"] as String);
|
||||
// }
|
||||
// } else {
|
||||
// throw EthApiException(
|
||||
// "fetchProxyTokenImplementation($contractAddress) failed with status code: "
|
||||
// "${response.statusCode}",
|
||||
// );
|
||||
// }
|
||||
// } on EthApiException catch (e) {
|
||||
// return EthereumResponse(
|
||||
// null,
|
||||
// e,
|
||||
// );
|
||||
// } catch (e, s) {
|
||||
// Logging.instance.log(
|
||||
// "fetchProxyTokenImplementation(): $e\n$s",
|
||||
// level: LogLevel.Error,
|
||||
// );
|
||||
// return EthereumResponse(
|
||||
// null,
|
||||
// EthApiException(e.toString()),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:decimal/decimal.dart';
|
||||
import 'package:ethereum_addresses/ethereum_addresses.dart';
|
||||
|
@ -24,6 +25,7 @@ import 'package:stackwallet/utilities/default_nodes.dart';
|
|||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
|
||||
import 'package:stackwallet/utilities/eth_commons.dart';
|
||||
import 'package:stackwallet/utilities/extensions/impl/contract_abi.dart';
|
||||
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
|
||||
import 'package:stackwallet/utilities/format.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
|
@ -116,7 +118,10 @@ class EthTokenWallet extends ChangeNotifier with EthTokenCache {
|
|||
required EthContract forContract,
|
||||
required String usingContractAddress,
|
||||
}) async {
|
||||
final abiResponse = await EthereumAPI.getTokenAbi(usingContractAddress);
|
||||
final abiResponse = await EthereumAPI.getTokenAbi(
|
||||
name: forContract.name,
|
||||
contractAddress: usingContractAddress,
|
||||
);
|
||||
// Fetch token ABI so we can call token functions
|
||||
if (abiResponse.value != null) {
|
||||
final updatedToken = forContract.copyWith(abi: abiResponse.value!);
|
||||
|
@ -132,12 +137,12 @@ class EthTokenWallet extends ChangeNotifier with EthTokenCache {
|
|||
final contractAddress =
|
||||
web3dart.EthereumAddress.fromHex(tokenContract.address);
|
||||
|
||||
if (tokenContract.abi == null) {
|
||||
_tokenContract = await _updateTokenABI(
|
||||
forContract: tokenContract,
|
||||
usingContractAddress: contractAddress.hex,
|
||||
);
|
||||
}
|
||||
// if (tokenContract.abi == null) {
|
||||
_tokenContract = await _updateTokenABI(
|
||||
forContract: tokenContract,
|
||||
usingContractAddress: contractAddress.hex,
|
||||
);
|
||||
// }
|
||||
|
||||
String? mnemonicString = await ethWallet.mnemonicString;
|
||||
|
||||
|
@ -149,7 +154,10 @@ class EthTokenWallet extends ChangeNotifier with EthTokenCache {
|
|||
_credentials = web3dart.EthPrivateKey.fromHex(privateKey);
|
||||
|
||||
_deployedContract = web3dart.DeployedContract(
|
||||
web3dart.ContractAbi.fromJson(tokenContract.abi!, tokenContract.name),
|
||||
ContractAbiExtensions.fromJsonList(
|
||||
jsonList: tokenContract.abi!,
|
||||
name: tokenContract.name,
|
||||
),
|
||||
contractAddress,
|
||||
);
|
||||
|
||||
|
@ -157,24 +165,73 @@ class EthTokenWallet extends ChangeNotifier with EthTokenCache {
|
|||
_balanceFunction = _deployedContract.function('balanceOf');
|
||||
_sendFunction = _deployedContract.function('transfer');
|
||||
} catch (_) {
|
||||
// function not found so likely a proxy so we need to fetch the impl
|
||||
final contractAddressResponse =
|
||||
await EthereumAPI.getProxyTokenImplementation(contractAddress.hex);
|
||||
//====================================================================
|
||||
final list = List<Map<String, dynamic>>.from(
|
||||
jsonDecode(tokenContract.abi!) as List);
|
||||
final functionNames = list.map((e) => e["name"] as String);
|
||||
|
||||
if (contractAddressResponse.value != null) {
|
||||
_tokenContract = await _updateTokenABI(
|
||||
forContract: tokenContract,
|
||||
usingContractAddress: contractAddressResponse.value!,
|
||||
if (!functionNames.contains("balanceOf")) {
|
||||
list.add(
|
||||
{
|
||||
"encoding": "0x70a08231",
|
||||
"inputs": [
|
||||
{"name": "account", "type": "address"}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{"name": "val_0", "type": "uint256"}
|
||||
],
|
||||
"signature": "balanceOf(address)",
|
||||
"type": "function"
|
||||
},
|
||||
);
|
||||
} else {
|
||||
throw contractAddressResponse.exception!;
|
||||
}
|
||||
|
||||
if (!functionNames.contains("transfer")) {
|
||||
list.add(
|
||||
{
|
||||
"encoding": "0xa9059cbb",
|
||||
"inputs": [
|
||||
{"name": "dst", "type": "address"},
|
||||
{"name": "rawAmount", "type": "uint256"}
|
||||
],
|
||||
"name": "transfer",
|
||||
"outputs": [
|
||||
{"name": "val_0", "type": "bool"}
|
||||
],
|
||||
"signature": "transfer(address,uint256)",
|
||||
"type": "function"
|
||||
},
|
||||
);
|
||||
}
|
||||
//--------------------------------------------------------------------
|
||||
//====================================================================
|
||||
|
||||
// function not found so likely a proxy so we need to fetch the impl
|
||||
//====================================================================
|
||||
final updatedToken = tokenContract.copyWith(abi: jsonEncode(list));
|
||||
// Store updated contract
|
||||
final id = await MainDB.instance.putEthContract(updatedToken);
|
||||
_tokenContract = updatedToken..id = id;
|
||||
//--------------------------------------------------------------------
|
||||
// final contractAddressResponse =
|
||||
// await EthereumAPI.getProxyTokenImplementation(contractAddress.hex);
|
||||
//
|
||||
// if (contractAddressResponse.value != null) {
|
||||
// _tokenContract = await _updateTokenABI(
|
||||
// forContract: tokenContract,
|
||||
// usingContractAddress: contractAddressResponse.value!,
|
||||
// );
|
||||
// } else {
|
||||
// throw contractAddressResponse.exception!;
|
||||
// }
|
||||
//====================================================================
|
||||
}
|
||||
|
||||
_deployedContract = web3dart.DeployedContract(
|
||||
web3dart.ContractAbi.fromJson(
|
||||
tokenContract.abi!,
|
||||
tokenContract.name,
|
||||
ContractAbiExtensions.fromJsonList(
|
||||
jsonList: tokenContract.abi!,
|
||||
name: tokenContract.name,
|
||||
),
|
||||
contractAddress,
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue