mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-23 19:05:51 +00:00
tezos and various tweaks
This commit is contained in:
parent
700943ada4
commit
391304f6da
8 changed files with 330 additions and 123 deletions
|
@ -443,7 +443,7 @@ class _ConfirmTransactionViewState
|
|||
"Amount",
|
||||
style: STextStyles.smallMed12(context),
|
||||
),
|
||||
Text(
|
||||
SelectableText(
|
||||
ref.watch(pAmountFormatter(coin)).format(
|
||||
widget.txData.amount!,
|
||||
ethContract: ref
|
||||
|
@ -469,7 +469,7 @@ class _ConfirmTransactionViewState
|
|||
"Transaction fee",
|
||||
style: STextStyles.smallMed12(context),
|
||||
),
|
||||
Text(
|
||||
SelectableText(
|
||||
ref
|
||||
.watch(pAmountFormatter(coin))
|
||||
.format(widget.txData.fee!),
|
||||
|
@ -495,7 +495,7 @@ class _ConfirmTransactionViewState
|
|||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
SelectableText(
|
||||
"~${widget.txData.fee!.raw.toInt() ~/ widget.txData.vSize!}",
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
),
|
||||
|
@ -520,7 +520,7 @@ class _ConfirmTransactionViewState
|
|||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
SelectableText(
|
||||
widget.txData.noteOnChain!,
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
),
|
||||
|
@ -543,7 +543,7 @@ class _ConfirmTransactionViewState
|
|||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
SelectableText(
|
||||
widget.txData.note!,
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
),
|
||||
|
@ -664,7 +664,7 @@ class _ConfirmTransactionViewState
|
|||
|
||||
return Row(
|
||||
children: [
|
||||
Text(
|
||||
SelectableText(
|
||||
ref.watch(pAmountFormatter(coin)).format(
|
||||
amount,
|
||||
ethContract: ref
|
||||
|
@ -687,7 +687,7 @@ class _ConfirmTransactionViewState
|
|||
context),
|
||||
),
|
||||
if (externalCalls)
|
||||
Text(
|
||||
SelectableText(
|
||||
"~$fiatAmount ${ref.watch(prefsChangeNotifierProvider.select(
|
||||
(value) => value.currency,
|
||||
))}",
|
||||
|
@ -724,7 +724,7 @@ class _ConfirmTransactionViewState
|
|||
const SizedBox(
|
||||
height: 2,
|
||||
),
|
||||
Text(
|
||||
SelectableText(
|
||||
widget.isPaynymTransaction
|
||||
? widget.txData.paynymAccountLite!.nymName
|
||||
: widget.txData.recipients!.first.address,
|
||||
|
@ -765,7 +765,7 @@ class _ConfirmTransactionViewState
|
|||
builder: (context) {
|
||||
final fee = widget.txData.fee!;
|
||||
|
||||
return Text(
|
||||
return SelectableText(
|
||||
ref
|
||||
.watch(pAmountFormatter(coin))
|
||||
.format(fee),
|
||||
|
@ -884,7 +884,7 @@ class _ConfirmTransactionViewState
|
|||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Text(
|
||||
SelectableText(
|
||||
(coin == Coin.epicCash)
|
||||
? "Local Note (optional)"
|
||||
: "Note (optional)",
|
||||
|
@ -987,7 +987,7 @@ class _ConfirmTransactionViewState
|
|||
builder: (context) {
|
||||
final fee = widget.txData.fee!;
|
||||
|
||||
return Text(
|
||||
return SelectableText(
|
||||
ref.watch(pAmountFormatter(coin)).format(fee),
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
);
|
||||
|
@ -1026,7 +1026,7 @@ class _ConfirmTransactionViewState
|
|||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textFieldDefaultBG,
|
||||
child: Text(
|
||||
child: SelectableText(
|
||||
"~${widget.txData.fee!.raw.toInt() ~/ widget.txData.vSize!}",
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
),
|
||||
|
@ -1075,7 +1075,7 @@ class _ConfirmTransactionViewState
|
|||
final fee = widget.txData.fee!;
|
||||
|
||||
final amount = widget.txData.amount!;
|
||||
return Text(
|
||||
return SelectableText(
|
||||
ref
|
||||
.watch(pAmountFormatter(coin))
|
||||
.format(amount + fee),
|
||||
|
|
|
@ -1486,7 +1486,7 @@ class _SendViewState extends ConsumerState<SendView> {
|
|||
style: STextStyles.smallMed12(context),
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
if (coin != Coin.ethereum)
|
||||
if (coin != Coin.ethereum && coin != Coin.tezos)
|
||||
CustomTextButton(
|
||||
text: "Send all ${coin.ticker}",
|
||||
onTap: () async {
|
||||
|
@ -1898,7 +1898,8 @@ class _SendViewState extends ConsumerState<SendView> {
|
|||
),
|
||||
if (coin != Coin.epicCash &&
|
||||
coin != Coin.nano &&
|
||||
coin != Coin.banano)
|
||||
coin != Coin.banano &&
|
||||
coin != Coin.tezos)
|
||||
Text(
|
||||
"Transaction fee (estimated)",
|
||||
style: STextStyles.smallMed12(context),
|
||||
|
@ -1906,13 +1907,15 @@ class _SendViewState extends ConsumerState<SendView> {
|
|||
),
|
||||
if (coin != Coin.epicCash &&
|
||||
coin != Coin.nano &&
|
||||
coin != Coin.banano)
|
||||
coin != Coin.banano &&
|
||||
coin != Coin.tezos)
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
if (coin != Coin.epicCash &&
|
||||
coin != Coin.nano &&
|
||||
coin != Coin.banano)
|
||||
coin != Coin.banano &&
|
||||
coin != Coin.tezos)
|
||||
Stack(
|
||||
children: [
|
||||
TextField(
|
||||
|
|
|
@ -1062,7 +1062,7 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
|||
),
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
if (coin != Coin.ethereum)
|
||||
if (coin != Coin.ethereum && coin != Coin.tezos)
|
||||
CustomTextButton(
|
||||
text: "Send all ${coin.ticker}",
|
||||
onTap: sendAllTapped,
|
||||
|
@ -1481,7 +1481,8 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
|||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
if (!([Coin.nano, Coin.banano, Coin.epicCash].contains(coin)))
|
||||
if (!([Coin.nano, Coin.banano, Coin.epicCash, Coin.tezos]
|
||||
.contains(coin)))
|
||||
ConditionalParent(
|
||||
condition: coin.isElectrumXCoin &&
|
||||
!(((coin == Coin.firo || coin == Coin.firoTestNet) &&
|
||||
|
@ -1532,11 +1533,13 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
|||
textAlign: TextAlign.left,
|
||||
),
|
||||
),
|
||||
if (!([Coin.nano, Coin.banano, Coin.epicCash].contains(coin)))
|
||||
if (!([Coin.nano, Coin.banano, Coin.epicCash, Coin.tezos]
|
||||
.contains(coin)))
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
if (!([Coin.nano, Coin.banano, Coin.epicCash].contains(coin)))
|
||||
if (!([Coin.nano, Coin.banano, Coin.epicCash, Coin.tezos]
|
||||
.contains(coin)))
|
||||
if (!isCustomFee)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
|
|
|
@ -117,7 +117,7 @@ class _WDesktopWalletSummaryState extends ConsumerState<DesktopWalletSummary> {
|
|||
children: [
|
||||
FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Text(
|
||||
child: SelectableText(
|
||||
ref
|
||||
.watch(pAmountFormatter(coin))
|
||||
.format(balanceToShow, ethContract: tokenContract),
|
||||
|
@ -125,7 +125,7 @@ class _WDesktopWalletSummaryState extends ConsumerState<DesktopWalletSummary> {
|
|||
),
|
||||
),
|
||||
if (externalCalls)
|
||||
Text(
|
||||
SelectableText(
|
||||
"${Amount.fromDecimal(
|
||||
priceTuple.item1 * balanceToShow.decimal,
|
||||
fractionDigits: 2,
|
||||
|
|
58
lib/wallets/api/tezos/tezos_account.dart
Normal file
58
lib/wallets/api/tezos/tezos_account.dart
Normal file
|
@ -0,0 +1,58 @@
|
|||
class TezosAccount {
|
||||
final int id;
|
||||
final String type;
|
||||
final String address;
|
||||
final String? publicKey;
|
||||
final bool revealed;
|
||||
final int balance;
|
||||
final int counter;
|
||||
|
||||
TezosAccount({
|
||||
required this.id,
|
||||
required this.type,
|
||||
required this.address,
|
||||
required this.publicKey,
|
||||
required this.revealed,
|
||||
required this.balance,
|
||||
required this.counter,
|
||||
});
|
||||
|
||||
TezosAccount copyWith({
|
||||
int? id,
|
||||
String? type,
|
||||
String? address,
|
||||
String? publicKey,
|
||||
bool? revealed,
|
||||
int? balance,
|
||||
int? counter,
|
||||
}) {
|
||||
return TezosAccount(
|
||||
id: id ?? this.id,
|
||||
type: type ?? this.type,
|
||||
address: address ?? this.address,
|
||||
publicKey: publicKey ?? this.publicKey,
|
||||
revealed: revealed ?? this.revealed,
|
||||
balance: balance ?? this.balance,
|
||||
counter: counter ?? this.counter,
|
||||
);
|
||||
}
|
||||
|
||||
factory TezosAccount.fromMap(Map<String, dynamic> map) {
|
||||
return TezosAccount(
|
||||
id: map['id'] as int,
|
||||
type: map['type'] as String,
|
||||
address: map['address'] as String,
|
||||
publicKey: map['publicKey'] as String?,
|
||||
revealed: map['revealed'] as bool,
|
||||
balance: map['balance'] as int,
|
||||
counter: map['counter'] as int,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'UserData{id: $id, type: $type, address: $address, '
|
||||
'publicKey: $publicKey, revealed: $revealed,'
|
||||
' balance: $balance, counter: $counter}';
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import 'package:stackwallet/networking/http.dart';
|
|||
import 'package:stackwallet/services/tor_service.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/utilities/prefs.dart';
|
||||
import 'package:stackwallet/wallets/api/tezos/tezos_account.dart';
|
||||
import 'package:stackwallet/wallets/api/tezos/tezos_transaction.dart';
|
||||
|
||||
abstract final class TezosAPI {
|
||||
|
@ -32,6 +33,34 @@ abstract final class TezosAPI {
|
|||
}
|
||||
}
|
||||
|
||||
static Future<TezosAccount> getAccount(String address,
|
||||
{String type = "user"}) async {
|
||||
try {
|
||||
final uriString = "$_baseURL/v1/accounts/$address?legacy=false";
|
||||
final response = await _client.get(
|
||||
url: Uri.parse(uriString),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
proxyInfo: Prefs.instance.useTor
|
||||
? TorService.sharedInstance.getProxyInfo()
|
||||
: null,
|
||||
);
|
||||
|
||||
final result = jsonDecode(response.body) as Map;
|
||||
|
||||
final account = TezosAccount.fromMap(Map<String, dynamic>.from(result));
|
||||
|
||||
print("Get account =================== $account");
|
||||
|
||||
return account;
|
||||
} catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"Error occurred in TezosAPI while getting account for $address: $e\n$s",
|
||||
level: LogLevel.Error,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<List<TezosTransaction>> getTransactions(String address) async {
|
||||
try {
|
||||
final transactionsCall =
|
||||
|
|
|
@ -15,8 +15,9 @@ class Tezos extends Bip39Currency {
|
|||
}
|
||||
|
||||
@override
|
||||
// TODO: implement genesisHash
|
||||
String get genesisHash => throw UnimplementedError();
|
||||
String get genesisHash => throw UnimplementedError(
|
||||
"Not used in tezos at the moment",
|
||||
);
|
||||
|
||||
@override
|
||||
int get minConfirms => 1;
|
||||
|
|
|
@ -10,6 +10,7 @@ import 'package:stackwallet/utilities/default_nodes.dart';
|
|||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/extensions/impl/string.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/wallets/api/tezos/tezos_account.dart';
|
||||
import 'package:stackwallet/wallets/api/tezos/tezos_api.dart';
|
||||
import 'package:stackwallet/wallets/api/tezos/tezos_rpc_api.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/tezos.dart';
|
||||
|
@ -20,8 +21,8 @@ import 'package:tezart/tezart.dart' as tezart;
|
|||
import 'package:tuple/tuple.dart';
|
||||
|
||||
// const kDefaultTransactionStorageLimit = 496;
|
||||
const kDefaultTransactionGasLimit = 10600;
|
||||
|
||||
// const kDefaultTransactionGasLimit = 10600;
|
||||
//
|
||||
// const kDefaultKeyRevealFee = 1270;
|
||||
// const kDefaultKeyRevealStorageLimit = 0;
|
||||
// const kDefaultKeyRevealGasLimit = 1100;
|
||||
|
@ -53,45 +54,51 @@ class TezosWallet extends Bip39Wallet {
|
|||
Future<tezart.OperationsList> _buildSendTransaction({
|
||||
required Amount amount,
|
||||
required String address,
|
||||
int? customGasLimit,
|
||||
Amount? customFee,
|
||||
required int counter,
|
||||
// required bool reveal,
|
||||
// int? customGasLimit,
|
||||
// Amount? customFee,
|
||||
// Amount? customRevealFee,
|
||||
}) async {
|
||||
try {
|
||||
final sourceKeyStore = await _getKeyStore();
|
||||
final server = (_xtzNode ?? getCurrentNode()).host;
|
||||
// if (kDebugMode) {
|
||||
// print("SERVER: $server");
|
||||
// print("COUNTER: $counter");
|
||||
// print("customFee: $customFee");
|
||||
// }
|
||||
final tezartClient = tezart.TezartClient(
|
||||
(_xtzNode ?? getCurrentNode()).host,
|
||||
server,
|
||||
);
|
||||
|
||||
final opList = await tezartClient.transferOperation(
|
||||
source: sourceKeyStore,
|
||||
destination: address,
|
||||
amount: amount.raw.toInt(),
|
||||
customGasLimit: customGasLimit,
|
||||
customFee: customFee?.raw.toInt(),
|
||||
// customFee: customFee?.raw.toInt(),
|
||||
// customGasLimit: customGasLimit,
|
||||
// reveal: false,
|
||||
);
|
||||
|
||||
final counter = (await TezosAPI.getCounter(
|
||||
(await getCurrentReceivingAddress())!.value,
|
||||
)) +
|
||||
1;
|
||||
// if (reveal) {
|
||||
// opList.prependOperation(
|
||||
// tezart.RevealOperation(
|
||||
// customGasLimit: customGasLimit,
|
||||
// customFee: customRevealFee?.raw.toInt(),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
|
||||
for (final op in opList.operations) {
|
||||
if (op is tezart.RevealOperation) {
|
||||
// op.storageLimit = kDefaultKeyRevealStorageLimit;
|
||||
// op.gasLimit = kDefaultKeyRevealGasLimit;
|
||||
// op.fee = kDefaultKeyRevealFee;
|
||||
op.counter = counter;
|
||||
} else if (op is tezart.TransactionOperation) {
|
||||
op.counter = counter + 1;
|
||||
// op.storageLimit = kDefaultTransactionStorageLimit;
|
||||
// op.gasLimit = kDefaultTransactionGasLimit;
|
||||
}
|
||||
op.counter = counter;
|
||||
counter++;
|
||||
}
|
||||
|
||||
return opList;
|
||||
} catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"Error in estimateFeeFor() in tezos_wallet.dart: $e\n$s}",
|
||||
"Error in _buildSendTransaction() in tezos_wallet.dart: $e\n$s}",
|
||||
level: LogLevel.Error,
|
||||
);
|
||||
rethrow;
|
||||
|
@ -122,97 +129,203 @@ class TezosWallet extends Bip39Wallet {
|
|||
|
||||
@override
|
||||
Future<TxData> prepareSend({required TxData txData}) async {
|
||||
if (txData.recipients == null || txData.recipients!.length != 1) {
|
||||
throw Exception("$runtimeType prepareSend requires 1 recipient");
|
||||
}
|
||||
|
||||
Amount sendAmount = txData.amount!;
|
||||
|
||||
if (sendAmount > info.cachedBalance.spendable) {
|
||||
throw Exception("Insufficient available balance");
|
||||
}
|
||||
|
||||
final bool isSendAll = sendAmount == info.cachedBalance.spendable;
|
||||
|
||||
Amount fee = await estimateFeeFor(sendAmount, -1);
|
||||
|
||||
int? customGasLimit;
|
||||
|
||||
if (isSendAll) {
|
||||
//Fee guides for emptying a tz account
|
||||
// https://github.com/TezTech/eztz/blob/master/PROTO_004_FEES.md
|
||||
customGasLimit = kDefaultTransactionGasLimit + 320;
|
||||
fee = Amount(
|
||||
rawValue: BigInt.from(fee.raw.toInt() + 32),
|
||||
fractionDigits: cryptoCurrency.fractionDigits,
|
||||
);
|
||||
sendAmount = sendAmount - fee;
|
||||
}
|
||||
|
||||
final opList = await _buildSendTransaction(
|
||||
amount: sendAmount,
|
||||
address: txData.recipients!.first.address,
|
||||
customFee: fee,
|
||||
customGasLimit: customGasLimit,
|
||||
);
|
||||
|
||||
return txData.copyWith(
|
||||
recipients: [
|
||||
(
|
||||
amount: sendAmount,
|
||||
address: txData.recipients!.first.address,
|
||||
)
|
||||
],
|
||||
fee: fee,
|
||||
tezosOperationsList: opList,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<TxData> confirmSend({required TxData txData}) async {
|
||||
await txData.tezosOperationsList!.executeAndMonitor();
|
||||
return txData.copyWith(
|
||||
txid: txData.tezosOperationsList!.result.id,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Amount> estimateFeeFor(Amount amount, int feeRate) async {
|
||||
if (amount.raw == BigInt.zero) {
|
||||
amount = Amount(
|
||||
rawValue: BigInt.one,
|
||||
fractionDigits: cryptoCurrency.fractionDigits,
|
||||
);
|
||||
}
|
||||
|
||||
final myAddressForSimulation = (await getCurrentReceivingAddress())!.value;
|
||||
|
||||
try {
|
||||
if (txData.recipients == null || txData.recipients!.length != 1) {
|
||||
throw Exception("$runtimeType prepareSend requires 1 recipient");
|
||||
}
|
||||
|
||||
Amount sendAmount = txData.amount!;
|
||||
|
||||
if (sendAmount > info.cachedBalance.spendable) {
|
||||
throw Exception("Insufficient available balance");
|
||||
}
|
||||
final account = await TezosAPI.getAccount(
|
||||
(await getCurrentReceivingAddress())!.value,
|
||||
);
|
||||
|
||||
// final bool isSendAll = sendAmount == info.cachedBalance.spendable;
|
||||
//
|
||||
// int? customGasLimit;
|
||||
// Amount? fee;
|
||||
// Amount? revealFee;
|
||||
//
|
||||
// if (isSendAll) {
|
||||
// final fees = await _estimate(
|
||||
// account,
|
||||
// txData.recipients!.first.address,
|
||||
// );
|
||||
// //Fee guides for emptying a tz account
|
||||
// // https://github.com/TezTech/eztz/blob/master/PROTO_004_FEES.md
|
||||
// // customGasLimit = kDefaultTransactionGasLimit + 320;
|
||||
// fee = Amount(
|
||||
// rawValue: BigInt.from(fees.transfer + 32),
|
||||
// fractionDigits: cryptoCurrency.fractionDigits,
|
||||
// );
|
||||
//
|
||||
// BigInt rawAmount = sendAmount.raw - fee.raw;
|
||||
//
|
||||
// if (!account.revealed) {
|
||||
// revealFee = Amount(
|
||||
// rawValue: BigInt.from(fees.reveal + 32),
|
||||
// fractionDigits: cryptoCurrency.fractionDigits,
|
||||
// );
|
||||
//
|
||||
// rawAmount = rawAmount - revealFee.raw;
|
||||
// }
|
||||
//
|
||||
// sendAmount = Amount(
|
||||
// rawValue: rawAmount,
|
||||
// fractionDigits: cryptoCurrency.fractionDigits,
|
||||
// );
|
||||
// }
|
||||
|
||||
final opList = await _buildSendTransaction(
|
||||
amount: amount,
|
||||
address: myAddressForSimulation,
|
||||
amount: sendAmount,
|
||||
address: txData.recipients!.first.address,
|
||||
counter: account.counter + 1,
|
||||
// reveal: !account.revealed,
|
||||
// customFee: isSendAll ? fee : null,
|
||||
// customRevealFee: isSendAll ? revealFee : null,
|
||||
// customGasLimit: customGasLimit,
|
||||
);
|
||||
|
||||
await opList.computeLimits();
|
||||
await opList.computeFees();
|
||||
await opList.simulate();
|
||||
|
||||
return txData.copyWith(
|
||||
recipients: [
|
||||
(
|
||||
amount: sendAmount,
|
||||
address: txData.recipients!.first.address,
|
||||
)
|
||||
],
|
||||
// fee: fee,
|
||||
fee: Amount(
|
||||
rawValue: opList.operations
|
||||
.map(
|
||||
(e) => BigInt.from(e.fee),
|
||||
)
|
||||
.fold(
|
||||
BigInt.zero,
|
||||
(p, e) => p + e,
|
||||
),
|
||||
fractionDigits: cryptoCurrency.fractionDigits,
|
||||
),
|
||||
tezosOperationsList: opList,
|
||||
);
|
||||
} catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"Error in prepareSend() in tezos_wallet.dart: $e\n$s}",
|
||||
level: LogLevel.Error,
|
||||
);
|
||||
|
||||
if (e
|
||||
.toString()
|
||||
.contains("(_operationResult['errors']): Must not be null")) {
|
||||
throw Exception("Probably insufficient balance");
|
||||
} else if (e.toString().contains(
|
||||
"The simulation of the operation: \"transaction\" failed with error(s) :"
|
||||
" contract.balance_too_low, tez.subtraction_underflow.",
|
||||
)) {
|
||||
throw Exception("Insufficient balance to pay fees");
|
||||
}
|
||||
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<TxData> confirmSend({required TxData txData}) async {
|
||||
await txData.tezosOperationsList!.inject();
|
||||
await txData.tezosOperationsList!.monitor();
|
||||
return txData.copyWith(
|
||||
txid: txData.tezosOperationsList!.result.id,
|
||||
);
|
||||
}
|
||||
|
||||
int _estCount = 0;
|
||||
|
||||
Future<({int reveal, int transfer})> _estimate(
|
||||
TezosAccount account, String recipientAddress) async {
|
||||
try {
|
||||
final opList = await _buildSendTransaction(
|
||||
amount: Amount(
|
||||
rawValue: BigInt.one,
|
||||
fractionDigits: cryptoCurrency.fractionDigits,
|
||||
),
|
||||
address: recipientAddress,
|
||||
counter: account.counter + 1,
|
||||
// reveal: !account.revealed,
|
||||
);
|
||||
|
||||
await opList.computeLimits();
|
||||
await opList.computeFees();
|
||||
await opList.simulate();
|
||||
|
||||
int reveal = 0;
|
||||
int transfer = 0;
|
||||
|
||||
for (final op in opList.operations) {
|
||||
if (op is tezart.TransactionOperation) {
|
||||
transfer += op.fee;
|
||||
} else if (op is tezart.RevealOperation) {
|
||||
reveal += op.fee;
|
||||
}
|
||||
}
|
||||
|
||||
return (reveal: reveal, transfer: transfer);
|
||||
} catch (e, s) {
|
||||
if (_estCount > 3) {
|
||||
_estCount = 0;
|
||||
Logging.instance.log(
|
||||
" Error in _estimate in tezos_wallet.dart: $e\n$s}",
|
||||
level: LogLevel.Error,
|
||||
);
|
||||
rethrow;
|
||||
} else {
|
||||
_estCount++;
|
||||
Logging.instance.log(
|
||||
"_estimate() retry _estCount=$_estCount",
|
||||
level: LogLevel.Warning,
|
||||
);
|
||||
return await _estimate(
|
||||
account,
|
||||
recipientAddress,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Amount> estimateFeeFor(
|
||||
Amount amount,
|
||||
int feeRate, {
|
||||
String recipientAddress = "tz1MXvDCyXSqBqXPNDcsdmVZKfoxL9FTHmp2",
|
||||
}) async {
|
||||
if (info.cachedBalance.spendable.raw == BigInt.zero) {
|
||||
return Amount(
|
||||
rawValue: BigInt.zero,
|
||||
fractionDigits: cryptoCurrency.fractionDigits,
|
||||
);
|
||||
}
|
||||
|
||||
final account = await TezosAPI.getAccount(
|
||||
(await getCurrentReceivingAddress())!.value,
|
||||
);
|
||||
|
||||
try {
|
||||
final fees = await _estimate(account, recipientAddress);
|
||||
|
||||
final fee = Amount(
|
||||
rawValue: opList.operations
|
||||
.map(
|
||||
(e) => BigInt.from(e.fee),
|
||||
)
|
||||
.fold(
|
||||
BigInt.zero,
|
||||
(p, e) => p + e,
|
||||
),
|
||||
rawValue: BigInt.from(fees.reveal + fees.transfer),
|
||||
fractionDigits: cryptoCurrency.fractionDigits,
|
||||
);
|
||||
|
||||
return fee;
|
||||
} catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"Error in estimateFeeFor() in tezos_wallet.dart: $e\n$s}",
|
||||
" Error in estimateFeeFor() in tezos_wallet.dart: $e\n$s}",
|
||||
level: LogLevel.Error,
|
||||
);
|
||||
rethrow;
|
||||
|
|
Loading…
Reference in a new issue