mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-11-16 17:27:37 +00:00
303 lines
10 KiB
Dart
303 lines
10 KiB
Dart
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||
|
import 'package:cake_wallet/buy/payment_method.dart';
|
||
|
import 'package:cake_wallet/core/selectable_option.dart';
|
||
|
import 'package:cake_wallet/entities/fiat_currency.dart';
|
||
|
import 'package:cake_wallet/entities/provider_types.dart';
|
||
|
import 'package:cake_wallet/exchange/limits.dart';
|
||
|
import 'package:cw_core/crypto_currency.dart';
|
||
|
|
||
|
enum ProviderRecommendation { bestRate, lowKyc, successRate }
|
||
|
|
||
|
extension RecommendationTitle on ProviderRecommendation {
|
||
|
String get title {
|
||
|
switch (this) {
|
||
|
case ProviderRecommendation.bestRate:
|
||
|
return 'BEST RATE';
|
||
|
case ProviderRecommendation.lowKyc:
|
||
|
return 'LOW KYC';
|
||
|
case ProviderRecommendation.successRate:
|
||
|
return 'SUCCESS RATE';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ProviderRecommendation? getRecommendationFromString(String title) {
|
||
|
switch (title) {
|
||
|
case 'BEST RATE':
|
||
|
return ProviderRecommendation.bestRate;
|
||
|
case 'LowKyc':
|
||
|
return ProviderRecommendation.lowKyc;
|
||
|
case 'SuccessRate':
|
||
|
return ProviderRecommendation.successRate;
|
||
|
default:
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class Quote extends SelectableOption {
|
||
|
Quote({
|
||
|
required this.rate,
|
||
|
required this.feeAmount,
|
||
|
required this.networkFee,
|
||
|
required this.transactionFee,
|
||
|
required this.payout,
|
||
|
required this.provider,
|
||
|
required this.paymentType,
|
||
|
required this.recommendations,
|
||
|
this.isBuyAction = true,
|
||
|
this.quoteId,
|
||
|
this.rampId,
|
||
|
this.rampName,
|
||
|
this.rampIconPath,
|
||
|
this.limits,
|
||
|
}) : super(title: provider.isAggregator ? rampName ?? '' : provider.title);
|
||
|
|
||
|
final double rate;
|
||
|
final double feeAmount;
|
||
|
final double networkFee;
|
||
|
final double transactionFee;
|
||
|
final double payout;
|
||
|
final PaymentType paymentType;
|
||
|
final BuyProvider provider;
|
||
|
final String? quoteId;
|
||
|
final List<ProviderRecommendation> recommendations;
|
||
|
String? rampId;
|
||
|
String? rampName;
|
||
|
String? rampIconPath;
|
||
|
bool _isSelected = false;
|
||
|
bool _isBestRate = false;
|
||
|
bool isBuyAction;
|
||
|
Limits? limits;
|
||
|
|
||
|
late FiatCurrency _fiatCurrency;
|
||
|
late CryptoCurrency _cryptoCurrency;
|
||
|
|
||
|
|
||
|
bool get isSelected => _isSelected;
|
||
|
bool get isBestRate => _isBestRate;
|
||
|
FiatCurrency get fiatCurrency => _fiatCurrency;
|
||
|
CryptoCurrency get cryptoCurrency => _cryptoCurrency;
|
||
|
|
||
|
@override
|
||
|
bool get isOptionSelected => this._isSelected;
|
||
|
|
||
|
@override
|
||
|
String get lightIconPath =>
|
||
|
provider.isAggregator ? rampIconPath ?? provider.lightIcon : provider.lightIcon;
|
||
|
|
||
|
@override
|
||
|
String get darkIconPath =>
|
||
|
provider.isAggregator ? rampIconPath ?? provider.darkIcon : provider.darkIcon;
|
||
|
|
||
|
@override
|
||
|
List<String> get badges => recommendations.map((e) => e.title).toList();
|
||
|
|
||
|
@override
|
||
|
String get topLeftSubTitle =>
|
||
|
this.rate > 0 ? '1 $cryptoName = ${rate.toStringAsFixed(2)} $fiatName' : '';
|
||
|
|
||
|
@override
|
||
|
String get bottomLeftSubTitle {
|
||
|
if (limits != null) {
|
||
|
final min = limits!.min;
|
||
|
final max = limits!.max;
|
||
|
return 'min: ${min} ${fiatCurrency.toString()} | max: ${max == double.infinity ? '' : '${max} ${fiatCurrency.toString()}'}';
|
||
|
}
|
||
|
return '';
|
||
|
}
|
||
|
|
||
|
String get fiatName => isBuyAction ? fiatCurrency.toString() : cryptoCurrency.toString();
|
||
|
|
||
|
String get cryptoName => isBuyAction ? cryptoCurrency.toString() : fiatCurrency.toString();
|
||
|
|
||
|
@override
|
||
|
String? get topRightSubTitle => '';
|
||
|
|
||
|
@override
|
||
|
String get topRightSubTitleLightIconPath => provider.isAggregator ? provider.lightIcon : '';
|
||
|
|
||
|
@override
|
||
|
String get topRightSubTitleDarkIconPath => provider.isAggregator ? provider.darkIcon : '';
|
||
|
|
||
|
String get quoteTitle => '${provider.title} - ${paymentType.name}';
|
||
|
|
||
|
String get formatedFee => '$feeAmount ${isBuyAction ? fiatCurrency : cryptoCurrency}';
|
||
|
|
||
|
set setIsSelected(bool isSelected) => _isSelected = isSelected;
|
||
|
set setIsBestRate(bool isBestRate) => _isBestRate = isBestRate;
|
||
|
set setFiatCurrency(FiatCurrency fiatCurrency) => _fiatCurrency = fiatCurrency;
|
||
|
set setCryptoCurrency(CryptoCurrency cryptoCurrency) => _cryptoCurrency = cryptoCurrency;
|
||
|
set setLimits(Limits limits) => this.limits = limits;
|
||
|
|
||
|
factory Quote.fromOnramperJson(Map<String, dynamic> json, bool isBuyAction,
|
||
|
Map<String, dynamic> metaData, PaymentType paymentType) {
|
||
|
final rate = _toDouble(json['rate']) ?? 0.0;
|
||
|
final networkFee = _toDouble(json['networkFee']) ?? 0.0;
|
||
|
final transactionFee = _toDouble(json['transactionFee']) ?? 0.0;
|
||
|
final feeAmount = double.parse((networkFee + transactionFee).toStringAsFixed(2));
|
||
|
|
||
|
final rampId = json['ramp'] as String? ?? '';
|
||
|
final rampData = metaData[rampId] ?? {};
|
||
|
final rampName = rampData['displayName'] as String? ?? '';
|
||
|
final rampIconPath = rampData['svg'] as String? ?? '';
|
||
|
|
||
|
final recommendations = json['recommendations'] != null
|
||
|
? List<String>.from(json['recommendations'] as List<dynamic>)
|
||
|
: <String>[];
|
||
|
|
||
|
final enumRecommendations = recommendations
|
||
|
.map((e) => getRecommendationFromString(e))
|
||
|
.whereType<ProviderRecommendation>()
|
||
|
.toList();
|
||
|
|
||
|
final availablePaymentMethods = json['availablePaymentMethods'] as List<dynamic>? ?? [];
|
||
|
double minLimit = 0.0;
|
||
|
double maxLimit = double.infinity;
|
||
|
|
||
|
for (var paymentMethod in availablePaymentMethods) {
|
||
|
if (paymentMethod is Map<String, dynamic>) {
|
||
|
final details = paymentMethod['details'] as Map<String, dynamic>?;
|
||
|
|
||
|
if (details != null) {
|
||
|
final limits = details['limits'] as Map<String, dynamic>?;
|
||
|
|
||
|
if (limits != null && limits.isNotEmpty) {
|
||
|
final firstLimitEntry = limits.values.first as Map<String, dynamic>?;
|
||
|
if (firstLimitEntry != null) {
|
||
|
minLimit = _toDouble(firstLimitEntry['min'])?.roundToDouble() ?? 0.0;
|
||
|
maxLimit = _toDouble(firstLimitEntry['max'])?.roundToDouble() ?? double.infinity;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Quote(
|
||
|
rate: rate,
|
||
|
feeAmount: feeAmount,
|
||
|
networkFee: networkFee,
|
||
|
transactionFee: transactionFee,
|
||
|
payout: json['payout'] as double? ?? 0.0,
|
||
|
rampId: rampId,
|
||
|
rampName: rampName,
|
||
|
rampIconPath: rampIconPath,
|
||
|
paymentType: paymentType,
|
||
|
quoteId: json['quoteId'] as String? ?? '',
|
||
|
recommendations: enumRecommendations,
|
||
|
provider: ProvidersHelper.getProviderByType(ProviderType.onramper)!,
|
||
|
isBuyAction: isBuyAction,
|
||
|
limits: Limits(min: minLimit, max: maxLimit),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
factory Quote.fromMoonPayJson(
|
||
|
Map<String, dynamic> json, bool isBuyAction, PaymentType paymentType) {
|
||
|
final rate = isBuyAction
|
||
|
? json['quoteCurrencyPrice'] as double? ?? 0.0
|
||
|
: json['baseCurrencyPrice'] as double? ?? 0.0;
|
||
|
final fee = _toDouble(json['feeAmount']) ?? 0.0;
|
||
|
final networkFee = _toDouble(json['networkFeeAmount']) ?? 0.0;
|
||
|
final transactionFee = _toDouble(json['extraFeeAmount']) ?? 0.0;
|
||
|
final feeAmount = double.parse((fee + networkFee + transactionFee).toStringAsFixed(2));
|
||
|
|
||
|
final baseCurrency = json['baseCurrency'] as Map<String, dynamic>?;
|
||
|
|
||
|
double minLimit = 0.0;
|
||
|
double maxLimit = double.infinity;
|
||
|
|
||
|
if (baseCurrency != null) {
|
||
|
minLimit = _toDouble(baseCurrency['minAmount']) ?? minLimit;
|
||
|
maxLimit = _toDouble(baseCurrency['maxAmount']) ?? maxLimit;
|
||
|
}
|
||
|
|
||
|
return Quote(
|
||
|
rate: rate,
|
||
|
feeAmount: feeAmount,
|
||
|
networkFee: networkFee,
|
||
|
transactionFee: transactionFee,
|
||
|
payout: _toDouble(json['quoteCurrencyAmount']) ?? 0.0,
|
||
|
paymentType: paymentType,
|
||
|
recommendations: [],
|
||
|
quoteId: json['signature'] as String? ?? '',
|
||
|
provider: ProvidersHelper.getProviderByType(ProviderType.moonpay)!,
|
||
|
isBuyAction: isBuyAction,
|
||
|
limits: Limits(min: minLimit, max: maxLimit),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
factory Quote.fromDFXJson(
|
||
|
Map<String, dynamic> json,
|
||
|
bool isBuyAction,
|
||
|
PaymentType paymentType,
|
||
|
) {
|
||
|
final rate = _toDouble(json['exchangeRate']) ?? 0.0;
|
||
|
final fees = json['fees'] as Map<String, dynamic>;
|
||
|
|
||
|
final minVolume = _toDouble(json['minVolume']) ?? 0.0;
|
||
|
final maxVolume = _toDouble(json['maxVolume']) ?? double.infinity;
|
||
|
|
||
|
return Quote(
|
||
|
rate: isBuyAction ? rate : 1 / rate,
|
||
|
feeAmount: _toDouble(json['feeAmount']) ?? 0.0,
|
||
|
networkFee: _toDouble(fees['network']) ?? 0.0,
|
||
|
transactionFee: _toDouble(fees['rate']) ?? 0.0,
|
||
|
payout: _toDouble(json['payout']) ?? 0.0,
|
||
|
paymentType: paymentType,
|
||
|
recommendations: [ProviderRecommendation.lowKyc],
|
||
|
provider: ProvidersHelper.getProviderByType(ProviderType.dfx)!,
|
||
|
isBuyAction: isBuyAction,
|
||
|
limits: Limits(min: minVolume, max: maxVolume),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
factory Quote.fromRobinhoodJson(
|
||
|
Map<String, dynamic> json, bool isBuyAction, PaymentType paymentType) {
|
||
|
final networkFee = json['networkFee'] as Map<String, dynamic>;
|
||
|
final processingFee = json['processingFee'] as Map<String, dynamic>;
|
||
|
final networkFeeAmount = _toDouble(networkFee['fiatAmount']) ?? 0.0;
|
||
|
final transactionFeeAmount = _toDouble(processingFee['fiatAmount']) ?? 0.0;
|
||
|
final feeAmount = double.parse((networkFeeAmount + transactionFeeAmount).toStringAsFixed(2));
|
||
|
|
||
|
return Quote(
|
||
|
rate: _toDouble(json['price']) ?? 0.0,
|
||
|
feeAmount: feeAmount,
|
||
|
networkFee: _toDouble(networkFee['fiatAmount']) ?? 0.0,
|
||
|
transactionFee: _toDouble(processingFee['fiatAmount']) ?? 0.0,
|
||
|
payout: _toDouble(json['cryptoAmount']) ?? 0.0,
|
||
|
paymentType: paymentType,
|
||
|
recommendations: [],
|
||
|
provider: ProvidersHelper.getProviderByType(ProviderType.robinhood)!,
|
||
|
isBuyAction: isBuyAction,
|
||
|
limits: Limits(min: 0.0, max: double.infinity),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
factory Quote.fromMeldJson(Map<String, dynamic> json, bool isBuyAction, PaymentType paymentType) {
|
||
|
final quotes = json['quotes'][0] as Map<String, dynamic>;
|
||
|
return Quote(
|
||
|
rate: quotes['exchangeRate'] as double? ?? 0.0,
|
||
|
feeAmount: quotes['totalFee'] as double? ?? 0.0,
|
||
|
networkFee: quotes['networkFee'] as double? ?? 0.0,
|
||
|
transactionFee: quotes['transactionFee'] as double? ?? 0.0,
|
||
|
payout: quotes['payout'] as double? ?? 0.0,
|
||
|
paymentType: paymentType,
|
||
|
recommendations: [],
|
||
|
provider: ProvidersHelper.getProviderByType(ProviderType.meld)!,
|
||
|
isBuyAction: isBuyAction,
|
||
|
limits: Limits(min: 0.0, max: double.infinity),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
static double? _toDouble(dynamic value) {
|
||
|
if (value is int) {
|
||
|
return value.toDouble();
|
||
|
} else if (value is double) {
|
||
|
return value;
|
||
|
} else if (value is String) {
|
||
|
return double.tryParse(value);
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
}
|