Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
506 changes: 89 additions & 417 deletions lib/pages/send_view/send_view.dart

Large diffs are not rendered by default.

187 changes: 38 additions & 149 deletions lib/pages/send_view/sol_token_send_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import '../../models/send_view_auto_fill_data.dart';
import '../../providers/providers.dart';
import '../../providers/ui/fee_rate_type_state_provider.dart';
import '../../providers/ui/preview_tx_button_state_provider.dart';
import '../../providers/wallet/send_fee_providers.dart';
import '../../route_generator.dart';
import '../../themes/stack_colors.dart';
import '../../utilities/address_utils.dart';
Expand All @@ -43,8 +44,8 @@ import '../../wallets/isar/providers/solana/current_sol_token_wallet_provider.da
import '../../wallets/isar/providers/solana/sol_token_balance_provider.dart';
import '../../wallets/isar/providers/wallet_info_provider.dart';
import '../../wallets/models/tx_data.dart';
import '../../widgets/animated_text.dart';
import '../../widgets/background.dart';
import '../../widgets/calculating_future_builder.dart';
import '../../widgets/custom_buttons/app_bar_icon_button.dart';
import '../../widgets/icon_widgets/clipboard_icon.dart';
import '../../widgets/icon_widgets/qrcode_icon.dart';
Expand Down Expand Up @@ -93,7 +94,8 @@ class SolTokenSendView extends ConsumerStatefulWidget {
ConsumerState<SolTokenSendView> createState() => _SolTokenSendViewState();
}

