Fix Private key for Ethereum wallets

This commit is contained in:
OmarHatem 2023-04-05 18:01:20 +02:00
parent db90dde952
commit b02b653ceb
6 changed files with 52 additions and 58 deletions

View file

@ -4,20 +4,19 @@ import 'package:cw_core/balance.dart';
import 'package:web3dart/web3dart.dart'; import 'package:web3dart/web3dart.dart';
class EthereumBalance extends Balance { class EthereumBalance extends Balance {
EthereumBalance({required int available, required int additional}) : super(available, additional); EthereumBalance(this.balance)
: super(balance.getValueInUnit(EtherUnit.wei).toInt(),
balance.getValueInUnit(EtherUnit.wei).toInt());
final EtherAmount balance;
@override @override
String get formattedAdditionalBalance { String get formattedAdditionalBalance => balance.getValueInUnit(EtherUnit.ether).toString();
return EtherAmount.fromUnitAndValue(EtherUnit.ether, additional.toString())
.getInEther
.toString();
}
@override @override
String get formattedAvailableBalance => String get formattedAvailableBalance => balance.getValueInUnit(EtherUnit.ether).toString();
EtherAmount.fromUnitAndValue(EtherUnit.ether, available.toString()).getInEther.toString();
String toJSON() => json.encode({'available': available, 'additional': additional}); String toJSON() => json.encode({'balanceInWei': balance.getInWei.toString()});
static EthereumBalance? fromJSON(String? jsonSource) { static EthereumBalance? fromJSON(String? jsonSource) {
if (jsonSource == null) { if (jsonSource == null) {
@ -26,9 +25,10 @@ class EthereumBalance extends Balance {
final decoded = json.decode(jsonSource) as Map; final decoded = json.decode(jsonSource) as Map;
return EthereumBalance( try {
available: decoded['available'] as int? ?? 0, return EthereumBalance(EtherAmount.inWei(BigInt.parse(decoded['balanceInWei'])));
additional: decoded['additional'] as int? ?? 0, } catch (e) {
); return EthereumBalance(EtherAmount.zero());
}
} }
} }

View file

@ -1,3 +1,5 @@
import 'dart:typed_data';
import 'package:cw_core/node.dart'; import 'package:cw_core/node.dart';
import 'package:cw_ethereum/ethereum_transaction_priority.dart'; import 'package:cw_ethereum/ethereum_transaction_priority.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
@ -17,10 +19,8 @@ class EthereumClient {
} }
} }
Future<EtherAmount> getBalance(String privateKey) async { Future<EtherAmount> getBalance(EthereumAddress address) async {
final private = EthPrivateKey.fromHex(privateKey); return await _client!.getBalance(address);
return _client!.getBalance(private.address);
} }
Future<int> getGasUnitPrice() async { Future<int> getGasUnitPrice() async {
@ -39,35 +39,33 @@ class EthereumClient {
return result.map((e) => e.toInt()).toList(); return result.map((e) => e.toInt()).toList();
} }
Future<String> signTransaction(String privateKey, String toAddress, String amount) async { Future<String> signTransaction(
final credentials = EthPrivateKey.fromHex(privateKey); EthPrivateKey privateKey,
String toAddress,
String amount,
int fee,
) async {
final transaction = Transaction( final transaction = Transaction(
from: credentials.address, from: privateKey.address,
to: EthereumAddress.fromHex(toAddress), to: EthereumAddress.fromHex(toAddress),
value: EtherAmount.zero(), value: EtherAmount.fromUnitAndValue(EtherUnit.ether, amount),
// maxPriorityFeePerGas: EtherAmount.inWei(BigInt.from(fee)),
); );
print("@@@@@@@@@@@@@@@@@");
print(transaction);
String tr = bytesToHex(await _client!.signTransaction(credentials, transaction)); final Uint8List signedTransaction = await _client!.signTransaction(privateKey, transaction);
print("@@@@@@@@@@@@@@@@@");
print(tr);
return tr; return bytesToHex(signedTransaction);
} }
Future<String> sendTransaction(String privateKey, String toAddress, String amount) async { Future<String> sendTransaction(EthPrivateKey privateKey, String toAddress, String amount) async {
final credentials = EthPrivateKey.fromHex(privateKey);
final transaction = Transaction( final transaction = Transaction(
from: credentials.address, from: privateKey.address,
to: EthereumAddress.fromHex(toAddress), to: EthereumAddress.fromHex(toAddress),
value: EtherAmount.fromUnitAndValue(EtherUnit.ether, amount), value: EtherAmount.fromUnitAndValue(EtherUnit.ether, amount),
); );
return await _client!.sendTransaction( return await _client!.sendTransaction(
credentials, privateKey,
transaction, transaction,
); );
} }

View file

@ -22,9 +22,7 @@ import 'package:cw_ethereum/file.dart';
import 'package:cw_ethereum/pending_ethereum_transaction.dart'; import 'package:cw_ethereum/pending_ethereum_transaction.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:web3dart/web3dart.dart'; import 'package:web3dart/web3dart.dart';
import 'package:ed25519_hd_key/ed25519_hd_key.dart';
import 'package:bip39/bip39.dart' as bip39; import 'package:bip39/bip39.dart' as bip39;
import 'package:hex/hex.dart';
part 'ethereum_wallet.g.dart'; part 'ethereum_wallet.g.dart';
@ -45,7 +43,7 @@ abstract class EthereumWalletBase
_client = EthereumClient(), _client = EthereumClient(),
walletAddresses = EthereumWalletAddresses(walletInfo), walletAddresses = EthereumWalletAddresses(walletInfo),
balance = ObservableMap<CryptoCurrency, EthereumBalance>.of( balance = ObservableMap<CryptoCurrency, EthereumBalance>.of(
{CryptoCurrency.eth: initialBalance ?? EthereumBalance(available: 0, additional: 0)}), {CryptoCurrency.eth: initialBalance ?? EthereumBalance(EtherAmount.zero())}),
super(walletInfo) { super(walletInfo) {
this.walletInfo = walletInfo; this.walletInfo = walletInfo;
} }
@ -53,7 +51,7 @@ abstract class EthereumWalletBase
final String _mnemonic; final String _mnemonic;
final String _password; final String _password;
late final String _privateKey; late final EthPrivateKey _privateKey;
late EthereumClient _client; late EthereumClient _client;
@ -75,7 +73,7 @@ abstract class EthereumWalletBase
await walletAddresses.init(); await walletAddresses.init();
_privateKey = await getPrivateKey(_mnemonic, _password); _privateKey = await getPrivateKey(_mnemonic, _password);
transactionHistory = EthereumTransactionHistory(); transactionHistory = EthereumTransactionHistory();
walletAddresses.address = EthPrivateKey.fromHex(_privateKey).address.toString(); walletAddresses.address = _privateKey.address.toString();
} }
@override @override
@ -121,11 +119,10 @@ abstract class EthereumWalletBase
@override @override
Future<PendingTransaction> createTransaction(Object credentials) async { Future<PendingTransaction> createTransaction(Object credentials) async {
print("!!!!!!!!!!!!!!!!!!!");
final _credentials = credentials as EthereumTransactionCredentials; final _credentials = credentials as EthereumTransactionCredentials;
final outputs = _credentials.outputs; final outputs = _credentials.outputs;
final hasMultiDestination = outputs.length > 1; final hasMultiDestination = outputs.length > 1;
final balance = await _client.getBalance(_privateKey); final balance = await _client.getBalance(_privateKey.address);
int totalAmount = 0; int totalAmount = 0;
if (hasMultiDestination) { if (hasMultiDestination) {
@ -150,7 +147,12 @@ abstract class EthereumWalletBase
} }
} }
await _client.signTransaction(_privateKey, _credentials.outputs.first.address, totalAmount.toString()); await _client.signTransaction(
_privateKey,
_credentials.outputs.first.address,
totalAmount.toString(),
_priorityFees[_credentials.priority!.raw],
);
return PendingEthereumTransaction( return PendingEthereumTransaction(
client: _client, client: _client,
@ -235,8 +237,8 @@ abstract class EthereumWalletBase
final jsonSource = await read(path: path, password: password); final jsonSource = await read(path: path, password: password);
final data = json.decode(jsonSource) as Map; final data = json.decode(jsonSource) as Map;
final mnemonic = data['mnemonic'] as String; final mnemonic = data['mnemonic'] as String;
final balance = EthereumBalance.fromJSON(data['balance'] as String) ?? final balance =
EthereumBalance(available: 0, additional: 0); EthereumBalance.fromJSON(data['balance'] as String) ?? EthereumBalance(EtherAmount.zero());
return EthereumWallet( return EthereumWallet(
walletInfo: walletInfo, walletInfo: walletInfo,
@ -252,21 +254,12 @@ abstract class EthereumWalletBase
} }
Future<EthereumBalance> _fetchBalances() async { Future<EthereumBalance> _fetchBalances() async {
final balance = await _client.getBalance(_privateKey); final balance = await _client.getBalance(_privateKey.address);
return EthereumBalance(balance);
return EthereumBalance(
available: balance.getInEther.toInt(),
additional: balance.getInEther.toInt(),
);
} }
Future<String> getPrivateKey(String mnemonic, String password) async { Future<EthPrivateKey> getPrivateKey(String mnemonic, String password) async {
final seed = bip39.mnemonicToSeedHex(mnemonic); final seed = bip39.mnemonicToSeedHex(mnemonic);
final master = await ED25519_HD_KEY.getMasterKeyFromSeed( return EthPrivateKey.fromHex(seed);
HEX.decode(seed),
masterSecret: password,
);
final privateKey = HEX.encode(master.key);
return privateKey;
} }
} }

