mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-16 17:27:39 +00:00
public firo fee estimate and firo fee ui updates
This commit is contained in:
parent
15c4d0e617
commit
88df57177b
3 changed files with 301 additions and 98 deletions
|
@ -167,13 +167,26 @@ class _SendViewState extends ConsumerState<SendView> {
|
||||||
late Future<String> _calculateFeesFuture;
|
late Future<String> _calculateFeesFuture;
|
||||||
|
|
||||||
Map<int, String> cachedFees = {};
|
Map<int, String> cachedFees = {};
|
||||||
|
Map<int, String> cachedFiroPrivateFees = {};
|
||||||
|
Map<int, String> cachedFiroPublicFees = {};
|
||||||
|
|
||||||
Future<String> calculateFees(int amount) async {
|
Future<String> calculateFees(int amount) async {
|
||||||
if (amount <= 0) {
|
if (amount <= 0) {
|
||||||
return "0";
|
return "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cachedFees[amount] != null) {
|
if (coin == Coin.firo || coin == Coin.firoTestNet) {
|
||||||
|
if (ref.read(publicPrivateBalanceStateProvider.state).state ==
|
||||||
|
"Private") {
|
||||||
|
if (cachedFiroPrivateFees[amount] != null) {
|
||||||
|
return cachedFiroPrivateFees[amount]!;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (cachedFiroPublicFees[amount] != null) {
|
||||||
|
return cachedFiroPublicFees[amount]!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (cachedFees[amount] != null) {
|
||||||
return cachedFees[amount]!;
|
return cachedFees[amount]!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,12 +208,33 @@ class _SendViewState extends ConsumerState<SendView> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
final fee = await manager.estimateFeeFor(amount, feeRate);
|
int fee;
|
||||||
|
|
||||||
cachedFees[amount] =
|
if (coin == Coin.firo || coin == Coin.firoTestNet) {
|
||||||
Format.satoshisToAmount(fee).toStringAsFixed(Constants.decimalPlaces);
|
if (ref.read(publicPrivateBalanceStateProvider.state).state ==
|
||||||
|
"Private") {
|
||||||
|
fee = await manager.estimateFeeFor(amount, feeRate);
|
||||||
|
|
||||||
return cachedFees[amount]!;
|
cachedFiroPrivateFees[amount] = Format.satoshisToAmount(fee)
|
||||||
|
.toStringAsFixed(Constants.decimalPlaces);
|
||||||
|
|
||||||
|
return cachedFiroPrivateFees[amount]!;
|
||||||
|
} else {
|
||||||
|
fee = await (manager.wallet as FiroWallet)
|
||||||
|
.estimateFeeForPublic(amount, feeRate);
|
||||||
|
|
||||||
|
cachedFiroPublicFees[amount] = Format.satoshisToAmount(fee)
|
||||||
|
.toStringAsFixed(Constants.decimalPlaces);
|
||||||
|
|
||||||
|
return cachedFiroPublicFees[amount]!;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fee = await manager.estimateFeeFor(amount, feeRate);
|
||||||
|
cachedFees[amount] =
|
||||||
|
Format.satoshisToAmount(fee).toStringAsFixed(Constants.decimalPlaces);
|
||||||
|
|
||||||
|
return cachedFees[amount]!;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> _firoBalanceFuture(
|
Future<String?> _firoBalanceFuture(
|
||||||
|
@ -309,6 +343,22 @@ class _SendViewState extends ConsumerState<SendView> {
|
||||||
.select((value) => value.getManagerProvider(walletId)));
|
.select((value) => value.getManagerProvider(walletId)));
|
||||||
final String locale = ref.watch(
|
final String locale = ref.watch(
|
||||||
localeServiceChangeNotifierProvider.select((value) => value.locale));
|
localeServiceChangeNotifierProvider.select((value) => value.locale));
|
||||||
|
|
||||||
|
if (coin == Coin.firo || coin == Coin.firoTestNet) {
|
||||||
|
ref.listen(publicPrivateBalanceStateProvider, (previous, next) {
|
||||||
|
if (_amountToSend == null) {
|
||||||
|
setState(() {
|
||||||
|
_calculateFeesFuture = calculateFees(0);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
_calculateFeesFuture =
|
||||||
|
calculateFees(Format.decimalAmountToSatoshis(_amountToSend!));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: CFColors.almostWhite,
|
backgroundColor: CFColors.almostWhite,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
|
@ -1200,74 +1250,126 @@ class _SendViewState extends ConsumerState<SendView> {
|
||||||
Constants.size.circularBorderRadius,
|
Constants.size.circularBorderRadius,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: (coin == Coin.firo ||
|
||||||
showModalBottomSheet<dynamic>(
|
coin == Coin.firoTestNet) &&
|
||||||
backgroundColor: Colors.transparent,
|
ref
|
||||||
context: context,
|
.watch(
|
||||||
shape: const RoundedRectangleBorder(
|
publicPrivateBalanceStateProvider
|
||||||
borderRadius: BorderRadius.vertical(
|
.state)
|
||||||
top: Radius.circular(20),
|
.state ==
|
||||||
|
"Private"
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
showModalBottomSheet<dynamic>(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
context: context,
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.vertical(
|
||||||
|
top: Radius.circular(20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
builder: (_) =>
|
||||||
|
TransactionFeeSelectionSheet(
|
||||||
|
walletId: walletId,
|
||||||
|
amount: Decimal.tryParse(
|
||||||
|
cryptoAmountController
|
||||||
|
.text) ??
|
||||||
|
Decimal.zero,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: ((coin == Coin.firo ||
|
||||||
|
coin == Coin.firoTestNet) &&
|
||||||
|
ref
|
||||||
|
.watch(
|
||||||
|
publicPrivateBalanceStateProvider
|
||||||
|
.state)
|
||||||
|
.state ==
|
||||||
|
"Private")
|
||||||
|
? Row(
|
||||||
|
children: [
|
||||||
|
FutureBuilder(
|
||||||
|
future: _calculateFeesFuture,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState ==
|
||||||
|
ConnectionState.done &&
|
||||||
|
snapshot.hasData) {
|
||||||
|
return Text(
|
||||||
|
"~${snapshot.data! as String} ${coin.ticker}",
|
||||||
|
style:
|
||||||
|
STextStyles.itemSubtitle,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return AnimatedText(
|
||||||
|
stringsToLoopThrough: const [
|
||||||
|
"Calculating",
|
||||||
|
"Calculating.",
|
||||||
|
"Calculating..",
|
||||||
|
"Calculating...",
|
||||||
|
],
|
||||||
|
style:
|
||||||
|
STextStyles.itemSubtitle,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
ref
|
||||||
|
.watch(
|
||||||
|
feeRateTypeStateProvider
|
||||||
|
.state)
|
||||||
|
.state
|
||||||
|
.prettyName,
|
||||||
|
style:
|
||||||
|
STextStyles.itemSubtitle12,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 10,
|
||||||
|
),
|
||||||
|
FutureBuilder(
|
||||||
|
future: _calculateFeesFuture,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState ==
|
||||||
|
ConnectionState
|
||||||
|
.done &&
|
||||||
|
snapshot.hasData) {
|
||||||
|
return Text(
|
||||||
|
"~${snapshot.data! as String} ${coin.ticker}",
|
||||||
|
style: STextStyles
|
||||||
|
.itemSubtitle,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return AnimatedText(
|
||||||
|
stringsToLoopThrough: const [
|
||||||
|
"Calculating",
|
||||||
|
"Calculating.",
|
||||||
|
"Calculating..",
|
||||||
|
"Calculating...",
|
||||||
|
],
|
||||||
|
style: STextStyles
|
||||||
|
.itemSubtitle,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SvgPicture.asset(
|
||||||
|
Assets.svg.chevronDown,
|
||||||
|
width: 8,
|
||||||
|
height: 4,
|
||||||
|
color: CFColors.gray3,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
builder: (_) =>
|
|
||||||
TransactionFeeSelectionSheet(
|
|
||||||
walletId: walletId,
|
|
||||||
amount: Decimal.tryParse(
|
|
||||||
cryptoAmountController.text) ??
|
|
||||||
Decimal.zero,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
ref
|
|
||||||
.watch(feeRateTypeStateProvider
|
|
||||||
.state)
|
|
||||||
.state
|
|
||||||
.prettyName,
|
|
||||||
style: STextStyles.itemSubtitle12,
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 10,
|
|
||||||
),
|
|
||||||
FutureBuilder(
|
|
||||||
future: _calculateFeesFuture,
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.connectionState ==
|
|
||||||
ConnectionState.done &&
|
|
||||||
snapshot.hasData) {
|
|
||||||
return Text(
|
|
||||||
"~${snapshot.data! as String} ${coin.ticker}",
|
|
||||||
style: STextStyles.itemSubtitle,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return AnimatedText(
|
|
||||||
stringsToLoopThrough: const [
|
|
||||||
"Calculating",
|
|
||||||
"Calculating.",
|
|
||||||
"Calculating..",
|
|
||||||
"Calculating...",
|
|
||||||
],
|
|
||||||
style: STextStyles.itemSubtitle,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SvgPicture.asset(
|
|
||||||
Assets.svg.chevronDown,
|
|
||||||
width: 8,
|
|
||||||
height: 4,
|
|
||||||
color: CFColors.gray3,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
@ -1335,21 +1437,25 @@ class _SendViewState extends ConsumerState<SendView> {
|
||||||
_amountToSend!);
|
_amountToSend!);
|
||||||
int availableBalance;
|
int availableBalance;
|
||||||
if ((coin == Coin.firo ||
|
if ((coin == Coin.firo ||
|
||||||
coin == Coin.firoTestNet)
|
coin == Coin.firoTestNet)) {
|
||||||
) {
|
|
||||||
if (ref
|
if (ref
|
||||||
.read(
|
.read(
|
||||||
publicPrivateBalanceStateProvider
|
publicPrivateBalanceStateProvider
|
||||||
.state)
|
.state)
|
||||||
.state ==
|
.state ==
|
||||||
"Private") {
|
"Private") {
|
||||||
availableBalance = Format.decimalAmountToSatoshis(
|
availableBalance =
|
||||||
await (manager.wallet as FiroWallet).availablePrivateBalance());
|
Format.decimalAmountToSatoshis(
|
||||||
|
await (manager.wallet
|
||||||
|
as FiroWallet)
|
||||||
|
.availablePrivateBalance());
|
||||||
} else {
|
} else {
|
||||||
availableBalance = Format.decimalAmountToSatoshis(
|
availableBalance =
|
||||||
await (manager.wallet as FiroWallet).availablePublicBalance());
|
Format.decimalAmountToSatoshis(
|
||||||
|
await (manager.wallet
|
||||||
|
as FiroWallet)
|
||||||
|
.availablePublicBalance());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
availableBalance =
|
availableBalance =
|
||||||
Format.decimalAmountToSatoshis(
|
Format.decimalAmountToSatoshis(
|
||||||
|
|
|
@ -4,6 +4,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:stackwallet/models/paymint/fee_object_model.dart';
|
import 'package:stackwallet/models/paymint/fee_object_model.dart';
|
||||||
import 'package:stackwallet/providers/providers.dart';
|
import 'package:stackwallet/providers/providers.dart';
|
||||||
import 'package:stackwallet/providers/ui/fee_rate_type_state_provider.dart';
|
import 'package:stackwallet/providers/ui/fee_rate_type_state_provider.dart';
|
||||||
|
import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart';
|
||||||
|
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
||||||
import 'package:stackwallet/utilities/cfcolors.dart';
|
import 'package:stackwallet/utilities/cfcolors.dart';
|
||||||
import 'package:stackwallet/utilities/constants.dart';
|
import 'package:stackwallet/utilities/constants.dart';
|
||||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
|
@ -58,35 +60,63 @@ class _TransactionFeeSelectionSheetState
|
||||||
required int amount,
|
required int amount,
|
||||||
required FeeRateType feeRateType,
|
required FeeRateType feeRateType,
|
||||||
required int feeRate,
|
required int feeRate,
|
||||||
|
required Coin coin,
|
||||||
}) async {
|
}) async {
|
||||||
switch (feeRateType) {
|
switch (feeRateType) {
|
||||||
case FeeRateType.fast:
|
case FeeRateType.fast:
|
||||||
if (ref.read(feeSheetSessionCacheProvider).fast[amount] == null) {
|
if (ref.read(feeSheetSessionCacheProvider).fast[amount] == null) {
|
||||||
ref.read(feeSheetSessionCacheProvider).fast[amount] =
|
final manager =
|
||||||
Format.satoshisToAmount(await ref
|
ref.read(walletsChangeNotifierProvider).getManager(walletId);
|
||||||
.read(walletsChangeNotifierProvider)
|
|
||||||
.getManager(walletId)
|
if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
|
||||||
.estimateFeeFor(amount, feeRate));
|
ref.read(publicPrivateBalanceStateProvider.state).state !=
|
||||||
|
"Private") {
|
||||||
|
ref.read(feeSheetSessionCacheProvider).fast[amount] =
|
||||||
|
Format.satoshisToAmount(await (manager.wallet as FiroWallet)
|
||||||
|
.estimateFeeForPublic(amount, feeRate));
|
||||||
|
} else {
|
||||||
|
ref.read(feeSheetSessionCacheProvider).fast[amount] =
|
||||||
|
Format.satoshisToAmount(
|
||||||
|
await manager.estimateFeeFor(amount, feeRate));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ref.read(feeSheetSessionCacheProvider).fast[amount]!;
|
return ref.read(feeSheetSessionCacheProvider).fast[amount]!;
|
||||||
|
|
||||||
case FeeRateType.average:
|
case FeeRateType.average:
|
||||||
if (ref.read(feeSheetSessionCacheProvider).average[amount] == null) {
|
if (ref.read(feeSheetSessionCacheProvider).average[amount] == null) {
|
||||||
ref.read(feeSheetSessionCacheProvider).average[amount] =
|
final manager =
|
||||||
Format.satoshisToAmount(await ref
|
ref.read(walletsChangeNotifierProvider).getManager(walletId);
|
||||||
.read(walletsChangeNotifierProvider)
|
|
||||||
.getManager(walletId)
|
if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
|
||||||
.estimateFeeFor(amount, feeRate));
|
ref.read(publicPrivateBalanceStateProvider.state).state !=
|
||||||
|
"Private") {
|
||||||
|
ref.read(feeSheetSessionCacheProvider).average[amount] =
|
||||||
|
Format.satoshisToAmount(await (manager.wallet as FiroWallet)
|
||||||
|
.estimateFeeForPublic(amount, feeRate));
|
||||||
|
} else {
|
||||||
|
ref.read(feeSheetSessionCacheProvider).average[amount] =
|
||||||
|
Format.satoshisToAmount(
|
||||||
|
await manager.estimateFeeFor(amount, feeRate));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ref.read(feeSheetSessionCacheProvider).average[amount]!;
|
return ref.read(feeSheetSessionCacheProvider).average[amount]!;
|
||||||
|
|
||||||
case FeeRateType.slow:
|
case FeeRateType.slow:
|
||||||
if (ref.read(feeSheetSessionCacheProvider).slow[amount] == null) {
|
if (ref.read(feeSheetSessionCacheProvider).slow[amount] == null) {
|
||||||
ref.read(feeSheetSessionCacheProvider).slow[amount] =
|
final manager =
|
||||||
Format.satoshisToAmount(await ref
|
ref.read(walletsChangeNotifierProvider).getManager(walletId);
|
||||||
.read(walletsChangeNotifierProvider)
|
|
||||||
.getManager(walletId)
|
if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
|
||||||
.estimateFeeFor(amount, feeRate));
|
ref.read(publicPrivateBalanceStateProvider.state).state !=
|
||||||
|
"Private") {
|
||||||
|
ref.read(feeSheetSessionCacheProvider).slow[amount] =
|
||||||
|
Format.satoshisToAmount(await (manager.wallet as FiroWallet)
|
||||||
|
.estimateFeeForPublic(amount, feeRate));
|
||||||
|
} else {
|
||||||
|
ref.read(feeSheetSessionCacheProvider).slow[amount] =
|
||||||
|
Format.satoshisToAmount(
|
||||||
|
await manager.estimateFeeFor(amount, feeRate));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ref.read(feeSheetSessionCacheProvider).slow[amount]!;
|
return ref.read(feeSheetSessionCacheProvider).slow[amount]!;
|
||||||
}
|
}
|
||||||
|
@ -249,6 +279,7 @@ class _TransactionFeeSelectionSheetState
|
||||||
if (feeObject != null)
|
if (feeObject != null)
|
||||||
FutureBuilder(
|
FutureBuilder(
|
||||||
future: feeFor(
|
future: feeFor(
|
||||||
|
coin: manager.coin,
|
||||||
feeRateType: FeeRateType.fast,
|
feeRateType: FeeRateType.fast,
|
||||||
feeRate: feeObject!.fast,
|
feeRate: feeObject!.fast,
|
||||||
amount: Format
|
amount: Format
|
||||||
|
@ -372,6 +403,7 @@ class _TransactionFeeSelectionSheetState
|
||||||
if (feeObject != null)
|
if (feeObject != null)
|
||||||
FutureBuilder(
|
FutureBuilder(
|
||||||
future: feeFor(
|
future: feeFor(
|
||||||
|
coin: manager.coin,
|
||||||
feeRateType: FeeRateType.fast,
|
feeRateType: FeeRateType.fast,
|
||||||
feeRate: feeObject!.fast,
|
feeRate: feeObject!.fast,
|
||||||
amount: Format
|
amount: Format
|
||||||
|
@ -496,6 +528,7 @@ class _TransactionFeeSelectionSheetState
|
||||||
if (feeObject != null)
|
if (feeObject != null)
|
||||||
FutureBuilder(
|
FutureBuilder(
|
||||||
future: feeFor(
|
future: feeFor(
|
||||||
|
coin: manager.coin,
|
||||||
feeRateType: FeeRateType.slow,
|
feeRateType: FeeRateType.slow,
|
||||||
feeRate: feeObject!.slow,
|
feeRate: feeObject!.slow,
|
||||||
amount: Format
|
amount: Format
|
||||||
|
|
|
@ -4483,6 +4483,70 @@ class FiroWallet extends CoinServiceAPI {
|
||||||
return fee;
|
return fee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<int> estimateFeeForPublic(int satoshiAmount, int feeRate) async {
|
||||||
|
final available =
|
||||||
|
Format.decimalAmountToSatoshis(await availablePublicBalance());
|
||||||
|
|
||||||
|
if (available == satoshiAmount) {
|
||||||
|
return satoshiAmount - sweepAllEstimate(feeRate);
|
||||||
|
} else if (satoshiAmount <= 0 || satoshiAmount > available) {
|
||||||
|
return roughFeeEstimate(1, 2, feeRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
int runningBalance = 0;
|
||||||
|
int inputCount = 0;
|
||||||
|
for (final output in _outputsList) {
|
||||||
|
runningBalance += output.value;
|
||||||
|
inputCount++;
|
||||||
|
if (runningBalance > satoshiAmount) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final oneOutPutFee = roughFeeEstimate(inputCount, 1, feeRate);
|
||||||
|
final twoOutPutFee = roughFeeEstimate(inputCount, 2, feeRate);
|
||||||
|
|
||||||
|
if (runningBalance - satoshiAmount > oneOutPutFee) {
|
||||||
|
if (runningBalance - satoshiAmount > oneOutPutFee + DUST_LIMIT) {
|
||||||
|
final change = runningBalance - satoshiAmount - twoOutPutFee;
|
||||||
|
if (change > DUST_LIMIT &&
|
||||||
|
runningBalance - satoshiAmount - change == twoOutPutFee) {
|
||||||
|
return runningBalance - satoshiAmount - change;
|
||||||
|
} else {
|
||||||
|
return runningBalance - satoshiAmount;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return runningBalance - satoshiAmount;
|
||||||
|
}
|
||||||
|
} else if (runningBalance - satoshiAmount == oneOutPutFee) {
|
||||||
|
return oneOutPutFee;
|
||||||
|
} else {
|
||||||
|
return twoOutPutFee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: correct formula for firo?
|
||||||
|
int roughFeeEstimate(int inputCount, int outputCount, int feeRatePerKB) {
|
||||||
|
return ((181 * inputCount) + (34 * outputCount) + 10) *
|
||||||
|
(feeRatePerKB / 1000).ceil();
|
||||||
|
}
|
||||||
|
|
||||||
|
int sweepAllEstimate(int feeRate) {
|
||||||
|
int available = 0;
|
||||||
|
int inputCount = 0;
|
||||||
|
for (final output in _outputsList) {
|
||||||
|
if (output.status.confirmed) {
|
||||||
|
available += output.value;
|
||||||
|
inputCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// transaction will only have 1 output minus the fee
|
||||||
|
final estimatedFee = roughFeeEstimate(inputCount, 1, feeRate);
|
||||||
|
|
||||||
|
return available - estimatedFee;
|
||||||
|
}
|
||||||
|
|
||||||
Future<List<models.Transaction>> getJMintTransactions(
|
Future<List<models.Transaction>> getJMintTransactions(
|
||||||
CachedElectrumX cachedClient,
|
CachedElectrumX cachedClient,
|
||||||
List<String> transactions,
|
List<String> transactions,
|
||||||
|
|
Loading…
Reference in a new issue