class _SolTokenSendViewState extends ConsumerState<SolTokenSendView> {
class _SolTokenSendViewState extends ConsumerState<SolTokenSendView>
with SendFeeForm {
late final String walletId;
late final String tokenMint;
late final ClipboardInterface clipboard;
Expand Down Expand Up @@ -122,12 +124,6 @@ class _SolTokenSendViewState extends ConsumerState<SolTokenSendView> {
bool _cryptoAmountChangeLock = false;
late VoidCallback onCryptoAmountChanged;

final updateFeesTimerDuration = const Duration(milliseconds: 500);

Timer? _cryptoAmountChangedFeeUpdateTimer;
Timer? _baseAmountChangedFeeUpdateTimer;
late Future<Amount> _calculateFeesFuture;

void _onTokenSendViewPasteAddressFieldButtonPressed() async {
final ClipboardData? data = await clipboard.getData(Clipboard.kTextPlain);
if (data?.text != null && data!.text!.isNotEmpty) {
Expand Down Expand Up @@ -294,6 +290,7 @@ class _SolTokenSendViewState extends ConsumerState<SolTokenSendView> {
_cryptoAmountChangeLock = false;
}
_updatePreviewButtonState(_address, _amountToSend);
followFeeAmount(_amountToSend);
}

// Controller assignments used for display must not edit the stored amount.
Expand Down Expand Up @@ -347,29 +344,10 @@ class _SolTokenSendViewState extends ConsumerState<SolTokenSendView> {
}

_updatePreviewButtonState(_address, _amountToSend);

_cryptoAmountChangedFeeUpdateTimer?.cancel();
_cryptoAmountChangedFeeUpdateTimer = Timer(updateFeesTimerDuration, () {
if (mounted) {
setState(() {
_calculateFeesFuture = calculateFees();
});
}
});
followFeeAmount(_amountToSend);
}
}

void _baseAmountChanged() {
_baseAmountChangedFeeUpdateTimer?.cancel();
_baseAmountChangedFeeUpdateTimer = Timer(updateFeesTimerDuration, () {
if (mounted && !_cryptoFocus.hasFocus) {
setState(() {
_calculateFeesFuture = calculateFees();
});
}
});
}

String? _updateInvalidAddressText(String address) {
if (_data != null && _data.contactLabel == address) {
return null;
Expand All @@ -391,48 +369,6 @@ class _SolTokenSendViewState extends ConsumerState<SolTokenSendView> {
(isValidAddress && amount != null && amount > Amount.zero);
}

Future<Amount> calculateFees() async {
final solana = Solana(CryptoCurrencyNetwork.main);
final minimumFee = Amount(
rawValue: BigInt.from(5000),
fractionDigits: solana.fractionDigits,
);
try {
final wallet = ref.read(pCurrentSolanaTokenWallet);
if (wallet == null) {
return minimumFee;
}

final feeObject = await wallet.fees;

late final BigInt feeRate;

switch (ref.read(feeRateTypeMobileStateProvider.state).state) {
case FeeRateType.fast:
feeRate = feeObject.fast;
break;
case FeeRateType.average:
feeRate = feeObject.medium;
break;
case FeeRateType.slow:
feeRate = feeObject.slow;
break;
default:
feeRate = BigInt.from(-1);
}

final Amount fee = await wallet.estimateFeeFor(Amount.zero, feeRate);
return fee;
} catch (e, s) {
Logging.instance.w(
"Failed to calculate Solana token fees: ",
error: e,
stackTrace: s,
);
return minimumFee;
}
}

Future<void> _previewTransaction() async {
// wait for keyboard to disappear
FocusScope.of(context).unfocus();
Expand Down Expand Up @@ -520,7 +456,7 @@ class _SolTokenSendViewState extends ConsumerState<SolTokenSendView> {
),
],
memo: memoController.text.isEmpty ? null : memoController.text,
feeRateType: ref.read(feeRateTypeMobileStateProvider),
feeRateType: ref.read(pFeeRateType),
note: noteController.text,
),
);
Expand Down Expand Up @@ -606,15 +542,14 @@ class _SolTokenSendViewState extends ConsumerState<SolTokenSendView> {

@override
void initState() {
ref.refresh(feeSheetSessionCacheProvider);

WidgetsBinding.instance.addPostFrameCallback((_) {
ref.read(feeRateTypeMobileStateProvider.state).state = FeeRateType.slow;
ref.read(pFeeRateType.state).state = FeeRateType.slow;
});

_calculateFeesFuture = calculateFees();
_data = widget.autoFillData;
walletId = widget.walletId;
fees = SendFeeRates(ref.read, walletId: walletId, isToken: true);
retryFeeOnFocusLoss([_cryptoFocus, _baseFocus]);
tokenMint = widget.tokenMint;
clipboard = widget.clipboard;

Expand All @@ -627,7 +562,6 @@ class _SolTokenSendViewState extends ConsumerState<SolTokenSendView> {

onCryptoAmountChanged = _cryptoAmountChanged;
cryptoAmountController.addListener(onCryptoAmountChanged);
baseAmountController.addListener(_baseAmountChanged);

if (_data != null) {
if (_data.amount != null) {
Expand All @@ -651,11 +585,7 @@ class _SolTokenSendViewState extends ConsumerState<SolTokenSendView> {

@override
void dispose() {
_cryptoAmountChangedFeeUpdateTimer?.cancel();
_baseAmountChangedFeeUpdateTimer?.cancel();

cryptoAmountController.removeListener(onCryptoAmountChanged);
baseAmountController.removeListener(_baseAmountChanged);

sendToController.dispose();
memoController.dispose();
Expand Down Expand Up @@ -1284,36 +1214,7 @@ class _SolTokenSendViewState extends ConsumerState<SolTokenSendView> {
Constants.size.circularBorderRadius,
),
),
onPressed: () {
showModalBottomSheet<dynamic>(
backgroundColor: Colors.transparent,
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(20),
),
),
builder: (_) =>
TransactionFeeSelectionSheet(
walletId: walletId,
isToken: true,
amount:
_amountToSend ??
Amount.zeroWith(
fractionDigits: tokenWallet
.tokenDecimals,
),
updateChosen: (_, fee) {
setState(() {
_calculateFeesFuture =
fee == null
? calculateFees()
: Future.value(fee);
});
},
),
);
},
onPressed: () => showFeeSheet(this),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
Expand All @@ -1322,52 +1223,40 @@ class _SolTokenSendViewState extends ConsumerState<SolTokenSendView> {
children: [
Text(
ref
.watch(
feeRateTypeMobileStateProvider
.state,
)
.watch(pFeeRateType.state)
.state
.prettyName,
style: STextStyles.itemSubtitle12(
context,
),
),
const SizedBox(width: 10),
FutureBuilder(
future: _calculateFeesFuture,
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
final formattedFee =
amountFormatter.format(
snapshot.data!,
withUnitName: true,
indicatePrecisionLoss:
false,
);
return Text(
"~$formattedFee",
style:
STextStyles.itemSubtitle(
context,
),
);
} else {
return AnimatedText(
stringsToLoopThrough:
const [
"Calculating",
"Calculating.",
"Calculating..",
"Calculating...",
],
style:
STextStyles.itemSubtitle(
context,
),
);
}
CalculatingFutureBuilder(
future: watchFee(),
style: STextStyles.itemSubtitle(
context,
),
fallback: Amount(
rawValue: BigInt.from(5000),
fractionDigits: tokenWallet
.cryptoCurrency
.fractionDigits,
),
builder: (fee) {
final formattedFee =
amountFormatter.format(
fee,
withUnitName: true,
indicatePrecisionLoss:
false,
);
return Text(
"~$formattedFee",
style:
STextStyles.itemSubtitle(
context,
),
);
},
),
],
Expand Down
Loading
Loading