fix: Eth transaction fees WIP

This commit is contained in:
Blazebrain 2024-07-15 16:22:06 +01:00
parent ba44949244
commit b9a469bc7e
7 changed files with 459 additions and 360 deletions

View file

@ -65,26 +65,60 @@ abstract class EVMChainClient {
Future<int> getGasUnitPrice() async { Future<int> getGasUnitPrice() async {
try { try {
final gasPrice = await _client!.getGasPrice(); final gasPrice = await _client!.getGasPrice();
print('Gas Unit Price in Function: ${gasPrice.getInWei.toInt()}');
return gasPrice.getInWei.toInt(); return gasPrice.getInWei.toInt();
} catch (_) { } catch (_) {
return 0; return 0;
} }
} }
Future<int> getEstimatedGas() async { Future<int?> getGasBaseFee() async {
try { try {
final estimatedGas = await _client!.estimateGas(); final blockInfo = await _client!.getBlockInformation(isContainFullObj: false);
return estimatedGas.toInt(); final baseFee = blockInfo.baseFeePerGas;
print('Gas BaseFee in Function: ${baseFee?.getInWei.toInt()}');
return baseFee!.getInWei.toInt();
} catch (_) { } catch (_) {
return 0; return 0;
} }
} }
Future<BigInt> getEstimatedGas({
EtherAmount? maxPriorityFeePerGas,
EtherAmount? maxFeePerGas,
EthereumAddress? sender,
EtherAmount? gasPrice,
EthereumAddress? toAddress,
EtherAmount? value,
}) async {
try {
print('About to start in estimateGas');
final estimatedGas = await _client!.estimateGas(
// maxPriorityFeePerGas: maxPriorityFeePerGas,
// maxFeePerGas: maxFeePerGas,
sender: sender,
// gasPrice: gasPrice,
to: toAddress,
value: value,
);
print('About to end in estimateGas');
print('Estimated Gas in Function: ${estimatedGas.toInt()}');
return estimatedGas;
} catch (e, s) {
print('Error fetching estimateGas: ${e.toString}, ${s.toString()}');
return BigInt.zero;
}
}
Future<PendingEVMChainTransaction> signTransaction({ Future<PendingEVMChainTransaction> signTransaction({
required Credentials privateKey, required Credentials privateKey,
required String toAddress, required String toAddress,
required BigInt amount, required BigInt amount,
required int gas, required BigInt gas,
required EVMChainTransactionPriority priority, required EVMChainTransactionPriority priority,
required CryptoCurrency currency, required CryptoCurrency currency,
required int exponent, required int exponent,
@ -97,7 +131,7 @@ abstract class EVMChainClient {
bool isNativeToken = currency == CryptoCurrency.eth || currency == CryptoCurrency.maticpoly; bool isNativeToken = currency == CryptoCurrency.eth || currency == CryptoCurrency.maticpoly;
final price = _client!.getGasPrice(); // final price = _client!.getGasPrice();
final Transaction transaction = createTransaction( final Transaction transaction = createTransaction(
from: privateKey.address, from: privateKey.address,
@ -130,11 +164,10 @@ abstract class EVMChainClient {
_sendTransaction = () async => await sendTransaction(signedTransaction); _sendTransaction = () async => await sendTransaction(signedTransaction);
return PendingEVMChainTransaction( return PendingEVMChainTransaction(
signedTransaction: signedTransaction, signedTransaction: signedTransaction,
amount: amount.toString(), amount: amount.toString(),
fee: BigInt.from(gas) * (await price).getInWei, fee: gas,
sendTransaction: _sendTransaction, sendTransaction: _sendTransaction,
exponent: exponent, exponent: exponent,
); );
@ -233,7 +266,6 @@ abstract class EVMChainClient {
final decodedResponse = jsonDecode(response.body)[0] as Map<String, dynamic>; final decodedResponse = jsonDecode(response.body)[0] as Map<String, dynamic>;
final symbol = (decodedResponse['symbol'] ?? '') as String; final symbol = (decodedResponse['symbol'] ?? '') as String;
String filteredSymbol = symbol.replaceFirst(RegExp('^\\\$'), ''); String filteredSymbol = symbol.replaceFirst(RegExp('^\\\$'), '');

View file

@ -27,6 +27,7 @@ import 'package:cw_evm/evm_chain_transaction_priority.dart';
import 'package:cw_evm/evm_chain_wallet_addresses.dart'; import 'package:cw_evm/evm_chain_wallet_addresses.dart';
import 'package:cw_evm/evm_ledger_credentials.dart'; import 'package:cw_evm/evm_ledger_credentials.dart';
import 'package:cw_evm/file.dart'; import 'package:cw_evm/file.dart';
import 'package:flutter/foundation.dart';
import 'package:hex/hex.dart'; import 'package:hex/hex.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
@ -172,16 +173,74 @@ abstract class EVMChainWalletBase
} }
@override @override
int calculateEstimatedFee(TransactionPriority priority, int? amount) { int calculateEstimatedFee(TransactionPriority priority, int? amount) => 0;
// { try {
// if (priority is EVMChainTransactionPriority) {
// final priorityFee = EtherAmount.fromInt(EtherUnit.gwei, priority.tip).getInWei.toInt();
// print('Priority Tip: ${priority.tip}');
// print('Priority Title: ${priority.title}');
// print('Priority Fee: $priorityFee');
// print('Gas Price: $_gasPrice');
// print('Estimated Gas: $_estimatedGas');
// final estimatedFee = (_gasPrice! + priorityFee) * (_estimatedGas ?? 0);
// print('EstimatedFee: $estimatedFee');
// return estimatedFee;
// }
// return 0;
// } catch (e) {
// return 0;
// }
// }
Future<BigInt> calculateActualEstimatedFee({
BigInt? amount,
required String receivingAddressHex,
required TransactionPriority priority,
}) async {
try { try {
if (priority is EVMChainTransactionPriority) { if (priority is EVMChainTransactionPriority) {
final priorityFee = EtherAmount.fromInt(EtherUnit.gwei, priority.tip).getInWei.toInt(); final priorityFeeInEther = EtherAmount.fromInt(EtherUnit.gwei, priority.tip);
return (_gasPrice! + priorityFee) * (_estimatedGas ?? 0); final priorityFee = priorityFeeInEther.getInWei.toInt();
debugPrint('Priority Fee: $priorityFee');
debugPrint('Priority Tip: ${priority.tip}');
debugPrint('Priority Title: ${priority.title}');
final gasBaseFee = await _client.getGasBaseFee();
debugPrint('Base Fee: $gasBaseFee');
final gasPrice = await _client.getGasUnitPrice();
debugPrint('Gas Price: $gasPrice');
int maxFeePerGas;
if (gasBaseFee != null) {
maxFeePerGas = gasBaseFee + priorityFee;
debugPrint('MaxFeePerGas with EIP1559: $maxFeePerGas');
} else {
maxFeePerGas = gasPrice;
debugPrint('MaxFeePerGas with gasPrice: $maxFeePerGas');
}
final estimatedGas = await _client.getEstimatedGas(
maxPriorityFeePerGas: priorityFeeInEther,
maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas),
sender: _evmChainPrivateKey.address,
gasPrice: EtherAmount.fromInt(EtherUnit.wei, gasPrice),
toAddress: EthereumAddress.fromHex(receivingAddressHex),
value: EtherAmount.fromBigInt(EtherUnit.wei, amount!),
);
debugPrint('Estimated Gas: ${estimatedGas.toInt()}');
final totalGasFee = estimatedGas * BigInt.from(maxFeePerGas);
debugPrint('Total Gas Fee: $totalGasFee');
return totalGasFee;
} }
return 0; return BigInt.zero;
} catch (e) { } catch (e) {
return 0; return BigInt.zero;
} }
} }
@ -196,6 +255,11 @@ abstract class EVMChainWalletBase
_transactionsUpdateTimer?.cancel(); _transactionsUpdateTimer?.cancel();
} }
String _getFeeInValue(BigInt fee) {
final _fee = (fee / BigInt.from(pow(10, 18))).toString();
return _fee.substring(0, min(10, _fee.length));
}
@action @action
@override @override
Future<void> connectToNode({required Node node}) async { Future<void> connectToNode({required Node node}) async {
@ -226,12 +290,13 @@ abstract class EVMChainWalletBase
await _updateBalance(); await _updateBalance();
await _updateTransactions(); await _updateTransactions();
_gasPrice = await _client.getGasUnitPrice(); _gasPrice = await _client.getGasUnitPrice();
_estimatedGas = await _client.getEstimatedGas(); // _estimatedGas = await _client.getEstimatedGas();
Timer.periodic( Timer.periodic(
const Duration(minutes: 1), (timer) async => _gasPrice = await _client.getGasUnitPrice()); const Duration(minutes: 1), (timer) async => _gasPrice = await _client.getGasUnitPrice());
Timer.periodic(const Duration(seconds: 10), Timer.periodic(const Duration(seconds: 10), (timer) async {
(timer) async => _estimatedGas = await _client.getEstimatedGas()); // return _estimatedGas = await _client.getEstimatedGas();
});
syncStatus = SyncedSyncStatus(); syncStatus = SyncedSyncStatus();
} catch (e) { } catch (e) {
@ -258,8 +323,12 @@ abstract class EVMChainWalletBase
final erc20Balance = balance[transactionCurrency]!; final erc20Balance = balance[transactionCurrency]!;
BigInt totalAmount = BigInt.zero; BigInt totalAmount = BigInt.zero;
BigInt estimatedFeesForTransaction = BigInt.zero;
int exponent = transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18; int exponent = transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18;
num amountToEVMChainMultiplier = pow(10, exponent); num amountToEVMChainMultiplier = pow(10, exponent);
String toAddress = _credentials.outputs.first.isParsedAddress
? _credentials.outputs.first.extractedAddress!
: _credentials.outputs.first.address;
// so far this can not be made with Ethereum as Ethereum does not support multiple recipients // so far this can not be made with Ethereum as Ethereum does not support multiple recipients
if (hasMultiDestination) { if (hasMultiDestination) {
@ -271,6 +340,13 @@ abstract class EVMChainWalletBase
outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0))); outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0)));
totalAmount = BigInt.from(totalOriginalAmount * amountToEVMChainMultiplier); totalAmount = BigInt.from(totalOriginalAmount * amountToEVMChainMultiplier);
estimatedFeesForTransaction = await calculateActualEstimatedFee(
amount: totalAmount,
receivingAddressHex: toAddress,
priority: _credentials.priority!,
);
debugPrint('Estimated Fees for Transaction: $estimatedFeesForTransaction');
if (erc20Balance.balance < totalAmount) { if (erc20Balance.balance < totalAmount) {
throw EVMChainTransactionCreationException(transactionCurrency); throw EVMChainTransactionCreationException(transactionCurrency);
} }
@ -278,28 +354,49 @@ abstract class EVMChainWalletBase
final output = outputs.first; final output = outputs.first;
// since the fees are taken from Ethereum // since the fees are taken from Ethereum
// then no need to subtract the fees from the amount if send all // then no need to subtract the fees from the amount if send all
final BigInt allAmount; // final BigInt allAmount;
if (transactionCurrency is Erc20Token) { // if (transactionCurrency is Erc20Token) {
allAmount = erc20Balance.balance; // allAmount = erc20Balance.balance;
} else { // } else {
final estimatedFee = BigInt.from(calculateEstimatedFee(_credentials.priority!, null)); // final estimatedFee = BigInt.from(calculateEstimatedFee(_credentials.priority!, null));
if (estimatedFee > erc20Balance.balance) { // if (estimatedFee > erc20Balance.balance) {
throw EVMChainTransactionFeesException(); // throw EVMChainTransactionFeesException();
} // }
// allAmount = erc20Balance.balance - estimatedFee;
// }
allAmount = erc20Balance.balance - estimatedFee; if (!output.sendAll) {
}
if (output.sendAll) {
totalAmount = allAmount;
} else {
final totalOriginalAmount = final totalOriginalAmount =
EVMChainFormatter.parseEVMChainAmountToDouble(output.formattedCryptoAmount ?? 0); EVMChainFormatter.parseEVMChainAmountToDouble(output.formattedCryptoAmount ?? 0);
totalAmount = BigInt.from(totalOriginalAmount * amountToEVMChainMultiplier); totalAmount = BigInt.from(totalOriginalAmount * amountToEVMChainMultiplier);
} }
if (output.sendAll && transactionCurrency is Erc20Token) {
totalAmount = erc20Balance.balance;
}
estimatedFeesForTransaction = await calculateActualEstimatedFee(
amount: totalAmount,
receivingAddressHex: toAddress,
priority: _credentials.priority!,
);
debugPrint('Estimated Fees for Transaction: $estimatedFeesForTransaction');
if (output.sendAll && transactionCurrency is! Erc20Token) {
totalAmount = (erc20Balance.balance - estimatedFeesForTransaction);
if (estimatedFeesForTransaction > erc20Balance.balance) {
throw EVMChainTransactionFeesException();
}
}
final feeIn = _getFeeInValue(estimatedFeesForTransaction);
final balanceIn = _getFeeInValue(erc20Balance.balance);
print('feeIn: $feeIn');
print('BalanceIn: $balanceIn');
if (erc20Balance.balance < totalAmount) { if (erc20Balance.balance < totalAmount) {
throw EVMChainTransactionCreationException(transactionCurrency); throw EVMChainTransactionCreationException(transactionCurrency);
} }
@ -312,11 +409,9 @@ abstract class EVMChainWalletBase
final pendingEVMChainTransaction = await _client.signTransaction( final pendingEVMChainTransaction = await _client.signTransaction(
privateKey: _evmChainPrivateKey, privateKey: _evmChainPrivateKey,
toAddress: _credentials.outputs.first.isParsedAddress toAddress: toAddress,
? _credentials.outputs.first.extractedAddress!
: _credentials.outputs.first.address,
amount: totalAmount, amount: totalAmount,
gas: _estimatedGas!, gas: estimatedFeesForTransaction,
priority: _credentials.priority!, priority: _credentials.priority!,
currency: transactionCurrency, currency: transactionCurrency,
exponent: exponent, exponent: exponent,
@ -400,7 +495,7 @@ abstract class EVMChainWalletBase
} }
final methodSignature = final methodSignature =
transactionInput.length >= 10 ? transactionInput.substring(0, 10) : null; transactionInput.length >= 10 ? transactionInput.substring(0, 10) : null;
return methodSignatureToType[methodSignature]; return methodSignatureToType[methodSignature];
} }

View file

@ -8,36 +8,6 @@ PODS:
- Flutter - Flutter
- ReachabilitySwift - ReachabilitySwift
- CryptoSwift (1.8.2) - CryptoSwift (1.8.2)
- cw_haven (0.0.1):
- cw_haven/Boost (= 0.0.1)
- cw_haven/Haven (= 0.0.1)
- cw_haven/OpenSSL (= 0.0.1)
- cw_haven/Sodium (= 0.0.1)
- cw_shared_external
- Flutter
- cw_haven/Boost (0.0.1):
- cw_shared_external
- Flutter
- cw_haven/Haven (0.0.1):
- cw_shared_external
- Flutter
- cw_haven/OpenSSL (0.0.1):
- cw_shared_external
- Flutter
- cw_haven/Sodium (0.0.1):
- cw_shared_external
- Flutter
- cw_shared_external (0.0.1):
- cw_shared_external/Boost (= 0.0.1)
- cw_shared_external/OpenSSL (= 0.0.1)
- cw_shared_external/Sodium (= 0.0.1)
- Flutter
- cw_shared_external/Boost (0.0.1):
- Flutter
- cw_shared_external/OpenSSL (0.0.1):
- Flutter
- cw_shared_external/Sodium (0.0.1):
- Flutter
- device_display_brightness (0.0.1): - device_display_brightness (0.0.1):
- Flutter - Flutter
- device_info_plus (0.0.1): - device_info_plus (0.0.1):
@ -97,6 +67,8 @@ PODS:
- Toast - Toast
- in_app_review (0.2.0): - in_app_review (0.2.0):
- Flutter - Flutter
- integration_test (0.0.1):
- Flutter
- MTBBarcodeScanner (5.0.11) - MTBBarcodeScanner (5.0.11)
- OrderedSet (5.0.0) - OrderedSet (5.0.0)
- package_info (0.0.1): - package_info (0.0.1):
@ -145,8 +117,6 @@ DEPENDENCIES:
- barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`) - barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`)
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
- CryptoSwift - CryptoSwift
- cw_haven (from `.symlinks/plugins/cw_haven/ios`)
- cw_shared_external (from `.symlinks/plugins/cw_shared_external/ios`)
- device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`) - device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- devicelocale (from `.symlinks/plugins/devicelocale/ios`) - devicelocale (from `.symlinks/plugins/devicelocale/ios`)
@ -158,6 +128,7 @@ DEPENDENCIES:
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- in_app_review (from `.symlinks/plugins/in_app_review/ios`) - in_app_review (from `.symlinks/plugins/in_app_review/ios`)
- integration_test (from `.symlinks/plugins/integration_test/ios`)
- package_info (from `.symlinks/plugins/package_info/ios`) - package_info (from `.symlinks/plugins/package_info/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
@ -194,10 +165,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/barcode_scan2/ios" :path: ".symlinks/plugins/barcode_scan2/ios"
connectivity_plus: connectivity_plus:
:path: ".symlinks/plugins/connectivity_plus/ios" :path: ".symlinks/plugins/connectivity_plus/ios"
cw_haven:
:path: ".symlinks/plugins/cw_haven/ios"
cw_shared_external:
:path: ".symlinks/plugins/cw_shared_external/ios"
device_display_brightness: device_display_brightness:
:path: ".symlinks/plugins/device_display_brightness/ios" :path: ".symlinks/plugins/device_display_brightness/ios"
device_info_plus: device_info_plus:
@ -220,6 +187,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/fluttertoast/ios" :path: ".symlinks/plugins/fluttertoast/ios"
in_app_review: in_app_review:
:path: ".symlinks/plugins/in_app_review/ios" :path: ".symlinks/plugins/in_app_review/ios"
integration_test:
:path: ".symlinks/plugins/integration_test/ios"
package_info: package_info:
:path: ".symlinks/plugins/package_info/ios" :path: ".symlinks/plugins/package_info/ios"
package_info_plus: package_info_plus:
@ -252,8 +221,6 @@ SPEC CHECKSUMS:
BigInt: f668a80089607f521586bbe29513d708491ef2f7 BigInt: f668a80089607f521586bbe29513d708491ef2f7
connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d
CryptoSwift: c63a805d8bb5e5538e88af4e44bb537776af11ea CryptoSwift: c63a805d8bb5e5538e88af4e44bb537776af11ea
cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a
cw_shared_external: 2972d872b8917603478117c9957dfca611845a92
device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7 device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
devicelocale: b22617f40038496deffba44747101255cee005b0 devicelocale: b22617f40038496deffba44747101255cee005b0
@ -267,6 +234,7 @@ SPEC CHECKSUMS:
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
fluttertoast: 48c57db1b71b0ce9e6bba9f31c940ff4b001293c fluttertoast: 48c57db1b71b0ce9e6bba9f31c940ff4b001293c
in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d
integration_test: 13825b8a9334a850581300559b8839134b124670
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
@ -278,7 +246,7 @@ SPEC CHECKSUMS:
reactive_ble_mobile: 9ce6723d37ccf701dbffd202d487f23f5de03b4c reactive_ble_mobile: 9ce6723d37ccf701dbffd202d487f23f5de03b4c
SDWebImage: 066c47b573f408f18caa467d71deace7c0f8280d SDWebImage: 066c47b573f408f18caa467d71deace7c0f8280d
sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986 sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sp_scanner: eaa617fa827396b967116b7f1f43549ca62e9a12 sp_scanner: eaa617fa827396b967116b7f1f43549ca62e9a12
SwiftProtobuf: 5e8349171e7c2f88f5b9e683cb3cb79d1dc780b3 SwiftProtobuf: 5e8349171e7c2f88f5b9e683cb3cb79d1dc780b3

