diff --git a/packages/espressocash_app/lib/features/fees/models/fee_type.dart b/packages/espressocash_app/lib/features/fees/models/fee_type.dart index 3090246221..cdcfecc2be 100644 --- a/packages/espressocash_app/lib/features/fees/models/fee_type.dart +++ b/packages/espressocash_app/lib/features/fees/models/fee_type.dart @@ -16,5 +16,6 @@ sealed class FeeType with _$FeeType { const factory FeeType.withdraw({ required int amount, required RampPartner partner, + required Ed25519HDPublicKey? address, }) = FeeTypeWithdraw; } diff --git a/packages/espressocash_app/lib/features/fees/src/services/fee_calculator.dart b/packages/espressocash_app/lib/features/fees/src/services/fee_calculator.dart index c20fbb886b..73db75825d 100644 --- a/packages/espressocash_app/lib/features/fees/src/services/fee_calculator.dart +++ b/packages/espressocash_app/lib/features/fees/src/services/fee_calculator.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:espressocash_api/espressocash_api.dart'; import 'package:injectable/injectable.dart'; import 'package:solana/solana.dart'; @@ -19,18 +21,13 @@ class FeeCalculator { (fees) async { switch (type) { case FeeTypeDirect(:final address): - final hasAta = await _solanaClient.hasAssociatedTokenAccount( - owner: address, - mint: Token.usdc.publicKey, - ); - - return hasAta + return await _hasUsdcAta(address) ? fees.directPayment.ataExists : fees.directPayment.ataDoesNotExist; case FeeTypeLink(): return fees.escrowPayment; - case FeeTypeWithdraw(:final amount, :final partner): - final feePercentage = switch (partner) { + case FeeTypeWithdraw(:final amount, :final partner, :final address): + final percentageFee = switch (partner) { RampPartner.scalex => fees.withdrawFeePercentage.scalex, RampPartner.coinflow => fees.withdrawFeePercentage.coinflow, RampPartner.guardarian => fees.withdrawFeePercentage.guardarian, @@ -38,10 +35,22 @@ class FeeCalculator { fees.withdrawFeePercentage.rampNetwork, RampPartner.kado => fees.withdrawFeePercentage.kado, }; - final calculatedFee = (amount * feePercentage).ceil(); + final percentageFeeAmount = (amount * percentageFee).ceil(); - return fees.directPayment.ataExists + calculatedFee; + final accountCreationFeeAmount = address == null + ? 0 + : await _hasUsdcAta(address) + ? fees.directPayment.ataExists + : fees.directPayment.ataDoesNotExist; + + return max(percentageFeeAmount, accountCreationFeeAmount); } }, ).then((fee) => CryptoAmount(value: fee, cryptoCurrency: Currency.usdc)); + + Future _hasUsdcAta(Ed25519HDPublicKey address) => + _solanaClient.hasAssociatedTokenAccount( + owner: address, + mint: Token.usdc.publicKey, + ); } diff --git a/packages/espressocash_app/lib/features/ramp/services/off_ramp_order_service.dart b/packages/espressocash_app/lib/features/ramp/services/off_ramp_order_service.dart index e9211e1899..a78ed40e5a 100644 --- a/packages/espressocash_app/lib/features/ramp/services/off_ramp_order_service.dart +++ b/packages/espressocash_app/lib/features/ramp/services/off_ramp_order_service.dart @@ -38,6 +38,7 @@ typedef OffRampOrder = ({ DateTime? resolved, FiatAmount? receiveAmount, String partnerOrderId, + Ed25519HDPublicKey? depositAddress, }); @Singleton(scope: authScope) @@ -112,6 +113,10 @@ class OffRampOrderService implements Disposable { ) as FiatAmount, ); + final depositAddress = row.depositAddress + .maybeWhere((it) => it.isNotEmpty) + ?.let(Ed25519HDPublicKey.fromBase58); + return ( id: row.id, created: row.created, @@ -121,6 +126,7 @@ class OffRampOrderService implements Disposable { resolved: row.resolvedAt, receiveAmount: receiveAmount, partnerOrderId: row.partnerOrderId, + depositAddress: depositAddress, ); }); } diff --git a/packages/espressocash_app/lib/features/ramp/src/widgets/off_ramp_confirmation.dart b/packages/espressocash_app/lib/features/ramp/src/widgets/off_ramp_confirmation.dart index 770bef4bf2..c53dd6f7a3 100644 --- a/packages/espressocash_app/lib/features/ramp/src/widgets/off_ramp_confirmation.dart +++ b/packages/espressocash_app/lib/features/ramp/src/widgets/off_ramp_confirmation.dart @@ -65,6 +65,7 @@ class OffRampConfirmation extends StatelessWidget { type: FeeType.withdraw( amount: order.amount.value, partner: order.partner, + address: order.depositAddress, ), ), const SizedBox(height: 21), diff --git a/packages/espressocash_app/lib/storybook/stories/screens/off_ramp_order_screen.dart b/packages/espressocash_app/lib/storybook/stories/screens/off_ramp_order_screen.dart index e1ed23f883..313e272997 100644 --- a/packages/espressocash_app/lib/storybook/stories/screens/off_ramp_order_screen.dart +++ b/packages/espressocash_app/lib/storybook/stories/screens/off_ramp_order_screen.dart @@ -26,6 +26,7 @@ final offRampOrderScreenStory = Story( partner: RampPartner.scalex, resolved: null, partnerOrderId: 'PARTNER_ORDER_ID', + depositAddress: null, ), ), );