mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-03 09:29:48 +00:00
Merge branch 'main' into CW-529-Modify-2FA-introduction-screens
This commit is contained in:
commit
a5895e8832
76 changed files with 9627 additions and 492 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 |
|
@ -1,2 +1,4 @@
|
|||
Monero Polyseed support, create and restore from a 16 words phrase and without the need to remember the wallet creation date
|
||||
Bug fixes and enhancements
|
||||
Polyseed enhancements
|
||||
New on-ramp provider DFX
|
||||
Usability enhancements
|
||||
Bug fixes
|
|
@ -1,3 +1,2 @@
|
|||
Monero Polyseed support, create and restore from a 16 words phrase and without the need to remember the wallet creation date
|
||||
Add NFTs tab to see all of your purchased NFTs on Ethereum
|
||||
Bug fixes and enhancements
|
||||
Support multiple address types for Bitcoin Cash
|
||||
Bug fixes
|
8717
assets/text/cakewallet_weak_bitcoin_seeds_hashed_sorted_version1.txt
Normal file
8717
assets/text/cakewallet_weak_bitcoin_seeds_hashed_sorted_version1.txt
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,7 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:bitbox/bitbox.dart' as bitbox;
|
||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
|
||||
|
@ -210,9 +211,28 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
|||
txb.addInput(input.hash, input.vout);
|
||||
});
|
||||
|
||||
final String bchPrefix = "bitcoincash:";
|
||||
|
||||
outputs.forEach((item) {
|
||||
final outputAmount = hasMultiDestination ? item.formattedCryptoAmount : amount;
|
||||
final outputAddress = item.isParsedAddress ? item.extractedAddress! : item.address;
|
||||
String outputAddress = item.isParsedAddress ? item.extractedAddress! : item.address;
|
||||
|
||||
if (!outputAddress.startsWith(bchPrefix)) {
|
||||
outputAddress = "$bchPrefix$outputAddress";
|
||||
}
|
||||
|
||||
bool isP2sh = outputAddress.startsWith("p", bchPrefix.length);
|
||||
|
||||
if (isP2sh) {
|
||||
final p2sh = P2shAddress.fromAddress(
|
||||
address: outputAddress,
|
||||
network: BitcoinCashNetwork.mainnet,
|
||||
);
|
||||
|
||||
txb.addOutput(Uint8List.fromList(p2sh.toScriptPubKey().toBytes()), outputAmount!);
|
||||
return;
|
||||
}
|
||||
|
||||
txb.addOutput(outputAddress, outputAmount!);
|
||||
});
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ dependencies:
|
|||
git:
|
||||
url: https://github.com/cake-tech/bitbox-flutter.git
|
||||
ref: master
|
||||
bitcoin_base: ^3.0.1
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -245,7 +245,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
|
|||
}
|
||||
|
||||
static CryptoCurrency fromFullName(String name) {
|
||||
if (CryptoCurrency._fullNameCurrencyMap[name.toLowerCase()] == null) {
|
||||
if (CryptoCurrency._fullNameCurrencyMap[name.split("(").first.trim().toLowerCase()] == null) {
|
||||
final s = 'Unexpected token: $name for CryptoCurrency fromFullName';
|
||||
throw ArgumentError.value(name, 'Fullname', s);
|
||||
}
|
||||
|
|
|
@ -623,15 +623,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
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:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -122,6 +122,8 @@ PODS:
|
|||
- Flutter
|
||||
- MTBBarcodeScanner (5.0.11)
|
||||
- OrderedSet (5.0.0)
|
||||
- package_info (0.0.1):
|
||||
- Flutter
|
||||
- package_info_plus (0.4.5):
|
||||
- Flutter
|
||||
- path_provider_foundation (0.0.1):
|
||||
|
@ -143,8 +145,6 @@ PODS:
|
|||
- SwiftProtobuf (1.22.0)
|
||||
- SwiftyGif (5.4.4)
|
||||
- Toast (4.0.0)
|
||||
- tor (0.0.1):
|
||||
- Flutter
|
||||
- uni_links (0.0.1):
|
||||
- Flutter
|
||||
- UnstoppableDomainsResolution (4.0.0):
|
||||
|
@ -175,13 +175,13 @@ DEPENDENCIES:
|
|||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
||||
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
|
||||
- local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`)
|
||||
- package_info (from `.symlinks/plugins/package_info/ios`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||
- sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`)
|
||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- tor (from `.symlinks/plugins/tor/ios`)
|
||||
- uni_links (from `.symlinks/plugins/uni_links/ios`)
|
||||
- UnstoppableDomainsResolution (~> 4.0.0)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
|
@ -236,6 +236,8 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/in_app_review/ios"
|
||||
local_auth_ios:
|
||||
:path: ".symlinks/plugins/local_auth_ios/ios"
|
||||
package_info:
|
||||
:path: ".symlinks/plugins/package_info/ios"
|
||||
package_info_plus:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
path_provider_foundation:
|
||||
|
@ -248,8 +250,6 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/share_plus/ios"
|
||||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
tor:
|
||||
:path: ".symlinks/plugins/tor/ios"
|
||||
uni_links:
|
||||
:path: ".symlinks/plugins/uni_links/ios"
|
||||
url_launcher_ios:
|
||||
|
@ -282,6 +282,7 @@ SPEC CHECKSUMS:
|
|||
local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605
|
||||
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
||||
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
||||
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
|
||||
package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
|
||||
|
@ -293,7 +294,6 @@ SPEC CHECKSUMS:
|
|||
SwiftProtobuf: 40bd808372cb8706108f22d28f8ab4a6b9bc6989
|
||||
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
|
||||
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
||||
tor: 662a9f5b980b5c86decb8ba611de9bcd4c8286eb
|
||||
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
||||
UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841
|
||||
url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b
|
||||
|
|
|
@ -2,11 +2,11 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:cake_wallet/buy/buy_provider_description.dart';
|
||||
|
||||
class BuyException implements Exception {
|
||||
BuyException({required this.description, required this.text});
|
||||
BuyException({required this.title, required this.content});
|
||||
|
||||
final BuyProviderDescription description;
|
||||
final String text;
|
||||
final String title;
|
||||
final String content;
|
||||
|
||||
@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_provider_description.dart';
|
||||
import 'package:cake_wallet/buy/order.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
abstract class BuyProvider {
|
||||
BuyProvider({required this.wallet, required this.isTestEnvironment});
|
||||
BuyProvider({
|
||||
required this.wallet,
|
||||
required this.isTestEnvironment,
|
||||
});
|
||||
|
||||
final WalletBase wallet;
|
||||
final bool isTestEnvironment;
|
||||
|
||||
String get title;
|
||||
BuyProviderDescription get description;
|
||||
String get trackUrl;
|
||||
|
||||
WalletType get walletType => wallet.type;
|
||||
String get walletAddress => wallet.walletAddresses.address;
|
||||
String get walletId => wallet.id;
|
||||
String get buyOptionDescription;
|
||||
|
||||
String get sellOptionDescription;
|
||||
|
||||
String get lightIcon;
|
||||
|
||||
String get darkIcon;
|
||||
|
||||
@override
|
||||
String toString() => title;
|
||||
|
||||
Future<String> requestUrl(String amount, String sourceCurrency);
|
||||
Future<Order> findOrderById(String id);
|
||||
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency);
|
||||
Future<void> launchProvider(BuildContext context, bool? isBuyAction);
|
||||
|
||||
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 'package:cake_wallet/buy/buy_provider.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.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:url_launcher/url_launcher.dart';
|
||||
|
||||
class DFXBuyProvider {
|
||||
DFXBuyProvider({required WalletBase wallet}) : this._wallet = wallet;
|
||||
|
||||
final WalletBase _wallet;
|
||||
class DFXBuyProvider extends BuyProvider {
|
||||
DFXBuyProvider({required WalletBase wallet, bool isTestEnvironment = false})
|
||||
: super(wallet: wallet, isTestEnvironment: isTestEnvironment);
|
||||
|
||||
static const _baseUrl = 'api.dfx.swiss';
|
||||
static const _authPath = '/v1/auth/signMessage';
|
||||
|
@ -22,8 +22,23 @@ class DFXBuyProvider {
|
|||
static const _signInPath = '/v1/auth/signIn';
|
||||
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 {
|
||||
switch (_wallet.type) {
|
||||
switch (wallet.type) {
|
||||
case WalletType.bitcoin:
|
||||
return 'BTC';
|
||||
case WalletType.bitcoinCash:
|
||||
|
@ -35,12 +50,12 @@ class DFXBuyProvider {
|
|||
case WalletType.ethereum:
|
||||
return 'ETH';
|
||||
default:
|
||||
throw Exception("WalletType is not available for DFX ${_wallet.type}");
|
||||
throw Exception("WalletType is not available for DFX ${wallet.type}");
|
||||
}
|
||||
}
|
||||
|
||||
String get blockchain {
|
||||
switch (_wallet.type) {
|
||||
switch (wallet.type) {
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.bitcoinCash:
|
||||
case WalletType.litecoin:
|
||||
|
@ -50,12 +65,12 @@ class DFXBuyProvider {
|
|||
case WalletType.ethereum:
|
||||
return 'Ethereum';
|
||||
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 {
|
||||
final walletAddress = _wallet.walletAddresses.address;
|
||||
final walletAddress = wallet.walletAddresses.address;
|
||||
final uri = Uri.https(_baseUrl, _authPath, {'address': walletAddress});
|
||||
|
||||
var response = await http.get(uri, headers: {'accept': 'application/json'});
|
||||
|
@ -71,7 +86,7 @@ class DFXBuyProvider {
|
|||
|
||||
Future<String> signUp() async {
|
||||
final signMessage = getSignature(await getSignMessage());
|
||||
final walletAddress = _wallet.walletAddresses.address;
|
||||
final walletAddress = wallet.walletAddresses.address;
|
||||
|
||||
final requestBody = jsonEncode({
|
||||
'wallet': walletName,
|
||||
|
@ -86,6 +101,10 @@ class DFXBuyProvider {
|
|||
if (response.statusCode == 201) {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
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 {
|
||||
throw Exception(
|
||||
'Failed to sign up. Status: ${response.statusCode} ${response.body}');
|
||||
|
@ -94,7 +113,7 @@ class DFXBuyProvider {
|
|||
|
||||
Future<String> signIn() async {
|
||||
final signMessage = getSignature(await getSignMessage());
|
||||
final walletAddress = _wallet.walletAddresses.address;
|
||||
final walletAddress = wallet.walletAddresses.address;
|
||||
|
||||
final requestBody = jsonEncode({
|
||||
'address': walletAddress,
|
||||
|
@ -108,6 +127,10 @@ class DFXBuyProvider {
|
|||
if (response.statusCode == 201) {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
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 {
|
||||
throw Exception(
|
||||
'Failed to sign in. Status: ${response.statusCode} ${response.body}');
|
||||
|
@ -115,24 +138,25 @@ class DFXBuyProvider {
|
|||
}
|
||||
|
||||
String getSignature(String message) {
|
||||
switch (_wallet.type) {
|
||||
switch (wallet.type) {
|
||||
case WalletType.ethereum:
|
||||
return _wallet.signMessage(message);
|
||||
return wallet.signMessage(message);
|
||||
case WalletType.monero:
|
||||
case WalletType.litecoin:
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.bitcoinCash:
|
||||
return _wallet.signMessage(message,
|
||||
address: _wallet.walletAddresses.address);
|
||||
return wallet.signMessage(message,
|
||||
address: wallet.walletAddresses.address);
|
||||
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 {
|
||||
final assetOut = this.assetOut;
|
||||
final blockchain = this.blockchain;
|
||||
final actionType = isBuyAction == true ? '/buy' : '/sell';
|
||||
|
||||
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,
|
||||
'lang': 'en',
|
||||
'asset-out': assetOut,
|
||||
|
@ -156,8 +180,8 @@ class DFXBuyProvider {
|
|||
|
||||
if (await canLaunchUrl(uri)) {
|
||||
if (DeviceInfo.instance.isMobile) {
|
||||
Navigator.of(context).pushNamed(Routes.webViewPage,
|
||||
arguments: [S.of(context).buy, uri]);
|
||||
Navigator.of(context)
|
||||
.pushNamed(Routes.webViewPage, arguments: ["DFX Connect", uri]);
|
||||
} else {
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
import 'dart:convert';
|
||||
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/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:crypto/crypto.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:cake_wallet/buy/buy_amount.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/.secrets.g.dart' as secrets;
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class MoonPaySellProvider {
|
||||
MoonPaySellProvider({this.isTest = false})
|
||||
: baseUrl = isTest ? _baseTestUrl : _baseProductUrl;
|
||||
MoonPaySellProvider({required SettingsStore settingsStore,
|
||||
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 _baseProductUrl = 'sell.moonpay.com';
|
||||
|
||||
static String themeToMoonPayTheme(ThemeBase theme) {
|
||||
switch (theme.type) {
|
||||
case ThemeType.bright:
|
||||
return 'light';
|
||||
case ThemeType.light:
|
||||
return 'light';
|
||||
case ThemeType.dark:
|
||||
return 'dark';
|
||||
}
|
||||
}
|
||||
|
||||
static String get _apiKey => secrets.moonPayApiKey;
|
||||
static String get _secretKey => secrets.moonPaySecretKey;
|
||||
final bool isTest;
|
||||
final String baseUrl;
|
||||
|
||||
Future<Uri> requestUrl(
|
||||
{required CryptoCurrency currency,
|
||||
Future<Uri> requestUrl({
|
||||
required CryptoCurrency currency,
|
||||
required String refundWalletAddress,
|
||||
required SettingsStore settingsStore}) async {
|
||||
|
||||
required SettingsStore settingsStore,
|
||||
}) async {
|
||||
final customParams = {
|
||||
'theme': themeToMoonPayTheme(settingsStore.currentTheme),
|
||||
'language': settingsStore.languageCode,
|
||||
|
@ -50,11 +63,15 @@ class MoonPaySellProvider {
|
|||
};
|
||||
|
||||
final originalUri = Uri.https(
|
||||
baseUrl, '', <String, dynamic>{
|
||||
baseUrl,
|
||||
'',
|
||||
<String, dynamic>{
|
||||
'apiKey': _apiKey,
|
||||
'defaultBaseCurrencyCode': currency.toString().toLowerCase(),
|
||||
'refundWalletAddress': refundWalletAddress
|
||||
}..addAll(customParams));
|
||||
'refundWalletAddress': refundWalletAddress,
|
||||
}..addAll(customParams),
|
||||
);
|
||||
|
||||
final messageBytes = utf8.encode('?${originalUri.query}');
|
||||
final key = utf8.encode(_secretKey);
|
||||
final hmac = Hmac(sha256, key);
|
||||
|
@ -70,6 +87,38 @@ class MoonPaySellProvider {
|
|||
final signedUri = originalUri.replace(queryParameters: query);
|
||||
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 {
|
||||
|
@ -88,20 +137,24 @@ class MoonPayBuyProvider extends BuyProvider {
|
|||
static const _secretKey = secrets.moonPaySecretKey;
|
||||
|
||||
@override
|
||||
String get title => 'MoonPay';
|
||||
String get title => 'Moon Pay';
|
||||
|
||||
@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 =>
|
||||
walletTypeToCryptoCurrency(walletType).title.toLowerCase();
|
||||
walletTypeToCryptoCurrency(wallet.type).title.toLowerCase();
|
||||
|
||||
@override
|
||||
String get trackUrl => baseUrl + '/transaction_receipt?transactionId=';
|
||||
|
||||
String baseUrl;
|
||||
|
||||
@override
|
||||
Future<String> requestUrl(String amount, String sourceCurrency) async {
|
||||
final enabledPaymentMethods =
|
||||
'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay'
|
||||
|
@ -109,7 +162,7 @@ class MoonPayBuyProvider extends BuyProvider {
|
|||
|
||||
final suffix = '?apiKey=' + _apiKey + '¤cyCode=' +
|
||||
currencyCode + '&enabledPaymentMethods=' + enabledPaymentMethods +
|
||||
'&walletAddress=' + walletAddress +
|
||||
'&walletAddress=' + wallet.walletAddresses.address +
|
||||
'&baseCurrencyCode=' + sourceCurrency.toLowerCase() +
|
||||
'&baseCurrencyAmount=' + amount + '&lockAmount=true' +
|
||||
'&showAllCurrencies=false' + '&showWalletAddressForm=false';
|
||||
|
@ -127,7 +180,6 @@ class MoonPayBuyProvider extends BuyProvider {
|
|||
return isTestEnvironment ? originalUrl : urlWithSignature;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) async {
|
||||
final url = _apiUrl + _currenciesSuffix + '/$currencyCode' +
|
||||
_quoteSuffix + '/?apiKey=' + _apiKey +
|
||||
|
@ -138,8 +190,8 @@ class MoonPayBuyProvider extends BuyProvider {
|
|||
|
||||
if (response.statusCode != 200) {
|
||||
throw BuyException(
|
||||
description: description,
|
||||
text: 'Quote is not found!');
|
||||
title: buyOptionDescription,
|
||||
content: 'Quote is not found!');
|
||||
}
|
||||
|
||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||
|
@ -153,7 +205,6 @@ class MoonPayBuyProvider extends BuyProvider {
|
|||
minAmount: minSourceAmount);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Order> findOrderById(String id) async {
|
||||
final url = _apiUrl + _transactionsSuffix + '/$id' +
|
||||
'?apiKey=' + _apiKey;
|
||||
|
@ -162,8 +213,8 @@ class MoonPayBuyProvider extends BuyProvider {
|
|||
|
||||
if (response.statusCode != 200) {
|
||||
throw BuyException(
|
||||
description: description,
|
||||
text: 'Transaction $id is not found!');
|
||||
title: buyOptionDescription,
|
||||
content: 'Transaction $id is not found!');
|
||||
}
|
||||
|
||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||
|
@ -175,13 +226,13 @@ class MoonPayBuyProvider extends BuyProvider {
|
|||
|
||||
return Order(
|
||||
id: id,
|
||||
provider: description,
|
||||
provider: BuyProviderDescription.moonPay,
|
||||
transferId: id,
|
||||
state: state,
|
||||
createdAt: createdAt,
|
||||
amount: amount.toString(),
|
||||
receiveAddress: walletAddress,
|
||||
walletId: walletId
|
||||
receiveAddress: wallet.walletAddresses.address,
|
||||
walletId: wallet.id
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -201,4 +252,14 @@ class MoonPayBuyProvider extends BuyProvider {
|
|||
|
||||
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/buy/buy_provider.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.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:url_launcher/url_launcher.dart';
|
||||
|
||||
class OnRamperBuyProvider {
|
||||
OnRamperBuyProvider({required SettingsStore settingsStore, required WalletBase wallet})
|
||||
: this._settingsStore = settingsStore,
|
||||
this._wallet = wallet;
|
||||
|
||||
final SettingsStore _settingsStore;
|
||||
final WalletBase _wallet;
|
||||
class OnRamperBuyProvider extends BuyProvider {
|
||||
OnRamperBuyProvider(this._settingsStore,
|
||||
{required WalletBase wallet, bool isTestEnvironment = false})
|
||||
: super(wallet: wallet, isTestEnvironment: isTestEnvironment);
|
||||
|
||||
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 _normalizeCryptoCurrency {
|
||||
switch (_wallet.currency) {
|
||||
switch (wallet.currency) {
|
||||
case CryptoCurrency.ltc:
|
||||
return "LTC_LITECOIN";
|
||||
case CryptoCurrency.xmr:
|
||||
|
@ -32,7 +47,7 @@ class OnRamperBuyProvider {
|
|||
case CryptoCurrency.nano:
|
||||
return "XNO_NANO";
|
||||
default:
|
||||
return _wallet.currency.title;
|
||||
return wallet.currency.title;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +55,7 @@ class OnRamperBuyProvider {
|
|||
return color.value.toRadixString(16).replaceAll(RegExp(r'^ff'), "");
|
||||
}
|
||||
|
||||
Uri requestUrl(BuildContext context) {
|
||||
Uri requestOnramperUrl(BuildContext context) {
|
||||
String primaryColor,
|
||||
secondaryColor,
|
||||
primaryTextColor,
|
||||
|
@ -50,9 +65,10 @@ class OnRamperBuyProvider {
|
|||
|
||||
primaryColor = getColorStr(Theme.of(context).primaryColor);
|
||||
secondaryColor = getColorStr(Theme.of(context).colorScheme.background);
|
||||
primaryTextColor = getColorStr(Theme.of(context).extension<CakeTextTheme>()!.titleColor);
|
||||
secondaryTextColor =
|
||||
getColorStr(Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor);
|
||||
primaryTextColor =
|
||||
getColorStr(Theme.of(context).extension<CakeTextTheme>()!.titleColor);
|
||||
secondaryTextColor = getColorStr(
|
||||
Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor);
|
||||
containerColor = getColorStr(Theme.of(context).colorScheme.background);
|
||||
cardColor = getColorStr(Theme.of(context).cardColor);
|
||||
|
||||
|
@ -60,12 +76,13 @@ class OnRamperBuyProvider {
|
|||
cardColor = getColorStr(Colors.white);
|
||||
}
|
||||
|
||||
final networkName = _wallet.currency.fullName?.toUpperCase().replaceAll(" ", "");
|
||||
final networkName =
|
||||
wallet.currency.fullName?.toUpperCase().replaceAll(" ", "");
|
||||
|
||||
return Uri.https(_baseUrl, '', <String, dynamic>{
|
||||
'apiKey': _apiKey,
|
||||
'defaultCrypto': _normalizeCryptoCurrency,
|
||||
'networkWallets': '${networkName}:${_wallet.walletAddresses.address}',
|
||||
'networkWallets': '${networkName}:${wallet.walletAddresses.address}',
|
||||
'supportSell': "false",
|
||||
'supportSwap': "false",
|
||||
'primaryColor': primaryColor,
|
||||
|
@ -77,10 +94,11 @@ class OnRamperBuyProvider {
|
|||
});
|
||||
}
|
||||
|
||||
Future<void> launchProvider(BuildContext context) async {
|
||||
final uri = requestUrl(context);
|
||||
Future<void> launchProvider(BuildContext context, bool? isBuyAction) async {
|
||||
final uri = requestOnramperUrl(context);
|
||||
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 {
|
||||
await launchUrl(uri);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
import 'dart:convert';
|
||||
|
||||
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/src/widgets/alert_with_one_action.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:url_launcher/url_launcher.dart';
|
||||
|
||||
class RobinhoodBuyProvider {
|
||||
RobinhoodBuyProvider({required WalletBase wallet}) : this._wallet = wallet;
|
||||
|
||||
final WalletBase _wallet;
|
||||
class RobinhoodBuyProvider extends BuyProvider{
|
||||
RobinhoodBuyProvider({required WalletBase wallet, bool isTestEnvironment = false})
|
||||
: super(wallet: wallet, isTestEnvironment: isTestEnvironment);
|
||||
|
||||
static const _baseUrl = 'applink.robinhood.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 _apiSecret => secrets.robinhoodCIdApiSecret;
|
||||
|
||||
bool get isAvailable => [
|
||||
WalletType.bitcoin,
|
||||
WalletType.bitcoinCash,
|
||||
WalletType.litecoin,
|
||||
WalletType.ethereum
|
||||
].contains(_wallet.type);
|
||||
|
||||
String getSignature(String message) {
|
||||
switch (_wallet.type) {
|
||||
switch (wallet.type) {
|
||||
case WalletType.ethereum:
|
||||
return _wallet.signMessage(message);
|
||||
return wallet.signMessage(message);
|
||||
case WalletType.litecoin:
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.bitcoinCash:
|
||||
return _wallet.signMessage(message, address: _wallet.walletAddresses.address);
|
||||
return wallet.signMessage(message, address: wallet.walletAddresses.address);
|
||||
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 {
|
||||
final walletAddress = _wallet.walletAddresses.address;
|
||||
final walletAddress = wallet.walletAddresses.address;
|
||||
final valid_until = (DateTime.now().millisecondsSinceEpoch / 1000).round() + 10;
|
||||
final message = "$_apiSecret:${valid_until}";
|
||||
|
||||
|
@ -64,22 +76,22 @@ class RobinhoodBuyProvider {
|
|||
}
|
||||
}
|
||||
|
||||
Future<Uri> requestUrl() async {
|
||||
Future<Uri> requestProviderUrl() async {
|
||||
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>{
|
||||
'applicationId': _applicationId,
|
||||
'connectId': connectId,
|
||||
'walletAddress': _wallet.walletAddresses.address,
|
||||
'userIdentifier': _wallet.walletAddresses.address,
|
||||
'walletAddress': wallet.walletAddresses.address,
|
||||
'userIdentifier': wallet.walletAddresses.address,
|
||||
'supportedNetworks': networkName
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> launchProvider(BuildContext context) async {
|
||||
Future<void> launchProvider(BuildContext context, bool? isBuyAction) async {
|
||||
try {
|
||||
final uri = await requestUrl();
|
||||
final uri = await requestProviderUrl();
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
} catch (_) {
|
||||
await showPopUp<void>(
|
||||
|
@ -93,4 +105,5 @@ class RobinhoodBuyProvider {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:convert';
|
||||
import 'package:cake_wallet/buy/buy_exception.dart';
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:cake_wallet/buy/buy_amount.dart';
|
||||
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||
|
@ -35,16 +36,20 @@ class WyreBuyProvider extends BuyProvider {
|
|||
String get title => 'Wyre';
|
||||
|
||||
@override
|
||||
BuyProviderDescription get description => BuyProviderDescription.wyre;
|
||||
String get buyOptionDescription => '';
|
||||
|
||||
@override
|
||||
String get lightIcon => 'assets/images/robinhood_light.png';
|
||||
|
||||
@override
|
||||
String get darkIcon => 'assets/images/robinhood_dark.png';
|
||||
|
||||
String get trackUrl => isTestEnvironment
|
||||
? _trackTestUrl
|
||||
: _trackProductUrl;
|
||||
|
||||
String baseApiUrl;
|
||||
|
||||
@override
|
||||
Future<String> requestUrl(String amount, String sourceCurrency) async {
|
||||
final timestamp = DateTime.now().millisecondsSinceEpoch.toString();
|
||||
final url = baseApiUrl + _ordersSuffix + _reserveSuffix +
|
||||
|
@ -53,8 +58,8 @@ class WyreBuyProvider extends BuyProvider {
|
|||
final body = {
|
||||
'amount': amount,
|
||||
'sourceCurrency': sourceCurrency,
|
||||
'destCurrency': walletTypeToCryptoCurrency(walletType).title,
|
||||
'dest': walletTypeToString(walletType).toLowerCase() + ':' + walletAddress,
|
||||
'destCurrency': walletTypeToCryptoCurrency(wallet.type).title,
|
||||
'dest': walletTypeToString(wallet.type).toLowerCase() + ':' + wallet.walletAddresses.address,
|
||||
'referrerAccountId': _accountId,
|
||||
'lockFields': ['amount', 'sourceCurrency', 'destCurrency', 'dest']
|
||||
};
|
||||
|
@ -68,8 +73,8 @@ class WyreBuyProvider extends BuyProvider {
|
|||
|
||||
if (response.statusCode != 200) {
|
||||
throw BuyException(
|
||||
description: description,
|
||||
text: 'Url $url is not found!');
|
||||
title: buyOptionDescription,
|
||||
content: 'Url $url is not found!');
|
||||
}
|
||||
|
||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||
|
@ -77,14 +82,13 @@ class WyreBuyProvider extends BuyProvider {
|
|||
return urlFromResponse;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) async {
|
||||
final quoteUrl = _baseProductApiUrl + _ordersSuffix + _quoteSuffix;
|
||||
final body = {
|
||||
'amount': amount,
|
||||
'sourceCurrency': sourceCurrency,
|
||||
'destCurrency': walletTypeToCryptoCurrency(walletType).title,
|
||||
'dest': walletTypeToString(walletType).toLowerCase() + ':' + walletAddress,
|
||||
'destCurrency': walletTypeToCryptoCurrency(wallet.type).title,
|
||||
'dest': walletTypeToString(wallet.type).toLowerCase() + ':' + wallet.walletAddresses.address,
|
||||
'accountId': _accountId,
|
||||
'country': _countryCode
|
||||
};
|
||||
|
@ -99,8 +103,8 @@ class WyreBuyProvider extends BuyProvider {
|
|||
|
||||
if (response.statusCode != 200) {
|
||||
throw BuyException(
|
||||
description: description,
|
||||
text: 'Quote is not found!');
|
||||
title: buyOptionDescription,
|
||||
content: 'Quote is not found!');
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Order> findOrderById(String id) async {
|
||||
final orderUrl = baseApiUrl + _ordersSuffix + '/$id';
|
||||
final orderUri = Uri.parse(orderUrl);
|
||||
|
@ -119,8 +122,8 @@ class WyreBuyProvider extends BuyProvider {
|
|||
|
||||
if (orderResponse.statusCode != 200) {
|
||||
throw BuyException(
|
||||
description: description,
|
||||
text: 'Order $id is not found!');
|
||||
title: buyOptionDescription,
|
||||
content: 'Order $id is not found!');
|
||||
}
|
||||
|
||||
final orderResponseJSON =
|
||||
|
@ -141,8 +144,8 @@ class WyreBuyProvider extends BuyProvider {
|
|||
|
||||
if (transferResponse.statusCode != 200) {
|
||||
throw BuyException(
|
||||
description: description,
|
||||
text: 'Transfer $transferId is not found!');
|
||||
title: buyOptionDescription,
|
||||
content: 'Transfer $transferId is not found!');
|
||||
}
|
||||
|
||||
final transferResponseJSON =
|
||||
|
@ -151,15 +154,25 @@ class WyreBuyProvider extends BuyProvider {
|
|||
|
||||
return Order(
|
||||
id: id,
|
||||
provider: description,
|
||||
provider: BuyProviderDescription.wyre,
|
||||
transferId: transferId,
|
||||
from: from,
|
||||
to: to,
|
||||
state: state,
|
||||
createdAt: createdAt,
|
||||
amount: amount.toString(),
|
||||
receiveAddress: walletAddress,
|
||||
walletId: walletId
|
||||
receiveAddress: wallet.walletAddresses.address,
|
||||
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();
|
||||
}
|
|
@ -92,7 +92,7 @@ class AddressValidator extends TextValidator {
|
|||
case CryptoCurrency.eos:
|
||||
return '[0-9a-zA-Z]';
|
||||
case CryptoCurrency.bch:
|
||||
return '^(?!bitcoincash:)[0-9a-zA-Z]*\$|^(?!bitcoincash:)q[0-9a-zA-Z]{41}\$|^(?!bitcoincash:)q[0-9a-zA-Z]{42}\$|^bitcoincash:q[0-9a-zA-Z]{41}\$|^bitcoincash:q[0-9a-zA-Z]{42}\$';
|
||||
return '^(?!bitcoincash:)[0-9a-zA-Z]*\$|^(?!bitcoincash:)q|p[0-9a-zA-Z]{41}\$|^(?!bitcoincash:)q|p[0-9a-zA-Z]{42}\$|^bitcoincash:q|p[0-9a-zA-Z]{41}\$|^bitcoincash:q|p[0-9a-zA-Z]{42}\$';
|
||||
case CryptoCurrency.bnb:
|
||||
return '[0-9a-zA-Z]';
|
||||
case CryptoCurrency.ltc:
|
||||
|
|
|
@ -138,7 +138,7 @@ class EvmChainServiceImpl implements ChainService {
|
|||
try {
|
||||
// Load the private key
|
||||
final List<ChainKeyModel> keys = wcKeyService
|
||||
.getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type));
|
||||
.getKeysForChain(appStore.wallet!);
|
||||
|
||||
final Credentials credentials = EthPrivateKey.fromHex(keys[0].privateKey);
|
||||
|
||||
|
@ -177,7 +177,7 @@ class EvmChainServiceImpl implements ChainService {
|
|||
try {
|
||||
// Load the private key
|
||||
final List<ChainKeyModel> keys = wcKeyService
|
||||
.getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type));
|
||||
.getKeysForChain(appStore.wallet!);
|
||||
|
||||
final EthPrivateKey credentials = EthPrivateKey.fromHex(keys[0].privateKey);
|
||||
|
||||
|
@ -215,7 +215,7 @@ class EvmChainServiceImpl implements ChainService {
|
|||
|
||||
// Load the private key
|
||||
final List<ChainKeyModel> keys = wcKeyService
|
||||
.getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type));
|
||||
.getKeysForChain(appStore.wallet!);
|
||||
|
||||
final Credentials credentials = EthPrivateKey.fromHex(keys[0].privateKey);
|
||||
|
||||
|
@ -275,7 +275,7 @@ class EvmChainServiceImpl implements ChainService {
|
|||
}
|
||||
|
||||
final List<ChainKeyModel> keys = wcKeyService
|
||||
.getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type));
|
||||
.getKeysForChain(appStore.wallet!);
|
||||
|
||||
return EthSigUtil.signTypedData(
|
||||
privateKey: keys[0].privateKey,
|
||||
|
|
|
@ -1,48 +1,22 @@
|
|||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cw_core/balance.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
|
||||
abstract class WalletConnectKeyService {
|
||||
/// Returns a list of all the keys.
|
||||
List<ChainKeyModel> getKeys();
|
||||
|
||||
/// Returns a list of all the chain ids.
|
||||
List<String> getChains();
|
||||
List<ChainKeyModel> getKeys(WalletBase wallet);
|
||||
|
||||
/// Returns a list of all the keys for a given chain id.
|
||||
/// If the chain is not found, returns an empty list.
|
||||
/// - [chain]: The chain to get the keys for.
|
||||
List<ChainKeyModel> getKeysForChain(String chain);
|
||||
List<ChainKeyModel> getKeysForChain(WalletBase wallet);
|
||||
|
||||
/// Returns a list of all the accounts in namespace:chainId:address format.
|
||||
List<String> getAllAccounts();
|
||||
}
|
||||
|
||||
class KeyServiceImpl implements WalletConnectKeyService {
|
||||
KeyServiceImpl(this.wallet)
|
||||
: _keys = [
|
||||
ChainKeyModel(
|
||||
chains: [
|
||||
'eip155:1',
|
||||
'eip155:5',
|
||||
'eip155:137',
|
||||
'eip155:42161',
|
||||
'eip155:80001',
|
||||
],
|
||||
privateKey: _getPrivateKeyForWallet(wallet),
|
||||
publicKey: _getPublicKeyForWallet(wallet),
|
||||
),
|
||||
];
|
||||
|
||||
late final WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet;
|
||||
|
||||
late final List<ChainKeyModel> _keys;
|
||||
|
||||
static String _getPrivateKeyForWallet(WalletBase wallet) {
|
||||
switch (wallet.type) {
|
||||
case WalletType.ethereum:
|
||||
|
@ -64,31 +38,31 @@ class KeyServiceImpl implements WalletConnectKeyService {
|
|||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
List<String> getChains() {
|
||||
final List<String> chainIds = [];
|
||||
for (final ChainKeyModel key in _keys) {
|
||||
chainIds.addAll(key.chains);
|
||||
}
|
||||
return chainIds;
|
||||
List<ChainKeyModel> getKeys(WalletBase wallet) {
|
||||
final keys = [
|
||||
ChainKeyModel(
|
||||
chains: [
|
||||
'eip155:1',
|
||||
'eip155:5',
|
||||
'eip155:137',
|
||||
'eip155:42161',
|
||||
'eip155:80001',
|
||||
],
|
||||
privateKey: _getPrivateKeyForWallet(wallet),
|
||||
publicKey: _getPublicKeyForWallet(wallet),
|
||||
),
|
||||
];
|
||||
return keys;
|
||||
}
|
||||
|
||||
@override
|
||||
List<ChainKeyModel> getKeys() => _keys;
|
||||
List<ChainKeyModel> getKeysForChain(WalletBase wallet) {
|
||||
final chain = getChainNameSpaceAndIdBasedOnWalletType(wallet.type);
|
||||
|
||||
@override
|
||||
List<ChainKeyModel> getKeysForChain(String chain) {
|
||||
return _keys.where((e) => e.chains.contains(chain)).toList();
|
||||
}
|
||||
final keys = getKeys(wallet);
|
||||
|
||||
@override
|
||||
List<String> getAllAccounts() {
|
||||
final List<String> accounts = [];
|
||||
for (final ChainKeyModel key in _keys) {
|
||||
for (final String chain in key.chains) {
|
||||
accounts.add('$chain:${key.publicKey}');
|
||||
}
|
||||
}
|
||||
return accounts;
|
||||
return keys.where((e) => e.chains.contains(chain)).toList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ abstract class Web3WalletServiceBase with Store {
|
|||
);
|
||||
|
||||
// Setup our accounts
|
||||
List<ChainKeyModel> chainKeys = walletKeyService.getKeys();
|
||||
List<ChainKeyModel> chainKeys = walletKeyService.getKeys(appStore.wallet!);
|
||||
for (final chainKey in chainKeys) {
|
||||
for (final chainId in chainKey.chains) {
|
||||
_web3Wallet.registerAccount(
|
||||
|
@ -136,6 +136,7 @@ abstract class Web3WalletServiceBase with Store {
|
|||
_web3Wallet.onAuthRequest.unsubscribe(_onAuthRequest);
|
||||
_web3Wallet.core.pairing.onPairingDelete.unsubscribe(_onPairingDelete);
|
||||
_web3Wallet.core.pairing.onPairingExpire.unsubscribe(_onPairingDelete);
|
||||
isInitialized = false;
|
||||
}
|
||||
|
||||
Web3Wallet getWeb3Wallet() {
|
||||
|
@ -236,7 +237,7 @@ abstract class Web3WalletServiceBase with Store {
|
|||
Future<void> _onAuthRequest(AuthRequest? args) async {
|
||||
if (args != null) {
|
||||
final chaindIdNamespace = getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type);
|
||||
List<ChainKeyModel> chainKeys = walletKeyService.getKeysForChain(chaindIdNamespace);
|
||||
List<ChainKeyModel> chainKeys = walletKeyService.getKeysForChain(appStore.wallet!);
|
||||
// Create the message to be signed
|
||||
final String iss = 'did:pkh:$chaindIdNamespace:${chainKeys.first.publicKey}';
|
||||
final Widget modalWidget = Web3RequestModal(
|
||||
|
|
19
lib/di.dart
19
lib/di.dart
|
@ -1,6 +1,7 @@
|
|||
import 'package:cake_wallet/anonpay/anonpay_api.dart';
|
||||
import 'package:cake_wallet/anonpay/anonpay_info_base.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/bitcoin_cash/bitcoin_cash.dart';
|
||||
import 'package:cake_wallet/buy/payfura/payfura_buy_provider.dart';
|
||||
|
@ -378,7 +379,8 @@ Future<void> setup({
|
|||
settingsStore: settingsStore,
|
||||
yatStore: getIt.get<YatStore>(),
|
||||
ordersStore: getIt.get<OrdersStore>(),
|
||||
anonpayTransactionsStore: getIt.get<AnonpayTransactionsStore>()));
|
||||
anonpayTransactionsStore: getIt.get<AnonpayTransactionsStore>(),
|
||||
keyService: getIt.get<KeyService>()));
|
||||
|
||||
getIt.registerFactory<AuthService>(
|
||||
() => AuthService(
|
||||
|
@ -477,7 +479,7 @@ Future<void> setup({
|
|||
|
||||
final appStore = getIt.get<AppStore>();
|
||||
|
||||
getIt.registerLazySingleton<WalletConnectKeyService>(() => KeyServiceImpl(appStore.wallet!));
|
||||
getIt.registerLazySingleton<WalletConnectKeyService>(() => KeyServiceImpl());
|
||||
|
||||
getIt.registerLazySingleton<Web3WalletService>(() {
|
||||
final Web3WalletService web3WalletService = Web3WalletService(
|
||||
|
@ -796,11 +798,15 @@ Future<void> setup({
|
|||
getIt.registerFactory<RobinhoodBuyProvider>(
|
||||
() => RobinhoodBuyProvider(wallet: getIt.get<AppStore>().wallet!));
|
||||
|
||||
getIt.registerFactory<DFXBuyProvider>(
|
||||
() => DFXBuyProvider(wallet: getIt.get<AppStore>().wallet!));
|
||||
getIt
|
||||
.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(
|
||||
settingsStore: getIt.get<AppStore>().settingsStore,
|
||||
getIt.get<AppStore>().settingsStore,
|
||||
wallet: getIt.get<AppStore>().wallet!,
|
||||
));
|
||||
|
||||
|
@ -944,7 +950,8 @@ Future<void> setup({
|
|||
|
||||
getIt.registerFactory(() => BuyAmountViewModel());
|
||||
|
||||
getIt.registerFactory(() => BuyOptionsPage(getIt.get<DashboardViewModel>()));
|
||||
getIt.registerFactoryParam<BuySellOptionsPage, bool, void>(
|
||||
(isBuyOption, _) => BuySellOptionsPage(getIt.get<DashboardViewModel>(), isBuyOption));
|
||||
|
||||
getIt.registerFactory(() {
|
||||
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';
|
||||
|
||||
enum BuyProviderType {
|
||||
AskEachTime,
|
||||
Robinhood,
|
||||
Onramper,
|
||||
DFX;
|
||||
askEachTime,
|
||||
robinhood,
|
||||
dfx,
|
||||
onramper,
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
extension BuyProviderTypeName on BuyProviderType {
|
||||
String get name {
|
||||
switch (this) {
|
||||
case BuyProviderType.AskEachTime:
|
||||
return S.current.ask_each_time;
|
||||
case BuyProviderType.Robinhood:
|
||||
return "Robinhood";
|
||||
case BuyProviderType.Onramper:
|
||||
return "Onramper";
|
||||
case BuyProviderType.DFX:
|
||||
return "DFX";
|
||||
case BuyProviderType.askEachTime:
|
||||
return 'Ask each time';
|
||||
case BuyProviderType.robinhood:
|
||||
return 'Robinhood Connect';
|
||||
case BuyProviderType.dfx:
|
||||
return 'DFX Connect';
|
||||
case BuyProviderType.onramper:
|
||||
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) {
|
||||
case WalletType.nano:
|
||||
case WalletType.banano:
|
||||
return [
|
||||
BuyProviderType.AskEachTime,
|
||||
BuyProviderType.Onramper
|
||||
];
|
||||
return [BuyProviderType.askEachTime, BuyProviderType.onramper];
|
||||
case WalletType.monero:
|
||||
return [
|
||||
BuyProviderType.AskEachTime,
|
||||
BuyProviderType.Onramper,
|
||||
BuyProviderType.DFX
|
||||
BuyProviderType.askEachTime,
|
||||
BuyProviderType.onramper,
|
||||
BuyProviderType.dfx
|
||||
];
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.ethereum:
|
||||
return [
|
||||
BuyProviderType.AskEachTime,
|
||||
BuyProviderType.Onramper,
|
||||
BuyProviderType.DFX,
|
||||
BuyProviderType.Robinhood
|
||||
BuyProviderType.askEachTime,
|
||||
BuyProviderType.onramper,
|
||||
BuyProviderType.dfx,
|
||||
BuyProviderType.robinhood
|
||||
];
|
||||
case WalletType.litecoin:
|
||||
case WalletType.bitcoinCash:
|
||||
return [
|
||||
BuyProviderType.AskEachTime,
|
||||
BuyProviderType.Onramper,
|
||||
BuyProviderType.Robinhood
|
||||
BuyProviderType.askEachTime,
|
||||
BuyProviderType.onramper,
|
||||
BuyProviderType.robinhood
|
||||
];
|
||||
default:
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ Future<void> loadCurrentWallet() async {
|
|||
final type = deserializeFromInt(typeRaw);
|
||||
final walletLoadingService = getIt.get<WalletLoadingService>();
|
||||
final wallet = await walletLoadingService.load(type, name);
|
||||
appStore.changeCurrentWallet(wallet);
|
||||
await appStore.changeCurrentWallet(wallet);
|
||||
|
||||
getIt.get<BackgroundTasks>().registerSyncTask();
|
||||
}
|
||||
|
|
|
@ -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/routes.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/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class MainActions {
|
||||
final String Function(BuildContext context) name;
|
||||
|
@ -46,53 +37,22 @@ class MainActions {
|
|||
canShow: (viewModel) => viewModel.hasBuyAction,
|
||||
onTap: (BuildContext context, DashboardViewModel viewModel) async {
|
||||
if (!viewModel.isEnabledBuyAction) {
|
||||
await _showErrorDialog(context, S.of(context).unsupported_asset);
|
||||
await _showErrorDialog(
|
||||
context, S.of(context).buy, S.of(context).unsupported_asset);
|
||||
return;
|
||||
}
|
||||
|
||||
final defaultBuyProvider = viewModel.defaultBuyProvider;
|
||||
try {
|
||||
await _launchProviderByType(context, defaultBuyProvider);
|
||||
defaultBuyProvider != null
|
||||
? await defaultBuyProvider.launchProvider(context, true)
|
||||
: await Navigator.of(context).pushNamed(Routes.buySellPage, arguments: true);
|
||||
} 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._(
|
||||
name: (context) => S.of(context).receive,
|
||||
image: 'assets/images/received.png',
|
||||
|
@ -127,42 +87,35 @@ class MainActions {
|
|||
isEnabled: (viewModel) => viewModel.isEnabledSellAction,
|
||||
canShow: (viewModel) => viewModel.hasSellAction,
|
||||
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) {
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.litecoin:
|
||||
case WalletType.ethereum:
|
||||
case WalletType.polygon:
|
||||
case WalletType.bitcoinCash:
|
||||
if (viewModel.isEnabledSellAction) {
|
||||
final moonPaySellProvider = MoonPaySellProvider();
|
||||
final uri = await moonPaySellProvider.requestUrl(
|
||||
currency: viewModel.wallet.currency,
|
||||
refundWalletAddress: viewModel.wallet.walletAddresses.address,
|
||||
settingsStore: viewModel.settingsStore,
|
||||
final defaultSellProvider = viewModel.defaultSellProvider;
|
||||
try {
|
||||
defaultSellProvider != null
|
||||
? await defaultSellProvider.launchProvider(context, false)
|
||||
: await Navigator.of(context).pushNamed(Routes.buySellPage, arguments: false);
|
||||
} catch (e) {
|
||||
await _showErrorDialog(context, defaultSellProvider.toString(), e.toString());
|
||||
}
|
||||
},
|
||||
);
|
||||
if (DeviceInfo.instance.isMobile) {
|
||||
Navigator.of(context).pushNamed(Routes.webViewPage,
|
||||
arguments: [S.of(context).sell, uri]);
|
||||
} else {
|
||||
await launchUrl(uri);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
static Future<void> _showErrorDialog(
|
||||
BuildContext context, String title, String errorMessage) async {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithOneAction(
|
||||
alertTitle: S.of(context).sell,
|
||||
alertContent: S.of(context).unsupported_asset,
|
||||
alertTitle: title,
|
||||
alertContent: errorMessage,
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: () => Navigator.of(context).pop());
|
||||
buttonAction: () => Navigator.of(context).pop(),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
|
@ -390,8 +390,10 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
return MaterialPageRoute<void>(
|
||||
builder: (_) => getIt.get<OrderDetailsPage>(param1: settings.arguments as Order));
|
||||
|
||||
case Routes.buy:
|
||||
return MaterialPageRoute<void>(builder: (_) => getIt.get<BuyOptionsPage>());
|
||||
case Routes.buySellPage:
|
||||
final args = settings.arguments as bool;
|
||||
return MaterialPageRoute<void>(
|
||||
builder: (_) => getIt.get<BuySellOptionsPage>(param1: args));
|
||||
|
||||
case Routes.buyWebView:
|
||||
final args = settings.arguments as List;
|
||||
|
|
|
@ -55,7 +55,7 @@ class Routes {
|
|||
static const supportLiveChat = '/support/live_chat';
|
||||
static const supportOtherLinks = '/support/other';
|
||||
static const orderDetails = '/order_details';
|
||||
static const buy = '/buy';
|
||||
static const buySellPage = '/buy_sell_page';
|
||||
static const buyWebView = '/buy_web_view';
|
||||
static const unspentCoinsList = '/unspent_coins_list';
|
||||
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/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/buy/buy_provider.dart';
|
||||
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
||||
import 'package:cake_wallet/generated/i18n.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:flutter/material.dart';
|
||||
|
||||
class BuyOptionsPage extends BasePage {
|
||||
BuyOptionsPage(this.dashboardViewModel);
|
||||
class BuySellOptionsPage extends BasePage {
|
||||
BuySellOptionsPage(this.dashboardViewModel, this.isBuyAction);
|
||||
|
||||
final DashboardViewModel dashboardViewModel;
|
||||
final iconDarkRobinhood = 'assets/images/robinhood_dark.png';
|
||||
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';
|
||||
final bool isBuyAction;
|
||||
|
||||
@override
|
||||
String get title => S.current.buy;
|
||||
String get title => isBuyAction ? S.current.buy : S.current.sell;
|
||||
|
||||
@override
|
||||
AppBarStyle get appBarStyle => AppBarStyle.regular;
|
||||
|
@ -32,17 +24,9 @@ class BuyOptionsPage extends BasePage {
|
|||
Widget body(BuildContext context) {
|
||||
final isLightMode =
|
||||
Theme.of(context).extension<OptionTileTheme>()?.useDarkImage ?? false;
|
||||
final iconRobinhood = Image.asset(
|
||||
isLightMode ? iconLightRobinhood : iconDarkRobinhood,
|
||||
height: 40,
|
||||
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;
|
||||
final availableProviders = isBuyAction
|
||||
? dashboardViewModel.availableBuyProviders
|
||||
: dashboardViewModel.availableSellProviders;
|
||||
|
||||
return Container(
|
||||
child: Center(
|
||||
|
@ -50,47 +34,33 @@ class BuyOptionsPage extends BasePage {
|
|||
constraints: BoxConstraints(maxWidth: 330),
|
||||
child: Column(
|
||||
children: [
|
||||
if (availableProviders.contains(BuyProviderType.Onramper))
|
||||
Padding(
|
||||
...availableProviders.map((provider) {
|
||||
final icon = Image.asset(
|
||||
isLightMode ? provider.lightIcon : provider.darkIcon,
|
||||
height: 40,
|
||||
width: 40,
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: OptionTile(
|
||||
image: iconOnramper,
|
||||
title: "Onramper",
|
||||
description: S.of(context).onramper_option_description,
|
||||
onPressed: () async => await getIt
|
||||
.get<OnRamperBuyProvider>()
|
||||
.launchProvider(context),
|
||||
),
|
||||
),
|
||||
if (availableProviders.contains(BuyProviderType.Robinhood))
|
||||
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),
|
||||
),
|
||||
image: icon,
|
||||
title: provider.toString(),
|
||||
description: isBuyAction
|
||||
? provider.buyOptionDescription
|
||||
: provider.sellOptionDescription,
|
||||
onPressed: () =>
|
||||
provider.launchProvider(context, isBuyAction),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
Spacer(),
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
|
||||
child: Text(
|
||||
S.of(context).select_buy_provider_notice,
|
||||
isBuyAction
|
||||
? S.of(context).select_buy_provider_notice
|
||||
: S.of(context).select_sell_provider_notice,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
|
|
|
@ -29,11 +29,10 @@ class BuyListItem extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isSelected = selectedProvider?.description == provider.description;
|
||||
final isSelected = selectedProvider?.buyOptionDescription == provider.buyOptionDescription;
|
||||
final iconColor = isSelected ? Colors.white : Colors.black;
|
||||
|
||||
final providerIcon = getBuyProviderIcon(provider.description,
|
||||
iconColor: iconColor)!;
|
||||
final providerIcon = Image.asset('assets/images/wyre-icon.png', width: 36, height: 36);
|
||||
|
||||
final backgroundColor = isSelected
|
||||
? Palette.greyBlueCraiola
|
||||
|
@ -76,7 +75,7 @@ class BuyListItem extends StatelessWidget {
|
|||
padding: EdgeInsets.only(right: 10),
|
||||
child: providerIcon),
|
||||
Text(
|
||||
provider.description.title,
|
||||
provider.title,
|
||||
style: TextStyle(
|
||||
color: secondaryTextColor,
|
||||
fontSize: 20,
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sideba
|
|||
import 'package:cake_wallet/src/screens/dashboard/pages/market_place_page.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/bottom_sheet_listener.dart';
|
||||
import 'package:cake_wallet/src/widgets/gradient_background.dart';
|
||||
import 'package:cake_wallet/src/widgets/vulnerable_seeds_popup.dart';
|
||||
import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:cake_wallet/utils/version_comparator.dart';
|
||||
|
@ -60,7 +61,8 @@ class DashboardPage extends StatelessWidget {
|
|||
);
|
||||
|
||||
if (DeviceInfo.instance.isDesktop) {
|
||||
if (responsiveLayoutUtil.screenWidth > ResponsiveLayoutUtilBase.kDesktopMaxDashBoardWidthConstraint) {
|
||||
if (responsiveLayoutUtil.screenWidth >
|
||||
ResponsiveLayoutUtilBase.kDesktopMaxDashBoardWidthConstraint) {
|
||||
return getIt.get<DesktopSidebarWrapper>();
|
||||
} else {
|
||||
return dashboardPageView;
|
||||
|
@ -295,6 +297,8 @@ class _DashboardPageView extends BasePage {
|
|||
|
||||
_showReleaseNotesPopup(context);
|
||||
|
||||
_showVulnerableSeedsPopup(context);
|
||||
|
||||
var needToPresentYat = false;
|
||||
var isInactive = false;
|
||||
|
||||
|
@ -354,4 +358,22 @@ class _DashboardPageView extends BasePage {
|
|||
sharedPrefs.setInt(PreferencesKey.lastSeenAppVersion, currentAppVersion);
|
||||
}
|
||||
}
|
||||
|
||||
void _showVulnerableSeedsPopup(BuildContext context) async {
|
||||
final List<String> affectedWalletNames = await dashboardViewModel.checkAffectedWallets();
|
||||
|
||||
if (affectedWalletNames.isNotEmpty) {
|
||||
Future<void>.delayed(
|
||||
Duration(seconds: 1),
|
||||
() {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return VulnerableSeedsPopup(affectedWalletNames);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'package:cake_wallet/entities/preferences_key.dart';
|
|||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/release_notes/release_notes_screen.dart';
|
||||
import 'package:cake_wallet/src/screens/yat_emoji_id.dart';
|
||||
import 'package:cake_wallet/src/widgets/vulnerable_seeds_popup.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/utils/version_comparator.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -110,5 +111,25 @@ class DesktopDashboardPage extends StatelessWidget {
|
|||
} else if (isNewInstall!) {
|
||||
sharedPrefs.setInt(PreferencesKey.lastSeenAppVersion, currentAppVersion);
|
||||
}
|
||||
|
||||
_showVulnerableSeedsPopup(context);
|
||||
}
|
||||
|
||||
void _showVulnerableSeedsPopup(BuildContext context) async {
|
||||
final List<String> affectedWalletNames = await dashboardViewModel.checkAffectedWallets();
|
||||
|
||||
if (affectedWalletNames.isNotEmpty) {
|
||||
Future<void>.delayed(
|
||||
Duration(seconds: 1),
|
||||
() {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return VulnerableSeedsPopup(affectedWalletNames);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,24 @@ class BalancePage extends StatelessWidget {
|
|||
Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor,
|
||||
height: 1,
|
||||
),
|
||||
unselectedLabelStyle: TextStyle(
|
||||
fontSize: 18,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w600,
|
||||
color:
|
||||
Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor,
|
||||
height: 1,
|
||||
),
|
||||
labelColor:
|
||||
Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor,
|
||||
dividerColor:
|
||||
Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor,
|
||||
indicatorColor:
|
||||
Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor,
|
||||
unselectedLabelColor: Theme.of(context)
|
||||
.extension<DashboardPageTheme>()!
|
||||
.pageTitleTextColor
|
||||
.withOpacity(0.5),
|
||||
tabs: [
|
||||
Tab(text: 'My Crypto'),
|
||||
Tab(text: 'My NFTs'),
|
||||
|
|
|
@ -411,10 +411,6 @@ class ExchangePage extends BasePage {
|
|||
}
|
||||
});
|
||||
|
||||
reaction((_) => exchangeViewModel.isReceiveAddressEnabled, (bool isEnabled) {
|
||||
receiveKey.currentState!.isAddressEditable(isEditable: isEnabled);
|
||||
});
|
||||
|
||||
reaction((_) => exchangeViewModel.isReceiveAmountEditable, (bool isReceiveAmountEditable) {
|
||||
receiveKey.currentState!.isAmountEditable(isEditable: isReceiveAmountEditable);
|
||||
});
|
||||
|
@ -670,7 +666,6 @@ class ExchangePage extends BasePage {
|
|||
? exchangeViewModel.wallet.walletAddresses.address
|
||||
: exchangeViewModel.receiveAddress,
|
||||
initialIsAmountEditable: exchangeViewModel.isReceiveAmountEditable,
|
||||
initialIsAddressEditable: exchangeViewModel.isReceiveAddressEnabled,
|
||||
isAmountEstimated: true,
|
||||
isMoneroWallet: exchangeViewModel.isMoneroWallet,
|
||||
currencies: exchangeViewModel.receiveCurrencies,
|
||||
|
|
|
@ -174,8 +174,6 @@ class ExchangeTemplatePage extends BasePage {
|
|||
? exchangeViewModel.wallet.walletAddresses.address
|
||||
: exchangeViewModel.receiveAddress,
|
||||
initialIsAmountEditable: false,
|
||||
initialIsAddressEditable:
|
||||
exchangeViewModel.isReceiveAddressEnabled,
|
||||
isAmountEstimated: true,
|
||||
isMoneroWallet: exchangeViewModel.isMoneroWallet,
|
||||
currencies: exchangeViewModel.receiveCurrencies,
|
||||
|
@ -328,11 +326,6 @@ class ExchangeTemplatePage extends BasePage {
|
|||
}
|
||||
});
|
||||
|
||||
reaction((_) => exchangeViewModel.isReceiveAddressEnabled,
|
||||
(bool isEnabled) {
|
||||
receiveKey.currentState!.isAddressEditable(isEditable: isEnabled);
|
||||
});
|
||||
|
||||
reaction((_) => exchangeViewModel.provider, (ExchangeProvider? provider) {
|
||||
receiveKey.currentState!.isAmountEditable(isEditable: false);
|
||||
});
|
||||
|
|
|
@ -23,7 +23,6 @@ class ExchangeCard extends StatefulWidget {
|
|||
required this.initialAddress,
|
||||
required this.initialWalletName,
|
||||
required this.initialIsAmountEditable,
|
||||
required this.initialIsAddressEditable,
|
||||
required this.isAmountEstimated,
|
||||
required this.currencies,
|
||||
required this.onCurrencySelected,
|
||||
|
@ -31,6 +30,7 @@ class ExchangeCard extends StatefulWidget {
|
|||
this.currencyValueValidator,
|
||||
this.addressTextFieldValidator,
|
||||
this.title = '',
|
||||
this.initialIsAddressEditable = true,
|
||||
this.hasRefundAddress = false,
|
||||
this.isMoneroWallet = false,
|
||||
this.currencyButtonColor = Colors.transparent,
|
||||
|
|
|
@ -43,10 +43,18 @@ class OtherSettingsPage extends BasePage {
|
|||
if(_otherSettingsViewModel.isEnabledBuyAction)
|
||||
SettingsPickerCell(
|
||||
title: S.current.default_buy_provider,
|
||||
items: _otherSettingsViewModel.availableBuyProviders,
|
||||
items: _otherSettingsViewModel.availableBuyProvidersTypes,
|
||||
displayItem: _otherSettingsViewModel.getBuyProviderType,
|
||||
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(
|
||||
title: S.current.settings_terms_and_conditions,
|
||||
|
|
91
lib/src/widgets/vulnerable_seeds_popup.dart
Normal file
91
lib/src/widgets/vulnerable_seeds_popup.dart
Normal file
|
@ -0,0 +1,91 @@
|
|||
import 'package:cake_wallet/src/widgets/alert_background.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
|
||||
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class VulnerableSeedsPopup extends StatelessWidget {
|
||||
final List<String> affectedWalletNames;
|
||||
|
||||
const VulnerableSeedsPopup(this.affectedWalletNames, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
AlertBackground(
|
||||
child: AlertDialog(
|
||||
insetPadding: EdgeInsets.only(left: 16, right: 16, bottom: 48),
|
||||
elevation: 0.0,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(30))),
|
||||
content: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(30.0),
|
||||
gradient: LinearGradient(colors: [
|
||||
Theme.of(context).extension<DashboardPageTheme>()!.firstGradientBackgroundColor,
|
||||
Theme.of(context)
|
||||
.extension<DashboardPageTheme>()!
|
||||
.secondGradientBackgroundColor,
|
||||
], begin: Alignment.centerLeft, end: Alignment.centerRight)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||
child: Stack(
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 16.0),
|
||||
child: Container(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: DefaultTextStyle(
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.none,
|
||||
fontSize: 24.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: 'Lato',
|
||||
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor,
|
||||
),
|
||||
child: Text("Emergency Notice"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(top: 48, bottom: 16),
|
||||
child: Container(
|
||||
width: double.maxFinite,
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: MediaQuery.of(context).size.height * 0.7,
|
||||
),
|
||||
child: Text(
|
||||
"Your Bitcoin wallet(s) below use a legacy seed format that is vulnerable, which MAY result in you losing money from these wallet(s) if no action is taken.\nWe recommend that you IMMEDIATELY create wallet(s) in Cake Wallet and immediately transfer the funds to these wallet(s).\nVulnerable wallet name(s):\n\n[${affectedWalletNames.join(", ")}]\n\nFor assistance, please use the in-app support or email support@cakewallet.com",
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.none,
|
||||
fontSize: 16.0,
|
||||
fontFamily: 'Lato',
|
||||
color: Theme.of(context)
|
||||
.extension<DashboardPageTheme>()!
|
||||
.textColor,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
AlertCloseButton(bottom: 30)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -26,8 +26,7 @@ abstract class AppStoreBase with Store {
|
|||
AuthenticationStore authenticationStore;
|
||||
|
||||
@observable
|
||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>?
|
||||
wallet;
|
||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>? wallet;
|
||||
|
||||
WalletListStore walletList;
|
||||
|
||||
|
@ -36,16 +35,16 @@ abstract class AppStoreBase with Store {
|
|||
NodeListStore nodeListStore;
|
||||
|
||||
@action
|
||||
void changeCurrentWallet(
|
||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>,
|
||||
TransactionInfo>
|
||||
wallet) {
|
||||
Future<void> changeCurrentWallet(
|
||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet) async {
|
||||
this.wallet?.close();
|
||||
this.wallet = wallet;
|
||||
this.wallet!.setExceptionHandler(ExceptionHandler.onError);
|
||||
|
||||
if (isEVMCompatibleChain(wallet.type)) {
|
||||
getIt.get<Web3WalletService>().init();
|
||||
await getIt.get<Web3WalletService>().onDispose();
|
||||
getIt.get<Web3WalletService>().create();
|
||||
await getIt.get<Web3WalletService>().init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:io';
|
|||
|
||||
import 'package:cake_wallet/bitcoin/bitcoin.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/buy_provider_types.dart';
|
||||
import 'package:cake_wallet/entities/cake_2fa_preset_options.dart';
|
||||
|
@ -147,7 +148,9 @@ abstract class SettingsStoreBase with Store {
|
|||
initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
||||
currentSyncMode = initialSyncMode,
|
||||
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);
|
||||
|
||||
if (initialMoneroTransactionPriority != null) {
|
||||
|
@ -181,9 +184,25 @@ abstract class SettingsStoreBase with Store {
|
|||
initializeTrocadorProviderStates();
|
||||
|
||||
WalletType.values.forEach((walletType) {
|
||||
final key = 'defaultBuyProvider_${walletType.toString()}';
|
||||
final providerIndex = sharedPreferences.getInt(key);
|
||||
defaultBuyProviders[walletType] = providerIndex != null ? BuyProviderType.values[providerIndex] : BuyProviderType.AskEachTime;
|
||||
final key = 'buyProvider_${walletType.toString()}';
|
||||
final providerId = sharedPreferences.getString(key);
|
||||
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(
|
||||
|
@ -196,6 +215,20 @@ abstract class SettingsStoreBase with Store {
|
|||
(bool 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) {
|
||||
final String? key;
|
||||
switch (change.key) {
|
||||
|
@ -251,16 +284,6 @@ abstract class SettingsStoreBase with Store {
|
|||
(bool 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(
|
||||
(_) => walletListOrder,
|
||||
(WalletListOrderType walletListOrder) =>
|
||||
|
@ -594,7 +617,10 @@ abstract class SettingsStoreBase with Store {
|
|||
ObservableMap<String, bool> trocadorProviderStates = ObservableMap<String, bool>();
|
||||
|
||||
@observable
|
||||
ObservableMap<WalletType, BuyProviderType> defaultBuyProviders = ObservableMap<WalletType, BuyProviderType>();
|
||||
ObservableMap<WalletType, BuyProviderType> defaultBuyProviders;
|
||||
|
||||
@observable
|
||||
ObservableMap<WalletType, BuyProviderType> defaultSellProviders;
|
||||
|
||||
@observable
|
||||
SortBalanceBy sortBalanceBy;
|
||||
|
|
|
@ -61,8 +61,7 @@ abstract class BuyViewModelBase with Store {
|
|||
String _url = '';
|
||||
|
||||
try {
|
||||
_url = await selectedProvider
|
||||
!.requestUrl(doubleAmount.toString(), fiatCurrency.title);
|
||||
_url = await selectedProvider!.requestUrl(doubleAmount.toString(), fiatCurrency.title);
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||
import 'package:cake_wallet/core/key_service.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/buy_provider_types.dart';
|
||||
|
@ -24,13 +28,21 @@ import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
|
|||
import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart';
|
||||
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
|
||||
import 'package:cake_wallet/wallet_type_utils.dart';
|
||||
import 'package:cryptography/cryptography.dart';
|
||||
import 'package:cw_core/balance.dart';
|
||||
import 'package:cw_core/cake_hive.dart';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cw_core/sync_status.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
import 'package:cw_core/utils/file.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:eth_sig_util/util/utils.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
||||
|
||||
part 'dashboard_view_model.g.dart';
|
||||
|
||||
|
@ -46,7 +58,8 @@ abstract class DashboardViewModelBase with Store {
|
|||
required this.settingsStore,
|
||||
required this.yatStore,
|
||||
required this.ordersStore,
|
||||
required this.anonpayTransactionsStore})
|
||||
required this.anonpayTransactionsStore,
|
||||
required this.keyService})
|
||||
: hasSellAction = false,
|
||||
hasBuyAction = false,
|
||||
hasExchangeAction = false,
|
||||
|
@ -262,6 +275,8 @@ abstract class DashboardViewModelBase with Store {
|
|||
|
||||
bool get hasRescan => wallet.type == WalletType.monero || wallet.type == WalletType.haven;
|
||||
|
||||
final KeyService keyService;
|
||||
|
||||
BalanceViewModel balanceViewModel;
|
||||
|
||||
AppStore appStore;
|
||||
|
@ -282,13 +297,31 @@ abstract class DashboardViewModelBase with Store {
|
|||
|
||||
Map<String, List<FilterItem>> filterItems;
|
||||
|
||||
BuyProviderType get defaultBuyProvider =>
|
||||
settingsStore.defaultBuyProviders[wallet.type] ??
|
||||
BuyProviderType.AskEachTime;
|
||||
BuyProvider? get defaultBuyProvider => BuyProviderHelper.getProviderByType(
|
||||
settingsStore.defaultBuyProviders[wallet.type] ?? BuyProviderType.askEachTime);
|
||||
|
||||
BuyProvider? get defaultSellProvider => BuyProviderHelper.getProviderByType(
|
||||
settingsStore.defaultSellProviders[wallet.type] ?? BuyProviderType.askEachTime);
|
||||
|
||||
bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled;
|
||||
|
||||
List<BuyProviderType> get availableProviders => BuyProviderType.getAvailableProviders(wallet.type);
|
||||
List<BuyProvider> get availableBuyProviders {
|
||||
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;
|
||||
|
||||
|
@ -302,16 +335,15 @@ abstract class DashboardViewModelBase with Store {
|
|||
bool hasExchangeAction;
|
||||
|
||||
@computed
|
||||
bool get isEnabledBuyAction => !settingsStore.disableBuy && wallet.type != WalletType.haven;
|
||||
bool get isEnabledBuyAction =>
|
||||
!settingsStore.disableBuy && availableBuyProviders.isNotEmpty;
|
||||
|
||||
@observable
|
||||
bool hasBuyAction;
|
||||
|
||||
@computed
|
||||
bool get isEnabledSellAction =>
|
||||
!settingsStore.disableSell &&
|
||||
wallet.type != WalletType.haven &&
|
||||
wallet.type != WalletType.monero;
|
||||
!settingsStore.disableSell && availableSellProviders.isNotEmpty;
|
||||
|
||||
@observable
|
||||
bool hasSellAction;
|
||||
|
@ -433,4 +465,32 @@ abstract class DashboardViewModelBase with Store {
|
|||
|
||||
@action
|
||||
void setSyncAll(bool value) => settingsStore.currentSyncAll = value;
|
||||
|
||||
Future<List<String>> checkAffectedWallets() async {
|
||||
// await load file
|
||||
final vulnerableSeedsString = await rootBundle.loadString('assets/text/cakewallet_weak_bitcoin_seeds_hashed_sorted_version1.txt');
|
||||
final vulnerableSeeds = vulnerableSeedsString.split("\n");
|
||||
|
||||
final walletInfoSource = await CakeHive.openBox<WalletInfo>(WalletInfo.boxName);
|
||||
|
||||
List<String> affectedWallets = [];
|
||||
for (var walletInfo in walletInfoSource.values) {
|
||||
if (walletInfo.type == WalletType.bitcoin) {
|
||||
final password = await keyService.getWalletPassword(walletName: walletInfo.name);
|
||||
final path = await pathForWallet(name: walletInfo.name, type: walletInfo.type);
|
||||
final jsonSource = await read(path: path, password: password);
|
||||
final data = json.decode(jsonSource) as Map;
|
||||
final mnemonic = data['mnemonic'] as String;
|
||||
|
||||
final hash = await Cryptography.instance.sha256().hash(utf8.encode(mnemonic));
|
||||
final seedSha = bytesToHex(hash.bytes);
|
||||
|
||||
if (vulnerableSeeds.contains(seedSha)) {
|
||||
affectedWallets.add(walletInfo.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return affectedWallets;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
|||
receiveAddress = '',
|
||||
depositAddress = '',
|
||||
isDepositAddressEnabled = false,
|
||||
isReceiveAddressEnabled = false,
|
||||
isReceiveAmountEditable = false,
|
||||
_useTorOnly = false,
|
||||
receiveCurrencies = <CryptoCurrency>[],
|
||||
|
@ -108,7 +107,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
|||
bestRateSync = Timer.periodic(Duration(seconds: 10), (timer) => _calculateBestRate());
|
||||
|
||||
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
||||
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
|
||||
depositAmount = '';
|
||||
receiveAmount = '';
|
||||
receiveAddress = '';
|
||||
|
@ -201,9 +199,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
|||
@observable
|
||||
bool isDepositAddressEnabled;
|
||||
|
||||
@observable
|
||||
bool isReceiveAddressEnabled;
|
||||
|
||||
@observable
|
||||
bool isReceiveAmountEntered;
|
||||
|
||||
|
@ -315,7 +310,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
|||
isFixedRateMode = false;
|
||||
_onPairChange();
|
||||
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
||||
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
|
||||
}
|
||||
|
||||
@action
|
||||
|
@ -324,7 +318,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
|||
isFixedRateMode = false;
|
||||
_onPairChange();
|
||||
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
||||
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
|
||||
}
|
||||
|
||||
@action
|
||||
|
@ -535,7 +528,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
|||
depositAddress = depositCurrency == wallet.currency ? wallet.walletAddresses.address : '';
|
||||
receiveAddress = receiveCurrency == wallet.currency ? wallet.walletAddresses.address : '';
|
||||
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
||||
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
|
||||
isFixedRateMode = false;
|
||||
_onPairChange();
|
||||
}
|
||||
|
|
|
@ -50,8 +50,10 @@ abstract class OrderDetailsViewModelBase with Store {
|
|||
@action
|
||||
Future<void> _updateOrder() async {
|
||||
try {
|
||||
if (_provider != null) {
|
||||
final updatedOrder = await _provider!.findOrderById(order.id);
|
||||
if (_provider != null && (_provider is MoonPayBuyProvider || _provider is WyreBuyProvider)) {
|
||||
final updatedOrder = _provider is MoonPayBuyProvider
|
||||
? await (_provider as MoonPayBuyProvider).findOrderById(order.id)
|
||||
: await (_provider as WyreBuyProvider).findOrderById(order.id);
|
||||
updatedOrder.from = order.from;
|
||||
updatedOrder.to = order.to;
|
||||
updatedOrder.receiveAddress = order.receiveAddress;
|
||||
|
@ -87,8 +89,14 @@ abstract class OrderDetailsViewModelBase with Store {
|
|||
value: order.provider.title)
|
||||
);
|
||||
|
||||
if (_provider?.trackUrl.isNotEmpty ?? false) {
|
||||
final buildURL = _provider!.trackUrl + '${order.transferId}';
|
||||
if (_provider != null && (_provider is MoonPayBuyProvider || _provider is WyreBuyProvider)) {
|
||||
|
||||
final trackUrl = _provider is MoonPayBuyProvider
|
||||
? (_provider as MoonPayBuyProvider).trackUrl
|
||||
: (_provider as WyreBuyProvider).trackUrl;
|
||||
|
||||
if (trackUrl.isNotEmpty ?? false) {
|
||||
final buildURL = trackUrl + '${order.transferId}';
|
||||
items.add(
|
||||
TrackTradeListItem(
|
||||
title: 'Track',
|
||||
|
@ -101,6 +109,7 @@ abstract class OrderDetailsViewModelBase with Store {
|
|||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
items.add(
|
||||
StandartListItem(
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/entities/buy_provider_types.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:cw_core/balance.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
|
@ -59,12 +60,24 @@ abstract class OtherSettingsViewModelBase with Store {
|
|||
bool get isEnabledBuyAction =>
|
||||
!_settingsStore.disableBuy && _wallet.type != WalletType.haven;
|
||||
|
||||
List<BuyProviderType> get availableBuyProviders =>
|
||||
BuyProviderType.getAvailableProviders(walletType);
|
||||
@computed
|
||||
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 =>
|
||||
_settingsStore.defaultBuyProviders[walletType] ??
|
||||
BuyProviderType.AskEachTime;
|
||||
BuyProviderType.askEachTime;
|
||||
|
||||
BuyProviderType get sellProviderType =>
|
||||
_settingsStore.defaultSellProviders[walletType] ??
|
||||
BuyProviderType.askEachTime;
|
||||
|
||||
String getDisplayPriority(dynamic priority) {
|
||||
final _priority = priority as TransactionPriority;
|
||||
|
@ -81,13 +94,27 @@ abstract class OtherSettingsViewModelBase with Store {
|
|||
|
||||
String getBuyProviderType(dynamic 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) =>
|
||||
_settingsStore.priority[_wallet.type] = priority;
|
||||
|
||||
void onBuyProviderTypeSelected(BuyProviderType buyProviderType) =>
|
||||
@action
|
||||
BuyProviderType onBuyProviderTypeSelected(BuyProviderType buyProviderType) =>
|
||||
_settingsStore.defaultBuyProviders[walletType] = buyProviderType;
|
||||
|
||||
@action
|
||||
BuyProviderType onSellProviderTypeSelected(
|
||||
BuyProviderType sellProviderType) =>
|
||||
_settingsStore.defaultSellProviders[walletType] = sellProviderType;
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ abstract class WalletCreationVMBase with Store {
|
|||
: await process(credentials);
|
||||
walletInfo.address = wallet.walletAddresses.address;
|
||||
await _walletInfoSource.add(walletInfo);
|
||||
_appStore.changeCurrentWallet(wallet);
|
||||
await _appStore.changeCurrentWallet(wallet);
|
||||
getIt.get<BackgroundTasks>().registerSyncTask();
|
||||
_appStore.authenticationStore.allowed();
|
||||
state = ExecutedSuccessfullyState();
|
||||
|
|
|
@ -45,7 +45,7 @@ abstract class WalletListViewModelBase with Store {
|
|||
@action
|
||||
Future<void> loadWallet(WalletListItem walletItem) async {
|
||||
final wallet = await _walletLoadingService.load(walletItem.type, walletItem.name);
|
||||
_appStore.changeCurrentWallet(wallet);
|
||||
await _appStore.changeCurrentWallet(wallet);
|
||||
}
|
||||
|
||||
WalletListOrderType? get orderType => _appStore.settingsStore.walletListOrder;
|
||||
|
|
|
@ -41,7 +41,6 @@ PODS:
|
|||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- tor (0.0.1)
|
||||
- url_launcher_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- wakelock_plus (0.0.1):
|
||||
|
@ -60,7 +59,6 @@ DEPENDENCIES:
|
|||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`)
|
||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- tor (from `Flutter/ephemeral/.symlinks/plugins/tor/macos`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
- wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`)
|
||||
|
||||
|
@ -93,8 +91,6 @@ EXTERNAL SOURCES:
|
|||
:path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos
|
||||
shared_preferences_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
||||
tor:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/tor/macos
|
||||
url_launcher_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||
wakelock_plus:
|
||||
|
@ -102,7 +98,7 @@ EXTERNAL SOURCES:
|
|||
|
||||
SPEC CHECKSUMS:
|
||||
connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308
|
||||
cw_monero: f8b7f104508efba2591548e76b5c058d05cba3f0
|
||||
cw_monero: ec03de55a19c4a2b174ea687e0f4202edc716fa4
|
||||
device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
|
||||
devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225
|
||||
flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
|
||||
|
@ -114,7 +110,6 @@ SPEC CHECKSUMS:
|
|||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
|
||||
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
|
||||
tor: 2138c48428e696b83eacdda404de6d5574932e26
|
||||
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
|
||||
wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269
|
||||
|
||||
|
|
|
@ -756,6 +756,8 @@
|
|||
"dfx_option_description": "ﺎﺑﻭﺭﻭﺃ ﻲﻓ ﺕﺎﻛﺮﺸﻟﺍﻭ ﺔﺋﺰﺠﺘﻟﺍ ءﻼﻤﻌﻟ .ﻲﻓﺎﺿﺇ KYC ﻥﻭﺪﺑ ﻭﺭﻮﻳ 990 ﻰﻟﺇ ﻞﺼﻳ ﺎﻣ .ﻱﺮﺴﻳﻮﺴﻟﺍ",
|
||||
"polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ",
|
||||
"wallet_seed_legacy": "بذرة محفظة قديمة",
|
||||
"default_sell_provider": " ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ",
|
||||
"select_sell_provider_notice": ".ﻖﻴﺒﻄﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻚﺑ ﺹﺎﺨﻟﺍ ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ ﻦﻴﻴﻌﺗ ﻖﻳﺮﻃ ﻦﻋ ﺔﺷﺎﺸﻟﺍ ﻩﺬﻫ ﻲﻄﺨﺗ",
|
||||
"custom_drag": "مخصص (عقد وسحب)",
|
||||
"switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ"
|
||||
}
|
||||
|
|
|
@ -752,6 +752,8 @@
|
|||
"dfx_option_description": "Купете крипто с EUR и CHF. До 990 € без допълнителен KYC. За клиенти на дребно и корпоративни клиенти в Европа",
|
||||
"polygonscan_history": "История на PolygonScan",
|
||||
"wallet_seed_legacy": "Наследено портфейл семе",
|
||||
"default_sell_provider": "Доставчик за продажба по подразбиране",
|
||||
"select_sell_provider_notice": "Изберете доставчик на продажба по-горе. Можете да пропуснете този екран, като зададете своя доставчик на продажба по подразбиране в настройките на приложението.",
|
||||
"custom_drag": "Персонализиране (задръжте и плъзнете)",
|
||||
"switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -752,6 +752,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ě",
|
||||
"polygonscan_history": "Historie PolygonScan",
|
||||
"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)",
|
||||
"switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -760,6 +760,8 @@
|
|||
"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",
|
||||
"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)",
|
||||
"switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -761,6 +761,8 @@
|
|||
"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",
|
||||
"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)",
|
||||
"switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -760,6 +760,8 @@
|
|||
"seed_language_chinese_traditional": "Chino (tradicional)",
|
||||
"polygonscan_history": "Historial de PolygonScan",
|
||||
"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)",
|
||||
"switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -760,6 +760,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",
|
||||
"polygonscan_history": "Historique de PolygonScan",
|
||||
"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)",
|
||||
"switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -742,6 +742,8 @@
|
|||
"polygonscan_history": "PolygonScan tarihin kowane zamani",
|
||||
"wallet_seed_legacy": "Tallarin walat walat",
|
||||
"setup_totp_recommended": "Saita TOTP",
|
||||
"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)",
|
||||
"switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -760,6 +760,8 @@
|
|||
"dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। अतिरिक्त केवाईसी के बिना 990€ तक। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए",
|
||||
"polygonscan_history": "पॉलीगॉनस्कैन इतिहास",
|
||||
"wallet_seed_legacy": "विरासत बटुए बीज",
|
||||
"default_sell_provider": "डिफ़ॉल्ट विक्रय प्रदाता",
|
||||
"select_sell_provider_notice": "ऊपर एक विक्रय प्रदाता का चयन करें। आप ऐप सेटिंग में अपना डिफ़ॉल्ट विक्रय प्रदाता सेट करके इस स्क्रीन को छोड़ सकते हैं।",
|
||||
"custom_drag": "कस्टम (पकड़ और खींचें)",
|
||||
"switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)"
|
||||
}
|
||||
|
|
|
@ -758,6 +758,8 @@
|
|||
"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",
|
||||
"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)",
|
||||
"switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -748,6 +748,8 @@
|
|||
"dfx_option_description": "Beli kripto dengan EUR & CHF. Hingga 990€ tanpa KYC tambahan. Untuk pelanggan ritel dan korporat di Eropa",
|
||||
"polygonscan_history": "Sejarah PolygonScan",
|
||||
"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)",
|
||||
"switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -760,6 +760,8 @@
|
|||
"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",
|
||||
"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)",
|
||||
"switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -760,6 +760,8 @@
|
|||
"dfx_option_description": "EUR と CHF で暗号通貨を購入します。追加のKYCなしで最大990ユーロ。ヨーロッパの小売および法人顧客向け",
|
||||
"polygonscan_history": "ポリゴンスキャン履歴",
|
||||
"wallet_seed_legacy": "レガシーウォレットシード",
|
||||
"default_sell_provider": "デフォルトの販売プロバイダー",
|
||||
"select_sell_provider_notice": "上記の販売プロバイダーを選択してください。アプリ設定でデフォルトの販売プロバイダーを設定することで、この画面をスキップできます。",
|
||||
"custom_drag": "カスタム(ホールドとドラッグ)",
|
||||
"switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)"
|
||||
}
|
||||
|
|
|
@ -758,6 +758,8 @@
|
|||
"dfx_option_description": "EUR 및 CHF로 암호화폐를 구매하세요. 추가 KYC 없이 최대 990€. 유럽의 소매 및 기업 고객용",
|
||||
"polygonscan_history": "다각형 스캔 기록",
|
||||
"wallet_seed_legacy": "레거시 지갑 시드",
|
||||
"default_sell_provider": "기본 판매 공급자",
|
||||
"select_sell_provider_notice": "위에서 판매 공급자를 선택하세요. 앱 설정에서 기본 판매 공급자를 설정하면 이 화면을 건너뛸 수 있습니다.",
|
||||
"custom_drag": "사용자 정의 (홀드 앤 드래그)",
|
||||
"switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)"
|
||||
}
|
||||
|
|
|
@ -758,6 +758,8 @@
|
|||
"dfx_option_description": "EUR & CHF ဖြင့် crypto ကိုဝယ်ပါ။ အပို KYC မပါဘဲ 990€ အထိ။ ဥရောပရှိ လက်လီရောင်းချသူများနှင့် ကော်ပိုရိတ်ဖောက်သည်များအတွက်",
|
||||
"polygonscan_history": "PolygonScan မှတ်တမ်း",
|
||||
"wallet_seed_legacy": "အမွေအနှစ်ပိုက်ဆံအိတ်မျိုးစေ့",
|
||||
"default_sell_provider": "ပုံသေရောင်းချပေးသူ",
|
||||
"select_sell_provider_notice": "အထက်ဖော်ပြပါ အရောင်းဝန်ဆောင်မှုပေးသူကို ရွေးပါ။ အက်ပ်ဆက်တင်များတွင် သင်၏မူလရောင်းချပေးသူကို သတ်မှတ်ခြင်းဖြင့် ဤစခရင်ကို ကျော်နိုင်သည်။",
|
||||
"custom_drag": "စိတ်ကြိုက် (Drag)",
|
||||
"switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)"
|
||||
}
|
||||
|
|
|
@ -760,6 +760,8 @@
|
|||
"dfx_option_description": "Koop crypto met EUR & CHF. Tot 990€ zonder extra KYC. Voor particuliere en zakelijke klanten in Europa",
|
||||
"polygonscan_history": "PolygonScan-geschiedenis",
|
||||
"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)",
|
||||
"switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -760,6 +760,8 @@
|
|||
"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",
|
||||
"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)",
|
||||
"switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -759,6 +759,8 @@
|
|||
"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",
|
||||
"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)",
|
||||
"switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -760,6 +760,8 @@
|
|||
"dfx_option_description": "Покупайте криптовалюту за EUR и CHF. До 990€ без дополнительного KYC. Для розничных и корпоративных клиентов в Европе",
|
||||
"polygonscan_history": "История PolygonScan",
|
||||
"wallet_seed_legacy": "Наследие семя кошелька",
|
||||
"default_sell_provider": "Поставщик продаж по умолчанию",
|
||||
"select_sell_provider_notice": "Выберите поставщика услуг продажи выше. Вы можете пропустить этот экран, установив поставщика услуг продаж по умолчанию в настройках приложения.",
|
||||
"custom_drag": "Пользователь (удерживайте и перетаскивайте)",
|
||||
"switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon)."
|
||||
}
|
||||
|
|
|
@ -758,6 +758,8 @@
|
|||
"dfx_option_description": "ซื้อ crypto ด้วย EUR และ CHF สูงถึง 990€ โดยไม่มี KYC เพิ่มเติม สำหรับลูกค้ารายย่อยและลูกค้าองค์กรในยุโรป",
|
||||
"polygonscan_history": "ประวัติ PolygonScan",
|
||||
"wallet_seed_legacy": "เมล็ดกระเป๋าเงินมรดก",
|
||||
"default_sell_provider": "ผู้ให้บริการการขายเริ่มต้น",
|
||||
"select_sell_provider_notice": "เลือกผู้ให้บริการการขายด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการการขายเริ่มต้นในการตั้งค่าแอป",
|
||||
"custom_drag": "กำหนดเอง (ค้างและลาก)",
|
||||
"switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -754,6 +754,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",
|
||||
"polygonscan_history": "Kasaysayan ng PolygonScan",
|
||||
"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)",
|
||||
"switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -758,6 +758,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",
|
||||
"polygonscan_history": "PolygonScan geçmişi",
|
||||
"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)",
|
||||
"switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -760,6 +760,8 @@
|
|||
"seed_language_chinese_traditional": "Китайський (традиційний)",
|
||||
"polygonscan_history": "Історія PolygonScan",
|
||||
"wallet_seed_legacy": "Спадець насіння гаманця",
|
||||
"default_sell_provider": "Постачальник продажу за замовчуванням",
|
||||
"select_sell_provider_notice": "Виберіть вище постачальника послуг продажу. Ви можете пропустити цей екран, встановивши постачальника послуг продажу за умовчанням у налаштуваннях програми.",
|
||||
"custom_drag": "На замовлення (утримуйте та перетягується)",
|
||||
"switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -752,6 +752,8 @@
|
|||
"dfx_option_description": "EUR ﺭﻭﺍ CHF ﯽﻓﺎﺿﺍ ۔ﮟﯾﺪﯾﺮﺧ ﻮﭩﭘﺮﮐ ﮫﺗﺎﺳ ﮯﮐ KYC ﮯﯿﻟ ﮯﮐ ﻦﯿﻓﺭﺎﺻ ﭧﯾﺭﻮﭘﺭﺎﮐ ﺭﻭﺍ ﮦﺩﺭﻮﺧ ﮟ",
|
||||
"polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ",
|
||||
"wallet_seed_legacy": "میراثی پرس کا بیج",
|
||||
"default_sell_provider": " ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ",
|
||||
"select_sell_provider_notice": "۔ﮟﯿﮨ ﮯﺘﮑﺳ ﮌﻮﮭﭼ ﻮﮐ ﻦﯾﺮﮑﺳﺍ ﺱﺍ ﺮﮐ ﮮﺩ ﺐﯿﺗﺮﺗ ﻮﮐ ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ ﮯﻨﭘﺍ ﮟﯿﻣ ﺕﺎﺒ",
|
||||
"custom_drag": "کسٹم (ہولڈ اینڈ ڈریگ)",
|
||||
"switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ "
|
||||
}
|
||||
|
|
|
@ -754,6 +754,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",
|
||||
"polygonscan_history": "PolygonScan itan",
|
||||
"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)",
|
||||
"switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)"
|
||||
}
|
||||
|
|
|
@ -759,6 +759,8 @@
|
|||
"dfx_option_description": "用欧元和瑞士法郎购买加密货币。高达 990 欧元,无需额外 KYC。对于欧洲的零售和企业客户",
|
||||
"polygonscan_history": "多边形扫描历史",
|
||||
"wallet_seed_legacy": "旧的钱包种子",
|
||||
"default_sell_provider": "默认销售提供商",
|
||||
"select_sell_provider_notice": "选择上面的销售提供商。您可以通过在应用程序设置中设置默认销售提供商来跳过此屏幕。",
|
||||
"custom_drag": "定制(保持和拖动)",
|
||||
"switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)"
|
||||
}
|
||||
|
|
|
@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
|
|||
APP_ANDROID_TYPE=$1
|
||||
|
||||
MONERO_COM_NAME="Monero.com"
|
||||
MONERO_COM_VERSION="1.8.0"
|
||||
MONERO_COM_BUILD_NUMBER=69
|
||||
MONERO_COM_VERSION="1.9.0"
|
||||
MONERO_COM_BUILD_NUMBER=71
|
||||
MONERO_COM_BUNDLE_ID="com.monero.app"
|
||||
MONERO_COM_PACKAGE="com.monero.app"
|
||||
MONERO_COM_SCHEME="monero.com"
|
||||
|
||||
CAKEWALLET_NAME="Cake Wallet"
|
||||
CAKEWALLET_VERSION="4.11.0"
|
||||
CAKEWALLET_BUILD_NUMBER=184
|
||||
CAKEWALLET_VERSION="4.12.1"
|
||||
CAKEWALLET_BUILD_NUMBER=188
|
||||
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
|
||||
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
|
||||
CAKEWALLET_SCHEME="cakewallet"
|
||||
|
|
|
@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
|
|||
APP_IOS_TYPE=$1
|
||||
|
||||
MONERO_COM_NAME="Monero.com"
|
||||
MONERO_COM_VERSION="1.8.0"
|
||||
MONERO_COM_BUILD_NUMBER=67
|
||||
MONERO_COM_VERSION="1.9.0"
|
||||
MONERO_COM_BUILD_NUMBER=69
|
||||
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
|
||||
|
||||
CAKEWALLET_NAME="Cake Wallet"
|
||||
CAKEWALLET_VERSION="4.11.0"
|
||||
CAKEWALLET_BUILD_NUMBER=202
|
||||
CAKEWALLET_VERSION="4.12.1"
|
||||
CAKEWALLET_BUILD_NUMBER=206
|
||||
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
||||
|
||||
HAVEN_NAME="Haven"
|
||||
|
|
|
@ -15,8 +15,8 @@ if [ -n "$1" ]; then
|
|||
fi
|
||||
|
||||
CAKEWALLET_NAME="Cake Wallet"
|
||||
CAKEWALLET_VERSION="1.4.0"
|
||||
CAKEWALLET_BUILD_NUMBER=45
|
||||
CAKEWALLET_VERSION="1.5.1"
|
||||
CAKEWALLET_BUILD_NUMBER=48
|
||||
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
||||
|
||||
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then
|
||||
|
|
Loading…
Reference in a new issue