View file

@ -1,331 +1,331 @@
part of 'haven.dart'; // part of 'haven.dart';
class CWHavenAccountList extends HavenAccountList { // class CWHavenAccountList extends HavenAccountList {
CWHavenAccountList(this._wallet); // CWHavenAccountList(this._wallet);
final Object _wallet; // final Object _wallet;
@override // @override
@computed // @computed
ObservableList<Account> get accounts { // ObservableList<Account> get accounts {
final havenWallet = _wallet as HavenWallet; // final havenWallet = _wallet as HavenWallet;
final accounts = havenWallet.walletAddresses.accountList.accounts // final accounts = havenWallet.walletAddresses.accountList.accounts
.map((acc) => Account(id: acc.id, label: acc.label)) // .map((acc) => Account(id: acc.id, label: acc.label))
.toList(); // .toList();
return ObservableList<Account>.of(accounts); // return ObservableList<Account>.of(accounts);
} // }
@override // @override
void update(Object wallet) { // void update(Object wallet) {
final havenWallet = wallet as HavenWallet; // final havenWallet = wallet as HavenWallet;
havenWallet.walletAddresses.accountList.update(); // havenWallet.walletAddresses.accountList.update();
} // }
@override // @override
void refresh(Object wallet) { // void refresh(Object wallet) {
final havenWallet = wallet as HavenWallet; // final havenWallet = wallet as HavenWallet;
havenWallet.walletAddresses.accountList.refresh(); // havenWallet.walletAddresses.accountList.refresh();
} // }
@override // @override
List<Account> getAll(Object wallet) { // List<Account> getAll(Object wallet) {
final havenWallet = wallet as HavenWallet; // final havenWallet = wallet as HavenWallet;
return havenWallet.walletAddresses.accountList // return havenWallet.walletAddresses.accountList
.getAll() // .getAll()
.map((acc) => Account(id: acc.id, label: acc.label)) // .map((acc) => Account(id: acc.id, label: acc.label))
.toList(); // .toList();
} // }
@override // @override
Future<void> addAccount(Object wallet, {required String label}) async { // Future<void> addAccount(Object wallet, {required String label}) async {
final havenWallet = wallet as HavenWallet; // final havenWallet = wallet as HavenWallet;
await havenWallet.walletAddresses.accountList.addAccount(label: label); // await havenWallet.walletAddresses.accountList.addAccount(label: label);
} // }
@override // @override
Future<void> setLabelAccount(Object wallet, // Future<void> setLabelAccount(Object wallet,
{required int accountIndex, required String label}) async { // {required int accountIndex, required String label}) async {
final havenWallet = wallet as HavenWallet; // final havenWallet = wallet as HavenWallet;
await havenWallet.walletAddresses.accountList // await havenWallet.walletAddresses.accountList
.setLabelAccount(accountIndex: accountIndex, label: label); // .setLabelAccount(accountIndex: accountIndex, label: label);
} // }
} // }
class CWHavenSubaddressList extends MoneroSubaddressList { // class CWHavenSubaddressList extends MoneroSubaddressList {
CWHavenSubaddressList(this._wallet); // CWHavenSubaddressList(this._wallet);
final Object _wallet; // final Object _wallet;
@override // @override
@computed // @computed
ObservableList<Subaddress> get subaddresses { // ObservableList<Subaddress> get subaddresses {
final havenWallet = _wallet as HavenWallet; // final havenWallet = _wallet as HavenWallet;
final subAddresses = havenWallet.walletAddresses.subaddressList.subaddresses // final subAddresses = havenWallet.walletAddresses.subaddressList.subaddresses
.map((sub) => Subaddress(id: sub.id, address: sub.address, label: sub.label)) // .map((sub) => Subaddress(id: sub.id, address: sub.address, label: sub.label))
.toList(); // .toList();
return ObservableList<Subaddress>.of(subAddresses); // return ObservableList<Subaddress>.of(subAddresses);
} // }
@override // @override
void update(Object wallet, {required int accountIndex}) { // void update(Object wallet, {required int accountIndex}) {
final havenWallet = wallet as HavenWallet; // final havenWallet = wallet as HavenWallet;
havenWallet.walletAddresses.subaddressList.update(accountIndex: accountIndex); // havenWallet.walletAddresses.subaddressList.update(accountIndex: accountIndex);
} // }
@override // @override
void refresh(Object wallet, {required int accountIndex}) { // void refresh(Object wallet, {required int accountIndex}) {
final havenWallet = wallet as HavenWallet; // final havenWallet = wallet as HavenWallet;
havenWallet.walletAddresses.subaddressList.refresh(accountIndex: accountIndex); // havenWallet.walletAddresses.subaddressList.refresh(accountIndex: accountIndex);
} // }
@override // @override
List<Subaddress> getAll(Object wallet) { // List<Subaddress> getAll(Object wallet) {
final havenWallet = wallet as HavenWallet; // final havenWallet = wallet as HavenWallet;
return havenWallet.walletAddresses.subaddressList // return havenWallet.walletAddresses.subaddressList
.getAll() // .getAll()
.map((sub) => Subaddress(id: sub.id, label: sub.label, address: sub.address)) // .map((sub) => Subaddress(id: sub.id, label: sub.label, address: sub.address))
.toList(); // .toList();
} // }
@override // @override
Future<void> addSubaddress(Object wallet, // Future<void> addSubaddress(Object wallet,
{required int accountIndex, required String label}) async { // {required int accountIndex, required String label}) async {
final havenWallet = wallet as HavenWallet; // final havenWallet = wallet as HavenWallet;
await havenWallet.walletAddresses.subaddressList // await havenWallet.walletAddresses.subaddressList
.addSubaddress(accountIndex: accountIndex, label: label); // .addSubaddress(accountIndex: accountIndex, label: label);
} // }
@override // @override
Future<void> setLabelSubaddress(Object wallet, // Future<void> setLabelSubaddress(Object wallet,
{required int accountIndex, required int addressIndex, required String label}) async { // {required int accountIndex, required int addressIndex, required String label}) async {
final havenWallet = wallet as HavenWallet; // final havenWallet = wallet as HavenWallet;
await havenWallet.walletAddresses.subaddressList // await havenWallet.walletAddresses.subaddressList
.setLabelSubaddress(accountIndex: accountIndex, addressIndex: addressIndex, label: label); // .setLabelSubaddress(accountIndex: accountIndex, addressIndex: addressIndex, label: label);
} // }
} // }
class CWHavenWalletDetails extends HavenWalletDetails { // class CWHavenWalletDetails extends HavenWalletDetails {
CWHavenWalletDetails(this._wallet); // CWHavenWalletDetails(this._wallet);
final Object _wallet; // final Object _wallet;
@computed // @computed
@override // @override
Account get account { // Account get account {
final havenWallet = _wallet as HavenWallet; // final havenWallet = _wallet as HavenWallet;
final acc = havenWallet.walletAddresses.account as monero_account.Account; // final acc = havenWallet.walletAddresses.account as monero_account.Account;
return Account(id: acc.id, label: acc.label); // return Account(id: acc.id, label: acc.label);
} // }
@computed // @computed
@override // @override
HavenBalance get balance { // HavenBalance get balance {
final havenWallet = _wallet as HavenWallet; // final havenWallet = _wallet as HavenWallet;
final balance = havenWallet.balance; // final balance = havenWallet.balance;
throw Exception('Unimplemented'); // throw Exception('Unimplemented');
//return HavenBalance( // //return HavenBalance(
// fullBalance: balance.fullBalance, // // fullBalance: balance.fullBalance,
// unlockedBalance: balance.unlockedBalance); // // unlockedBalance: balance.unlockedBalance);
} // }
} // }
class CWHaven extends Haven { // class CWHaven extends Haven {
@override // @override
HavenAccountList getAccountList(Object wallet) { // HavenAccountList getAccountList(Object wallet) {
return CWHavenAccountList(wallet); // return CWHavenAccountList(wallet);
} // }
@override // @override
MoneroSubaddressList getSubaddressList(Object wallet) { // MoneroSubaddressList getSubaddressList(Object wallet) {
return CWHavenSubaddressList(wallet); // return CWHavenSubaddressList(wallet);
} // }
@override // @override
TransactionHistoryBase getTransactionHistory(Object wallet) { // TransactionHistoryBase getTransactionHistory(Object wallet) {
final havenWallet = wallet as HavenWallet; // final havenWallet = wallet as HavenWallet;
return havenWallet.transactionHistory; // return havenWallet.transactionHistory;
} // }
@override // @override
HavenWalletDetails getMoneroWalletDetails(Object wallet) { // HavenWalletDetails getMoneroWalletDetails(Object wallet) {
return CWHavenWalletDetails(wallet); // return CWHavenWalletDetails(wallet);
} // }
@override // @override
int getHeightByDate({required DateTime date}) => getHavenHeightByDate(date: date); // int getHeightByDate({required DateTime date}) => getHavenHeightByDate(date: date);
@override // @override
Future<int> getCurrentHeight() => getHavenCurrentHeight(); // Future<int> getCurrentHeight() => getHavenCurrentHeight();
@override // @override
TransactionPriority getDefaultTransactionPriority() { // TransactionPriority getDefaultTransactionPriority() {
return MoneroTransactionPriority.automatic; // return MoneroTransactionPriority.automatic;
} // }
@override // @override
TransactionPriority deserializeMoneroTransactionPriority({required int raw}) { // TransactionPriority deserializeMoneroTransactionPriority({required int raw}) {
return MoneroTransactionPriority.deserialize(raw: raw); // return MoneroTransactionPriority.deserialize(raw: raw);
} // }
@override // @override
List<TransactionPriority> getTransactionPriorities() { // List<TransactionPriority> getTransactionPriorities() {
return MoneroTransactionPriority.all; // return MoneroTransactionPriority.all;
} // }
@override // @override
List<String> getMoneroWordList(String language) { // List<String> getMoneroWordList(String language) {
switch (language.toLowerCase()) { // switch (language.toLowerCase()) {
case 'english': // case 'english':
return EnglishMnemonics.words; // return EnglishMnemonics.words;
case 'chinese (simplified)': // case 'chinese (simplified)':
return ChineseSimplifiedMnemonics.words; // return ChineseSimplifiedMnemonics.words;
case 'dutch': // case 'dutch':
return DutchMnemonics.words; // return DutchMnemonics.words;
case 'german': // case 'german':
return GermanMnemonics.words; // return GermanMnemonics.words;
case 'japanese': // case 'japanese':
return JapaneseMnemonics.words; // return JapaneseMnemonics.words;
case 'portuguese': // case 'portuguese':
return PortugueseMnemonics.words; // return PortugueseMnemonics.words;
case 'russian': // case 'russian':
return RussianMnemonics.words; // return RussianMnemonics.words;
case 'spanish': // case 'spanish':
return SpanishMnemonics.words; // return SpanishMnemonics.words;
case 'french': // case 'french':
return FrenchMnemonics.words; // return FrenchMnemonics.words;
case 'italian': // case 'italian':
return ItalianMnemonics.words; // return ItalianMnemonics.words;
default: // default:
return EnglishMnemonics.words; // return EnglishMnemonics.words;
} // }
} // }
@override // @override
WalletCredentials createHavenRestoreWalletFromKeysCredentials( // WalletCredentials createHavenRestoreWalletFromKeysCredentials(
{required String name, // {required String name,
required String spendKey, // required String spendKey,
required String viewKey, // required String viewKey,
required String address, // required String address,
required String password, // required String password,
required String language, // required String language,
required int height}) { // required int height}) {
return HavenRestoreWalletFromKeysCredentials( // return HavenRestoreWalletFromKeysCredentials(
name: name, // name: name,
spendKey: spendKey, // spendKey: spendKey,
viewKey: viewKey, // viewKey: viewKey,
address: address, // address: address,
password: password, // password: password,
language: language, // language: language,
height: height); // height: height);
} // }
@override // @override
WalletCredentials createHavenRestoreWalletFromSeedCredentials( // WalletCredentials createHavenRestoreWalletFromSeedCredentials(
{required String name, // {required String name,
required String password, // required String password,
required int height, // required int height,
required String mnemonic}) { // required String mnemonic}) {
return HavenRestoreWalletFromSeedCredentials( // return HavenRestoreWalletFromSeedCredentials(
name: name, password: password, height: height, mnemonic: mnemonic); // name: name, password: password, height: height, mnemonic: mnemonic);
} // }
@override // @override
WalletCredentials createHavenNewWalletCredentials( // WalletCredentials createHavenNewWalletCredentials(
{required String name, required String language, String? password}) { // {required String name, required String language, String? password}) {
return HavenNewWalletCredentials(name: name, password: password, language: language); // return HavenNewWalletCredentials(name: name, password: password, language: language);
} // }
@override // @override
Map<String, String> getKeys(Object wallet) { // Map<String, String> getKeys(Object wallet) {
final havenWallet = wallet as HavenWallet; // final havenWallet = wallet as HavenWallet;
final keys = havenWallet.keys; // final keys = havenWallet.keys;
return <String, String>{ // return <String, String>{
'privateSpendKey': keys.privateSpendKey, // 'privateSpendKey': keys.privateSpendKey,
'privateViewKey': keys.privateViewKey, // 'privateViewKey': keys.privateViewKey,
'publicSpendKey': keys.publicSpendKey, // 'publicSpendKey': keys.publicSpendKey,
'publicViewKey': keys.publicViewKey // 'publicViewKey': keys.publicViewKey
}; // };
} // }
@override // @override
Object createHavenTransactionCreationCredentials( // Object createHavenTransactionCreationCredentials(
{required List<Output> outputs, // {required List<Output> outputs,
required TransactionPriority priority, // required TransactionPriority priority,
required String assetType}) { // required String assetType}) {
return HavenTransactionCreationCredentials( // return HavenTransactionCreationCredentials(
outputs: outputs // outputs: outputs
.map((out) => OutputInfo( // .map((out) => OutputInfo(
fiatAmount: out.fiatAmount, // fiatAmount: out.fiatAmount,
cryptoAmount: out.cryptoAmount, // cryptoAmount: out.cryptoAmount,
address: out.address, // address: out.address,
note: out.note, // note: out.note,
sendAll: out.sendAll, // sendAll: out.sendAll,
extractedAddress: out.extractedAddress, // extractedAddress: out.extractedAddress,
isParsedAddress: out.isParsedAddress, // isParsedAddress: out.isParsedAddress,
formattedCryptoAmount: out.formattedCryptoAmount)) // formattedCryptoAmount: out.formattedCryptoAmount))
.toList(), // .toList(),
priority: priority as MoneroTransactionPriority, // priority: priority as MoneroTransactionPriority,
assetType: assetType); // assetType: assetType);
} // }
@override // @override
String formatterMoneroAmountToString({required int amount}) { // String formatterMoneroAmountToString({required int amount}) {
return moneroAmountToString(amount: amount); // return moneroAmountToString(amount: amount);
} // }
@override // @override
double formatterMoneroAmountToDouble({required int amount}) { // double formatterMoneroAmountToDouble({required int amount}) {
return moneroAmountToDouble(amount: amount); // return moneroAmountToDouble(amount: amount);
} // }
@override // @override
int formatterMoneroParseAmount({required String amount}) { // int formatterMoneroParseAmount({required String amount}) {
return moneroParseAmount(amount: amount); // return moneroParseAmount(amount: amount);
} // }
@override // @override
Account getCurrentAccount(Object wallet) { // Account getCurrentAccount(Object wallet) {
final havenWallet = wallet as HavenWallet; // final havenWallet = wallet as HavenWallet;
final acc = havenWallet.walletAddresses.account as monero_account.Account; // final acc = havenWallet.walletAddresses.account as monero_account.Account;
return Account(id: acc.id, label: acc.label); // return Account(id: acc.id, label: acc.label);
} // }
@override // @override
void setCurrentAccount(Object wallet, int id, String label) { // void setCurrentAccount(Object wallet, int id, String label) {
final havenWallet = wallet as HavenWallet; // final havenWallet = wallet as HavenWallet;
havenWallet.walletAddresses.account = monero_account.Account(id: id, label: label); // havenWallet.walletAddresses.account = monero_account.Account(id: id, label: label);
} // }
@override // @override
void onStartup() { // void onStartup() {
monero_wallet_api.onStartup(); // monero_wallet_api.onStartup();
} // }
@override // @override
int getTransactionInfoAccountId(TransactionInfo tx) { // int getTransactionInfoAccountId(TransactionInfo tx) {
final havenTransactionInfo = tx as HavenTransactionInfo; // final havenTransactionInfo = tx as HavenTransactionInfo;
return havenTransactionInfo.accountIndex; // return havenTransactionInfo.accountIndex;
} // }
@override // @override
WalletService createHavenWalletService(Box<WalletInfo> walletInfoSource) { // WalletService createHavenWalletService(Box<WalletInfo> walletInfoSource) {
return HavenWalletService(walletInfoSource); // return HavenWalletService(walletInfoSource);
} // }
@override // @override
String getTransactionAddress(Object wallet, int accountIndex, int addressIndex) { // String getTransactionAddress(Object wallet, int accountIndex, int addressIndex) {
final havenWallet = wallet as HavenWallet; // final havenWallet = wallet as HavenWallet;
return havenWallet.getTransactionAddress(accountIndex, addressIndex); // return havenWallet.getTransactionAddress(accountIndex, addressIndex);
} // }
@override // @override
CryptoCurrency assetOfTransaction(TransactionInfo tx) { // CryptoCurrency assetOfTransaction(TransactionInfo tx) {
final transaction = tx as HavenTransactionInfo; // final transaction = tx as HavenTransactionInfo;
final asset = CryptoCurrency.fromString(transaction.assetType); // final asset = CryptoCurrency.fromString(transaction.assetType);
return asset; // return asset;
} // }
@override // @override
List<AssetRate> getAssetRate() => // List<AssetRate> getAssetRate() =>
getRate().map((rate) => AssetRate(rate.getAssetType(), rate.getRate())).toList(); // getRate().map((rate) => AssetRate(rate.getAssetType(), rate.getRate())).toList();
} // }

