mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 11:39:22 +00:00
CW-539-DFX-off-ramp-sell-provider (#1229)
* buy_provider_types refactoring * refactor MoonPay and sell option flow * dfx sell flow * add default sell provider flow * localization * Update other_settings_page.dart * [skip ci] update localization * [skip ci] providers fixes * [skip ci] ui fixes * refactor sell and buy flow * handle dfx availability by country * PR fixes
This commit is contained in:
parent
92914a8532
commit
914565eb72
49 changed files with 623 additions and 370 deletions
BIN
assets/images/moonpay_dark.png
Normal file
BIN
assets/images/moonpay_dark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
assets/images/moonpay_light.png
Normal file
BIN
assets/images/moonpay_light.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
|
@ -623,15 +623,6 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
tor:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
path: "."
|
|
||||||
ref: main
|
|
||||||
resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5"
|
|
||||||
url: "https://github.com/cake-tech/tor.git"
|
|
||||||
source: git
|
|
||||||
version: "0.0.1"
|
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -2,11 +2,11 @@ import 'package:flutter/foundation.dart';
|
||||||
import 'package:cake_wallet/buy/buy_provider_description.dart';
|
import 'package:cake_wallet/buy/buy_provider_description.dart';
|
||||||
|
|
||||||
class BuyException implements Exception {
|
class BuyException implements Exception {
|
||||||
BuyException({required this.description, required this.text});
|
BuyException({required this.title, required this.content});
|
||||||
|
|
||||||
final BuyProviderDescription description;
|
final String title;
|
||||||
final String text;
|
final String content;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => '${description.title}: $text';
|
String toString() => '$title: $content';
|
||||||
}
|
}
|
|
@ -1,27 +1,35 @@
|
||||||
import 'package:cake_wallet/buy/buy_amount.dart';
|
import 'package:cake_wallet/buy/buy_amount.dart';
|
||||||
import 'package:cake_wallet/buy/buy_provider_description.dart';
|
|
||||||
import 'package:cake_wallet/buy/order.dart';
|
import 'package:cake_wallet/buy/order.dart';
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
abstract class BuyProvider {
|
abstract class BuyProvider {
|
||||||
BuyProvider({required this.wallet, required this.isTestEnvironment});
|
BuyProvider({
|
||||||
|
required this.wallet,
|
||||||
|
required this.isTestEnvironment,
|
||||||
|
});
|
||||||
|
|
||||||
final WalletBase wallet;
|
final WalletBase wallet;
|
||||||
final bool isTestEnvironment;
|
final bool isTestEnvironment;
|
||||||
|
|
||||||
String get title;
|
String get title;
|
||||||
BuyProviderDescription get description;
|
|
||||||
String get trackUrl;
|
|
||||||
|
|
||||||
WalletType get walletType => wallet.type;
|
String get buyOptionDescription;
|
||||||
String get walletAddress => wallet.walletAddresses.address;
|
|
||||||
String get walletId => wallet.id;
|
String get sellOptionDescription;
|
||||||
|
|
||||||
|
String get lightIcon;
|
||||||
|
|
||||||
|
String get darkIcon;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => title;
|
String toString() => title;
|
||||||
|
|
||||||
Future<String> requestUrl(String amount, String sourceCurrency);
|
Future<void> launchProvider(BuildContext context, bool? isBuyAction);
|
||||||
Future<Order> findOrderById(String id);
|
|
||||||
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency);
|
Future<String> requestUrl(String amount, String sourceCurrency) => throw UnimplementedError();
|
||||||
}
|
|
||||||
|
Future<Order> findOrderById(String id) => throw UnimplementedError();
|
||||||
|
|
||||||
|
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) => throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||||
|
@ -11,10 +12,9 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class DFXBuyProvider {
|
class DFXBuyProvider extends BuyProvider {
|
||||||
DFXBuyProvider({required WalletBase wallet}) : this._wallet = wallet;
|
DFXBuyProvider({required WalletBase wallet, bool isTestEnvironment = false})
|
||||||
|
: super(wallet: wallet, isTestEnvironment: isTestEnvironment);
|
||||||
final WalletBase _wallet;
|
|
||||||
|
|
||||||
static const _baseUrl = 'api.dfx.swiss';
|
static const _baseUrl = 'api.dfx.swiss';
|
||||||
static const _authPath = '/v1/auth/signMessage';
|
static const _authPath = '/v1/auth/signMessage';
|
||||||
|
@ -22,8 +22,23 @@ class DFXBuyProvider {
|
||||||
static const _signInPath = '/v1/auth/signIn';
|
static const _signInPath = '/v1/auth/signIn';
|
||||||
static const walletName = 'CakeWallet';
|
static const walletName = 'CakeWallet';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get title => 'DFX Connect';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get buyOptionDescription => S.current.dfx_option_description;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sellOptionDescription => S.current.dfx_option_description;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get lightIcon => 'assets/images/dfx_light.png';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get darkIcon => 'assets/images/dfx_dark.png';
|
||||||
|
|
||||||
String get assetOut {
|
String get assetOut {
|
||||||
switch (_wallet.type) {
|
switch (wallet.type) {
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
return 'BTC';
|
return 'BTC';
|
||||||
case WalletType.bitcoinCash:
|
case WalletType.bitcoinCash:
|
||||||
|
@ -35,12 +50,12 @@ class DFXBuyProvider {
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
return 'ETH';
|
return 'ETH';
|
||||||
default:
|
default:
|
||||||
throw Exception("WalletType is not available for DFX ${_wallet.type}");
|
throw Exception("WalletType is not available for DFX ${wallet.type}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String get blockchain {
|
String get blockchain {
|
||||||
switch (_wallet.type) {
|
switch (wallet.type) {
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
case WalletType.bitcoinCash:
|
case WalletType.bitcoinCash:
|
||||||
case WalletType.litecoin:
|
case WalletType.litecoin:
|
||||||
|
@ -50,12 +65,12 @@ class DFXBuyProvider {
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
return 'Ethereum';
|
return 'Ethereum';
|
||||||
default:
|
default:
|
||||||
throw Exception("WalletType is not available for DFX ${_wallet.type}");
|
throw Exception("WalletType is not available for DFX ${wallet.type}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> getSignMessage() async {
|
Future<String> getSignMessage() async {
|
||||||
final walletAddress = _wallet.walletAddresses.address;
|
final walletAddress = wallet.walletAddresses.address;
|
||||||
final uri = Uri.https(_baseUrl, _authPath, {'address': walletAddress});
|
final uri = Uri.https(_baseUrl, _authPath, {'address': walletAddress});
|
||||||
|
|
||||||
var response = await http.get(uri, headers: {'accept': 'application/json'});
|
var response = await http.get(uri, headers: {'accept': 'application/json'});
|
||||||
|
@ -71,7 +86,7 @@ class DFXBuyProvider {
|
||||||
|
|
||||||
Future<String> signUp() async {
|
Future<String> signUp() async {
|
||||||
final signMessage = getSignature(await getSignMessage());
|
final signMessage = getSignature(await getSignMessage());
|
||||||
final walletAddress = _wallet.walletAddresses.address;
|
final walletAddress = wallet.walletAddresses.address;
|
||||||
|
|
||||||
final requestBody = jsonEncode({
|
final requestBody = jsonEncode({
|
||||||
'wallet': walletName,
|
'wallet': walletName,
|
||||||
|
@ -86,6 +101,10 @@ class DFXBuyProvider {
|
||||||
if (response.statusCode == 201) {
|
if (response.statusCode == 201) {
|
||||||
final responseBody = jsonDecode(response.body);
|
final responseBody = jsonDecode(response.body);
|
||||||
return responseBody['accessToken'] as String;
|
return responseBody['accessToken'] as String;
|
||||||
|
} else if (response.statusCode == 403) {
|
||||||
|
final responseBody = jsonDecode(response.body);
|
||||||
|
final message = responseBody['message'] ?? 'Service unavailable in your country';
|
||||||
|
throw Exception(message);
|
||||||
} else {
|
} else {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
'Failed to sign up. Status: ${response.statusCode} ${response.body}');
|
'Failed to sign up. Status: ${response.statusCode} ${response.body}');
|
||||||
|
@ -94,7 +113,7 @@ class DFXBuyProvider {
|
||||||
|
|
||||||
Future<String> signIn() async {
|
Future<String> signIn() async {
|
||||||
final signMessage = getSignature(await getSignMessage());
|
final signMessage = getSignature(await getSignMessage());
|
||||||
final walletAddress = _wallet.walletAddresses.address;
|
final walletAddress = wallet.walletAddresses.address;
|
||||||
|
|
||||||
final requestBody = jsonEncode({
|
final requestBody = jsonEncode({
|
||||||
'address': walletAddress,
|
'address': walletAddress,
|
||||||
|
@ -108,6 +127,10 @@ class DFXBuyProvider {
|
||||||
if (response.statusCode == 201) {
|
if (response.statusCode == 201) {
|
||||||
final responseBody = jsonDecode(response.body);
|
final responseBody = jsonDecode(response.body);
|
||||||
return responseBody['accessToken'] as String;
|
return responseBody['accessToken'] as String;
|
||||||
|
} else if (response.statusCode == 403) {
|
||||||
|
final responseBody = jsonDecode(response.body);
|
||||||
|
final message = responseBody['message'] ?? 'Service unavailable in your country';
|
||||||
|
throw Exception(message);
|
||||||
} else {
|
} else {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
'Failed to sign in. Status: ${response.statusCode} ${response.body}');
|
'Failed to sign in. Status: ${response.statusCode} ${response.body}');
|
||||||
|
@ -115,24 +138,25 @@ class DFXBuyProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
String getSignature(String message) {
|
String getSignature(String message) {
|
||||||
switch (_wallet.type) {
|
switch (wallet.type) {
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
return _wallet.signMessage(message);
|
return wallet.signMessage(message);
|
||||||
case WalletType.monero:
|
case WalletType.monero:
|
||||||
case WalletType.litecoin:
|
case WalletType.litecoin:
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
case WalletType.bitcoinCash:
|
case WalletType.bitcoinCash:
|
||||||
return _wallet.signMessage(message,
|
return wallet.signMessage(message,
|
||||||
address: _wallet.walletAddresses.address);
|
address: wallet.walletAddresses.address);
|
||||||
default:
|
default:
|
||||||
throw Exception("WalletType is not available for DFX ${_wallet.type}");
|
throw Exception("WalletType is not available for DFX ${wallet.type}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> launchProvider(BuildContext context) async {
|
Future<void> launchProvider(BuildContext context, bool? isBuyAction) async {
|
||||||
try {
|
try {
|
||||||
final assetOut = this.assetOut;
|
final assetOut = this.assetOut;
|
||||||
final blockchain = this.blockchain;
|
final blockchain = this.blockchain;
|
||||||
|
final actionType = isBuyAction == true ? '/buy' : '/sell';
|
||||||
|
|
||||||
String accessToken;
|
String accessToken;
|
||||||
|
|
||||||
|
@ -146,7 +170,7 @@ class DFXBuyProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final uri = Uri.https('services.dfx.swiss', '/buy', {
|
final uri = Uri.https('services.dfx.swiss', actionType, {
|
||||||
'session': accessToken,
|
'session': accessToken,
|
||||||
'lang': 'en',
|
'lang': 'en',
|
||||||
'asset-out': assetOut,
|
'asset-out': assetOut,
|
||||||
|
@ -156,8 +180,8 @@ class DFXBuyProvider {
|
||||||
|
|
||||||
if (await canLaunchUrl(uri)) {
|
if (await canLaunchUrl(uri)) {
|
||||||
if (DeviceInfo.instance.isMobile) {
|
if (DeviceInfo.instance.isMobile) {
|
||||||
Navigator.of(context).pushNamed(Routes.webViewPage,
|
Navigator.of(context)
|
||||||
arguments: [S.of(context).buy, uri]);
|
.pushNamed(Routes.webViewPage, arguments: ["DFX Connect", uri]);
|
||||||
} else {
|
} else {
|
||||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:cake_wallet/palette.dart';
|
import 'package:cake_wallet/palette.dart';
|
||||||
|
import 'package:cake_wallet/routes.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||||
import 'package:cake_wallet/store/settings_store.dart';
|
import 'package:cake_wallet/store/settings_store.dart';
|
||||||
import 'package:cake_wallet/themes/theme_base.dart';
|
import 'package:cake_wallet/themes/theme_base.dart';
|
||||||
|
import 'package:cake_wallet/utils/device_info.dart';
|
||||||
import 'package:crypto/crypto.dart';
|
import 'package:crypto/crypto.dart';
|
||||||
import 'package:cake_wallet/buy/buy_exception.dart';
|
import 'package:cake_wallet/buy/buy_exception.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
import 'package:cake_wallet/buy/buy_amount.dart';
|
import 'package:cake_wallet/buy/buy_amount.dart';
|
||||||
import 'package:cake_wallet/buy/buy_provider.dart';
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
|
@ -14,33 +19,41 @@ import 'package:cw_core/wallet_type.dart';
|
||||||
import 'package:cake_wallet/exchange/trade_state.dart';
|
import 'package:cake_wallet/exchange/trade_state.dart';
|
||||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class MoonPaySellProvider {
|
class MoonPaySellProvider {
|
||||||
MoonPaySellProvider({this.isTest = false})
|
MoonPaySellProvider({required SettingsStore settingsStore,
|
||||||
: baseUrl = isTest ? _baseTestUrl : _baseProductUrl;
|
required WalletBase wallet, this.isTest = false})
|
||||||
|
: baseUrl = isTest ? _baseTestUrl : _baseProductUrl,
|
||||||
|
this._settingsStore = settingsStore,
|
||||||
|
this._wallet = wallet;
|
||||||
|
|
||||||
|
final SettingsStore _settingsStore;
|
||||||
|
final WalletBase _wallet;
|
||||||
|
|
||||||
static const _baseTestUrl = 'sell-sandbox.moonpay.com';
|
static const _baseTestUrl = 'sell-sandbox.moonpay.com';
|
||||||
static const _baseProductUrl = 'sell.moonpay.com';
|
static const _baseProductUrl = 'sell.moonpay.com';
|
||||||
|
|
||||||
static String themeToMoonPayTheme(ThemeBase theme) {
|
static String themeToMoonPayTheme(ThemeBase theme) {
|
||||||
switch (theme.type) {
|
switch (theme.type) {
|
||||||
case ThemeType.bright:
|
case ThemeType.bright:
|
||||||
return 'light';
|
|
||||||
case ThemeType.light:
|
case ThemeType.light:
|
||||||
return 'light';
|
return 'light';
|
||||||
case ThemeType.dark:
|
case ThemeType.dark:
|
||||||
return 'dark';
|
return 'dark';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static String get _apiKey => secrets.moonPayApiKey;
|
|
||||||
static String get _secretKey => secrets.moonPaySecretKey;
|
static String get _apiKey => secrets.moonPayApiKey;
|
||||||
|
static String get _secretKey => secrets.moonPaySecretKey;
|
||||||
final bool isTest;
|
final bool isTest;
|
||||||
final String baseUrl;
|
final String baseUrl;
|
||||||
|
|
||||||
Future<Uri> requestUrl(
|
Future<Uri> requestUrl({
|
||||||
{required CryptoCurrency currency,
|
required CryptoCurrency currency,
|
||||||
required String refundWalletAddress,
|
required String refundWalletAddress,
|
||||||
required SettingsStore settingsStore}) async {
|
required SettingsStore settingsStore,
|
||||||
|
}) async {
|
||||||
final customParams = {
|
final customParams = {
|
||||||
'theme': themeToMoonPayTheme(settingsStore.currentTheme),
|
'theme': themeToMoonPayTheme(settingsStore.currentTheme),
|
||||||
'language': settingsStore.languageCode,
|
'language': settingsStore.languageCode,
|
||||||
|
@ -50,11 +63,15 @@ class MoonPaySellProvider {
|
||||||
};
|
};
|
||||||
|
|
||||||
final originalUri = Uri.https(
|
final originalUri = Uri.https(
|
||||||
baseUrl, '', <String, dynamic>{
|
baseUrl,
|
||||||
|
'',
|
||||||
|
<String, dynamic>{
|
||||||
'apiKey': _apiKey,
|
'apiKey': _apiKey,
|
||||||
'defaultBaseCurrencyCode': currency.toString().toLowerCase(),
|
'defaultBaseCurrencyCode': currency.toString().toLowerCase(),
|
||||||
'refundWalletAddress': refundWalletAddress
|
'refundWalletAddress': refundWalletAddress,
|
||||||
}..addAll(customParams));
|
}..addAll(customParams),
|
||||||
|
);
|
||||||
|
|
||||||
final messageBytes = utf8.encode('?${originalUri.query}');
|
final messageBytes = utf8.encode('?${originalUri.query}');
|
||||||
final key = utf8.encode(_secretKey);
|
final key = utf8.encode(_secretKey);
|
||||||
final hmac = Hmac(sha256, key);
|
final hmac = Hmac(sha256, key);
|
||||||
|
@ -70,6 +87,38 @@ class MoonPaySellProvider {
|
||||||
final signedUri = originalUri.replace(queryParameters: query);
|
final signedUri = originalUri.replace(queryParameters: query);
|
||||||
return signedUri;
|
return signedUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> launchProvider(BuildContext context) async {
|
||||||
|
try {
|
||||||
|
final uri = await requestUrl(
|
||||||
|
currency: _wallet.currency,
|
||||||
|
refundWalletAddress: _wallet.walletAddresses.address,
|
||||||
|
settingsStore: _settingsStore,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (await canLaunchUrl(uri)) {
|
||||||
|
if (DeviceInfo.instance.isMobile) {
|
||||||
|
Navigator.of(context).pushNamed(Routes.webViewPage, arguments: ['MoonPay', uri]);
|
||||||
|
} else {
|
||||||
|
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw Exception('Could not launch URL');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
await showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertWithOneAction(
|
||||||
|
alertTitle: 'MoonPay',
|
||||||
|
alertContent: 'The MoonPay service is currently unavailable: $e',
|
||||||
|
buttonText: S.of(context).ok,
|
||||||
|
buttonAction: () => Navigator.of(context).pop(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MoonPayBuyProvider extends BuyProvider {
|
class MoonPayBuyProvider extends BuyProvider {
|
||||||
|
@ -88,20 +137,24 @@ class MoonPayBuyProvider extends BuyProvider {
|
||||||
static const _secretKey = secrets.moonPaySecretKey;
|
static const _secretKey = secrets.moonPaySecretKey;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get title => 'MoonPay';
|
String get title => 'Moon Pay';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
BuyProviderDescription get description => BuyProviderDescription.moonPay;
|
String get buyOptionDescription => '';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get lightIcon => 'assets/images/moonpay_light.png';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get darkIcon => 'assets/images/moonpay_dark.png';
|
||||||
|
|
||||||
String get currencyCode =>
|
String get currencyCode =>
|
||||||
walletTypeToCryptoCurrency(walletType).title.toLowerCase();
|
walletTypeToCryptoCurrency(wallet.type).title.toLowerCase();
|
||||||
|
|
||||||
@override
|
|
||||||
String get trackUrl => baseUrl + '/transaction_receipt?transactionId=';
|
String get trackUrl => baseUrl + '/transaction_receipt?transactionId=';
|
||||||
|
|
||||||
String baseUrl;
|
String baseUrl;
|
||||||
|
|
||||||
@override
|
|
||||||
Future<String> requestUrl(String amount, String sourceCurrency) async {
|
Future<String> requestUrl(String amount, String sourceCurrency) async {
|
||||||
final enabledPaymentMethods =
|
final enabledPaymentMethods =
|
||||||
'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay'
|
'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay'
|
||||||
|
@ -109,7 +162,7 @@ class MoonPayBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
final suffix = '?apiKey=' + _apiKey + '¤cyCode=' +
|
final suffix = '?apiKey=' + _apiKey + '¤cyCode=' +
|
||||||
currencyCode + '&enabledPaymentMethods=' + enabledPaymentMethods +
|
currencyCode + '&enabledPaymentMethods=' + enabledPaymentMethods +
|
||||||
'&walletAddress=' + walletAddress +
|
'&walletAddress=' + wallet.walletAddresses.address +
|
||||||
'&baseCurrencyCode=' + sourceCurrency.toLowerCase() +
|
'&baseCurrencyCode=' + sourceCurrency.toLowerCase() +
|
||||||
'&baseCurrencyAmount=' + amount + '&lockAmount=true' +
|
'&baseCurrencyAmount=' + amount + '&lockAmount=true' +
|
||||||
'&showAllCurrencies=false' + '&showWalletAddressForm=false';
|
'&showAllCurrencies=false' + '&showWalletAddressForm=false';
|
||||||
|
@ -127,7 +180,6 @@ class MoonPayBuyProvider extends BuyProvider {
|
||||||
return isTestEnvironment ? originalUrl : urlWithSignature;
|
return isTestEnvironment ? originalUrl : urlWithSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) async {
|
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) async {
|
||||||
final url = _apiUrl + _currenciesSuffix + '/$currencyCode' +
|
final url = _apiUrl + _currenciesSuffix + '/$currencyCode' +
|
||||||
_quoteSuffix + '/?apiKey=' + _apiKey +
|
_quoteSuffix + '/?apiKey=' + _apiKey +
|
||||||
|
@ -138,8 +190,8 @@ class MoonPayBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
throw BuyException(
|
throw BuyException(
|
||||||
description: description,
|
title: buyOptionDescription,
|
||||||
text: 'Quote is not found!');
|
content: 'Quote is not found!');
|
||||||
}
|
}
|
||||||
|
|
||||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
@ -153,7 +205,6 @@ class MoonPayBuyProvider extends BuyProvider {
|
||||||
minAmount: minSourceAmount);
|
minAmount: minSourceAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Order> findOrderById(String id) async {
|
Future<Order> findOrderById(String id) async {
|
||||||
final url = _apiUrl + _transactionsSuffix + '/$id' +
|
final url = _apiUrl + _transactionsSuffix + '/$id' +
|
||||||
'?apiKey=' + _apiKey;
|
'?apiKey=' + _apiKey;
|
||||||
|
@ -162,8 +213,8 @@ class MoonPayBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
throw BuyException(
|
throw BuyException(
|
||||||
description: description,
|
title: buyOptionDescription,
|
||||||
text: 'Transaction $id is not found!');
|
content: 'Transaction $id is not found!');
|
||||||
}
|
}
|
||||||
|
|
||||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
@ -175,13 +226,13 @@ class MoonPayBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
return Order(
|
return Order(
|
||||||
id: id,
|
id: id,
|
||||||
provider: description,
|
provider: BuyProviderDescription.moonPay,
|
||||||
transferId: id,
|
transferId: id,
|
||||||
state: state,
|
state: state,
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
amount: amount.toString(),
|
amount: amount.toString(),
|
||||||
receiveAddress: walletAddress,
|
receiveAddress: wallet.walletAddresses.address,
|
||||||
walletId: walletId
|
walletId: wallet.id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,4 +252,14 @@ class MoonPayBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
return isBuyEnable;
|
return isBuyEnable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// TODO: implement sellOptionDescription
|
||||||
|
String get sellOptionDescription => throw UnimplementedError();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> launchProvider(BuildContext context, bool? isBuyAction) {
|
||||||
|
// TODO: implement launchProvider
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||||
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/store/settings_store.dart';
|
import 'package:cake_wallet/store/settings_store.dart';
|
||||||
|
@ -9,20 +10,34 @@ import 'package:cw_core/wallet_base.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class OnRamperBuyProvider {
|
class OnRamperBuyProvider extends BuyProvider {
|
||||||
OnRamperBuyProvider({required SettingsStore settingsStore, required WalletBase wallet})
|
OnRamperBuyProvider(this._settingsStore,
|
||||||
: this._settingsStore = settingsStore,
|
{required WalletBase wallet, bool isTestEnvironment = false})
|
||||||
this._wallet = wallet;
|
: super(wallet: wallet, isTestEnvironment: isTestEnvironment);
|
||||||
|
|
||||||
final SettingsStore _settingsStore;
|
|
||||||
final WalletBase _wallet;
|
|
||||||
|
|
||||||
static const _baseUrl = 'buy.onramper.com';
|
static const _baseUrl = 'buy.onramper.com';
|
||||||
|
|
||||||
|
final SettingsStore _settingsStore;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get title => 'Onramper';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get buyOptionDescription => S.current.onramper_option_description;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sellOptionDescription => S.current.onramper_option_description;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get lightIcon => 'assets/images/onramper_light.png';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get darkIcon => 'assets/images/onramper_dark.png';
|
||||||
|
|
||||||
String get _apiKey => secrets.onramperApiKey;
|
String get _apiKey => secrets.onramperApiKey;
|
||||||
|
|
||||||
String get _normalizeCryptoCurrency {
|
String get _normalizeCryptoCurrency {
|
||||||
switch (_wallet.currency) {
|
switch (wallet.currency) {
|
||||||
case CryptoCurrency.ltc:
|
case CryptoCurrency.ltc:
|
||||||
return "LTC_LITECOIN";
|
return "LTC_LITECOIN";
|
||||||
case CryptoCurrency.xmr:
|
case CryptoCurrency.xmr:
|
||||||
|
@ -32,7 +47,7 @@ class OnRamperBuyProvider {
|
||||||
case CryptoCurrency.nano:
|
case CryptoCurrency.nano:
|
||||||
return "XNO_NANO";
|
return "XNO_NANO";
|
||||||
default:
|
default:
|
||||||
return _wallet.currency.title;
|
return wallet.currency.title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +55,7 @@ class OnRamperBuyProvider {
|
||||||
return color.value.toRadixString(16).replaceAll(RegExp(r'^ff'), "");
|
return color.value.toRadixString(16).replaceAll(RegExp(r'^ff'), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
Uri requestUrl(BuildContext context) {
|
Uri requestOnramperUrl(BuildContext context) {
|
||||||
String primaryColor,
|
String primaryColor,
|
||||||
secondaryColor,
|
secondaryColor,
|
||||||
primaryTextColor,
|
primaryTextColor,
|
||||||
|
@ -50,9 +65,10 @@ class OnRamperBuyProvider {
|
||||||
|
|
||||||
primaryColor = getColorStr(Theme.of(context).primaryColor);
|
primaryColor = getColorStr(Theme.of(context).primaryColor);
|
||||||
secondaryColor = getColorStr(Theme.of(context).colorScheme.background);
|
secondaryColor = getColorStr(Theme.of(context).colorScheme.background);
|
||||||
primaryTextColor = getColorStr(Theme.of(context).extension<CakeTextTheme>()!.titleColor);
|
primaryTextColor =
|
||||||
secondaryTextColor =
|
getColorStr(Theme.of(context).extension<CakeTextTheme>()!.titleColor);
|
||||||
getColorStr(Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor);
|
secondaryTextColor = getColorStr(
|
||||||
|
Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor);
|
||||||
containerColor = getColorStr(Theme.of(context).colorScheme.background);
|
containerColor = getColorStr(Theme.of(context).colorScheme.background);
|
||||||
cardColor = getColorStr(Theme.of(context).cardColor);
|
cardColor = getColorStr(Theme.of(context).cardColor);
|
||||||
|
|
||||||
|
@ -60,12 +76,13 @@ class OnRamperBuyProvider {
|
||||||
cardColor = getColorStr(Colors.white);
|
cardColor = getColorStr(Colors.white);
|
||||||
}
|
}
|
||||||
|
|
||||||
final networkName = _wallet.currency.fullName?.toUpperCase().replaceAll(" ", "");
|
final networkName =
|
||||||
|
wallet.currency.fullName?.toUpperCase().replaceAll(" ", "");
|
||||||
|
|
||||||
return Uri.https(_baseUrl, '', <String, dynamic>{
|
return Uri.https(_baseUrl, '', <String, dynamic>{
|
||||||
'apiKey': _apiKey,
|
'apiKey': _apiKey,
|
||||||
'defaultCrypto': _normalizeCryptoCurrency,
|
'defaultCrypto': _normalizeCryptoCurrency,
|
||||||
'networkWallets': '${networkName}:${_wallet.walletAddresses.address}',
|
'networkWallets': '${networkName}:${wallet.walletAddresses.address}',
|
||||||
'supportSell': "false",
|
'supportSell': "false",
|
||||||
'supportSwap': "false",
|
'supportSwap': "false",
|
||||||
'primaryColor': primaryColor,
|
'primaryColor': primaryColor,
|
||||||
|
@ -77,10 +94,11 @@ class OnRamperBuyProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> launchProvider(BuildContext context) async {
|
Future<void> launchProvider(BuildContext context, bool? isBuyAction) async {
|
||||||
final uri = requestUrl(context);
|
final uri = requestOnramperUrl(context);
|
||||||
if (DeviceInfo.instance.isMobile) {
|
if (DeviceInfo.instance.isMobile) {
|
||||||
Navigator.of(context).pushNamed(Routes.webViewPage, arguments: [S.of(context).buy, uri]);
|
Navigator.of(context)
|
||||||
|
.pushNamed(Routes.webViewPage, arguments: [S.of(context).buy, uri]);
|
||||||
} else {
|
} else {
|
||||||
await launchUrl(uri);
|
await launchUrl(uri);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||||
|
import 'package:cake_wallet/buy/buy_amount.dart';
|
||||||
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
|
import 'package:cake_wallet/buy/buy_provider_description.dart';
|
||||||
|
import 'package:cake_wallet/buy/order.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||||
|
@ -10,40 +14,48 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class RobinhoodBuyProvider {
|
class RobinhoodBuyProvider extends BuyProvider{
|
||||||
RobinhoodBuyProvider({required WalletBase wallet}) : this._wallet = wallet;
|
RobinhoodBuyProvider({required WalletBase wallet, bool isTestEnvironment = false})
|
||||||
|
: super(wallet: wallet, isTestEnvironment: isTestEnvironment);
|
||||||
final WalletBase _wallet;
|
|
||||||
|
|
||||||
static const _baseUrl = 'applink.robinhood.com';
|
static const _baseUrl = 'applink.robinhood.com';
|
||||||
static const _cIdBaseUrl = 'exchange-helper.cakewallet.com';
|
static const _cIdBaseUrl = 'exchange-helper.cakewallet.com';
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get title => 'Robinhood Connect';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get buyOptionDescription => S.current.robinhood_option_description;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sellOptionDescription => S.current.robinhood_option_description;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get lightIcon => 'assets/images/robinhood_light.png';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get darkIcon => 'assets/images/robinhood_dark.png';
|
||||||
|
|
||||||
String get _applicationId => secrets.robinhoodApplicationId;
|
String get _applicationId => secrets.robinhoodApplicationId;
|
||||||
|
|
||||||
String get _apiSecret => secrets.robinhoodCIdApiSecret;
|
String get _apiSecret => secrets.robinhoodCIdApiSecret;
|
||||||
|
|
||||||
bool get isAvailable => [
|
|
||||||
WalletType.bitcoin,
|
|
||||||
WalletType.bitcoinCash,
|
|
||||||
WalletType.litecoin,
|
|
||||||
WalletType.ethereum
|
|
||||||
].contains(_wallet.type);
|
|
||||||
|
|
||||||
String getSignature(String message) {
|
String getSignature(String message) {
|
||||||
switch (_wallet.type) {
|
switch (wallet.type) {
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
return _wallet.signMessage(message);
|
return wallet.signMessage(message);
|
||||||
case WalletType.litecoin:
|
case WalletType.litecoin:
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
case WalletType.bitcoinCash:
|
case WalletType.bitcoinCash:
|
||||||
return _wallet.signMessage(message, address: _wallet.walletAddresses.address);
|
return wallet.signMessage(message, address: wallet.walletAddresses.address);
|
||||||
default:
|
default:
|
||||||
throw Exception("WalletType is not available for Robinhood ${_wallet.type}");
|
throw Exception("WalletType is not available for Robinhood ${wallet.type}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> getConnectId() async {
|
Future<String> getConnectId() async {
|
||||||
final walletAddress = _wallet.walletAddresses.address;
|
final walletAddress = wallet.walletAddresses.address;
|
||||||
final valid_until = (DateTime.now().millisecondsSinceEpoch / 1000).round() + 10;
|
final valid_until = (DateTime.now().millisecondsSinceEpoch / 1000).round() + 10;
|
||||||
final message = "$_apiSecret:${valid_until}";
|
final message = "$_apiSecret:${valid_until}";
|
||||||
|
|
||||||
|
@ -64,22 +76,22 @@ class RobinhoodBuyProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Uri> requestUrl() async {
|
Future<Uri> requestProviderUrl() async {
|
||||||
final connectId = await getConnectId();
|
final connectId = await getConnectId();
|
||||||
final networkName = _wallet.currency.fullName?.toUpperCase().replaceAll(" ", "_");
|
final networkName = wallet.currency.fullName?.toUpperCase().replaceAll(" ", "_");
|
||||||
|
|
||||||
return Uri.https(_baseUrl, '/u/connect', <String, dynamic>{
|
return Uri.https(_baseUrl, '/u/connect', <String, dynamic>{
|
||||||
'applicationId': _applicationId,
|
'applicationId': _applicationId,
|
||||||
'connectId': connectId,
|
'connectId': connectId,
|
||||||
'walletAddress': _wallet.walletAddresses.address,
|
'walletAddress': wallet.walletAddresses.address,
|
||||||
'userIdentifier': _wallet.walletAddresses.address,
|
'userIdentifier': wallet.walletAddresses.address,
|
||||||
'supportedNetworks': networkName
|
'supportedNetworks': networkName
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> launchProvider(BuildContext context) async {
|
Future<void> launchProvider(BuildContext context, bool? isBuyAction) async {
|
||||||
try {
|
try {
|
||||||
final uri = await requestUrl();
|
final uri = await requestProviderUrl();
|
||||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
await showPopUp<void>(
|
await showPopUp<void>(
|
||||||
|
@ -93,4 +105,5 @@ class RobinhoodBuyProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:cake_wallet/buy/buy_exception.dart';
|
import 'package:cake_wallet/buy/buy_exception.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
import 'package:cake_wallet/buy/buy_amount.dart';
|
import 'package:cake_wallet/buy/buy_amount.dart';
|
||||||
import 'package:cake_wallet/buy/buy_provider.dart';
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
|
@ -35,16 +36,20 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
String get title => 'Wyre';
|
String get title => 'Wyre';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
BuyProviderDescription get description => BuyProviderDescription.wyre;
|
String get buyOptionDescription => '';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
String get lightIcon => 'assets/images/robinhood_light.png';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get darkIcon => 'assets/images/robinhood_dark.png';
|
||||||
|
|
||||||
String get trackUrl => isTestEnvironment
|
String get trackUrl => isTestEnvironment
|
||||||
? _trackTestUrl
|
? _trackTestUrl
|
||||||
: _trackProductUrl;
|
: _trackProductUrl;
|
||||||
|
|
||||||
String baseApiUrl;
|
String baseApiUrl;
|
||||||
|
|
||||||
@override
|
|
||||||
Future<String> requestUrl(String amount, String sourceCurrency) async {
|
Future<String> requestUrl(String amount, String sourceCurrency) async {
|
||||||
final timestamp = DateTime.now().millisecondsSinceEpoch.toString();
|
final timestamp = DateTime.now().millisecondsSinceEpoch.toString();
|
||||||
final url = baseApiUrl + _ordersSuffix + _reserveSuffix +
|
final url = baseApiUrl + _ordersSuffix + _reserveSuffix +
|
||||||
|
@ -53,8 +58,8 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
final body = {
|
final body = {
|
||||||
'amount': amount,
|
'amount': amount,
|
||||||
'sourceCurrency': sourceCurrency,
|
'sourceCurrency': sourceCurrency,
|
||||||
'destCurrency': walletTypeToCryptoCurrency(walletType).title,
|
'destCurrency': walletTypeToCryptoCurrency(wallet.type).title,
|
||||||
'dest': walletTypeToString(walletType).toLowerCase() + ':' + walletAddress,
|
'dest': walletTypeToString(wallet.type).toLowerCase() + ':' + wallet.walletAddresses.address,
|
||||||
'referrerAccountId': _accountId,
|
'referrerAccountId': _accountId,
|
||||||
'lockFields': ['amount', 'sourceCurrency', 'destCurrency', 'dest']
|
'lockFields': ['amount', 'sourceCurrency', 'destCurrency', 'dest']
|
||||||
};
|
};
|
||||||
|
@ -68,8 +73,8 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
throw BuyException(
|
throw BuyException(
|
||||||
description: description,
|
title: buyOptionDescription,
|
||||||
text: 'Url $url is not found!');
|
content: 'Url $url is not found!');
|
||||||
}
|
}
|
||||||
|
|
||||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
@ -77,14 +82,13 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
return urlFromResponse;
|
return urlFromResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) async {
|
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) async {
|
||||||
final quoteUrl = _baseProductApiUrl + _ordersSuffix + _quoteSuffix;
|
final quoteUrl = _baseProductApiUrl + _ordersSuffix + _quoteSuffix;
|
||||||
final body = {
|
final body = {
|
||||||
'amount': amount,
|
'amount': amount,
|
||||||
'sourceCurrency': sourceCurrency,
|
'sourceCurrency': sourceCurrency,
|
||||||
'destCurrency': walletTypeToCryptoCurrency(walletType).title,
|
'destCurrency': walletTypeToCryptoCurrency(wallet.type).title,
|
||||||
'dest': walletTypeToString(walletType).toLowerCase() + ':' + walletAddress,
|
'dest': walletTypeToString(wallet.type).toLowerCase() + ':' + wallet.walletAddresses.address,
|
||||||
'accountId': _accountId,
|
'accountId': _accountId,
|
||||||
'country': _countryCode
|
'country': _countryCode
|
||||||
};
|
};
|
||||||
|
@ -99,8 +103,8 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
throw BuyException(
|
throw BuyException(
|
||||||
description: description,
|
title: buyOptionDescription,
|
||||||
text: 'Quote is not found!');
|
content: 'Quote is not found!');
|
||||||
}
|
}
|
||||||
|
|
||||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
@ -111,7 +115,6 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
return BuyAmount(sourceAmount: sourceAmount, destAmount: destAmount, achSourceAmount: achAmount);
|
return BuyAmount(sourceAmount: sourceAmount, destAmount: destAmount, achSourceAmount: achAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Order> findOrderById(String id) async {
|
Future<Order> findOrderById(String id) async {
|
||||||
final orderUrl = baseApiUrl + _ordersSuffix + '/$id';
|
final orderUrl = baseApiUrl + _ordersSuffix + '/$id';
|
||||||
final orderUri = Uri.parse(orderUrl);
|
final orderUri = Uri.parse(orderUrl);
|
||||||
|
@ -119,8 +122,8 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
if (orderResponse.statusCode != 200) {
|
if (orderResponse.statusCode != 200) {
|
||||||
throw BuyException(
|
throw BuyException(
|
||||||
description: description,
|
title: buyOptionDescription,
|
||||||
text: 'Order $id is not found!');
|
content: 'Order $id is not found!');
|
||||||
}
|
}
|
||||||
|
|
||||||
final orderResponseJSON =
|
final orderResponseJSON =
|
||||||
|
@ -141,8 +144,8 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
if (transferResponse.statusCode != 200) {
|
if (transferResponse.statusCode != 200) {
|
||||||
throw BuyException(
|
throw BuyException(
|
||||||
description: description,
|
title: buyOptionDescription,
|
||||||
text: 'Transfer $transferId is not found!');
|
content: 'Transfer $transferId is not found!');
|
||||||
}
|
}
|
||||||
|
|
||||||
final transferResponseJSON =
|
final transferResponseJSON =
|
||||||
|
@ -151,15 +154,25 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
return Order(
|
return Order(
|
||||||
id: id,
|
id: id,
|
||||||
provider: description,
|
provider: BuyProviderDescription.wyre,
|
||||||
transferId: transferId,
|
transferId: transferId,
|
||||||
from: from,
|
from: from,
|
||||||
to: to,
|
to: to,
|
||||||
state: state,
|
state: state,
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
amount: amount.toString(),
|
amount: amount.toString(),
|
||||||
receiveAddress: walletAddress,
|
receiveAddress: wallet.walletAddresses.address,
|
||||||
walletId: walletId
|
walletId: wallet.id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> launchProvider(BuildContext context, bool? isBuyAction) {
|
||||||
|
// TODO: implement launchProvider
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// TODO: implement sellOptionDescription
|
||||||
|
String get sellOptionDescription => throw UnimplementedError();
|
||||||
}
|
}
|
10
lib/di.dart
10
lib/di.dart
|
@ -1,6 +1,7 @@
|
||||||
import 'package:cake_wallet/anonpay/anonpay_api.dart';
|
import 'package:cake_wallet/anonpay/anonpay_api.dart';
|
||||||
import 'package:cake_wallet/anonpay/anonpay_info_base.dart';
|
import 'package:cake_wallet/anonpay/anonpay_info_base.dart';
|
||||||
import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
|
import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
|
||||||
|
import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart';
|
||||||
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
|
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
|
||||||
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
||||||
import 'package:cake_wallet/buy/payfura/payfura_buy_provider.dart';
|
import 'package:cake_wallet/buy/payfura/payfura_buy_provider.dart';
|
||||||
|
@ -796,8 +797,12 @@ Future<void> setup({
|
||||||
getIt
|
getIt
|
||||||
.registerFactory<DFXBuyProvider>(() => DFXBuyProvider(wallet: getIt.get<AppStore>().wallet!));
|
.registerFactory<DFXBuyProvider>(() => DFXBuyProvider(wallet: getIt.get<AppStore>().wallet!));
|
||||||
|
|
||||||
|
getIt.registerFactory<MoonPaySellProvider>(() => MoonPaySellProvider(
|
||||||
|
settingsStore: getIt.get<AppStore>().settingsStore,
|
||||||
|
wallet: getIt.get<AppStore>().wallet!));
|
||||||
|
|
||||||
getIt.registerFactory<OnRamperBuyProvider>(() => OnRamperBuyProvider(
|
getIt.registerFactory<OnRamperBuyProvider>(() => OnRamperBuyProvider(
|
||||||
settingsStore: getIt.get<AppStore>().settingsStore,
|
getIt.get<AppStore>().settingsStore,
|
||||||
wallet: getIt.get<AppStore>().wallet!,
|
wallet: getIt.get<AppStore>().wallet!,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -941,7 +946,8 @@ Future<void> setup({
|
||||||
|
|
||||||
getIt.registerFactory(() => BuyAmountViewModel());
|
getIt.registerFactory(() => BuyAmountViewModel());
|
||||||
|
|
||||||
getIt.registerFactory(() => BuyOptionsPage(getIt.get<DashboardViewModel>()));
|
getIt.registerFactoryParam<BuySellOptionsPage, bool, void>(
|
||||||
|
(isBuyOption, _) => BuySellOptionsPage(getIt.get<DashboardViewModel>(), isBuyOption));
|
||||||
|
|
||||||
getIt.registerFactory(() {
|
getIt.registerFactory(() {
|
||||||
final wallet = getIt.get<AppStore>().wallet;
|
final wallet = getIt.get<AppStore>().wallet;
|
||||||
|
|
|
@ -1,57 +1,112 @@
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
|
import 'package:cake_wallet/buy/dfx/dfx_buy_provider.dart';
|
||||||
|
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
|
||||||
|
import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart';
|
||||||
|
import 'package:cake_wallet/di.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
|
||||||
enum BuyProviderType {
|
enum BuyProviderType {
|
||||||
AskEachTime,
|
askEachTime,
|
||||||
Robinhood,
|
robinhood,
|
||||||
Onramper,
|
dfx,
|
||||||
DFX;
|
onramper,
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
extension BuyProviderTypeName on BuyProviderType {
|
||||||
String toString() {
|
String get name {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case BuyProviderType.AskEachTime:
|
case BuyProviderType.askEachTime:
|
||||||
return S.current.ask_each_time;
|
return 'Ask each time';
|
||||||
case BuyProviderType.Robinhood:
|
case BuyProviderType.robinhood:
|
||||||
return "Robinhood";
|
return 'Robinhood Connect';
|
||||||
case BuyProviderType.Onramper:
|
case BuyProviderType.dfx:
|
||||||
return "Onramper";
|
return 'DFX Connect';
|
||||||
case BuyProviderType.DFX:
|
case BuyProviderType.onramper:
|
||||||
return "DFX";
|
return 'Onramper';
|
||||||
|
default:
|
||||||
|
return this.toString().split('.').last;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<BuyProviderType> getAvailableProviders(WalletType walletType) {
|
String get id {
|
||||||
|
switch (this) {
|
||||||
|
case BuyProviderType.askEachTime:
|
||||||
|
return 'ask_each_time_provider';
|
||||||
|
case BuyProviderType.robinhood:
|
||||||
|
return 'robinhood_connect_provider';
|
||||||
|
case BuyProviderType.dfx:
|
||||||
|
return 'dfx_connect_provider';
|
||||||
|
case BuyProviderType.onramper:
|
||||||
|
return 'onramper_provider';
|
||||||
|
default:
|
||||||
|
return this.toString().split('.').last.replaceAll('.', '_')
|
||||||
|
.toLowerCase() + '_provider';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BuyProviderHelper {
|
||||||
|
static List<BuyProviderType> getAvailableBuyProviderTypes(
|
||||||
|
WalletType walletType) {
|
||||||
switch (walletType) {
|
switch (walletType) {
|
||||||
case WalletType.nano:
|
case WalletType.nano:
|
||||||
case WalletType.banano:
|
case WalletType.banano:
|
||||||
return [
|
return [BuyProviderType.askEachTime, BuyProviderType.onramper];
|
||||||
BuyProviderType.AskEachTime,
|
|
||||||
BuyProviderType.Onramper
|
|
||||||
];
|
|
||||||
case WalletType.monero:
|
case WalletType.monero:
|
||||||
return [
|
return [
|
||||||
BuyProviderType.AskEachTime,
|
BuyProviderType.askEachTime,
|
||||||
BuyProviderType.Onramper,
|
BuyProviderType.onramper,
|
||||||
BuyProviderType.DFX
|
BuyProviderType.dfx
|
||||||
];
|
];
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
return [
|
return [
|
||||||
BuyProviderType.AskEachTime,
|
BuyProviderType.askEachTime,
|
||||||
BuyProviderType.Onramper,
|
BuyProviderType.onramper,
|
||||||
BuyProviderType.DFX,
|
BuyProviderType.dfx,
|
||||||
BuyProviderType.Robinhood
|
BuyProviderType.robinhood
|
||||||
];
|
];
|
||||||
case WalletType.litecoin:
|
case WalletType.litecoin:
|
||||||
case WalletType.bitcoinCash:
|
case WalletType.bitcoinCash:
|
||||||
return [
|
return [
|
||||||
BuyProviderType.AskEachTime,
|
BuyProviderType.askEachTime,
|
||||||
BuyProviderType.Onramper,
|
BuyProviderType.onramper,
|
||||||
BuyProviderType.Robinhood
|
BuyProviderType.robinhood
|
||||||
];
|
];
|
||||||
default:
|
default:
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static List<BuyProviderType> getAvailableSellProviderTypes(
|
||||||
|
WalletType walletType) {
|
||||||
|
switch (walletType) {
|
||||||
|
case WalletType.nano:
|
||||||
|
case WalletType.banano:
|
||||||
|
return [BuyProviderType.askEachTime];
|
||||||
|
case WalletType.monero:
|
||||||
|
return [BuyProviderType.askEachTime, BuyProviderType.dfx];
|
||||||
|
case WalletType.bitcoin:
|
||||||
|
case WalletType.ethereum:
|
||||||
|
return [BuyProviderType.askEachTime, BuyProviderType.dfx];
|
||||||
|
case WalletType.litecoin:
|
||||||
|
case WalletType.bitcoinCash:
|
||||||
|
return [BuyProviderType.askEachTime];
|
||||||
|
default:
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static BuyProvider? getProviderByType(BuyProviderType type) {
|
||||||
|
switch (type) {
|
||||||
|
case BuyProviderType.robinhood:
|
||||||
|
return getIt.get<RobinhoodBuyProvider>();
|
||||||
|
case BuyProviderType.dfx:
|
||||||
|
return getIt.get<DFXBuyProvider>();
|
||||||
|
case BuyProviderType.onramper:
|
||||||
|
return getIt.get<OnRamperBuyProvider>();
|
||||||
|
case BuyProviderType.askEachTime:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,9 @@
|
||||||
import 'package:cake_wallet/buy/dfx/dfx_buy_provider.dart';
|
|
||||||
import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart';
|
|
||||||
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
|
|
||||||
import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart';
|
|
||||||
import 'package:cake_wallet/di.dart';
|
|
||||||
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||||
import 'package:cake_wallet/utils/device_info.dart';
|
|
||||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
class MainActions {
|
class MainActions {
|
||||||
final String Function(BuildContext context) name;
|
final String Function(BuildContext context) name;
|
||||||
|
@ -46,53 +37,22 @@ class MainActions {
|
||||||
canShow: (viewModel) => viewModel.hasBuyAction,
|
canShow: (viewModel) => viewModel.hasBuyAction,
|
||||||
onTap: (BuildContext context, DashboardViewModel viewModel) async {
|
onTap: (BuildContext context, DashboardViewModel viewModel) async {
|
||||||
if (!viewModel.isEnabledBuyAction) {
|
if (!viewModel.isEnabledBuyAction) {
|
||||||
await _showErrorDialog(context, S.of(context).unsupported_asset);
|
await _showErrorDialog(
|
||||||
|
context, S.of(context).buy, S.of(context).unsupported_asset);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final defaultBuyProvider = viewModel.defaultBuyProvider;
|
final defaultBuyProvider = viewModel.defaultBuyProvider;
|
||||||
try {
|
try {
|
||||||
await _launchProviderByType(context, defaultBuyProvider);
|
defaultBuyProvider != null
|
||||||
|
? await defaultBuyProvider.launchProvider(context, true)
|
||||||
|
: await Navigator.of(context).pushNamed(Routes.buySellPage, arguments: true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await _showErrorDialog(context, e.toString());
|
await _showErrorDialog(context, defaultBuyProvider.toString(), e.toString());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
static Future<void> _launchProviderByType(BuildContext context, BuyProviderType providerType) async {
|
|
||||||
switch (providerType) {
|
|
||||||
case BuyProviderType.AskEachTime:
|
|
||||||
Navigator.pushNamed(context, Routes.buy);
|
|
||||||
break;
|
|
||||||
case BuyProviderType.Onramper:
|
|
||||||
await getIt.get<OnRamperBuyProvider>().launchProvider(context);
|
|
||||||
break;
|
|
||||||
case BuyProviderType.Robinhood:
|
|
||||||
await getIt.get<RobinhoodBuyProvider>().launchProvider(context);
|
|
||||||
break;
|
|
||||||
case BuyProviderType.DFX:
|
|
||||||
await getIt.get<DFXBuyProvider>().launchProvider(context);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw UnsupportedError('Unsupported buy provider type');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Future<void> _showErrorDialog(BuildContext context, String errorMessage) async {
|
|
||||||
await showPopUp<void>(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return AlertWithOneAction(
|
|
||||||
alertTitle: S.of(context).buy,
|
|
||||||
alertContent: errorMessage,
|
|
||||||
buttonText: S.of(context).ok,
|
|
||||||
buttonAction: () => Navigator.of(context).pop(),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static MainActions receiveAction = MainActions._(
|
static MainActions receiveAction = MainActions._(
|
||||||
name: (context) => S.of(context).receive,
|
name: (context) => S.of(context).receive,
|
||||||
image: 'assets/images/received.png',
|
image: 'assets/images/received.png',
|
||||||
|
@ -127,42 +87,35 @@ class MainActions {
|
||||||
isEnabled: (viewModel) => viewModel.isEnabledSellAction,
|
isEnabled: (viewModel) => viewModel.isEnabledSellAction,
|
||||||
canShow: (viewModel) => viewModel.hasSellAction,
|
canShow: (viewModel) => viewModel.hasSellAction,
|
||||||
onTap: (BuildContext context, DashboardViewModel viewModel) async {
|
onTap: (BuildContext context, DashboardViewModel viewModel) async {
|
||||||
final walletType = viewModel.type;
|
if (!viewModel.isEnabledSellAction) {
|
||||||
|
await _showErrorDialog(
|
||||||
|
context, S.of(context).sell, S.of(context).unsupported_asset);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (walletType) {
|
final defaultSellProvider = viewModel.defaultSellProvider;
|
||||||
case WalletType.bitcoin:
|
try {
|
||||||
case WalletType.litecoin:
|
defaultSellProvider != null
|
||||||
case WalletType.ethereum:
|
? await defaultSellProvider.launchProvider(context, false)
|
||||||
case WalletType.polygon:
|
: await Navigator.of(context).pushNamed(Routes.buySellPage, arguments: false);
|
||||||
case WalletType.bitcoinCash:
|
} catch (e) {
|
||||||
if (viewModel.isEnabledSellAction) {
|
await _showErrorDialog(context, defaultSellProvider.toString(), e.toString());
|
||||||
final moonPaySellProvider = MoonPaySellProvider();
|
|
||||||
final uri = await moonPaySellProvider.requestUrl(
|
|
||||||
currency: viewModel.wallet.currency,
|
|
||||||
refundWalletAddress: viewModel.wallet.walletAddresses.address,
|
|
||||||
settingsStore: viewModel.settingsStore,
|
|
||||||
);
|
|
||||||
if (DeviceInfo.instance.isMobile) {
|
|
||||||
Navigator.of(context).pushNamed(Routes.webViewPage,
|
|
||||||
arguments: [S.of(context).sell, uri]);
|
|
||||||
} else {
|
|
||||||
await launchUrl(uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
await showPopUp<void>(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return AlertWithOneAction(
|
|
||||||
alertTitle: S.of(context).sell,
|
|
||||||
alertContent: S.of(context).unsupported_asset,
|
|
||||||
buttonText: S.of(context).ok,
|
|
||||||
buttonAction: () => Navigator.of(context).pop());
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
static Future<void> _showErrorDialog(
|
||||||
|
BuildContext context, String title, String errorMessage) async {
|
||||||
|
await showPopUp<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertWithOneAction(
|
||||||
|
alertTitle: title,
|
||||||
|
alertContent: errorMessage,
|
||||||
|
buttonText: S.of(context).ok,
|
||||||
|
buttonAction: () => Navigator.of(context).pop(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -390,8 +390,10 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
return MaterialPageRoute<void>(
|
return MaterialPageRoute<void>(
|
||||||
builder: (_) => getIt.get<OrderDetailsPage>(param1: settings.arguments as Order));
|
builder: (_) => getIt.get<OrderDetailsPage>(param1: settings.arguments as Order));
|
||||||
|
|
||||||
case Routes.buy:
|
case Routes.buySellPage:
|
||||||
return MaterialPageRoute<void>(builder: (_) => getIt.get<BuyOptionsPage>());
|
final args = settings.arguments as bool;
|
||||||
|
return MaterialPageRoute<void>(
|
||||||
|
builder: (_) => getIt.get<BuySellOptionsPage>(param1: args));
|
||||||
|
|
||||||
case Routes.buyWebView:
|
case Routes.buyWebView:
|
||||||
final args = settings.arguments as List;
|
final args = settings.arguments as List;
|
||||||
|
|
|
@ -55,7 +55,7 @@ class Routes {
|
||||||
static const supportLiveChat = '/support/live_chat';
|
static const supportLiveChat = '/support/live_chat';
|
||||||
static const supportOtherLinks = '/support/other';
|
static const supportOtherLinks = '/support/other';
|
||||||
static const orderDetails = '/order_details';
|
static const orderDetails = '/order_details';
|
||||||
static const buy = '/buy';
|
static const buySellPage = '/buy_sell_page';
|
||||||
static const buyWebView = '/buy_web_view';
|
static const buyWebView = '/buy_web_view';
|
||||||
static const unspentCoinsList = '/unspent_coins_list';
|
static const unspentCoinsList = '/unspent_coins_list';
|
||||||
static const unspentCoinsDetails = '/unspent_coins_details';
|
static const unspentCoinsDetails = '/unspent_coins_details';
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
import 'package:cake_wallet/buy/dfx/dfx_buy_provider.dart';
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
|
|
||||||
import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart';
|
|
||||||
import 'package:cake_wallet/di.dart';
|
|
||||||
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
|
@ -11,19 +8,14 @@ import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
|
||||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class BuyOptionsPage extends BasePage {
|
class BuySellOptionsPage extends BasePage {
|
||||||
BuyOptionsPage(this.dashboardViewModel);
|
BuySellOptionsPage(this.dashboardViewModel, this.isBuyAction);
|
||||||
|
|
||||||
final DashboardViewModel dashboardViewModel;
|
final DashboardViewModel dashboardViewModel;
|
||||||
final iconDarkRobinhood = 'assets/images/robinhood_dark.png';
|
final bool isBuyAction;
|
||||||
final iconLightRobinhood = 'assets/images/robinhood_light.png';
|
|
||||||
final iconDarkOnramper = 'assets/images/onramper_dark.png';
|
|
||||||
final iconLightOnramper = 'assets/images/onramper_light.png';
|
|
||||||
final iconDarkDFX = 'assets/images/dfx_dark.png';
|
|
||||||
final iconLightDFX = 'assets/images/dfx_light.png';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get title => S.current.buy;
|
String get title => isBuyAction ? S.current.buy : S.current.sell;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
AppBarStyle get appBarStyle => AppBarStyle.regular;
|
AppBarStyle get appBarStyle => AppBarStyle.regular;
|
||||||
|
@ -32,17 +24,9 @@ class BuyOptionsPage extends BasePage {
|
||||||
Widget body(BuildContext context) {
|
Widget body(BuildContext context) {
|
||||||
final isLightMode =
|
final isLightMode =
|
||||||
Theme.of(context).extension<OptionTileTheme>()?.useDarkImage ?? false;
|
Theme.of(context).extension<OptionTileTheme>()?.useDarkImage ?? false;
|
||||||
final iconRobinhood = Image.asset(
|
final availableProviders = isBuyAction
|
||||||
isLightMode ? iconLightRobinhood : iconDarkRobinhood,
|
? dashboardViewModel.availableBuyProviders
|
||||||
height: 40,
|
: dashboardViewModel.availableSellProviders;
|
||||||
width: 40);
|
|
||||||
final iconOnramper = Image.asset(
|
|
||||||
isLightMode ? iconLightOnramper : iconDarkOnramper,
|
|
||||||
height: 40,
|
|
||||||
width: 40);
|
|
||||||
final iconDFX = Image.asset(isLightMode ? iconLightDFX : iconDarkDFX,
|
|
||||||
height: 40, width: 40);
|
|
||||||
final availableProviders = dashboardViewModel.availableProviders;
|
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
child: Center(
|
child: Center(
|
||||||
|
@ -50,57 +34,43 @@ class BuyOptionsPage extends BasePage {
|
||||||
constraints: BoxConstraints(maxWidth: 330),
|
constraints: BoxConstraints(maxWidth: 330),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
if (availableProviders.contains(BuyProviderType.Onramper))
|
...availableProviders.map((provider) {
|
||||||
Padding(
|
final icon = Image.asset(
|
||||||
|
isLightMode ? provider.lightIcon : provider.darkIcon,
|
||||||
|
height: 40,
|
||||||
|
width: 40,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Padding(
|
||||||
padding: EdgeInsets.only(top: 24),
|
padding: EdgeInsets.only(top: 24),
|
||||||
child: OptionTile(
|
child: OptionTile(
|
||||||
image: iconOnramper,
|
image: icon,
|
||||||
title: "Onramper",
|
title: provider.toString(),
|
||||||
description: S.of(context).onramper_option_description,
|
description: isBuyAction
|
||||||
onPressed: () async => await getIt
|
? provider.buyOptionDescription
|
||||||
.get<OnRamperBuyProvider>()
|
: provider.sellOptionDescription,
|
||||||
.launchProvider(context),
|
onPressed: () =>
|
||||||
|
provider.launchProvider(context, isBuyAction),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
if (availableProviders.contains(BuyProviderType.Robinhood))
|
}).toList(),
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.only(top: 24),
|
|
||||||
child: OptionTile(
|
|
||||||
image: iconRobinhood,
|
|
||||||
title: "Robinhood Connect",
|
|
||||||
description: S.of(context).robinhood_option_description,
|
|
||||||
onPressed: () async => await getIt
|
|
||||||
.get<RobinhoodBuyProvider>()
|
|
||||||
.launchProvider(context),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (availableProviders.contains(BuyProviderType.DFX))
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.only(top: 24),
|
|
||||||
child: OptionTile(
|
|
||||||
image: iconDFX,
|
|
||||||
title: "DFX Connect",
|
|
||||||
description: S.of(context).dfx_option_description,
|
|
||||||
onPressed: () async => await getIt
|
|
||||||
.get<DFXBuyProvider>()
|
|
||||||
.launchProvider(context),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Spacer(),
|
Spacer(),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
|
padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
|
||||||
child: Text(
|
child: Text(
|
||||||
S.of(context).select_buy_provider_notice,
|
isBuyAction
|
||||||
textAlign: TextAlign.center,
|
? S.of(context).select_buy_provider_notice
|
||||||
style: TextStyle(
|
: S.of(context).select_sell_provider_notice,
|
||||||
fontSize: 14,
|
textAlign: TextAlign.center,
|
||||||
fontWeight: FontWeight.normal,
|
style: TextStyle(
|
||||||
color: Theme.of(context)
|
fontSize: 14,
|
||||||
.extension<TransactionTradeTheme>()!
|
fontWeight: FontWeight.normal,
|
||||||
.detailsTitlesColor,
|
color: Theme.of(context)
|
||||||
|
.extension<TransactionTradeTheme>()!
|
||||||
|
.detailsTitlesColor,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -29,11 +29,10 @@ class BuyListItem extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final isSelected = selectedProvider?.description == provider.description;
|
final isSelected = selectedProvider?.buyOptionDescription == provider.buyOptionDescription;
|
||||||
final iconColor = isSelected ? Colors.white : Colors.black;
|
final iconColor = isSelected ? Colors.white : Colors.black;
|
||||||
|
|
||||||
final providerIcon = getBuyProviderIcon(provider.description,
|
final providerIcon = Image.asset('assets/images/wyre-icon.png', width: 36, height: 36);
|
||||||
iconColor: iconColor)!;
|
|
||||||
|
|
||||||
final backgroundColor = isSelected
|
final backgroundColor = isSelected
|
||||||
? Palette.greyBlueCraiola
|
? Palette.greyBlueCraiola
|
||||||
|
@ -76,7 +75,7 @@ class BuyListItem extends StatelessWidget {
|
||||||
padding: EdgeInsets.only(right: 10),
|
padding: EdgeInsets.only(right: 10),
|
||||||
child: providerIcon),
|
child: providerIcon),
|
||||||
Text(
|
Text(
|
||||||
provider.description.title,
|
provider.title,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: secondaryTextColor,
|
color: secondaryTextColor,
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
|
|
|
@ -43,10 +43,18 @@ class OtherSettingsPage extends BasePage {
|
||||||
if(_otherSettingsViewModel.isEnabledBuyAction)
|
if(_otherSettingsViewModel.isEnabledBuyAction)
|
||||||
SettingsPickerCell(
|
SettingsPickerCell(
|
||||||
title: S.current.default_buy_provider,
|
title: S.current.default_buy_provider,
|
||||||
items: _otherSettingsViewModel.availableBuyProviders,
|
items: _otherSettingsViewModel.availableBuyProvidersTypes,
|
||||||
displayItem: _otherSettingsViewModel.getBuyProviderType,
|
displayItem: _otherSettingsViewModel.getBuyProviderType,
|
||||||
selectedItem: _otherSettingsViewModel.buyProviderType,
|
selectedItem: _otherSettingsViewModel.buyProviderType,
|
||||||
onItemSelected: _otherSettingsViewModel.onBuyProviderTypeSelected,
|
onItemSelected: _otherSettingsViewModel.onBuyProviderTypeSelected
|
||||||
|
),
|
||||||
|
if(_otherSettingsViewModel.isEnabledSellAction)
|
||||||
|
SettingsPickerCell(
|
||||||
|
title: S.current.default_sell_provider,
|
||||||
|
items: _otherSettingsViewModel.availableSellProvidersTypes,
|
||||||
|
displayItem: _otherSettingsViewModel.getSellProviderType,
|
||||||
|
selectedItem: _otherSettingsViewModel.sellProviderType,
|
||||||
|
onItemSelected: _otherSettingsViewModel.onSellProviderTypeSelected,
|
||||||
),
|
),
|
||||||
SettingsCellWithArrow(
|
SettingsCellWithArrow(
|
||||||
title: S.current.settings_terms_and_conditions,
|
title: S.current.settings_terms_and_conditions,
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||||
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
||||||
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
|
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
|
||||||
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
||||||
import 'package:cake_wallet/entities/cake_2fa_preset_options.dart';
|
import 'package:cake_wallet/entities/cake_2fa_preset_options.dart';
|
||||||
|
@ -147,7 +148,9 @@ abstract class SettingsStoreBase with Store {
|
||||||
initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
||||||
currentSyncMode = initialSyncMode,
|
currentSyncMode = initialSyncMode,
|
||||||
currentSyncAll = initialSyncAll,
|
currentSyncAll = initialSyncAll,
|
||||||
priority = ObservableMap<WalletType, TransactionPriority>() {
|
priority = ObservableMap<WalletType, TransactionPriority>(),
|
||||||
|
defaultBuyProviders = ObservableMap<WalletType, BuyProviderType>(),
|
||||||
|
defaultSellProviders = ObservableMap<WalletType, BuyProviderType>() {
|
||||||
//this.nodes = ObservableMap<WalletType, Node>.of(nodes);
|
//this.nodes = ObservableMap<WalletType, Node>.of(nodes);
|
||||||
|
|
||||||
if (initialMoneroTransactionPriority != null) {
|
if (initialMoneroTransactionPriority != null) {
|
||||||
|
@ -181,9 +184,25 @@ abstract class SettingsStoreBase with Store {
|
||||||
initializeTrocadorProviderStates();
|
initializeTrocadorProviderStates();
|
||||||
|
|
||||||
WalletType.values.forEach((walletType) {
|
WalletType.values.forEach((walletType) {
|
||||||
final key = 'defaultBuyProvider_${walletType.toString()}';
|
final key = 'buyProvider_${walletType.toString()}';
|
||||||
final providerIndex = sharedPreferences.getInt(key);
|
final providerId = sharedPreferences.getString(key);
|
||||||
defaultBuyProviders[walletType] = providerIndex != null ? BuyProviderType.values[providerIndex] : BuyProviderType.AskEachTime;
|
if (providerId != null) {
|
||||||
|
defaultBuyProviders[walletType] = BuyProviderType.values
|
||||||
|
.firstWhere((provider) => provider.id == providerId, orElse: () => BuyProviderType.askEachTime);
|
||||||
|
} else {
|
||||||
|
defaultBuyProviders[walletType] = BuyProviderType.askEachTime;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
WalletType.values.forEach((walletType) {
|
||||||
|
final key = 'sellProvider_${walletType.toString()}';
|
||||||
|
final providerId = sharedPreferences.getString(key);
|
||||||
|
if (providerId != null) {
|
||||||
|
defaultSellProviders[walletType] = BuyProviderType.values
|
||||||
|
.firstWhere((provider) => provider.id == providerId, orElse: () => BuyProviderType.askEachTime);
|
||||||
|
} else {
|
||||||
|
defaultSellProviders[walletType] = BuyProviderType.askEachTime;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
reaction(
|
reaction(
|
||||||
|
@ -196,6 +215,20 @@ abstract class SettingsStoreBase with Store {
|
||||||
(bool shouldShowYatPopup) =>
|
(bool shouldShowYatPopup) =>
|
||||||
sharedPreferences.setBool(PreferencesKey.shouldShowYatPopup, shouldShowYatPopup));
|
sharedPreferences.setBool(PreferencesKey.shouldShowYatPopup, shouldShowYatPopup));
|
||||||
|
|
||||||
|
defaultBuyProviders.observe((change) {
|
||||||
|
final String key = 'buyProvider_${change.key.toString()}';
|
||||||
|
if (change.newValue != null) {
|
||||||
|
sharedPreferences.setString(key, change.newValue!.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
defaultSellProviders.observe((change) {
|
||||||
|
final String key = 'sellProvider_${change.key.toString()}';
|
||||||
|
if (change.newValue != null) {
|
||||||
|
sharedPreferences.setString(key, change.newValue!.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
priority.observe((change) {
|
priority.observe((change) {
|
||||||
final String? key;
|
final String? key;
|
||||||
switch (change.key) {
|
switch (change.key) {
|
||||||
|
@ -251,16 +284,6 @@ abstract class SettingsStoreBase with Store {
|
||||||
(bool disableSell) =>
|
(bool disableSell) =>
|
||||||
sharedPreferences.setBool(PreferencesKey.disableSellKey, disableSell));
|
sharedPreferences.setBool(PreferencesKey.disableSellKey, disableSell));
|
||||||
|
|
||||||
reaction(
|
|
||||||
(_) => defaultBuyProviders.asObservable(),
|
|
||||||
(ObservableMap<WalletType, BuyProviderType> providers) {
|
|
||||||
providers.forEach((walletType, provider) {
|
|
||||||
final key = 'defaultBuyProvider_${walletType.toString()}';
|
|
||||||
sharedPreferences.setInt(key, provider.index);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
reaction(
|
reaction(
|
||||||
(_) => walletListOrder,
|
(_) => walletListOrder,
|
||||||
(WalletListOrderType walletListOrder) =>
|
(WalletListOrderType walletListOrder) =>
|
||||||
|
@ -594,7 +617,10 @@ abstract class SettingsStoreBase with Store {
|
||||||
ObservableMap<String, bool> trocadorProviderStates = ObservableMap<String, bool>();
|
ObservableMap<String, bool> trocadorProviderStates = ObservableMap<String, bool>();
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
ObservableMap<WalletType, BuyProviderType> defaultBuyProviders = ObservableMap<WalletType, BuyProviderType>();
|
ObservableMap<WalletType, BuyProviderType> defaultBuyProviders;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
ObservableMap<WalletType, BuyProviderType> defaultSellProviders;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
SortBalanceBy sortBalanceBy;
|
SortBalanceBy sortBalanceBy;
|
||||||
|
|
|
@ -61,8 +61,7 @@ abstract class BuyViewModelBase with Store {
|
||||||
String _url = '';
|
String _url = '';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_url = await selectedProvider
|
_url = await selectedProvider!.requestUrl(doubleAmount.toString(), fiatCurrency.title);
|
||||||
!.requestUrl(doubleAmount.toString(), fiatCurrency.title);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e.toString());
|
print(e.toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
import 'package:cake_wallet/core/key_service.dart';
|
import 'package:cake_wallet/core/key_service.dart';
|
||||||
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
|
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
|
||||||
import 'package:cake_wallet/entities/balance_display_mode.dart';
|
import 'package:cake_wallet/entities/balance_display_mode.dart';
|
||||||
|
@ -41,6 +42,7 @@ import 'package:cw_core/wallet_type.dart';
|
||||||
import 'package:eth_sig_util/util/utils.dart';
|
import 'package:eth_sig_util/util/utils.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
|
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
||||||
|
|
||||||
part 'dashboard_view_model.g.dart';
|
part 'dashboard_view_model.g.dart';
|
||||||
|
|
||||||
|
@ -295,13 +297,31 @@ abstract class DashboardViewModelBase with Store {
|
||||||
|
|
||||||
Map<String, List<FilterItem>> filterItems;
|
Map<String, List<FilterItem>> filterItems;
|
||||||
|
|
||||||
BuyProviderType get defaultBuyProvider =>
|
BuyProvider? get defaultBuyProvider => BuyProviderHelper.getProviderByType(
|
||||||
settingsStore.defaultBuyProviders[wallet.type] ?? BuyProviderType.AskEachTime;
|
settingsStore.defaultBuyProviders[wallet.type] ?? BuyProviderType.askEachTime);
|
||||||
|
|
||||||
|
BuyProvider? get defaultSellProvider => BuyProviderHelper.getProviderByType(
|
||||||
|
settingsStore.defaultSellProviders[wallet.type] ?? BuyProviderType.askEachTime);
|
||||||
|
|
||||||
bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled;
|
bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled;
|
||||||
|
|
||||||
List<BuyProviderType> get availableProviders =>
|
List<BuyProvider> get availableBuyProviders {
|
||||||
BuyProviderType.getAvailableProviders(wallet.type);
|
final providerTypes = BuyProviderHelper.getAvailableBuyProviderTypes(wallet.type);
|
||||||
|
return providerTypes
|
||||||
|
.map((type) => BuyProviderHelper.getProviderByType(type))
|
||||||
|
.where((provider) => provider != null)
|
||||||
|
.cast<BuyProvider>()
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<BuyProvider> get availableSellProviders {
|
||||||
|
final providerTypes = BuyProviderHelper.getAvailableSellProviderTypes(wallet.type);
|
||||||
|
return providerTypes
|
||||||
|
.map((type) => BuyProviderHelper.getProviderByType(type))
|
||||||
|
.where((provider) => provider != null)
|
||||||
|
.cast<BuyProvider>()
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
bool get shouldShowYatPopup => settingsStore.shouldShowYatPopup;
|
bool get shouldShowYatPopup => settingsStore.shouldShowYatPopup;
|
||||||
|
|
||||||
|
@ -315,16 +335,15 @@ abstract class DashboardViewModelBase with Store {
|
||||||
bool hasExchangeAction;
|
bool hasExchangeAction;
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
bool get isEnabledBuyAction => !settingsStore.disableBuy && wallet.type != WalletType.haven;
|
bool get isEnabledBuyAction =>
|
||||||
|
!settingsStore.disableBuy && availableBuyProviders.isNotEmpty;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
bool hasBuyAction;
|
bool hasBuyAction;
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
bool get isEnabledSellAction =>
|
bool get isEnabledSellAction =>
|
||||||
!settingsStore.disableSell &&
|
!settingsStore.disableSell && availableSellProviders.isNotEmpty;
|
||||||
wallet.type != WalletType.haven &&
|
|
||||||
wallet.type != WalletType.monero;
|
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
bool hasSellAction;
|
bool hasSellAction;
|
||||||
|
|
|
@ -50,8 +50,10 @@ abstract class OrderDetailsViewModelBase with Store {
|
||||||
@action
|
@action
|
||||||
Future<void> _updateOrder() async {
|
Future<void> _updateOrder() async {
|
||||||
try {
|
try {
|
||||||
if (_provider != null) {
|
if (_provider != null && (_provider is MoonPayBuyProvider || _provider is WyreBuyProvider)) {
|
||||||
final updatedOrder = await _provider!.findOrderById(order.id);
|
final updatedOrder = _provider is MoonPayBuyProvider
|
||||||
|
? await (_provider as MoonPayBuyProvider).findOrderById(order.id)
|
||||||
|
: await (_provider as WyreBuyProvider).findOrderById(order.id);
|
||||||
updatedOrder.from = order.from;
|
updatedOrder.from = order.from;
|
||||||
updatedOrder.to = order.to;
|
updatedOrder.to = order.to;
|
||||||
updatedOrder.receiveAddress = order.receiveAddress;
|
updatedOrder.receiveAddress = order.receiveAddress;
|
||||||
|
@ -87,19 +89,26 @@ abstract class OrderDetailsViewModelBase with Store {
|
||||||
value: order.provider.title)
|
value: order.provider.title)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (_provider?.trackUrl.isNotEmpty ?? false) {
|
if (_provider != null && (_provider is MoonPayBuyProvider || _provider is WyreBuyProvider)) {
|
||||||
final buildURL = _provider!.trackUrl + '${order.transferId}';
|
|
||||||
items.add(
|
final trackUrl = _provider is MoonPayBuyProvider
|
||||||
TrackTradeListItem(
|
? (_provider as MoonPayBuyProvider).trackUrl
|
||||||
title: 'Track',
|
: (_provider as WyreBuyProvider).trackUrl;
|
||||||
value: buildURL,
|
|
||||||
onTap: () {
|
if (trackUrl.isNotEmpty ?? false) {
|
||||||
try {
|
final buildURL = trackUrl + '${order.transferId}';
|
||||||
launch(buildURL);
|
items.add(
|
||||||
} catch (e) {}
|
TrackTradeListItem(
|
||||||
}
|
title: 'Track',
|
||||||
)
|
value: buildURL,
|
||||||
);
|
onTap: () {
|
||||||
|
try {
|
||||||
|
launch(buildURL);
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
items.add(
|
items.add(
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||||
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
||||||
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
|
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/store/settings_store.dart';
|
import 'package:cake_wallet/store/settings_store.dart';
|
||||||
import 'package:cw_core/balance.dart';
|
import 'package:cw_core/balance.dart';
|
||||||
import 'package:cw_core/transaction_history.dart';
|
import 'package:cw_core/transaction_history.dart';
|
||||||
|
@ -59,12 +60,24 @@ abstract class OtherSettingsViewModelBase with Store {
|
||||||
bool get isEnabledBuyAction =>
|
bool get isEnabledBuyAction =>
|
||||||
!_settingsStore.disableBuy && _wallet.type != WalletType.haven;
|
!_settingsStore.disableBuy && _wallet.type != WalletType.haven;
|
||||||
|
|
||||||
List<BuyProviderType> get availableBuyProviders =>
|
@computed
|
||||||
BuyProviderType.getAvailableProviders(walletType);
|
bool get isEnabledSellAction =>
|
||||||
|
!_settingsStore.disableSell && _wallet.type != WalletType.haven;
|
||||||
|
|
||||||
|
List<BuyProviderType> get availableBuyProvidersTypes {
|
||||||
|
return BuyProviderHelper.getAvailableBuyProviderTypes(walletType);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<BuyProviderType> get availableSellProvidersTypes =>
|
||||||
|
BuyProviderHelper.getAvailableSellProviderTypes(walletType);
|
||||||
|
|
||||||
BuyProviderType get buyProviderType =>
|
BuyProviderType get buyProviderType =>
|
||||||
_settingsStore.defaultBuyProviders[walletType] ??
|
_settingsStore.defaultBuyProviders[walletType] ??
|
||||||
BuyProviderType.AskEachTime;
|
BuyProviderType.askEachTime;
|
||||||
|
|
||||||
|
BuyProviderType get sellProviderType =>
|
||||||
|
_settingsStore.defaultSellProviders[walletType] ??
|
||||||
|
BuyProviderType.askEachTime;
|
||||||
|
|
||||||
String getDisplayPriority(dynamic priority) {
|
String getDisplayPriority(dynamic priority) {
|
||||||
final _priority = priority as TransactionPriority;
|
final _priority = priority as TransactionPriority;
|
||||||
|
@ -81,13 +94,27 @@ abstract class OtherSettingsViewModelBase with Store {
|
||||||
|
|
||||||
String getBuyProviderType(dynamic buyProviderType) {
|
String getBuyProviderType(dynamic buyProviderType) {
|
||||||
final _buyProviderType = buyProviderType as BuyProviderType;
|
final _buyProviderType = buyProviderType as BuyProviderType;
|
||||||
|
return _buyProviderType == BuyProviderType.askEachTime
|
||||||
|
? S.current.ask_each_time
|
||||||
|
: _buyProviderType.name;
|
||||||
|
}
|
||||||
|
|
||||||
return _buyProviderType.toString();
|
String getSellProviderType(dynamic sellProviderType) {
|
||||||
|
final _sellProviderType = sellProviderType as BuyProviderType;
|
||||||
|
return _sellProviderType == BuyProviderType.askEachTime
|
||||||
|
? S.current.ask_each_time
|
||||||
|
: _sellProviderType.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onDisplayPrioritySelected(TransactionPriority priority) =>
|
void onDisplayPrioritySelected(TransactionPriority priority) =>
|
||||||
_settingsStore.priority[_wallet.type] = priority;
|
_settingsStore.priority[_wallet.type] = priority;
|
||||||
|
|
||||||
void onBuyProviderTypeSelected(BuyProviderType buyProviderType) =>
|
@action
|
||||||
|
BuyProviderType onBuyProviderTypeSelected(BuyProviderType buyProviderType) =>
|
||||||
_settingsStore.defaultBuyProviders[walletType] = buyProviderType;
|
_settingsStore.defaultBuyProviders[walletType] = buyProviderType;
|
||||||
|
|
||||||
|
@action
|
||||||
|
BuyProviderType onSellProviderTypeSelected(
|
||||||
|
BuyProviderType sellProviderType) =>
|
||||||
|
_settingsStore.defaultSellProviders[walletType] = sellProviderType;
|
||||||
}
|
}
|
||||||
|
|
|
@ -754,6 +754,8 @@
|
||||||
"dfx_option_description": "ﺎﺑﻭﺭﻭﺃ ﻲﻓ ﺕﺎﻛﺮﺸﻟﺍﻭ ﺔﺋﺰﺠﺘﻟﺍ ءﻼﻤﻌﻟ .ﻲﻓﺎﺿﺇ KYC ﻥﻭﺪﺑ ﻭﺭﻮﻳ 990 ﻰﻟﺇ ﻞﺼﻳ ﺎﻣ .ﻱﺮﺴﻳﻮﺴﻟﺍ",
|
"dfx_option_description": "ﺎﺑﻭﺭﻭﺃ ﻲﻓ ﺕﺎﻛﺮﺸﻟﺍﻭ ﺔﺋﺰﺠﺘﻟﺍ ءﻼﻤﻌﻟ .ﻲﻓﺎﺿﺇ KYC ﻥﻭﺪﺑ ﻭﺭﻮﻳ 990 ﻰﻟﺇ ﻞﺼﻳ ﺎﻣ .ﻱﺮﺴﻳﻮﺴﻟﺍ",
|
||||||
"polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ",
|
"polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ",
|
||||||
"wallet_seed_legacy": "بذرة محفظة قديمة",
|
"wallet_seed_legacy": "بذرة محفظة قديمة",
|
||||||
|
"default_sell_provider": " ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ",
|
||||||
|
"select_sell_provider_notice": ".ﻖﻴﺒﻄﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻚﺑ ﺹﺎﺨﻟﺍ ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ ﻦﻴﻴﻌﺗ ﻖﻳﺮﻃ ﻦﻋ ﺔﺷﺎﺸﻟﺍ ﻩﺬﻫ ﻲﻄﺨﺗ",
|
||||||
"custom_drag": "مخصص (عقد وسحب)",
|
"custom_drag": "مخصص (عقد وسحب)",
|
||||||
"switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ"
|
"switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ"
|
||||||
}
|
}
|
||||||
|
|
|
@ -750,6 +750,8 @@
|
||||||
"dfx_option_description": "Купете крипто с EUR и CHF. До 990 € без допълнителен KYC. За клиенти на дребно и корпоративни клиенти в Европа",
|
"dfx_option_description": "Купете крипто с EUR и CHF. До 990 € без допълнителен KYC. За клиенти на дребно и корпоративни клиенти в Европа",
|
||||||
"polygonscan_history": "История на PolygonScan",
|
"polygonscan_history": "История на PolygonScan",
|
||||||
"wallet_seed_legacy": "Наследено портфейл семе",
|
"wallet_seed_legacy": "Наследено портфейл семе",
|
||||||
|
"default_sell_provider": "Доставчик за продажба по подразбиране",
|
||||||
|
"select_sell_provider_notice": "Изберете доставчик на продажба по-горе. Можете да пропуснете този екран, като зададете своя доставчик на продажба по подразбиране в настройките на приложението.",
|
||||||
"custom_drag": "Персонализиране (задръжте и плъзнете)",
|
"custom_drag": "Персонализиране (задръжте и плъзнете)",
|
||||||
"switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -750,6 +750,8 @@
|
||||||
"dfx_option_description": "Nakupujte kryptoměny za EUR a CHF. Až 990 € bez dalších KYC. Pro maloobchodní a firemní zákazníky v Evropě",
|
"dfx_option_description": "Nakupujte kryptoměny za EUR a CHF. Až 990 € bez dalších KYC. Pro maloobchodní a firemní zákazníky v Evropě",
|
||||||
"polygonscan_history": "Historie PolygonScan",
|
"polygonscan_history": "Historie PolygonScan",
|
||||||
"wallet_seed_legacy": "Starší semeno peněženky",
|
"wallet_seed_legacy": "Starší semeno peněženky",
|
||||||
|
"default_sell_provider": "Výchozí poskytovatel prodeje",
|
||||||
|
"select_sell_provider_notice": "Výše vyberte poskytovatele prodeje. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele prodeje v nastavení aplikace.",
|
||||||
"custom_drag": "Custom (Hold and Drag)",
|
"custom_drag": "Custom (Hold and Drag)",
|
||||||
"switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,6 +758,8 @@
|
||||||
"dfx_option_description": "Krypto mit EUR und CHF kaufen. Bis zu 990€ ohne zusätzliches KYC. Für Privat- und Firmenkunden in Europa",
|
"dfx_option_description": "Krypto mit EUR und CHF kaufen. Bis zu 990€ ohne zusätzliches KYC. Für Privat- und Firmenkunden in Europa",
|
||||||
"polygonscan_history": "PolygonScan-Verlauf",
|
"polygonscan_history": "PolygonScan-Verlauf",
|
||||||
"wallet_seed_legacy": "Legacy Wallet Seed",
|
"wallet_seed_legacy": "Legacy Wallet Seed",
|
||||||
|
"default_sell_provider": "Standard-Verkaufsanbieter",
|
||||||
|
"select_sell_provider_notice": "Wählen Sie oben einen Verkaufsanbieter aus. Sie können diesen Bildschirm überspringen, indem Sie in den App-Einstellungen Ihren Standard-Verkaufsanbieter festlegen.",
|
||||||
"custom_drag": "Custom (Hold and Drag)",
|
"custom_drag": "Custom (Hold and Drag)",
|
||||||
"switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -759,6 +759,8 @@
|
||||||
"dfx_option_description": "Buy crypto with EUR & CHF. Up to 990€ without additional KYC. For retail and corporate customers in Europe",
|
"dfx_option_description": "Buy crypto with EUR & CHF. Up to 990€ without additional KYC. For retail and corporate customers in Europe",
|
||||||
"polygonscan_history": "PolygonScan history",
|
"polygonscan_history": "PolygonScan history",
|
||||||
"wallet_seed_legacy": "Legacy wallet seed",
|
"wallet_seed_legacy": "Legacy wallet seed",
|
||||||
|
"default_sell_provider": "Default Sell Provider",
|
||||||
|
"select_sell_provider_notice": "Select a sell provider above. You can skip this screen by setting your default sell provider in app settings.",
|
||||||
"custom_drag": "Custom (Hold and Drag)",
|
"custom_drag": "Custom (Hold and Drag)",
|
||||||
"switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,6 +758,8 @@
|
||||||
"dfx_option_description": "Compre criptomonedas con EUR y CHF. Hasta 990€ sin KYC adicional. Para clientes minoristas y corporativos en Europa",
|
"dfx_option_description": "Compre criptomonedas con EUR y CHF. Hasta 990€ sin KYC adicional. Para clientes minoristas y corporativos en Europa",
|
||||||
"polygonscan_history": "Historial de PolygonScan",
|
"polygonscan_history": "Historial de PolygonScan",
|
||||||
"wallet_seed_legacy": "Semilla de billetera heredada",
|
"wallet_seed_legacy": "Semilla de billetera heredada",
|
||||||
|
"default_sell_provider": "Proveedor de venta predeterminado",
|
||||||
|
"select_sell_provider_notice": "Seleccione un proveedor de venta arriba. Puede omitir esta pantalla configurando su proveedor de venta predeterminado en la configuración de la aplicación.",
|
||||||
"custom_drag": "Custom (mantenía y arrastre)",
|
"custom_drag": "Custom (mantenía y arrastre)",
|
||||||
"switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,6 +758,8 @@
|
||||||
"dfx_option_description": "Achetez des crypto-monnaies avec EUR et CHF. Jusqu'à 990€ sans KYC supplémentaire. Pour les clients particuliers et entreprises en Europe",
|
"dfx_option_description": "Achetez des crypto-monnaies avec EUR et CHF. Jusqu'à 990€ sans KYC supplémentaire. Pour les clients particuliers et entreprises en Europe",
|
||||||
"polygonscan_history": "Historique de PolygonScan",
|
"polygonscan_history": "Historique de PolygonScan",
|
||||||
"wallet_seed_legacy": "Graine de portefeuille hérité",
|
"wallet_seed_legacy": "Graine de portefeuille hérité",
|
||||||
|
"default_sell_provider": "Fournisseur de vente par défaut",
|
||||||
|
"select_sell_provider_notice": "Sélectionnez un fournisseur de vente ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur de vente par défaut dans les paramètres de l'application.",
|
||||||
"custom_drag": "Custom (maintenir et traîner)",
|
"custom_drag": "Custom (maintenir et traîner)",
|
||||||
"switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -736,6 +736,8 @@
|
||||||
"dfx_option_description": "Sayi crypto tare da EUR & CHF. Har zuwa € 990 ba tare da ƙarin KYC ba. Don 'yan kasuwa da abokan ciniki na kamfanoni a Turai",
|
"dfx_option_description": "Sayi crypto tare da EUR & CHF. Har zuwa € 990 ba tare da ƙarin KYC ba. Don 'yan kasuwa da abokan ciniki na kamfanoni a Turai",
|
||||||
"polygonscan_history": "PolygonScan tarihin kowane zamani",
|
"polygonscan_history": "PolygonScan tarihin kowane zamani",
|
||||||
"wallet_seed_legacy": "Tallarin walat walat",
|
"wallet_seed_legacy": "Tallarin walat walat",
|
||||||
|
"default_sell_provider": "Tsohuwar Mai Bayar Siyarwa",
|
||||||
|
"select_sell_provider_notice": "Zaɓi mai bada siyarwa a sama. Kuna iya tsallake wannan allon ta saita mai bada siyar da ku a cikin saitunan app.",
|
||||||
"custom_drag": "Al'ada (riƙe da ja)",
|
"custom_drag": "Al'ada (riƙe da ja)",
|
||||||
"switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,6 +758,8 @@
|
||||||
"dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। अतिरिक्त केवाईसी के बिना 990€ तक। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए",
|
"dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। अतिरिक्त केवाईसी के बिना 990€ तक। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए",
|
||||||
"polygonscan_history": "पॉलीगॉनस्कैन इतिहास",
|
"polygonscan_history": "पॉलीगॉनस्कैन इतिहास",
|
||||||
"wallet_seed_legacy": "विरासत बटुए बीज",
|
"wallet_seed_legacy": "विरासत बटुए बीज",
|
||||||
|
"default_sell_provider": "डिफ़ॉल्ट विक्रय प्रदाता",
|
||||||
|
"select_sell_provider_notice": "ऊपर एक विक्रय प्रदाता का चयन करें। आप ऐप सेटिंग में अपना डिफ़ॉल्ट विक्रय प्रदाता सेट करके इस स्क्रीन को छोड़ सकते हैं।",
|
||||||
"custom_drag": "कस्टम (पकड़ और खींचें)",
|
"custom_drag": "कस्टम (पकड़ और खींचें)",
|
||||||
"switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)"
|
"switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -756,6 +756,8 @@
|
||||||
"dfx_option_description": "Kupujte kripto s EUR i CHF. Do 990 € bez dodatnog KYC-a. Za maloprodajne i poslovne korisnike u Europi",
|
"dfx_option_description": "Kupujte kripto s EUR i CHF. Do 990 € bez dodatnog KYC-a. Za maloprodajne i poslovne korisnike u Europi",
|
||||||
"polygonscan_history": "Povijest PolygonScan",
|
"polygonscan_history": "Povijest PolygonScan",
|
||||||
"wallet_seed_legacy": "Sjeme naslijeđenog novčanika",
|
"wallet_seed_legacy": "Sjeme naslijeđenog novčanika",
|
||||||
|
"default_sell_provider": "Zadani dobavljač prodaje",
|
||||||
|
"select_sell_provider_notice": "Gore odaberite pružatelja usluga prodaje. Ovaj zaslon možete preskočiti postavljanjem zadanog pružatelja usluga prodaje u postavkama aplikacije.",
|
||||||
"custom_drag": "Prilagođeni (držite i povucite)",
|
"custom_drag": "Prilagođeni (držite i povucite)",
|
||||||
"switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -746,6 +746,8 @@
|
||||||
"dfx_option_description": "Beli kripto dengan EUR & CHF. Hingga 990€ tanpa KYC tambahan. Untuk pelanggan ritel dan korporat di Eropa",
|
"dfx_option_description": "Beli kripto dengan EUR & CHF. Hingga 990€ tanpa KYC tambahan. Untuk pelanggan ritel dan korporat di Eropa",
|
||||||
"polygonscan_history": "Sejarah PolygonScan",
|
"polygonscan_history": "Sejarah PolygonScan",
|
||||||
"wallet_seed_legacy": "Biji dompet warisan",
|
"wallet_seed_legacy": "Biji dompet warisan",
|
||||||
|
"default_sell_provider": "Penyedia Penjualan Default",
|
||||||
|
"select_sell_provider_notice": "Pilih penyedia jual di atas. Anda dapat melewati layar ini dengan mengatur penyedia penjualan default Anda di pengaturan aplikasi.",
|
||||||
"custom_drag": "Khusus (tahan dan seret)",
|
"custom_drag": "Khusus (tahan dan seret)",
|
||||||
"switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,6 +758,8 @@
|
||||||
"dfx_option_description": "Acquista criptovalute con EUR e CHF. Fino a 990€ senza KYC aggiuntivi. Per clienti al dettaglio e aziendali in Europa",
|
"dfx_option_description": "Acquista criptovalute con EUR e CHF. Fino a 990€ senza KYC aggiuntivi. Per clienti al dettaglio e aziendali in Europa",
|
||||||
"polygonscan_history": "Cronologia PolygonScan",
|
"polygonscan_history": "Cronologia PolygonScan",
|
||||||
"wallet_seed_legacy": "Seme di portafoglio legacy",
|
"wallet_seed_legacy": "Seme di portafoglio legacy",
|
||||||
|
"default_sell_provider": "Fornitore di vendita predefinito",
|
||||||
|
"select_sell_provider_notice": "Seleziona un fornitore di vendita sopra. Puoi saltare questa schermata impostando il tuo fornitore di vendita predefinito nelle impostazioni dell'app.",
|
||||||
"custom_drag": "Custom (Hold and Drag)",
|
"custom_drag": "Custom (Hold and Drag)",
|
||||||
"switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,6 +758,8 @@
|
||||||
"dfx_option_description": "EUR と CHF で暗号通貨を購入します。追加のKYCなしで最大990ユーロ。ヨーロッパの小売および法人顧客向け",
|
"dfx_option_description": "EUR と CHF で暗号通貨を購入します。追加のKYCなしで最大990ユーロ。ヨーロッパの小売および法人顧客向け",
|
||||||
"polygonscan_history": "ポリゴンスキャン履歴",
|
"polygonscan_history": "ポリゴンスキャン履歴",
|
||||||
"wallet_seed_legacy": "レガシーウォレットシード",
|
"wallet_seed_legacy": "レガシーウォレットシード",
|
||||||
|
"default_sell_provider": "デフォルトの販売プロバイダー",
|
||||||
|
"select_sell_provider_notice": "上記の販売プロバイダーを選択してください。アプリ設定でデフォルトの販売プロバイダーを設定することで、この画面をスキップできます。",
|
||||||
"custom_drag": "カスタム(ホールドとドラッグ)",
|
"custom_drag": "カスタム(ホールドとドラッグ)",
|
||||||
"switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)"
|
"switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -756,6 +756,8 @@
|
||||||
"dfx_option_description": "EUR 및 CHF로 암호화폐를 구매하세요. 추가 KYC 없이 최대 990€. 유럽의 소매 및 기업 고객용",
|
"dfx_option_description": "EUR 및 CHF로 암호화폐를 구매하세요. 추가 KYC 없이 최대 990€. 유럽의 소매 및 기업 고객용",
|
||||||
"polygonscan_history": "다각형 스캔 기록",
|
"polygonscan_history": "다각형 스캔 기록",
|
||||||
"wallet_seed_legacy": "레거시 지갑 시드",
|
"wallet_seed_legacy": "레거시 지갑 시드",
|
||||||
|
"default_sell_provider": "기본 판매 공급자",
|
||||||
|
"select_sell_provider_notice": "위에서 판매 공급자를 선택하세요. 앱 설정에서 기본 판매 공급자를 설정하면 이 화면을 건너뛸 수 있습니다.",
|
||||||
"custom_drag": "사용자 정의 (홀드 앤 드래그)",
|
"custom_drag": "사용자 정의 (홀드 앤 드래그)",
|
||||||
"switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)"
|
"switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -756,6 +756,8 @@
|
||||||
"dfx_option_description": "EUR & CHF ဖြင့် crypto ကိုဝယ်ပါ။ အပို KYC မပါဘဲ 990€ အထိ။ ဥရောပရှိ လက်လီရောင်းချသူများနှင့် ကော်ပိုရိတ်ဖောက်သည်များအတွက်",
|
"dfx_option_description": "EUR & CHF ဖြင့် crypto ကိုဝယ်ပါ။ အပို KYC မပါဘဲ 990€ အထိ။ ဥရောပရှိ လက်လီရောင်းချသူများနှင့် ကော်ပိုရိတ်ဖောက်သည်များအတွက်",
|
||||||
"polygonscan_history": "PolygonScan မှတ်တမ်း",
|
"polygonscan_history": "PolygonScan မှတ်တမ်း",
|
||||||
"wallet_seed_legacy": "အမွေအနှစ်ပိုက်ဆံအိတ်မျိုးစေ့",
|
"wallet_seed_legacy": "အမွေအနှစ်ပိုက်ဆံအိတ်မျိုးစေ့",
|
||||||
|
"default_sell_provider": "ပုံသေရောင်းချပေးသူ",
|
||||||
|
"select_sell_provider_notice": "အထက်ဖော်ပြပါ အရောင်းဝန်ဆောင်မှုပေးသူကို ရွေးပါ။ အက်ပ်ဆက်တင်များတွင် သင်၏မူလရောင်းချပေးသူကို သတ်မှတ်ခြင်းဖြင့် ဤစခရင်ကို ကျော်နိုင်သည်။",
|
||||||
"custom_drag": "စိတ်ကြိုက် (Drag)",
|
"custom_drag": "စိတ်ကြိုက် (Drag)",
|
||||||
"switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)"
|
"switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,6 +758,8 @@
|
||||||
"dfx_option_description": "Koop crypto met EUR & CHF. Tot 990€ zonder extra KYC. Voor particuliere en zakelijke klanten in Europa",
|
"dfx_option_description": "Koop crypto met EUR & CHF. Tot 990€ zonder extra KYC. Voor particuliere en zakelijke klanten in Europa",
|
||||||
"polygonscan_history": "PolygonScan-geschiedenis",
|
"polygonscan_history": "PolygonScan-geschiedenis",
|
||||||
"wallet_seed_legacy": "Legacy portemonnee zaad",
|
"wallet_seed_legacy": "Legacy portemonnee zaad",
|
||||||
|
"default_sell_provider": "Standaard verkoopaanbieder",
|
||||||
|
"select_sell_provider_notice": "Selecteer hierboven een verkoopaanbieder. U kunt dit scherm overslaan door uw standaardverkoopprovider in te stellen in de app-instellingen.",
|
||||||
"custom_drag": "Custom (vasthouden en slepen)",
|
"custom_drag": "Custom (vasthouden en slepen)",
|
||||||
"switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,6 +758,8 @@
|
||||||
"dfx_option_description": "Kupuj kryptowaluty za EUR i CHF. Do 990 € bez dodatkowego KYC. Dla klientów detalicznych i korporacyjnych w Europie",
|
"dfx_option_description": "Kupuj kryptowaluty za EUR i CHF. Do 990 € bez dodatkowego KYC. Dla klientów detalicznych i korporacyjnych w Europie",
|
||||||
"polygonscan_history": "Historia PolygonScan",
|
"polygonscan_history": "Historia PolygonScan",
|
||||||
"wallet_seed_legacy": "Dziedziczne ziarno portfela",
|
"wallet_seed_legacy": "Dziedziczne ziarno portfela",
|
||||||
|
"default_sell_provider": "Domyślny dostawca sprzedaży",
|
||||||
|
"select_sell_provider_notice": "Wybierz dostawcę sprzedaży powyżej. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę sprzedaży w ustawieniach aplikacji.",
|
||||||
"custom_drag": "Niestandardowe (trzymaj i przeciągnij)",
|
"custom_drag": "Niestandardowe (trzymaj i przeciągnij)",
|
||||||
"switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -757,6 +757,8 @@
|
||||||
"dfx_option_description": "Compre criptografia com EUR e CHF. Até 990€ sem KYC adicional. Para clientes de varejo e corporativos na Europa",
|
"dfx_option_description": "Compre criptografia com EUR e CHF. Até 990€ sem KYC adicional. Para clientes de varejo e corporativos na Europa",
|
||||||
"polygonscan_history": "História do PolygonScan",
|
"polygonscan_history": "História do PolygonScan",
|
||||||
"wallet_seed_legacy": "Semente de carteira herdada",
|
"wallet_seed_legacy": "Semente de carteira herdada",
|
||||||
|
"default_sell_provider": "Provedor de venda padrão",
|
||||||
|
"select_sell_provider_notice": "Selecione um fornecedor de venda acima. Você pode pular esta tela definindo seu provedor de venda padrão nas configurações do aplicativo.",
|
||||||
"custom_drag": "Personalizado (segure e arraste)",
|
"custom_drag": "Personalizado (segure e arraste)",
|
||||||
"switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,6 +758,8 @@
|
||||||
"dfx_option_description": "Покупайте криптовалюту за EUR и CHF. До 990€ без дополнительного KYC. Для розничных и корпоративных клиентов в Европе",
|
"dfx_option_description": "Покупайте криптовалюту за EUR и CHF. До 990€ без дополнительного KYC. Для розничных и корпоративных клиентов в Европе",
|
||||||
"polygonscan_history": "История PolygonScan",
|
"polygonscan_history": "История PolygonScan",
|
||||||
"wallet_seed_legacy": "Наследие семя кошелька",
|
"wallet_seed_legacy": "Наследие семя кошелька",
|
||||||
|
"default_sell_provider": "Поставщик продаж по умолчанию",
|
||||||
|
"select_sell_provider_notice": "Выберите поставщика услуг продажи выше. Вы можете пропустить этот экран, установив поставщика услуг продаж по умолчанию в настройках приложения.",
|
||||||
"custom_drag": "Пользователь (удерживайте и перетаскивайте)",
|
"custom_drag": "Пользователь (удерживайте и перетаскивайте)",
|
||||||
"switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon)."
|
"switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon)."
|
||||||
}
|
}
|
||||||
|
|
|
@ -756,6 +756,8 @@
|
||||||
"dfx_option_description": "ซื้อ crypto ด้วย EUR และ CHF สูงถึง 990€ โดยไม่มี KYC เพิ่มเติม สำหรับลูกค้ารายย่อยและลูกค้าองค์กรในยุโรป",
|
"dfx_option_description": "ซื้อ crypto ด้วย EUR และ CHF สูงถึง 990€ โดยไม่มี KYC เพิ่มเติม สำหรับลูกค้ารายย่อยและลูกค้าองค์กรในยุโรป",
|
||||||
"polygonscan_history": "ประวัติ PolygonScan",
|
"polygonscan_history": "ประวัติ PolygonScan",
|
||||||
"wallet_seed_legacy": "เมล็ดกระเป๋าเงินมรดก",
|
"wallet_seed_legacy": "เมล็ดกระเป๋าเงินมรดก",
|
||||||
|
"default_sell_provider": "ผู้ให้บริการการขายเริ่มต้น",
|
||||||
|
"select_sell_provider_notice": "เลือกผู้ให้บริการการขายด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการการขายเริ่มต้นในการตั้งค่าแอป",
|
||||||
"custom_drag": "กำหนดเอง (ค้างและลาก)",
|
"custom_drag": "กำหนดเอง (ค้างและลาก)",
|
||||||
"switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -752,6 +752,8 @@
|
||||||
"dfx_option_description": "Bumili ng crypto gamit ang EUR at CHF. Hanggang 990€ nang walang karagdagang KYC. Para sa retail at corporate na mga customer sa Europe",
|
"dfx_option_description": "Bumili ng crypto gamit ang EUR at CHF. Hanggang 990€ nang walang karagdagang KYC. Para sa retail at corporate na mga customer sa Europe",
|
||||||
"polygonscan_history": "Kasaysayan ng PolygonScan",
|
"polygonscan_history": "Kasaysayan ng PolygonScan",
|
||||||
"wallet_seed_legacy": "Legacy wallet seed",
|
"wallet_seed_legacy": "Legacy wallet seed",
|
||||||
|
"default_sell_provider": "Default na Sell Provider",
|
||||||
|
"select_sell_provider_notice": "Pumili ng provider ng nagbebenta sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na sell provider sa mga setting ng app.",
|
||||||
"custom_drag": "Pasadyang (hawakan at i -drag)",
|
"custom_drag": "Pasadyang (hawakan at i -drag)",
|
||||||
"switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -756,6 +756,8 @@
|
||||||
"dfx_option_description": "EUR ve CHF ile kripto satın alın. Ek KYC olmadan 990 €'ya kadar. Avrupa'daki perakende ve kurumsal müşteriler için",
|
"dfx_option_description": "EUR ve CHF ile kripto satın alın. Ek KYC olmadan 990 €'ya kadar. Avrupa'daki perakende ve kurumsal müşteriler için",
|
||||||
"polygonscan_history": "PolygonScan geçmişi",
|
"polygonscan_history": "PolygonScan geçmişi",
|
||||||
"wallet_seed_legacy": "Eski cüzdan tohumu",
|
"wallet_seed_legacy": "Eski cüzdan tohumu",
|
||||||
|
"default_sell_provider": "Varsayılan Satış Sağlayıcısı",
|
||||||
|
"select_sell_provider_notice": "Yukarıdan bir satış sağlayıcısı seçin. Uygulama ayarlarında varsayılan satış sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.",
|
||||||
"custom_drag": "Özel (Bekle ve Sürükle)",
|
"custom_drag": "Özel (Bekle ve Sürükle)",
|
||||||
"switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,6 +758,8 @@
|
||||||
"seed_language_chinese_traditional": "Китайський (традиційний)",
|
"seed_language_chinese_traditional": "Китайський (традиційний)",
|
||||||
"polygonscan_history": "Історія PolygonScan",
|
"polygonscan_history": "Історія PolygonScan",
|
||||||
"wallet_seed_legacy": "Спадець насіння гаманця",
|
"wallet_seed_legacy": "Спадець насіння гаманця",
|
||||||
|
"default_sell_provider": "Постачальник продажу за замовчуванням",
|
||||||
|
"select_sell_provider_notice": "Виберіть вище постачальника послуг продажу. Ви можете пропустити цей екран, встановивши постачальника послуг продажу за умовчанням у налаштуваннях програми.",
|
||||||
"custom_drag": "На замовлення (утримуйте та перетягується)",
|
"custom_drag": "На замовлення (утримуйте та перетягується)",
|
||||||
"switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -750,6 +750,8 @@
|
||||||
"dfx_option_description": "EUR ﺭﻭﺍ CHF ﯽﻓﺎﺿﺍ ۔ﮟﯾﺪﯾﺮﺧ ﻮﭩﭘﺮﮐ ﮫﺗﺎﺳ ﮯﮐ KYC ﮯﯿﻟ ﮯﮐ ﻦﯿﻓﺭﺎﺻ ﭧﯾﺭﻮﭘﺭﺎﮐ ﺭﻭﺍ ﮦﺩﺭﻮﺧ ﮟ",
|
"dfx_option_description": "EUR ﺭﻭﺍ CHF ﯽﻓﺎﺿﺍ ۔ﮟﯾﺪﯾﺮﺧ ﻮﭩﭘﺮﮐ ﮫﺗﺎﺳ ﮯﮐ KYC ﮯﯿﻟ ﮯﮐ ﻦﯿﻓﺭﺎﺻ ﭧﯾﺭﻮﭘﺭﺎﮐ ﺭﻭﺍ ﮦﺩﺭﻮﺧ ﮟ",
|
||||||
"polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ",
|
"polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ",
|
||||||
"wallet_seed_legacy": "میراثی پرس کا بیج",
|
"wallet_seed_legacy": "میراثی پرس کا بیج",
|
||||||
|
"default_sell_provider": " ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ",
|
||||||
|
"select_sell_provider_notice": "۔ﮟﯿﮨ ﮯﺘﮑﺳ ﮌﻮﮭﭼ ﻮﮐ ﻦﯾﺮﮑﺳﺍ ﺱﺍ ﺮﮐ ﮮﺩ ﺐﯿﺗﺮﺗ ﻮﮐ ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ ﮯﻨﭘﺍ ﮟﯿﻣ ﺕﺎﺒ",
|
||||||
"custom_drag": "کسٹم (ہولڈ اینڈ ڈریگ)",
|
"custom_drag": "کسٹم (ہولڈ اینڈ ڈریگ)",
|
||||||
"switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ "
|
"switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ "
|
||||||
}
|
}
|
||||||
|
|
|
@ -752,6 +752,8 @@
|
||||||
"dfx_option_description": "Ra crypto pẹlu EUR & CHF. Titi di 990 € laisi afikun KYC. Fun soobu ati awọn onibara ile-iṣẹ ni Yuroopu",
|
"dfx_option_description": "Ra crypto pẹlu EUR & CHF. Titi di 990 € laisi afikun KYC. Fun soobu ati awọn onibara ile-iṣẹ ni Yuroopu",
|
||||||
"polygonscan_history": "PolygonScan itan",
|
"polygonscan_history": "PolygonScan itan",
|
||||||
"wallet_seed_legacy": "Irugbin akole",
|
"wallet_seed_legacy": "Irugbin akole",
|
||||||
|
"default_sell_provider": "Aiyipada Olupese Tita",
|
||||||
|
"select_sell_provider_notice": "Yan olupese ti o ta loke. O le foju iboju yii nipa tito olupese iṣẹ tita aiyipada rẹ ni awọn eto app.",
|
||||||
"custom_drag": "Aṣa (mu ati fa)",
|
"custom_drag": "Aṣa (mu ati fa)",
|
||||||
"switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -757,6 +757,8 @@
|
||||||
"dfx_option_description": "用欧元和瑞士法郎购买加密货币。高达 990 欧元,无需额外 KYC。对于欧洲的零售和企业客户",
|
"dfx_option_description": "用欧元和瑞士法郎购买加密货币。高达 990 欧元,无需额外 KYC。对于欧洲的零售和企业客户",
|
||||||
"polygonscan_history": "多边形扫描历史",
|
"polygonscan_history": "多边形扫描历史",
|
||||||
"wallet_seed_legacy": "旧的钱包种子",
|
"wallet_seed_legacy": "旧的钱包种子",
|
||||||
|
"default_sell_provider": "默认销售提供商",
|
||||||
|
"select_sell_provider_notice": "选择上面的销售提供商。您可以通过在应用程序设置中设置默认销售提供商来跳过此屏幕。",
|
||||||
"custom_drag": "定制(保持和拖动)",
|
"custom_drag": "定制(保持和拖动)",
|
||||||
"switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)"
|
"switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue