ADd address validation and convert receive addresses as checksum addresses

This commit is contained in:
likho 2023-01-05 14:39:21 +02:00
parent a6c2750f20
commit 5d77dcafbe
3 changed files with 181 additions and 127 deletions

View file

@ -3,11 +3,14 @@ import 'dart:convert';
import 'dart:math'; import 'dart:math';
import 'package:bip39/bip39.dart' as bip39; import 'package:bip39/bip39.dart' as bip39;
import 'package:decimal/decimal.dart'; import 'package:decimal/decimal.dart';
import 'package:devicelocale/devicelocale.dart';
import 'package:ethereum_addresses/ethereum_addresses.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart'; import 'package:stackwallet/models/paymint/transactions_model.dart';
import 'package:stackwallet/models/paymint/utxo_model.dart'; import 'package:stackwallet/models/paymint/utxo_model.dart';
import 'package:stackwallet/services/price.dart'; import 'package:stackwallet/services/price.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/format.dart';
@ -16,6 +19,7 @@ import 'package:string_to_hex/string_to_hex.dart';
import 'package:web3dart/web3dart.dart'; import 'package:web3dart/web3dart.dart';
import 'package:web3dart/web3dart.dart' as web3; import 'package:web3dart/web3dart.dart' as web3;
import 'package:web3dart/web3dart.dart' as Transaction; import 'package:web3dart/web3dart.dart' as Transaction;
import 'package:stackwallet/models/models.dart' as models;
import 'package:http/http.dart'; import 'package:http/http.dart';
@ -142,7 +146,9 @@ class EthereumWallet extends CoinServiceAPI {
@override @override
Future<String> get currentReceivingAddress async { Future<String> get currentReceivingAddress async {
final _currentReceivingAddress = _credentials.address; final _currentReceivingAddress = _credentials.address;
return _currentReceivingAddress.toString(); final checkSumAddress =
checksumEthereumAddress(_currentReceivingAddress.toString());
return checkSumAddress;
} }
@override @override
@ -360,13 +366,13 @@ class EthereumWallet extends CoinServiceAPI {
@override @override
Future<void> refresh() async { Future<void> refresh() async {
print("CALLING REFRESH"); print("CALLING REFRESH");
// if (refreshMutex) { if (refreshMutex) {
// Logging.instance.log("$walletId $walletName refreshMutex denied", Logging.instance.log("$walletId $walletName refreshMutex denied",
// level: LogLevel.Info); level: LogLevel.Info);
// return; return;
// } else { } else {
// refreshMutex = true; refreshMutex = true;
// } }
print("SYNC STATUS IS "); print("SYNC STATUS IS ");
final blockNumber = await _client.getBlockNumber(); final blockNumber = await _client.getBlockNumber();
@ -468,15 +474,51 @@ class EthereumWallet extends CoinServiceAPI {
} }
@override @override
Future<void> updateSentCachedTxData(Map<String, dynamic> txData) { Future<void> updateSentCachedTxData(Map<String, dynamic> txData) async {
// TODO: implement updateSentCachedTxData final priceData =
throw UnimplementedError(); 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
bool validateAddress(String address) { bool validateAddress(String address) {
// TODO: implement validateAddress return isValidEthereumAddress(address);
return true;
} }
Future<TransactionData> _fetchTransactionData() async { Future<TransactionData> _fetchTransactionData() async {
@ -491,123 +533,127 @@ class EthereumWallet extends CoinServiceAPI {
print("HEIGHT TO HEX IS $hexHeight"); print("HEIGHT TO HEX IS $hexHeight");
print('0x$hexHeight'); print('0x$hexHeight');
final cachedTransactions =
DB.instance.get<dynamic>(boxName: walletId, key: 'latest_tx_model')
as TransactionData?;
final priceData = final priceData =
await _priceAPI.getPricesAnd24hChange(baseCurrency: _prefs.currency); await _priceAPI.getPricesAnd24hChange(baseCurrency: _prefs.currency);
Decimal currentPrice = priceData[coin]?.item1 ?? Decimal.zero; Decimal currentPrice = priceData[coin]?.item1 ?? Decimal.zero;
//Initilaize empty transactions array //Initilaize empty transactions array
final List<Map<String, dynamic>> midSortedArray = []; final List<Map<String, dynamic>> midSortedArray = [];
Map<String, dynamic> midSortedTx = {}; Map<String, dynamic> midSortedTx = {};
for (int i = currentBlock; // for (int i = currentBlock;
i >= 0 && (n > 0 || balance.toDouble() > 0.0); // i >= 0 && (n > 0 || balance.toDouble() > 0.0);
--i) { // --i) {
try { // try {
// print(StringToHex.toHexString(i.toString())) // // print(StringToHex.toHexString(i.toString()))
print( // print(
"BLOCK IS $i AND HEX IS --------->>>>>>> ${StringToHex.toHexString(i.toString())}"); // "BLOCK IS $i AND HEX IS --------->>>>>>> ${StringToHex.toHexString(i.toString())}");
String blockHex = i.toRadixString(16); // String blockHex = i.toRadixString(16);
var block = await _client.getBlockInformation( // var block = await _client.getBlockInformation(
blockNumber: '0x$blockHex', isContainFullObj: true); // blockNumber: '0x$blockHex', isContainFullObj: true);
//
if (block != null && block.transactions != null) { // if (block != null && block.transactions != null) {
block.transactions.forEach((element) { // block.transactions.forEach((element) {
// print("TRANSACTION OBJECT IS $element"); // // print("TRANSACTION OBJECT IS $element");
final jsonObject = json.encode(element); // final jsonObject = json.encode(element);
final decodedTransaction = jsonDecode(jsonObject); // final decodedTransaction = jsonDecode(jsonObject);
// print(somethingElse['from']); // // print(somethingElse['from']);
// print(jsonObject.containsKey(other)); // // print(jsonObject.containsKey(other));
Logging.instance.log(decodedTransaction, // Logging.instance.log(decodedTransaction,
level: LogLevel.Info, printFullLength: true); // level: LogLevel.Info, printFullLength: true);
//
if (thisAddress == decodedTransaction['from']) { // if (thisAddress == decodedTransaction['from']) {
//Ensure this is not a self send // //Ensure this is not a self send
if (decodedTransaction['from'] != decodedTransaction['to']) { // if (decodedTransaction['from'] != decodedTransaction['to']) {
midSortedTx["txType"] = "Sent"; // midSortedTx["txType"] = "Sent";
midSortedTx["txid"] = decodedTransaction["hash"]; // midSortedTx["txid"] = decodedTransaction["hash"];
midSortedTx["height"] = i; // midSortedTx["height"] = i;
midSortedTx["address"] = decodedTransaction['to']; // midSortedTx["address"] = decodedTransaction['to'];
int confirmations = 0; // int confirmations = 0;
try { // try {
confirmations = currentBlock - i; // confirmations = currentBlock - i;
} catch (e, s) { // } catch (e, s) {
debugPrint("$e $s"); // debugPrint("$e $s");
} // }
midSortedTx["confirmations"] = confirmations; // midSortedTx["confirmations"] = confirmations;
midSortedTx["inputSize"] = 1; // midSortedTx["inputSize"] = 1;
midSortedTx["outputSize"] = 1; // midSortedTx["outputSize"] = 1;
midSortedTx["aliens"] = <dynamic>[]; // midSortedTx["aliens"] = <dynamic>[];
midSortedTx["inputs"] = <dynamic>[]; // midSortedTx["inputs"] = <dynamic>[];
midSortedTx["outputs"] = <dynamic>[]; // midSortedTx["outputs"] = <dynamic>[];
//
midSortedArray.add(midSortedTx); // midSortedArray.add(midSortedTx);
Logging.instance.log( // Logging.instance.log(
"TX SENT FROM THIS ACCOUNT ${decodedTransaction['from']} ${decodedTransaction['to']}", // "TX SENT FROM THIS ACCOUNT ${decodedTransaction['from']} ${decodedTransaction['to']}",
level: LogLevel.Info); // level: LogLevel.Info);
--n; // --n;
} // }
//
if (thisAddress == decodedTransaction['to']) { // if (thisAddress == decodedTransaction['to']) {
if (decodedTransaction['from'] != decodedTransaction['to']) { // if (decodedTransaction['from'] != decodedTransaction['to']) {
midSortedTx["txType"] = "Received"; // midSortedTx["txType"] = "Received";
midSortedTx["txid"] = decodedTransaction["hash"]; // midSortedTx["txid"] = decodedTransaction["hash"];
midSortedTx["height"] = i; // midSortedTx["height"] = i;
midSortedTx["address"] = decodedTransaction['from']; // midSortedTx["address"] = decodedTransaction['from'];
int confirmations = 0; // int confirmations = 0;
try { // try {
confirmations = currentBlock - i; // confirmations = currentBlock - i;
} catch (e, s) { // } catch (e, s) {
debugPrint("$e $s"); // debugPrint("$e $s");
} // }
midSortedTx["confirmations"] = confirmations; // midSortedTx["confirmations"] = confirmations;
midSortedTx["inputSize"] = 1; // midSortedTx["inputSize"] = 1;
midSortedTx["outputSize"] = 1; // midSortedTx["outputSize"] = 1;
midSortedTx["aliens"] = <dynamic>[]; // midSortedTx["aliens"] = <dynamic>[];
midSortedTx["inputs"] = <dynamic>[]; // midSortedTx["inputs"] = <dynamic>[];
midSortedTx["outputs"] = <dynamic>[]; // midSortedTx["outputs"] = <dynamic>[];
midSortedArray.add(midSortedTx); // midSortedArray.add(midSortedTx);
} // }
} // }
} // }
}); // });
} // }
} catch (e, s) { // } catch (e, s) {
print("Error getting transactions ${e.toString()} $s"); // print("Error getting transactions ${e.toString()} $s");
} // }
} // }
// midSortedArray
midSortedArray // .sort((a, b) => (b["timestamp"] as int) - (a["timestamp"] as int));
.sort((a, b) => (b["timestamp"] as int) - (a["timestamp"] as int)); // final Map<String, dynamic> result = {"dateTimeChunks": <dynamic>[]};
final Map<String, dynamic> result = {"dateTimeChunks": <dynamic>[]}; // final dateArray = <dynamic>[];
final dateArray = <dynamic>[]; //
// for (int i = 0; i < midSortedArray.length; i++) {
for (int i = 0; i < midSortedArray.length; i++) { // final txObject = midSortedArray[i];
final txObject = midSortedArray[i]; // final date = extractDateFromTimestamp(txObject["timestamp"] as int);
final date = extractDateFromTimestamp(txObject["timestamp"] as int); // final txTimeArray = [txObject["timestamp"], date];
final txTimeArray = [txObject["timestamp"], date]; //
// if (dateArray.contains(txTimeArray[1])) {
if (dateArray.contains(txTimeArray[1])) { // result["dateTimeChunks"].forEach((dynamic chunk) {
result["dateTimeChunks"].forEach((dynamic chunk) { // if (extractDateFromTimestamp(chunk["timestamp"] as int) ==
if (extractDateFromTimestamp(chunk["timestamp"] as int) == // txTimeArray[1]) {
txTimeArray[1]) { // if (chunk["transactions"] == null) {
if (chunk["transactions"] == null) { // chunk["transactions"] = <Map<String, dynamic>>[];
chunk["transactions"] = <Map<String, dynamic>>[]; // }
} // chunk["transactions"].add(txObject);
chunk["transactions"].add(txObject); // }
} // });
}); // } else {
} else { // dateArray.add(txTimeArray[1]);
dateArray.add(txTimeArray[1]); // final chunk = {
final chunk = { // "timestamp": txTimeArray[0],
"timestamp": txTimeArray[0], // "transactions": [txObject],
"transactions": [txObject], // };
}; // result["dateTimeChunks"].add(chunk);
result["dateTimeChunks"].add(chunk); // }
} // }
} //
// final transactionsMap = cachedTransactions?.getAllTransactions() ?? {};
final transactionsMap = cachedTransactions?.getAllTransactions() ?? {}; // transactionsMap
transactionsMap // .addAll(TransactionData.fromJson(result).getAllTransactions());
.addAll(TransactionData.fromJson(result).getAllTransactions());
print("THIS CURRECT ADDRESS IS $thisAddress"); print("THIS CURRECT ADDRESS IS $thisAddress");
print("THIS CURRECT BLOCK IS $currentBlock"); print("THIS CURRECT BLOCK IS $currentBlock");

View file

@ -225,7 +225,7 @@ packages:
name: code_builder name: code_builder
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.3.0" version: "4.4.0"
collection: collection:
dependency: transitive dependency: transitive
description: description:
@ -429,6 +429,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "5.0.1" version: "5.0.1"
ethereum_addresses:
dependency: "direct main"
description:
name: ethereum_addresses
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
event_bus: event_bus:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1284,7 +1291,7 @@ packages:
name: shared_preferences_linux name: shared_preferences_linux
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.1" version: "2.1.2"
shared_preferences_macos: shared_preferences_macos:
dependency: transitive dependency: transitive
description: description:
@ -1312,7 +1319,7 @@ packages:
name: shared_preferences_windows name: shared_preferences_windows
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.1" version: "2.1.2"
shelf: shelf:
dependency: transitive dependency: transitive
description: description:
@ -1683,7 +1690,7 @@ packages:
name: win32 name: win32
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.1.2" version: "3.1.3"
window_size: window_size:
dependency: "direct main" dependency: "direct main"
description: description:

View file

@ -91,6 +91,7 @@ dependencies:
# Eth Plugins # Eth Plugins
web3dart: 2.3.5 web3dart: 2.3.5
string_to_hex: 0.2.2 string_to_hex: 0.2.2
ethereum_addresses: 1.0.2
# Storage plugins # Storage plugins
flutter_secure_storage: ^5.0.2 flutter_secure_storage: ^5.0.2