View file

@ -15,7 +15,7 @@ import in_app_review
import package_info import package_info
import package_info_plus import package_info_plus
import path_provider_foundation import path_provider_foundation
import share_plus_macos import share_plus
import shared_preferences_foundation import shared_preferences_foundation
import url_launcher_macos import url_launcher_macos
import wakelock_plus import wakelock_plus

View file

@ -10,6 +10,7 @@
#include <flutter_local_authentication/flutter_local_authentication_plugin_c_api.h> #include <flutter_local_authentication/flutter_local_authentication_plugin_c_api.h>
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h> #include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h> #include <permission_handler_windows/permission_handler_windows_plugin.h>
#include <share_plus/share_plus_windows_plugin_c_api.h>
#include <url_launcher_windows/url_launcher_windows.h> #include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
@ -21,6 +22,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
PermissionHandlerWindowsPluginRegisterWithRegistrar( PermissionHandlerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
SharePlusWindowsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
UrlLauncherWindowsRegisterWithRegistrar( UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows")); registry->GetRegistrarForPlugin("UrlLauncherWindows"));
} }

View file

@ -7,6 +7,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
flutter_local_authentication flutter_local_authentication
flutter_secure_storage_windows flutter_secure_storage_windows
permission_handler_windows permission_handler_windows
share_plus
url_launcher_windows url_launcher_windows
) )