View file

@ -3,11 +3,12 @@ import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/pending_transaction.dart'; import 'package:cw_core/pending_transaction.dart';
import 'package:cw_ethereum/ethereum_client.dart'; import 'package:cw_ethereum/ethereum_client.dart';
import 'package:cw_ethereum/ethereum_transaction_credentials.dart'; import 'package:cw_ethereum/ethereum_transaction_credentials.dart';
import 'package:web3dart/web3dart.dart';
class PendingEthereumTransaction with PendingTransaction { class PendingEthereumTransaction with PendingTransaction {
final EthereumClient client; final EthereumClient client;
final EthereumTransactionCredentials credentials; final EthereumTransactionCredentials credentials;
final String privateKey; final EthPrivateKey privateKey;
final int amount; final int amount;
PendingEthereumTransaction({ PendingEthereumTransaction({

View file

@ -104,6 +104,7 @@ abstract class BalanceViewModelBase with Store {
switch(wallet.type) { switch(wallet.type) {
case WalletType.monero: case WalletType.monero:
case WalletType.haven: case WalletType.haven:
case WalletType.ethereum:
return S.current.xmr_available_balance; return S.current.xmr_available_balance;
default: default:
return S.current.confirmed; return S.current.confirmed;
@ -115,6 +116,7 @@ abstract class BalanceViewModelBase with Store {
switch(wallet.type) { switch(wallet.type) {
case WalletType.monero: case WalletType.monero:
case WalletType.haven: case WalletType.haven:
case WalletType.ethereum:
return S.current.xmr_full_balance; return S.current.xmr_full_balance;
default: default:
return S.current.unconfirmed; return S.current.unconfirmed;