mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-10 20:54:33 +00:00
ADd address validation and convert receive addresses as checksum addresses
This commit is contained in:
parent
a6c2750f20
commit
5d77dcafbe
3 changed files with 181 additions and 127 deletions
|
@ -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");
|
||||||
|
|
15
pubspec.lock
15
pubspec.lock
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue