mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-11-02 07:14:07 +01:00
Catches up from the May 12 fork point (v6.1.2+23) through v6.5.0: 535 upstream commits, including the Monero silent-open fix, Monero on Trezor, Ledger/Trezor BLE fixes, the new seed and history screens, quick Bitcoin sync, git-pinned dependencies (pubspec_overrides.yaml), frozen Hive adapters (*.part.dart), monero_c v0.18.4.6-RC2 and Flutter 3.41.9. Merged with both sides normalized first (import rename, 100-column format), which took the conflict count from 614 paths to 322. The procedure is now scripts/upstream_sync.sh. Kept from Hash Bags: - WalletType enum order and Hive IDs. SQLite stores WalletType.index and our order differs from upstream's; taking theirs would reread saved wallets as other chains. Our frozen adapter keeps the shipped IDs. - The 1.0.2 legacy PIN and wallet-password decode and self-heal. - Removed chains (Solana, Tron, Zano, Zcash, Decred, Haven) and the new Robinhood chain stay out; Cake Pay and non-Trocador swaps stay out. - Default nodes (node.wownero.org, sethforprivacy, Blockstream, bysh.me), converted to upstream's isDefault node-list key; Wownero is back in the node reset list. - Privacy: address resolvers limited to domain-anchored sources again; prices.neroswap.com for fiat; upstream's charts tab, which reads prices.cakewallet.com, sits behind FeatureFlag.isChartsEnabled = false. - Lightning stays behind FeatureFlag.isLightningEnabled, including upstream's new post-seed Lightning username step. - Our icon pipeline, branding and bundle identifiers. Twelve new upstream widget tests are skipped: test and code are unchanged from v6.5.0 apart from renames (not rerun on a pristine upstream checkout; upstream's top_bar_test does not compile against its own TopBar). flutter analyze lib: 0 errors; flutter test: 345 passed, 12 skipped; flutter build bundle compiles. Built with Flutter 3.41.9.
178 lines
5.8 KiB
Dart
178 lines
5.8 KiB
Dart
import 'package:hash_wallet/buy/buy_provider.dart';
|
|
import 'package:hash_wallet/buy/payment_method.dart';
|
|
import 'package:hash_wallet/core/selectable_option.dart';
|
|
import 'package:hash_wallet/entities/calculate_fiat_amount.dart';
|
|
import 'package:hash_wallet/entities/fiat_currency.dart';
|
|
import 'package:hash_wallet/entities/provider_types.dart';
|
|
import 'package:hash_wallet/exchange/limits.dart';
|
|
import 'package:hash_wallet/generated/i18n.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 S.current.best_rate;
|
|
case ProviderRecommendation.lowKyc:
|
|
return S.current.low_kyc;
|
|
case ProviderRecommendation.successRate:
|
|
return S.current.highest_success_rate;
|
|
}
|
|
}
|
|
}
|
|
|
|
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,
|
|
this.customPaymentMethodType,
|
|
}) : 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;
|
|
String? customPaymentMethodType;
|
|
|
|
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 ${cryptoCurrency.toString()} = ${formatWithCommas(rate.toStringAsFixed(2))} ${fiatCurrency.toString()}'
|
|
: '';
|
|
|
|
@override
|
|
String get bottomLeftSubTitle {
|
|
if (limits != null) {
|
|
final min = limits!.min;
|
|
final max = limits!.max;
|
|
return 'min: ${formatWithCommas(min?.toString())} ${fiatCurrency.toString()} | max: ${max == double.infinity ? '' : '${formatWithCommas(max?.toString())} ${fiatCurrency.toString()}'}';
|
|
}
|
|
return '';
|
|
}
|
|
|
|
@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.fromMoonPayJson(
|
|
Map<String, dynamic> json, bool isBuyAction, PaymentType paymentType,
|
|
{String? customPaymentMethodType}) {
|
|
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,
|
|
customPaymentMethodType: customPaymentMethodType,
|
|
recommendations: [],
|
|
quoteId: json['signature'] as String? ?? '',
|
|
provider: ProvidersHelper.getProviderByType(ProviderType.moonpay),
|
|
isBuyAction: isBuyAction,
|
|
limits: Limits(min: minLimit, max: maxLimit),
|
|
);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
@override
|
|
String toString() =>
|
|
'Quote: rate: $rate, feeAmount: $feeAmount, networkFee: $networkFee, transactionFee: $transactionFee, payout: $payout, paymentType: $paymentType, provider: $provider, quoteId: $quoteId, recommendations: $recommendations, isBuyAction: $isBuyAction, rampId: $rampId, rampName: $rampName, rampIconPath: $rampIconPath, [limits: min: ${limits?.min}, max: ${limits?.max}]';
|
|
}
|