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
|
Polyseed enhancements
|
||||||
Bug fixes and 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
|
Support multiple address types for Bitcoin Cash
|
||||||
Add NFTs tab to see all of your purchased NFTs on Ethereum
|
Bug fixes
|
||||||
Bug fixes and enhancements
|
|
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 'dart:convert';
|
||||||
|
|
||||||
import 'package:bitbox/bitbox.dart' as bitbox;
|
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:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_transaction_credentials.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);
|
txb.addInput(input.hash, input.vout);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final String bchPrefix = "bitcoincash:";
|
||||||
|
|
||||||
outputs.forEach((item) {
|
outputs.forEach((item) {
|
||||||
final outputAmount = hasMultiDestination ? item.formattedCryptoAmount : amount;
|
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!);
|
txb.addOutput(outputAddress, outputAmount!);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ dependencies:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/cake-tech/bitbox-flutter.git
|
url: https://github.com/cake-tech/bitbox-flutter.git
|
||||||
ref: master
|
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) {
|
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';
|
final s = 'Unexpected token: $name for CryptoCurrency fromFullName';
|
||||||
throw ArgumentError.value(name, 'Fullname', s);
|
throw ArgumentError.value(name, 'Fullname', s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -623,15 +623,6 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
tor:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
path: "."
|
|
||||||
ref: main
|
|
||||||
resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5"
|
|
||||||
url: "https://github.com/cake-tech/tor.git"
|
|
||||||
source: git
|
|
||||||
version: "0.0.1"
|
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -122,6 +122,8 @@ PODS:
|
||||||
- Flutter
|
- Flutter
|
||||||
- MTBBarcodeScanner (5.0.11)
|
- MTBBarcodeScanner (5.0.11)
|
||||||
- OrderedSet (5.0.0)
|
- OrderedSet (5.0.0)
|
||||||
|
- package_info (0.0.1):
|
||||||
|
- Flutter
|
||||||
- package_info_plus (0.4.5):
|
- package_info_plus (0.4.5):
|
||||||
- Flutter
|
- Flutter
|
||||||
- path_provider_foundation (0.0.1):
|
- path_provider_foundation (0.0.1):
|
||||||
|
@ -143,8 +145,6 @@ PODS:
|
||||||
- SwiftProtobuf (1.22.0)
|
- SwiftProtobuf (1.22.0)
|
||||||
- SwiftyGif (5.4.4)
|
- SwiftyGif (5.4.4)
|
||||||
- Toast (4.0.0)
|
- Toast (4.0.0)
|
||||||
- tor (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- uni_links (0.0.1):
|
- uni_links (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- UnstoppableDomainsResolution (4.0.0):
|
- UnstoppableDomainsResolution (4.0.0):
|
||||||
|
@ -175,13 +175,13 @@ DEPENDENCIES:
|
||||||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
||||||
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
|
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
|
||||||
- local_auth_ios (from `.symlinks/plugins/local_auth_ios/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`)
|
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||||
- sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`)
|
- sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`)
|
||||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
- tor (from `.symlinks/plugins/tor/ios`)
|
|
||||||
- uni_links (from `.symlinks/plugins/uni_links/ios`)
|
- uni_links (from `.symlinks/plugins/uni_links/ios`)
|
||||||
- UnstoppableDomainsResolution (~> 4.0.0)
|
- UnstoppableDomainsResolution (~> 4.0.0)
|
||||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
|
@ -236,6 +236,8 @@ EXTERNAL SOURCES:
|
||||||
:path: ".symlinks/plugins/in_app_review/ios"
|
:path: ".symlinks/plugins/in_app_review/ios"
|
||||||
local_auth_ios:
|
local_auth_ios:
|
||||||
:path: ".symlinks/plugins/local_auth_ios/ios"
|
:path: ".symlinks/plugins/local_auth_ios/ios"
|
||||||
|
package_info:
|
||||||
|
:path: ".symlinks/plugins/package_info/ios"
|
||||||
package_info_plus:
|
package_info_plus:
|
||||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||||
path_provider_foundation:
|
path_provider_foundation:
|
||||||
|
@ -248,8 +250,6 @@ EXTERNAL SOURCES:
|
||||||
:path: ".symlinks/plugins/share_plus/ios"
|
:path: ".symlinks/plugins/share_plus/ios"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||||
tor:
|
|
||||||
:path: ".symlinks/plugins/tor/ios"
|
|
||||||
uni_links:
|
uni_links:
|
||||||
:path: ".symlinks/plugins/uni_links/ios"
|
:path: ".symlinks/plugins/uni_links/ios"
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
|
@ -282,6 +282,7 @@ SPEC CHECKSUMS:
|
||||||
local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605
|
local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605
|
||||||
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
||||||
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
||||||
|
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
|
||||||
package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
|
package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
|
||||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||||
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
|
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
|
||||||
|
@ -293,7 +294,6 @@ SPEC CHECKSUMS:
|
||||||
SwiftProtobuf: 40bd808372cb8706108f22d28f8ab4a6b9bc6989
|
SwiftProtobuf: 40bd808372cb8706108f22d28f8ab4a6b9bc6989
|
||||||
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
|
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
|
||||||
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
||||||
tor: 662a9f5b980b5c86decb8ba611de9bcd4c8286eb
|
|
||||||
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
||||||
UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841
|
UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841
|
||||||
url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b
|
url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b
|
||||||
|
|
|
@ -2,11 +2,11 @@ import 'package:flutter/foundation.dart';
|
||||||
import 'package:cake_wallet/buy/buy_provider_description.dart';
|
import 'package:cake_wallet/buy/buy_provider_description.dart';
|
||||||
|
|
||||||
class BuyException implements Exception {
|
class BuyException implements Exception {
|
||||||
BuyException({required this.description, required this.text});
|
BuyException({required this.title, required this.content});
|
||||||
|
|
||||||
final BuyProviderDescription description;
|
final String title;
|
||||||
final String text;
|
final String content;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => '${description.title}: $text';
|
String toString() => '$title: $content';
|
||||||
}
|
}
|
|
@ -1,27 +1,35 @@
|
||||||
import 'package:cake_wallet/buy/buy_amount.dart';
|
import 'package:cake_wallet/buy/buy_amount.dart';
|
||||||
import 'package:cake_wallet/buy/buy_provider_description.dart';
|
|
||||||
import 'package:cake_wallet/buy/order.dart';
|
import 'package:cake_wallet/buy/order.dart';
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
abstract class BuyProvider {
|
abstract class BuyProvider {
|
||||||
BuyProvider({required this.wallet, required this.isTestEnvironment});
|
BuyProvider({
|
||||||
|
required this.wallet,
|
||||||
|
required this.isTestEnvironment,
|
||||||
|
});
|
||||||
|
|
||||||
final WalletBase wallet;
|
final WalletBase wallet;
|
||||||
final bool isTestEnvironment;
|
final bool isTestEnvironment;
|
||||||
|
|
||||||
String get title;
|
String get title;
|
||||||
BuyProviderDescription get description;
|
|
||||||
String get trackUrl;
|
|
||||||
|
|
||||||
WalletType get walletType => wallet.type;
|
String get buyOptionDescription;
|
||||||
String get walletAddress => wallet.walletAddresses.address;
|
|
||||||
String get walletId => wallet.id;
|
String get sellOptionDescription;
|
||||||
|
|
||||||
|
String get lightIcon;
|
||||||
|
|
||||||
|
String get darkIcon;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => title;
|
String toString() => title;
|
||||||
|
|
||||||
Future<String> requestUrl(String amount, String sourceCurrency);
|
Future<void> launchProvider(BuildContext context, bool? isBuyAction);
|
||||||
Future<Order> findOrderById(String id);
|
|
||||||
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency);
|
Future<String> requestUrl(String amount, String sourceCurrency) => throw UnimplementedError();
|
||||||
}
|
|
||||||
|
Future<Order> findOrderById(String id) => throw UnimplementedError();
|
||||||
|
|
||||||
|
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) => throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||||
|
@ -11,10 +12,9 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class DFXBuyProvider {
|
class DFXBuyProvider extends BuyProvider {
|
||||||
DFXBuyProvider({required WalletBase wallet}) : this._wallet = wallet;
|
DFXBuyProvider({required WalletBase wallet, bool isTestEnvironment = false})
|
||||||
|
: super(wallet: wallet, isTestEnvironment: isTestEnvironment);
|
||||||
final WalletBase _wallet;
|
|
||||||
|
|
||||||
static const _baseUrl = 'api.dfx.swiss';
|
static const _baseUrl = 'api.dfx.swiss';
|
||||||
static const _authPath = '/v1/auth/signMessage';
|
static const _authPath = '/v1/auth/signMessage';
|
||||||
|
@ -22,8 +22,23 @@ class DFXBuyProvider {
|
||||||
static const _signInPath = '/v1/auth/signIn';
|
static const _signInPath = '/v1/auth/signIn';
|
||||||
static const walletName = 'CakeWallet';
|
static const walletName = 'CakeWallet';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get title => 'DFX Connect';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get buyOptionDescription => S.current.dfx_option_description;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sellOptionDescription => S.current.dfx_option_description;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get lightIcon => 'assets/images/dfx_light.png';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get darkIcon => 'assets/images/dfx_dark.png';
|
||||||
|
|
||||||
String get assetOut {
|
String get assetOut {
|
||||||
switch (_wallet.type) {
|
switch (wallet.type) {
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
return 'BTC';
|
return 'BTC';
|
||||||
case WalletType.bitcoinCash:
|
case WalletType.bitcoinCash:
|
||||||
|
@ -35,12 +50,12 @@ class DFXBuyProvider {
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
return 'ETH';
|
return 'ETH';
|
||||||
default:
|
default:
|
||||||
throw Exception("WalletType is not available for DFX ${_wallet.type}");
|
throw Exception("WalletType is not available for DFX ${wallet.type}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String get blockchain {
|
String get blockchain {
|
||||||
switch (_wallet.type) {
|
switch (wallet.type) {
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
case WalletType.bitcoinCash:
|
case WalletType.bitcoinCash:
|
||||||
case WalletType.litecoin:
|
case WalletType.litecoin:
|
||||||
|
@ -50,12 +65,12 @@ class DFXBuyProvider {
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
return 'Ethereum';
|
return 'Ethereum';
|
||||||
default:
|
default:
|
||||||
throw Exception("WalletType is not available for DFX ${_wallet.type}");
|
throw Exception("WalletType is not available for DFX ${wallet.type}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> getSignMessage() async {
|
Future<String> getSignMessage() async {
|
||||||
final walletAddress = _wallet.walletAddresses.address;
|
final walletAddress = wallet.walletAddresses.address;
|
||||||
final uri = Uri.https(_baseUrl, _authPath, {'address': walletAddress});
|
final uri = Uri.https(_baseUrl, _authPath, {'address': walletAddress});
|
||||||
|
|
||||||
var response = await http.get(uri, headers: {'accept': 'application/json'});
|
var response = await http.get(uri, headers: {'accept': 'application/json'});
|
||||||
|
@ -71,7 +86,7 @@ class DFXBuyProvider {
|
||||||
|
|
||||||
Future<String> signUp() async {
|
Future<String> signUp() async {
|
||||||
final signMessage = getSignature(await getSignMessage());
|
final signMessage = getSignature(await getSignMessage());
|
||||||
final walletAddress = _wallet.walletAddresses.address;
|
final walletAddress = wallet.walletAddresses.address;
|
||||||
|
|
||||||
final requestBody = jsonEncode({
|
final requestBody = jsonEncode({
|
||||||
'wallet': walletName,
|
'wallet': walletName,
|
||||||
|
@ -86,6 +101,10 @@ class DFXBuyProvider {
|
||||||
if (response.statusCode == 201) {
|
if (response.statusCode == 201) {
|
||||||
final responseBody = jsonDecode(response.body);
|
final responseBody = jsonDecode(response.body);
|
||||||
return responseBody['accessToken'] as String;
|
return responseBody['accessToken'] as String;
|
||||||
|
} else if (response.statusCode == 403) {
|
||||||
|
final responseBody = jsonDecode(response.body);
|
||||||
|
final message = responseBody['message'] ?? 'Service unavailable in your country';
|
||||||
|
throw Exception(message);
|
||||||
} else {
|
} else {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
'Failed to sign up. Status: ${response.statusCode} ${response.body}');
|
'Failed to sign up. Status: ${response.statusCode} ${response.body}');
|
||||||
|
@ -94,7 +113,7 @@ class DFXBuyProvider {
|
||||||
|
|
||||||
Future<String> signIn() async {
|
Future<String> signIn() async {
|
||||||
final signMessage = getSignature(await getSignMessage());
|
final signMessage = getSignature(await getSignMessage());
|
||||||
final walletAddress = _wallet.walletAddresses.address;
|
final walletAddress = wallet.walletAddresses.address;
|
||||||
|
|
||||||
final requestBody = jsonEncode({
|
final requestBody = jsonEncode({
|
||||||
'address': walletAddress,
|
'address': walletAddress,
|
||||||
|
@ -108,6 +127,10 @@ class DFXBuyProvider {
|
||||||
if (response.statusCode == 201) {
|
if (response.statusCode == 201) {
|
||||||
final responseBody = jsonDecode(response.body);
|
final responseBody = jsonDecode(response.body);
|
||||||
return responseBody['accessToken'] as String;
|
return responseBody['accessToken'] as String;
|
||||||
|
} else if (response.statusCode == 403) {
|
||||||
|
final responseBody = jsonDecode(response.body);
|
||||||
|
final message = responseBody['message'] ?? 'Service unavailable in your country';
|
||||||
|
throw Exception(message);
|
||||||
} else {
|
} else {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
'Failed to sign in. Status: ${response.statusCode} ${response.body}');
|
'Failed to sign in. Status: ${response.statusCode} ${response.body}');
|
||||||
|
@ -115,24 +138,25 @@ class DFXBuyProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
String getSignature(String message) {
|
String getSignature(String message) {
|
||||||
switch (_wallet.type) {
|
switch (wallet.type) {
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
return _wallet.signMessage(message);
|
return wallet.signMessage(message);
|
||||||
case WalletType.monero:
|
case WalletType.monero:
|
||||||
case WalletType.litecoin:
|
case WalletType.litecoin:
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
case WalletType.bitcoinCash:
|
case WalletType.bitcoinCash:
|
||||||
return _wallet.signMessage(message,
|
return wallet.signMessage(message,
|
||||||
address: _wallet.walletAddresses.address);
|
address: wallet.walletAddresses.address);
|
||||||
default:
|
default:
|
||||||
throw Exception("WalletType is not available for DFX ${_wallet.type}");
|
throw Exception("WalletType is not available for DFX ${wallet.type}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> launchProvider(BuildContext context) async {
|
Future<void> launchProvider(BuildContext context, bool? isBuyAction) async {
|
||||||
try {
|
try {
|
||||||
final assetOut = this.assetOut;
|
final assetOut = this.assetOut;
|
||||||
final blockchain = this.blockchain;
|
final blockchain = this.blockchain;
|
||||||
|
final actionType = isBuyAction == true ? '/buy' : '/sell';
|
||||||
|
|
||||||
String accessToken;
|
String accessToken;
|
||||||
|
|
||||||
|
@ -146,7 +170,7 @@ class DFXBuyProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final uri = Uri.https('services.dfx.swiss', '/buy', {
|
final uri = Uri.https('services.dfx.swiss', actionType, {
|
||||||
'session': accessToken,
|
'session': accessToken,
|
||||||
'lang': 'en',
|
'lang': 'en',
|
||||||
'asset-out': assetOut,
|
'asset-out': assetOut,
|
||||||
|
@ -156,8 +180,8 @@ class DFXBuyProvider {
|
||||||
|
|
||||||
if (await canLaunchUrl(uri)) {
|
if (await canLaunchUrl(uri)) {
|
||||||
if (DeviceInfo.instance.isMobile) {
|
if (DeviceInfo.instance.isMobile) {
|
||||||
Navigator.of(context).pushNamed(Routes.webViewPage,
|
Navigator.of(context)
|
||||||
arguments: [S.of(context).buy, uri]);
|
.pushNamed(Routes.webViewPage, arguments: ["DFX Connect", uri]);
|
||||||
} else {
|
} else {
|
||||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:cake_wallet/palette.dart';
|
import 'package:cake_wallet/palette.dart';
|
||||||
|
import 'package:cake_wallet/routes.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||||
import 'package:cake_wallet/store/settings_store.dart';
|
import 'package:cake_wallet/store/settings_store.dart';
|
||||||
import 'package:cake_wallet/themes/theme_base.dart';
|
import 'package:cake_wallet/themes/theme_base.dart';
|
||||||
|
import 'package:cake_wallet/utils/device_info.dart';
|
||||||
import 'package:crypto/crypto.dart';
|
import 'package:crypto/crypto.dart';
|
||||||
import 'package:cake_wallet/buy/buy_exception.dart';
|
import 'package:cake_wallet/buy/buy_exception.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
import 'package:cake_wallet/buy/buy_amount.dart';
|
import 'package:cake_wallet/buy/buy_amount.dart';
|
||||||
import 'package:cake_wallet/buy/buy_provider.dart';
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
|
@ -14,33 +19,41 @@ import 'package:cw_core/wallet_type.dart';
|
||||||
import 'package:cake_wallet/exchange/trade_state.dart';
|
import 'package:cake_wallet/exchange/trade_state.dart';
|
||||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class MoonPaySellProvider {
|
class MoonPaySellProvider {
|
||||||
MoonPaySellProvider({this.isTest = false})
|
MoonPaySellProvider({required SettingsStore settingsStore,
|
||||||
: baseUrl = isTest ? _baseTestUrl : _baseProductUrl;
|
required WalletBase wallet, this.isTest = false})
|
||||||
|
: baseUrl = isTest ? _baseTestUrl : _baseProductUrl,
|
||||||
|
this._settingsStore = settingsStore,
|
||||||
|
this._wallet = wallet;
|
||||||
|
|
||||||
|
final SettingsStore _settingsStore;
|
||||||
|
final WalletBase _wallet;
|
||||||
|
|
||||||
static const _baseTestUrl = 'sell-sandbox.moonpay.com';
|
static const _baseTestUrl = 'sell-sandbox.moonpay.com';
|
||||||
static const _baseProductUrl = 'sell.moonpay.com';
|
static const _baseProductUrl = 'sell.moonpay.com';
|
||||||
|
|
||||||
static String themeToMoonPayTheme(ThemeBase theme) {
|
static String themeToMoonPayTheme(ThemeBase theme) {
|
||||||
switch (theme.type) {
|
switch (theme.type) {
|
||||||
case ThemeType.bright:
|
case ThemeType.bright:
|
||||||
return 'light';
|
|
||||||
case ThemeType.light:
|
case ThemeType.light:
|
||||||
return 'light';
|
return 'light';
|
||||||
case ThemeType.dark:
|
case ThemeType.dark:
|
||||||
return 'dark';
|
return 'dark';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static String get _apiKey => secrets.moonPayApiKey;
|
|
||||||
static String get _secretKey => secrets.moonPaySecretKey;
|
static String get _apiKey => secrets.moonPayApiKey;
|
||||||
|
static String get _secretKey => secrets.moonPaySecretKey;
|
||||||
final bool isTest;
|
final bool isTest;
|
||||||
final String baseUrl;
|
final String baseUrl;
|
||||||
|
|
||||||
Future<Uri> requestUrl(
|
Future<Uri> requestUrl({
|
||||||
{required CryptoCurrency currency,
|
required CryptoCurrency currency,
|
||||||
required String refundWalletAddress,
|
required String refundWalletAddress,
|
||||||
required SettingsStore settingsStore}) async {
|
required SettingsStore settingsStore,
|
||||||
|
}) async {
|
||||||
final customParams = {
|
final customParams = {
|
||||||
'theme': themeToMoonPayTheme(settingsStore.currentTheme),
|
'theme': themeToMoonPayTheme(settingsStore.currentTheme),
|
||||||
'language': settingsStore.languageCode,
|
'language': settingsStore.languageCode,
|
||||||
|
@ -50,11 +63,15 @@ class MoonPaySellProvider {
|
||||||
};
|
};
|
||||||
|
|
||||||
final originalUri = Uri.https(
|
final originalUri = Uri.https(
|
||||||
baseUrl, '', <String, dynamic>{
|
baseUrl,
|
||||||
|
'',
|
||||||
|
<String, dynamic>{
|
||||||
'apiKey': _apiKey,
|
'apiKey': _apiKey,
|
||||||
'defaultBaseCurrencyCode': currency.toString().toLowerCase(),
|
'defaultBaseCurrencyCode': currency.toString().toLowerCase(),
|
||||||
'refundWalletAddress': refundWalletAddress
|
'refundWalletAddress': refundWalletAddress,
|
||||||
}..addAll(customParams));
|
}..addAll(customParams),
|
||||||
|
);
|
||||||
|
|
||||||
final messageBytes = utf8.encode('?${originalUri.query}');
|
final messageBytes = utf8.encode('?${originalUri.query}');
|
||||||
final key = utf8.encode(_secretKey);
|
final key = utf8.encode(_secretKey);
|
||||||
final hmac = Hmac(sha256, key);
|
final hmac = Hmac(sha256, key);
|
||||||
|
@ -70,6 +87,38 @@ class MoonPaySellProvider {
|
||||||
final signedUri = originalUri.replace(queryParameters: query);
|
final signedUri = originalUri.replace(queryParameters: query);
|
||||||
return signedUri;
|
return signedUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> launchProvider(BuildContext context) async {
|
||||||
|
try {
|
||||||
|
final uri = await requestUrl(
|
||||||
|
currency: _wallet.currency,
|
||||||
|
refundWalletAddress: _wallet.walletAddresses.address,
|
||||||
|
settingsStore: _settingsStore,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (await canLaunchUrl(uri)) {
|
||||||
|
if (DeviceInfo.instance.isMobile) {
|
||||||
|
Navigator.of(context).pushNamed(Routes.webViewPage, arguments: ['MoonPay', uri]);
|
||||||
|
} else {
|
||||||
|
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw Exception('Could not launch URL');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
await showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertWithOneAction(
|
||||||
|
alertTitle: 'MoonPay',
|
||||||
|
alertContent: 'The MoonPay service is currently unavailable: $e',
|
||||||
|
buttonText: S.of(context).ok,
|
||||||
|
buttonAction: () => Navigator.of(context).pop(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MoonPayBuyProvider extends BuyProvider {
|
class MoonPayBuyProvider extends BuyProvider {
|
||||||
|
@ -88,20 +137,24 @@ class MoonPayBuyProvider extends BuyProvider {
|
||||||
static const _secretKey = secrets.moonPaySecretKey;
|
static const _secretKey = secrets.moonPaySecretKey;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get title => 'MoonPay';
|
String get title => 'Moon Pay';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
BuyProviderDescription get description => BuyProviderDescription.moonPay;
|
String get buyOptionDescription => '';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get lightIcon => 'assets/images/moonpay_light.png';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get darkIcon => 'assets/images/moonpay_dark.png';
|
||||||
|
|
||||||
String get currencyCode =>
|
String get currencyCode =>
|
||||||
walletTypeToCryptoCurrency(walletType).title.toLowerCase();
|
walletTypeToCryptoCurrency(wallet.type).title.toLowerCase();
|
||||||
|
|
||||||
@override
|
|
||||||
String get trackUrl => baseUrl + '/transaction_receipt?transactionId=';
|
String get trackUrl => baseUrl + '/transaction_receipt?transactionId=';
|
||||||
|
|
||||||
String baseUrl;
|
String baseUrl;
|
||||||
|
|
||||||
@override
|
|
||||||
Future<String> requestUrl(String amount, String sourceCurrency) async {
|
Future<String> requestUrl(String amount, String sourceCurrency) async {
|
||||||
final enabledPaymentMethods =
|
final enabledPaymentMethods =
|
||||||
'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay'
|
'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay'
|
||||||
|
@ -109,7 +162,7 @@ class MoonPayBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
final suffix = '?apiKey=' + _apiKey + '¤cyCode=' +
|
final suffix = '?apiKey=' + _apiKey + '¤cyCode=' +
|
||||||
currencyCode + '&enabledPaymentMethods=' + enabledPaymentMethods +
|
currencyCode + '&enabledPaymentMethods=' + enabledPaymentMethods +
|
||||||
'&walletAddress=' + walletAddress +
|
'&walletAddress=' + wallet.walletAddresses.address +
|
||||||
'&baseCurrencyCode=' + sourceCurrency.toLowerCase() +
|
'&baseCurrencyCode=' + sourceCurrency.toLowerCase() +
|
||||||
'&baseCurrencyAmount=' + amount + '&lockAmount=true' +
|
'&baseCurrencyAmount=' + amount + '&lockAmount=true' +
|
||||||
'&showAllCurrencies=false' + '&showWalletAddressForm=false';
|
'&showAllCurrencies=false' + '&showWalletAddressForm=false';
|
||||||
|
@ -127,7 +180,6 @@ class MoonPayBuyProvider extends BuyProvider {
|
||||||
return isTestEnvironment ? originalUrl : urlWithSignature;
|
return isTestEnvironment ? originalUrl : urlWithSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) async {
|
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) async {
|
||||||
final url = _apiUrl + _currenciesSuffix + '/$currencyCode' +
|
final url = _apiUrl + _currenciesSuffix + '/$currencyCode' +
|
||||||
_quoteSuffix + '/?apiKey=' + _apiKey +
|
_quoteSuffix + '/?apiKey=' + _apiKey +
|
||||||
|
@ -138,8 +190,8 @@ class MoonPayBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
throw BuyException(
|
throw BuyException(
|
||||||
description: description,
|
title: buyOptionDescription,
|
||||||
text: 'Quote is not found!');
|
content: 'Quote is not found!');
|
||||||
}
|
}
|
||||||
|
|
||||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
@ -153,7 +205,6 @@ class MoonPayBuyProvider extends BuyProvider {
|
||||||
minAmount: minSourceAmount);
|
minAmount: minSourceAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Order> findOrderById(String id) async {
|
Future<Order> findOrderById(String id) async {
|
||||||
final url = _apiUrl + _transactionsSuffix + '/$id' +
|
final url = _apiUrl + _transactionsSuffix + '/$id' +
|
||||||
'?apiKey=' + _apiKey;
|
'?apiKey=' + _apiKey;
|
||||||
|
@ -162,8 +213,8 @@ class MoonPayBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
throw BuyException(
|
throw BuyException(
|
||||||
description: description,
|
title: buyOptionDescription,
|
||||||
text: 'Transaction $id is not found!');
|
content: 'Transaction $id is not found!');
|
||||||
}
|
}
|
||||||
|
|
||||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
@ -175,13 +226,13 @@ class MoonPayBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
return Order(
|
return Order(
|
||||||
id: id,
|
id: id,
|
||||||
provider: description,
|
provider: BuyProviderDescription.moonPay,
|
||||||
transferId: id,
|
transferId: id,
|
||||||
state: state,
|
state: state,
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
amount: amount.toString(),
|
amount: amount.toString(),
|
||||||
receiveAddress: walletAddress,
|
receiveAddress: wallet.walletAddresses.address,
|
||||||
walletId: walletId
|
walletId: wallet.id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,4 +252,14 @@ class MoonPayBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
return isBuyEnable;
|
return isBuyEnable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// TODO: implement sellOptionDescription
|
||||||
|
String get sellOptionDescription => throw UnimplementedError();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> launchProvider(BuildContext context, bool? isBuyAction) {
|
||||||
|
// TODO: implement launchProvider
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||||
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/store/settings_store.dart';
|
import 'package:cake_wallet/store/settings_store.dart';
|
||||||
|
@ -9,20 +10,34 @@ import 'package:cw_core/wallet_base.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class OnRamperBuyProvider {
|
class OnRamperBuyProvider extends BuyProvider {
|
||||||
OnRamperBuyProvider({required SettingsStore settingsStore, required WalletBase wallet})
|
OnRamperBuyProvider(this._settingsStore,
|
||||||
: this._settingsStore = settingsStore,
|
{required WalletBase wallet, bool isTestEnvironment = false})
|
||||||
this._wallet = wallet;
|
: super(wallet: wallet, isTestEnvironment: isTestEnvironment);
|
||||||
|
|
||||||
final SettingsStore _settingsStore;
|
|
||||||
final WalletBase _wallet;
|
|
||||||
|
|
||||||
static const _baseUrl = 'buy.onramper.com';
|
static const _baseUrl = 'buy.onramper.com';
|
||||||
|
|
||||||
|
final SettingsStore _settingsStore;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get title => 'Onramper';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get buyOptionDescription => S.current.onramper_option_description;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sellOptionDescription => S.current.onramper_option_description;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get lightIcon => 'assets/images/onramper_light.png';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get darkIcon => 'assets/images/onramper_dark.png';
|
||||||
|
|
||||||
String get _apiKey => secrets.onramperApiKey;
|
String get _apiKey => secrets.onramperApiKey;
|
||||||
|
|
||||||
String get _normalizeCryptoCurrency {
|
String get _normalizeCryptoCurrency {
|
||||||
switch (_wallet.currency) {
|
switch (wallet.currency) {
|
||||||
case CryptoCurrency.ltc:
|
case CryptoCurrency.ltc:
|
||||||
return "LTC_LITECOIN";
|
return "LTC_LITECOIN";
|
||||||
case CryptoCurrency.xmr:
|
case CryptoCurrency.xmr:
|
||||||
|
@ -32,7 +47,7 @@ class OnRamperBuyProvider {
|
||||||
case CryptoCurrency.nano:
|
case CryptoCurrency.nano:
|
||||||
return "XNO_NANO";
|
return "XNO_NANO";
|
||||||
default:
|
default:
|
||||||
return _wallet.currency.title;
|
return wallet.currency.title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +55,7 @@ class OnRamperBuyProvider {
|
||||||
return color.value.toRadixString(16).replaceAll(RegExp(r'^ff'), "");
|
return color.value.toRadixString(16).replaceAll(RegExp(r'^ff'), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
Uri requestUrl(BuildContext context) {
|
Uri requestOnramperUrl(BuildContext context) {
|
||||||
String primaryColor,
|
String primaryColor,
|
||||||
secondaryColor,
|
secondaryColor,
|
||||||
primaryTextColor,
|
primaryTextColor,
|
||||||
|
@ -50,9 +65,10 @@ class OnRamperBuyProvider {
|
||||||
|
|
||||||
primaryColor = getColorStr(Theme.of(context).primaryColor);
|
primaryColor = getColorStr(Theme.of(context).primaryColor);
|
||||||
secondaryColor = getColorStr(Theme.of(context).colorScheme.background);
|
secondaryColor = getColorStr(Theme.of(context).colorScheme.background);
|
||||||
primaryTextColor = getColorStr(Theme.of(context).extension<CakeTextTheme>()!.titleColor);
|
primaryTextColor =
|
||||||
secondaryTextColor =
|
getColorStr(Theme.of(context).extension<CakeTextTheme>()!.titleColor);
|
||||||
getColorStr(Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor);
|
secondaryTextColor = getColorStr(
|
||||||
|
Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor);
|
||||||
containerColor = getColorStr(Theme.of(context).colorScheme.background);
|
containerColor = getColorStr(Theme.of(context).colorScheme.background);
|
||||||
cardColor = getColorStr(Theme.of(context).cardColor);
|
cardColor = getColorStr(Theme.of(context).cardColor);
|
||||||
|
|
||||||
|
@ -60,12 +76,13 @@ class OnRamperBuyProvider {
|
||||||
cardColor = getColorStr(Colors.white);
|
cardColor = getColorStr(Colors.white);
|
||||||
}
|
}
|
||||||
|
|
||||||
final networkName = _wallet.currency.fullName?.toUpperCase().replaceAll(" ", "");
|
final networkName =
|
||||||
|
wallet.currency.fullName?.toUpperCase().replaceAll(" ", "");
|
||||||
|
|
||||||
return Uri.https(_baseUrl, '', <String, dynamic>{
|
return Uri.https(_baseUrl, '', <String, dynamic>{
|
||||||
'apiKey': _apiKey,
|
'apiKey': _apiKey,
|
||||||
'defaultCrypto': _normalizeCryptoCurrency,
|
'defaultCrypto': _normalizeCryptoCurrency,
|
||||||
'networkWallets': '${networkName}:${_wallet.walletAddresses.address}',
|
'networkWallets': '${networkName}:${wallet.walletAddresses.address}',
|
||||||
'supportSell': "false",
|
'supportSell': "false",
|
||||||
'supportSwap': "false",
|
'supportSwap': "false",
|
||||||
'primaryColor': primaryColor,
|
'primaryColor': primaryColor,
|
||||||
|
@ -77,10 +94,11 @@ class OnRamperBuyProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> launchProvider(BuildContext context) async {
|
Future<void> launchProvider(BuildContext context, bool? isBuyAction) async {
|
||||||
final uri = requestUrl(context);
|
final uri = requestOnramperUrl(context);
|
||||||
if (DeviceInfo.instance.isMobile) {
|
if (DeviceInfo.instance.isMobile) {
|
||||||
Navigator.of(context).pushNamed(Routes.webViewPage, arguments: [S.of(context).buy, uri]);
|
Navigator.of(context)
|
||||||
|
.pushNamed(Routes.webViewPage, arguments: [S.of(context).buy, uri]);
|
||||||
} else {
|
} else {
|
||||||
await launchUrl(uri);
|
await launchUrl(uri);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||||
|
import 'package:cake_wallet/buy/buy_amount.dart';
|
||||||
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
|
import 'package:cake_wallet/buy/buy_provider_description.dart';
|
||||||
|
import 'package:cake_wallet/buy/order.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||||
|
@ -10,40 +14,48 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class RobinhoodBuyProvider {
|
class RobinhoodBuyProvider extends BuyProvider{
|
||||||
RobinhoodBuyProvider({required WalletBase wallet}) : this._wallet = wallet;
|
RobinhoodBuyProvider({required WalletBase wallet, bool isTestEnvironment = false})
|
||||||
|
: super(wallet: wallet, isTestEnvironment: isTestEnvironment);
|
||||||
final WalletBase _wallet;
|
|
||||||
|
|
||||||
static const _baseUrl = 'applink.robinhood.com';
|
static const _baseUrl = 'applink.robinhood.com';
|
||||||
static const _cIdBaseUrl = 'exchange-helper.cakewallet.com';
|
static const _cIdBaseUrl = 'exchange-helper.cakewallet.com';
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get title => 'Robinhood Connect';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get buyOptionDescription => S.current.robinhood_option_description;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sellOptionDescription => S.current.robinhood_option_description;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get lightIcon => 'assets/images/robinhood_light.png';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get darkIcon => 'assets/images/robinhood_dark.png';
|
||||||
|
|
||||||
String get _applicationId => secrets.robinhoodApplicationId;
|
String get _applicationId => secrets.robinhoodApplicationId;
|
||||||
|
|
||||||
String get _apiSecret => secrets.robinhoodCIdApiSecret;
|
String get _apiSecret => secrets.robinhoodCIdApiSecret;
|
||||||
|
|
||||||
bool get isAvailable => [
|
|
||||||
WalletType.bitcoin,
|
|
||||||
WalletType.bitcoinCash,
|
|
||||||
WalletType.litecoin,
|
|
||||||
WalletType.ethereum
|
|
||||||
].contains(_wallet.type);
|
|
||||||
|
|
||||||
String getSignature(String message) {
|
String getSignature(String message) {
|
||||||
switch (_wallet.type) {
|
switch (wallet.type) {
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
return _wallet.signMessage(message);
|
return wallet.signMessage(message);
|
||||||
case WalletType.litecoin:
|
case WalletType.litecoin:
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
case WalletType.bitcoinCash:
|
case WalletType.bitcoinCash:
|
||||||
return _wallet.signMessage(message, address: _wallet.walletAddresses.address);
|
return wallet.signMessage(message, address: wallet.walletAddresses.address);
|
||||||
default:
|
default:
|
||||||
throw Exception("WalletType is not available for Robinhood ${_wallet.type}");
|
throw Exception("WalletType is not available for Robinhood ${wallet.type}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> getConnectId() async {
|
Future<String> getConnectId() async {
|
||||||
final walletAddress = _wallet.walletAddresses.address;
|
final walletAddress = wallet.walletAddresses.address;
|
||||||
final valid_until = (DateTime.now().millisecondsSinceEpoch / 1000).round() + 10;
|
final valid_until = (DateTime.now().millisecondsSinceEpoch / 1000).round() + 10;
|
||||||
final message = "$_apiSecret:${valid_until}";
|
final message = "$_apiSecret:${valid_until}";
|
||||||
|
|
||||||
|
@ -64,22 +76,22 @@ class RobinhoodBuyProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Uri> requestUrl() async {
|
Future<Uri> requestProviderUrl() async {
|
||||||
final connectId = await getConnectId();
|
final connectId = await getConnectId();
|
||||||
final networkName = _wallet.currency.fullName?.toUpperCase().replaceAll(" ", "_");
|
final networkName = wallet.currency.fullName?.toUpperCase().replaceAll(" ", "_");
|
||||||
|
|
||||||
return Uri.https(_baseUrl, '/u/connect', <String, dynamic>{
|
return Uri.https(_baseUrl, '/u/connect', <String, dynamic>{
|
||||||
'applicationId': _applicationId,
|
'applicationId': _applicationId,
|
||||||
'connectId': connectId,
|
'connectId': connectId,
|
||||||
'walletAddress': _wallet.walletAddresses.address,
|
'walletAddress': wallet.walletAddresses.address,
|
||||||
'userIdentifier': _wallet.walletAddresses.address,
|
'userIdentifier': wallet.walletAddresses.address,
|
||||||
'supportedNetworks': networkName
|
'supportedNetworks': networkName
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> launchProvider(BuildContext context) async {
|
Future<void> launchProvider(BuildContext context, bool? isBuyAction) async {
|
||||||
try {
|
try {
|
||||||
final uri = await requestUrl();
|
final uri = await requestProviderUrl();
|
||||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
await showPopUp<void>(
|
await showPopUp<void>(
|
||||||
|
@ -93,4 +105,5 @@ class RobinhoodBuyProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:cake_wallet/buy/buy_exception.dart';
|
import 'package:cake_wallet/buy/buy_exception.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
import 'package:cake_wallet/buy/buy_amount.dart';
|
import 'package:cake_wallet/buy/buy_amount.dart';
|
||||||
import 'package:cake_wallet/buy/buy_provider.dart';
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
|
@ -35,16 +36,20 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
String get title => 'Wyre';
|
String get title => 'Wyre';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
BuyProviderDescription get description => BuyProviderDescription.wyre;
|
String get buyOptionDescription => '';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
String get lightIcon => 'assets/images/robinhood_light.png';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get darkIcon => 'assets/images/robinhood_dark.png';
|
||||||
|
|
||||||
String get trackUrl => isTestEnvironment
|
String get trackUrl => isTestEnvironment
|
||||||
? _trackTestUrl
|
? _trackTestUrl
|
||||||
: _trackProductUrl;
|
: _trackProductUrl;
|
||||||
|
|
||||||
String baseApiUrl;
|
String baseApiUrl;
|
||||||
|
|
||||||
@override
|
|
||||||
Future<String> requestUrl(String amount, String sourceCurrency) async {
|
Future<String> requestUrl(String amount, String sourceCurrency) async {
|
||||||
final timestamp = DateTime.now().millisecondsSinceEpoch.toString();
|
final timestamp = DateTime.now().millisecondsSinceEpoch.toString();
|
||||||
final url = baseApiUrl + _ordersSuffix + _reserveSuffix +
|
final url = baseApiUrl + _ordersSuffix + _reserveSuffix +
|
||||||
|
@ -53,8 +58,8 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
final body = {
|
final body = {
|
||||||
'amount': amount,
|
'amount': amount,
|
||||||
'sourceCurrency': sourceCurrency,
|
'sourceCurrency': sourceCurrency,
|
||||||
'destCurrency': walletTypeToCryptoCurrency(walletType).title,
|
'destCurrency': walletTypeToCryptoCurrency(wallet.type).title,
|
||||||
'dest': walletTypeToString(walletType).toLowerCase() + ':' + walletAddress,
|
'dest': walletTypeToString(wallet.type).toLowerCase() + ':' + wallet.walletAddresses.address,
|
||||||
'referrerAccountId': _accountId,
|
'referrerAccountId': _accountId,
|
||||||
'lockFields': ['amount', 'sourceCurrency', 'destCurrency', 'dest']
|
'lockFields': ['amount', 'sourceCurrency', 'destCurrency', 'dest']
|
||||||
};
|
};
|
||||||
|
@ -68,8 +73,8 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
throw BuyException(
|
throw BuyException(
|
||||||
description: description,
|
title: buyOptionDescription,
|
||||||
text: 'Url $url is not found!');
|
content: 'Url $url is not found!');
|
||||||
}
|
}
|
||||||
|
|
||||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
@ -77,14 +82,13 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
return urlFromResponse;
|
return urlFromResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) async {
|
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) async {
|
||||||
final quoteUrl = _baseProductApiUrl + _ordersSuffix + _quoteSuffix;
|
final quoteUrl = _baseProductApiUrl + _ordersSuffix + _quoteSuffix;
|
||||||
final body = {
|
final body = {
|
||||||
'amount': amount,
|
'amount': amount,
|
||||||
'sourceCurrency': sourceCurrency,
|
'sourceCurrency': sourceCurrency,
|
||||||
'destCurrency': walletTypeToCryptoCurrency(walletType).title,
|
'destCurrency': walletTypeToCryptoCurrency(wallet.type).title,
|
||||||
'dest': walletTypeToString(walletType).toLowerCase() + ':' + walletAddress,
|
'dest': walletTypeToString(wallet.type).toLowerCase() + ':' + wallet.walletAddresses.address,
|
||||||
'accountId': _accountId,
|
'accountId': _accountId,
|
||||||
'country': _countryCode
|
'country': _countryCode
|
||||||
};
|
};
|
||||||
|
@ -99,8 +103,8 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
throw BuyException(
|
throw BuyException(
|
||||||
description: description,
|
title: buyOptionDescription,
|
||||||
text: 'Quote is not found!');
|
content: 'Quote is not found!');
|
||||||
}
|
}
|
||||||
|
|
||||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
@ -111,7 +115,6 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
return BuyAmount(sourceAmount: sourceAmount, destAmount: destAmount, achSourceAmount: achAmount);
|
return BuyAmount(sourceAmount: sourceAmount, destAmount: destAmount, achSourceAmount: achAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Order> findOrderById(String id) async {
|
Future<Order> findOrderById(String id) async {
|
||||||
final orderUrl = baseApiUrl + _ordersSuffix + '/$id';
|
final orderUrl = baseApiUrl + _ordersSuffix + '/$id';
|
||||||
final orderUri = Uri.parse(orderUrl);
|
final orderUri = Uri.parse(orderUrl);
|
||||||
|
@ -119,8 +122,8 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
if (orderResponse.statusCode != 200) {
|
if (orderResponse.statusCode != 200) {
|
||||||
throw BuyException(
|
throw BuyException(
|
||||||
description: description,
|
title: buyOptionDescription,
|
||||||
text: 'Order $id is not found!');
|
content: 'Order $id is not found!');
|
||||||
}
|
}
|
||||||
|
|
||||||
final orderResponseJSON =
|
final orderResponseJSON =
|
||||||
|
@ -141,8 +144,8 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
if (transferResponse.statusCode != 200) {
|
if (transferResponse.statusCode != 200) {
|
||||||
throw BuyException(
|
throw BuyException(
|
||||||
description: description,
|
title: buyOptionDescription,
|
||||||
text: 'Transfer $transferId is not found!');
|
content: 'Transfer $transferId is not found!');
|
||||||
}
|
}
|
||||||
|
|
||||||
final transferResponseJSON =
|
final transferResponseJSON =
|
||||||
|
@ -151,15 +154,25 @@ class WyreBuyProvider extends BuyProvider {
|
||||||
|
|
||||||
return Order(
|
return Order(
|
||||||
id: id,
|
id: id,
|
||||||
provider: description,
|
provider: BuyProviderDescription.wyre,
|
||||||
transferId: transferId,
|
transferId: transferId,
|
||||||
from: from,
|
from: from,
|
||||||
to: to,
|
to: to,
|
||||||
state: state,
|
state: state,
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
amount: amount.toString(),
|
amount: amount.toString(),
|
||||||
receiveAddress: walletAddress,
|
receiveAddress: wallet.walletAddresses.address,
|
||||||
walletId: walletId
|
walletId: wallet.id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> launchProvider(BuildContext context, bool? isBuyAction) {
|
||||||
|
// TODO: implement launchProvider
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// TODO: implement sellOptionDescription
|
||||||
|
String get sellOptionDescription => throw UnimplementedError();
|
||||||
}
|
}
|
|
@ -92,7 +92,7 @@ class AddressValidator extends TextValidator {
|
||||||
case CryptoCurrency.eos:
|
case CryptoCurrency.eos:
|
||||||
return '[0-9a-zA-Z]';
|
return '[0-9a-zA-Z]';
|
||||||
case CryptoCurrency.bch:
|
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:
|
case CryptoCurrency.bnb:
|
||||||
return '[0-9a-zA-Z]';
|
return '[0-9a-zA-Z]';
|
||||||
case CryptoCurrency.ltc:
|
case CryptoCurrency.ltc:
|
||||||
|
|
|
@ -138,7 +138,7 @@ class EvmChainServiceImpl implements ChainService {
|
||||||
try {
|
try {
|
||||||
// Load the private key
|
// Load the private key
|
||||||
final List<ChainKeyModel> keys = wcKeyService
|
final List<ChainKeyModel> keys = wcKeyService
|
||||||
.getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type));
|
.getKeysForChain(appStore.wallet!);
|
||||||
|
|
||||||
final Credentials credentials = EthPrivateKey.fromHex(keys[0].privateKey);
|
final Credentials credentials = EthPrivateKey.fromHex(keys[0].privateKey);
|
||||||
|
|
||||||
|
@ -177,7 +177,7 @@ class EvmChainServiceImpl implements ChainService {
|
||||||
try {
|
try {
|
||||||
// Load the private key
|
// Load the private key
|
||||||
final List<ChainKeyModel> keys = wcKeyService
|
final List<ChainKeyModel> keys = wcKeyService
|
||||||
.getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type));
|
.getKeysForChain(appStore.wallet!);
|
||||||
|
|
||||||
final EthPrivateKey credentials = EthPrivateKey.fromHex(keys[0].privateKey);
|
final EthPrivateKey credentials = EthPrivateKey.fromHex(keys[0].privateKey);
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ class EvmChainServiceImpl implements ChainService {
|
||||||
|
|
||||||
// Load the private key
|
// Load the private key
|
||||||
final List<ChainKeyModel> keys = wcKeyService
|
final List<ChainKeyModel> keys = wcKeyService
|
||||||
.getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type));
|
.getKeysForChain(appStore.wallet!);
|
||||||
|
|
||||||
final Credentials credentials = EthPrivateKey.fromHex(keys[0].privateKey);
|
final Credentials credentials = EthPrivateKey.fromHex(keys[0].privateKey);
|
||||||
|
|
||||||
|
@ -275,7 +275,7 @@ class EvmChainServiceImpl implements ChainService {
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<ChainKeyModel> keys = wcKeyService
|
final List<ChainKeyModel> keys = wcKeyService
|
||||||
.getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type));
|
.getKeysForChain(appStore.wallet!);
|
||||||
|
|
||||||
return EthSigUtil.signTypedData(
|
return EthSigUtil.signTypedData(
|
||||||
privateKey: keys[0].privateKey,
|
privateKey: keys[0].privateKey,
|
||||||
|
|
|
@ -1,48 +1,22 @@
|
||||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||||
import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart';
|
import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart';
|
||||||
import 'package:cake_wallet/polygon/polygon.dart';
|
import 'package:cake_wallet/polygon/polygon.dart';
|
||||||
import 'package:cw_core/balance.dart';
|
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||||
import 'package:cw_core/transaction_history.dart';
|
|
||||||
import 'package:cw_core/transaction_info.dart';
|
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
|
||||||
abstract class WalletConnectKeyService {
|
abstract class WalletConnectKeyService {
|
||||||
/// Returns a list of all the keys.
|
/// Returns a list of all the keys.
|
||||||
List<ChainKeyModel> getKeys();
|
List<ChainKeyModel> getKeys(WalletBase wallet);
|
||||||
|
|
||||||
/// Returns a list of all the chain ids.
|
|
||||||
List<String> getChains();
|
|
||||||
|
|
||||||
/// Returns a list of all the keys for a given chain id.
|
/// Returns a list of all the keys for a given chain id.
|
||||||
/// If the chain is not found, returns an empty list.
|
/// If the chain is not found, returns an empty list.
|
||||||
/// - [chain]: The chain to get the keys for.
|
/// - [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 {
|
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) {
|
static String _getPrivateKeyForWallet(WalletBase wallet) {
|
||||||
switch (wallet.type) {
|
switch (wallet.type) {
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
|
@ -64,31 +38,31 @@ class KeyServiceImpl implements WalletConnectKeyService {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<String> getChains() {
|
List<ChainKeyModel> getKeys(WalletBase wallet) {
|
||||||
final List<String> chainIds = [];
|
final keys = [
|
||||||
for (final ChainKeyModel key in _keys) {
|
ChainKeyModel(
|
||||||
chainIds.addAll(key.chains);
|
chains: [
|
||||||
}
|
'eip155:1',
|
||||||
return chainIds;
|
'eip155:5',
|
||||||
|
'eip155:137',
|
||||||
|
'eip155:42161',
|
||||||
|
'eip155:80001',
|
||||||
|
],
|
||||||
|
privateKey: _getPrivateKeyForWallet(wallet),
|
||||||
|
publicKey: _getPublicKeyForWallet(wallet),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<ChainKeyModel> getKeys() => _keys;
|
List<ChainKeyModel> getKeysForChain(WalletBase wallet) {
|
||||||
|
final chain = getChainNameSpaceAndIdBasedOnWalletType(wallet.type);
|
||||||
|
|
||||||
@override
|
final keys = getKeys(wallet);
|
||||||
List<ChainKeyModel> getKeysForChain(String chain) {
|
|
||||||
return _keys.where((e) => e.chains.contains(chain)).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
return keys.where((e) => e.chains.contains(chain)).toList();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ abstract class Web3WalletServiceBase with Store {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Setup our accounts
|
// Setup our accounts
|
||||||
List<ChainKeyModel> chainKeys = walletKeyService.getKeys();
|
List<ChainKeyModel> chainKeys = walletKeyService.getKeys(appStore.wallet!);
|
||||||
for (final chainKey in chainKeys) {
|
for (final chainKey in chainKeys) {
|
||||||
for (final chainId in chainKey.chains) {
|
for (final chainId in chainKey.chains) {
|
||||||
_web3Wallet.registerAccount(
|
_web3Wallet.registerAccount(
|
||||||
|
@ -136,6 +136,7 @@ abstract class Web3WalletServiceBase with Store {
|
||||||
_web3Wallet.onAuthRequest.unsubscribe(_onAuthRequest);
|
_web3Wallet.onAuthRequest.unsubscribe(_onAuthRequest);
|
||||||
_web3Wallet.core.pairing.onPairingDelete.unsubscribe(_onPairingDelete);
|
_web3Wallet.core.pairing.onPairingDelete.unsubscribe(_onPairingDelete);
|
||||||
_web3Wallet.core.pairing.onPairingExpire.unsubscribe(_onPairingDelete);
|
_web3Wallet.core.pairing.onPairingExpire.unsubscribe(_onPairingDelete);
|
||||||
|
isInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Web3Wallet getWeb3Wallet() {
|
Web3Wallet getWeb3Wallet() {
|
||||||
|
@ -236,7 +237,7 @@ abstract class Web3WalletServiceBase with Store {
|
||||||
Future<void> _onAuthRequest(AuthRequest? args) async {
|
Future<void> _onAuthRequest(AuthRequest? args) async {
|
||||||
if (args != null) {
|
if (args != null) {
|
||||||
final chaindIdNamespace = getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type);
|
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
|
// Create the message to be signed
|
||||||
final String iss = 'did:pkh:$chaindIdNamespace:${chainKeys.first.publicKey}';
|
final String iss = 'did:pkh:$chaindIdNamespace:${chainKeys.first.publicKey}';
|
||||||
final Widget modalWidget = Web3RequestModal(
|
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_api.dart';
|
||||||
import 'package:cake_wallet/anonpay/anonpay_info_base.dart';
|
import 'package:cake_wallet/anonpay/anonpay_info_base.dart';
|
||||||
import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
|
import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
|
||||||
|
import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart';
|
||||||
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
|
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
|
||||||
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
||||||
import 'package:cake_wallet/buy/payfura/payfura_buy_provider.dart';
|
import 'package:cake_wallet/buy/payfura/payfura_buy_provider.dart';
|
||||||
|
@ -378,7 +379,8 @@ Future<void> setup({
|
||||||
settingsStore: settingsStore,
|
settingsStore: settingsStore,
|
||||||
yatStore: getIt.get<YatStore>(),
|
yatStore: getIt.get<YatStore>(),
|
||||||
ordersStore: getIt.get<OrdersStore>(),
|
ordersStore: getIt.get<OrdersStore>(),
|
||||||
anonpayTransactionsStore: getIt.get<AnonpayTransactionsStore>()));
|
anonpayTransactionsStore: getIt.get<AnonpayTransactionsStore>(),
|
||||||
|
keyService: getIt.get<KeyService>()));
|
||||||
|
|
||||||
getIt.registerFactory<AuthService>(
|
getIt.registerFactory<AuthService>(
|
||||||
() => AuthService(
|
() => AuthService(
|
||||||
|
@ -477,7 +479,7 @@ Future<void> setup({
|
||||||
|
|
||||||
final appStore = getIt.get<AppStore>();
|
final appStore = getIt.get<AppStore>();
|
||||||
|
|
||||||
getIt.registerLazySingleton<WalletConnectKeyService>(() => KeyServiceImpl(appStore.wallet!));
|
getIt.registerLazySingleton<WalletConnectKeyService>(() => KeyServiceImpl());
|
||||||
|
|
||||||
getIt.registerLazySingleton<Web3WalletService>(() {
|
getIt.registerLazySingleton<Web3WalletService>(() {
|
||||||
final Web3WalletService web3WalletService = Web3WalletService(
|
final Web3WalletService web3WalletService = Web3WalletService(
|
||||||
|
@ -796,11 +798,15 @@ Future<void> setup({
|
||||||
getIt.registerFactory<RobinhoodBuyProvider>(
|
getIt.registerFactory<RobinhoodBuyProvider>(
|
||||||
() => RobinhoodBuyProvider(wallet: getIt.get<AppStore>().wallet!));
|
() => RobinhoodBuyProvider(wallet: getIt.get<AppStore>().wallet!));
|
||||||
|
|
||||||
getIt.registerFactory<DFXBuyProvider>(
|
getIt
|
||||||
() => DFXBuyProvider(wallet: getIt.get<AppStore>().wallet!));
|
.registerFactory<DFXBuyProvider>(() => DFXBuyProvider(wallet: getIt.get<AppStore>().wallet!));
|
||||||
|
|
||||||
|
getIt.registerFactory<MoonPaySellProvider>(() => MoonPaySellProvider(
|
||||||
|
settingsStore: getIt.get<AppStore>().settingsStore,
|
||||||
|
wallet: getIt.get<AppStore>().wallet!));
|
||||||
|
|
||||||
getIt.registerFactory<OnRamperBuyProvider>(() => OnRamperBuyProvider(
|
getIt.registerFactory<OnRamperBuyProvider>(() => OnRamperBuyProvider(
|
||||||
settingsStore: getIt.get<AppStore>().settingsStore,
|
getIt.get<AppStore>().settingsStore,
|
||||||
wallet: getIt.get<AppStore>().wallet!,
|
wallet: getIt.get<AppStore>().wallet!,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -944,7 +950,8 @@ Future<void> setup({
|
||||||
|
|
||||||
getIt.registerFactory(() => BuyAmountViewModel());
|
getIt.registerFactory(() => BuyAmountViewModel());
|
||||||
|
|
||||||
getIt.registerFactory(() => BuyOptionsPage(getIt.get<DashboardViewModel>()));
|
getIt.registerFactoryParam<BuySellOptionsPage, bool, void>(
|
||||||
|
(isBuyOption, _) => BuySellOptionsPage(getIt.get<DashboardViewModel>(), isBuyOption));
|
||||||
|
|
||||||
getIt.registerFactory(() {
|
getIt.registerFactory(() {
|
||||||
final wallet = getIt.get<AppStore>().wallet;
|
final wallet = getIt.get<AppStore>().wallet;
|
||||||
|
|
|
@ -1,57 +1,112 @@
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
|
import 'package:cake_wallet/buy/dfx/dfx_buy_provider.dart';
|
||||||
|
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
|
||||||
|
import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart';
|
||||||
|
import 'package:cake_wallet/di.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
|
||||||
enum BuyProviderType {
|
enum BuyProviderType {
|
||||||
AskEachTime,
|
askEachTime,
|
||||||
Robinhood,
|
robinhood,
|
||||||
Onramper,
|
dfx,
|
||||||
DFX;
|
onramper,
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
extension BuyProviderTypeName on BuyProviderType {
|
||||||
String toString() {
|
String get name {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case BuyProviderType.AskEachTime:
|
case BuyProviderType.askEachTime:
|
||||||
return S.current.ask_each_time;
|
return 'Ask each time';
|
||||||
case BuyProviderType.Robinhood:
|
case BuyProviderType.robinhood:
|
||||||
return "Robinhood";
|
return 'Robinhood Connect';
|
||||||
case BuyProviderType.Onramper:
|
case BuyProviderType.dfx:
|
||||||
return "Onramper";
|
return 'DFX Connect';
|
||||||
case BuyProviderType.DFX:
|
case BuyProviderType.onramper:
|
||||||
return "DFX";
|
return 'Onramper';
|
||||||
|
default:
|
||||||
|
return this.toString().split('.').last;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<BuyProviderType> getAvailableProviders(WalletType walletType) {
|
String get id {
|
||||||
|
switch (this) {
|
||||||
|
case BuyProviderType.askEachTime:
|
||||||
|
return 'ask_each_time_provider';
|
||||||
|
case BuyProviderType.robinhood:
|
||||||
|
return 'robinhood_connect_provider';
|
||||||
|
case BuyProviderType.dfx:
|
||||||
|
return 'dfx_connect_provider';
|
||||||
|
case BuyProviderType.onramper:
|
||||||
|
return 'onramper_provider';
|
||||||
|
default:
|
||||||
|
return this.toString().split('.').last.replaceAll('.', '_')
|
||||||
|
.toLowerCase() + '_provider';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BuyProviderHelper {
|
||||||
|
static List<BuyProviderType> getAvailableBuyProviderTypes(
|
||||||
|
WalletType walletType) {
|
||||||
switch (walletType) {
|
switch (walletType) {
|
||||||
case WalletType.nano:
|
case WalletType.nano:
|
||||||
case WalletType.banano:
|
case WalletType.banano:
|
||||||
return [
|
return [BuyProviderType.askEachTime, BuyProviderType.onramper];
|
||||||
BuyProviderType.AskEachTime,
|
|
||||||
BuyProviderType.Onramper
|
|
||||||
];
|
|
||||||
case WalletType.monero:
|
case WalletType.monero:
|
||||||
return [
|
return [
|
||||||
BuyProviderType.AskEachTime,
|
BuyProviderType.askEachTime,
|
||||||
BuyProviderType.Onramper,
|
BuyProviderType.onramper,
|
||||||
BuyProviderType.DFX
|
BuyProviderType.dfx
|
||||||
];
|
];
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
return [
|
return [
|
||||||
BuyProviderType.AskEachTime,
|
BuyProviderType.askEachTime,
|
||||||
BuyProviderType.Onramper,
|
BuyProviderType.onramper,
|
||||||
BuyProviderType.DFX,
|
BuyProviderType.dfx,
|
||||||
BuyProviderType.Robinhood
|
BuyProviderType.robinhood
|
||||||
];
|
];
|
||||||
case WalletType.litecoin:
|
case WalletType.litecoin:
|
||||||
case WalletType.bitcoinCash:
|
case WalletType.bitcoinCash:
|
||||||
return [
|
return [
|
||||||
BuyProviderType.AskEachTime,
|
BuyProviderType.askEachTime,
|
||||||
BuyProviderType.Onramper,
|
BuyProviderType.onramper,
|
||||||
BuyProviderType.Robinhood
|
BuyProviderType.robinhood
|
||||||
];
|
];
|
||||||
default:
|
default:
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static List<BuyProviderType> getAvailableSellProviderTypes(
|
||||||
|
WalletType walletType) {
|
||||||
|
switch (walletType) {
|
||||||
|
case WalletType.nano:
|
||||||
|
case WalletType.banano:
|
||||||
|
return [BuyProviderType.askEachTime];
|
||||||
|
case WalletType.monero:
|
||||||
|
return [BuyProviderType.askEachTime, BuyProviderType.dfx];
|
||||||
|
case WalletType.bitcoin:
|
||||||
|
case WalletType.ethereum:
|
||||||
|
return [BuyProviderType.askEachTime, BuyProviderType.dfx];
|
||||||
|
case WalletType.litecoin:
|
||||||
|
case WalletType.bitcoinCash:
|
||||||
|
return [BuyProviderType.askEachTime];
|
||||||
|
default:
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static BuyProvider? getProviderByType(BuyProviderType type) {
|
||||||
|
switch (type) {
|
||||||
|
case BuyProviderType.robinhood:
|
||||||
|
return getIt.get<RobinhoodBuyProvider>();
|
||||||
|
case BuyProviderType.dfx:
|
||||||
|
return getIt.get<DFXBuyProvider>();
|
||||||
|
case BuyProviderType.onramper:
|
||||||
|
return getIt.get<OnRamperBuyProvider>();
|
||||||
|
case BuyProviderType.askEachTime:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ Future<void> loadCurrentWallet() async {
|
||||||
final type = deserializeFromInt(typeRaw);
|
final type = deserializeFromInt(typeRaw);
|
||||||
final walletLoadingService = getIt.get<WalletLoadingService>();
|
final walletLoadingService = getIt.get<WalletLoadingService>();
|
||||||
final wallet = await walletLoadingService.load(type, name);
|
final wallet = await walletLoadingService.load(type, name);
|
||||||
appStore.changeCurrentWallet(wallet);
|
await appStore.changeCurrentWallet(wallet);
|
||||||
|
|
||||||
getIt.get<BackgroundTasks>().registerSyncTask();
|
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/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||||
import 'package:cake_wallet/utils/device_info.dart';
|
|
||||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
class MainActions {
|
class MainActions {
|
||||||
final String Function(BuildContext context) name;
|
final String Function(BuildContext context) name;
|
||||||
|
@ -46,53 +37,22 @@ class MainActions {
|
||||||
canShow: (viewModel) => viewModel.hasBuyAction,
|
canShow: (viewModel) => viewModel.hasBuyAction,
|
||||||
onTap: (BuildContext context, DashboardViewModel viewModel) async {
|
onTap: (BuildContext context, DashboardViewModel viewModel) async {
|
||||||
if (!viewModel.isEnabledBuyAction) {
|
if (!viewModel.isEnabledBuyAction) {
|
||||||
await _showErrorDialog(context, S.of(context).unsupported_asset);
|
await _showErrorDialog(
|
||||||
|
context, S.of(context).buy, S.of(context).unsupported_asset);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final defaultBuyProvider = viewModel.defaultBuyProvider;
|
final defaultBuyProvider = viewModel.defaultBuyProvider;
|
||||||
try {
|
try {
|
||||||
await _launchProviderByType(context, defaultBuyProvider);
|
defaultBuyProvider != null
|
||||||
|
? await defaultBuyProvider.launchProvider(context, true)
|
||||||
|
: await Navigator.of(context).pushNamed(Routes.buySellPage, arguments: true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await _showErrorDialog(context, e.toString());
|
await _showErrorDialog(context, defaultBuyProvider.toString(), e.toString());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
static Future<void> _launchProviderByType(BuildContext context, BuyProviderType providerType) async {
|
|
||||||
switch (providerType) {
|
|
||||||
case BuyProviderType.AskEachTime:
|
|
||||||
Navigator.pushNamed(context, Routes.buy);
|
|
||||||
break;
|
|
||||||
case BuyProviderType.Onramper:
|
|
||||||
await getIt.get<OnRamperBuyProvider>().launchProvider(context);
|
|
||||||
break;
|
|
||||||
case BuyProviderType.Robinhood:
|
|
||||||
await getIt.get<RobinhoodBuyProvider>().launchProvider(context);
|
|
||||||
break;
|
|
||||||
case BuyProviderType.DFX:
|
|
||||||
await getIt.get<DFXBuyProvider>().launchProvider(context);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw UnsupportedError('Unsupported buy provider type');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Future<void> _showErrorDialog(BuildContext context, String errorMessage) async {
|
|
||||||
await showPopUp<void>(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return AlertWithOneAction(
|
|
||||||
alertTitle: S.of(context).buy,
|
|
||||||
alertContent: errorMessage,
|
|
||||||
buttonText: S.of(context).ok,
|
|
||||||
buttonAction: () => Navigator.of(context).pop(),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static MainActions receiveAction = MainActions._(
|
static MainActions receiveAction = MainActions._(
|
||||||
name: (context) => S.of(context).receive,
|
name: (context) => S.of(context).receive,
|
||||||
image: 'assets/images/received.png',
|
image: 'assets/images/received.png',
|
||||||
|
@ -127,42 +87,35 @@ class MainActions {
|
||||||
isEnabled: (viewModel) => viewModel.isEnabledSellAction,
|
isEnabled: (viewModel) => viewModel.isEnabledSellAction,
|
||||||
canShow: (viewModel) => viewModel.hasSellAction,
|
canShow: (viewModel) => viewModel.hasSellAction,
|
||||||
onTap: (BuildContext context, DashboardViewModel viewModel) async {
|
onTap: (BuildContext context, DashboardViewModel viewModel) async {
|
||||||
final walletType = viewModel.type;
|
if (!viewModel.isEnabledSellAction) {
|
||||||
|
await _showErrorDialog(
|
||||||
|
context, S.of(context).sell, S.of(context).unsupported_asset);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (walletType) {
|
final defaultSellProvider = viewModel.defaultSellProvider;
|
||||||
case WalletType.bitcoin:
|
try {
|
||||||
case WalletType.litecoin:
|
defaultSellProvider != null
|
||||||
case WalletType.ethereum:
|
? await defaultSellProvider.launchProvider(context, false)
|
||||||
case WalletType.polygon:
|
: await Navigator.of(context).pushNamed(Routes.buySellPage, arguments: false);
|
||||||
case WalletType.bitcoinCash:
|
} catch (e) {
|
||||||
if (viewModel.isEnabledSellAction) {
|
await _showErrorDialog(context, defaultSellProvider.toString(), e.toString());
|
||||||
final moonPaySellProvider = MoonPaySellProvider();
|
|
||||||
final uri = await moonPaySellProvider.requestUrl(
|
|
||||||
currency: viewModel.wallet.currency,
|
|
||||||
refundWalletAddress: viewModel.wallet.walletAddresses.address,
|
|
||||||
settingsStore: viewModel.settingsStore,
|
|
||||||
);
|
|
||||||
if (DeviceInfo.instance.isMobile) {
|
|
||||||
Navigator.of(context).pushNamed(Routes.webViewPage,
|
|
||||||
arguments: [S.of(context).sell, uri]);
|
|
||||||
} else {
|
|
||||||
await launchUrl(uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
await showPopUp<void>(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return AlertWithOneAction(
|
|
||||||
alertTitle: S.of(context).sell,
|
|
||||||
alertContent: S.of(context).unsupported_asset,
|
|
||||||
buttonText: S.of(context).ok,
|
|
||||||
buttonAction: () => Navigator.of(context).pop());
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
static Future<void> _showErrorDialog(
|
||||||
|
BuildContext context, String title, String errorMessage) async {
|
||||||
|
await showPopUp<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertWithOneAction(
|
||||||
|
alertTitle: title,
|
||||||
|
alertContent: errorMessage,
|
||||||
|
buttonText: S.of(context).ok,
|
||||||
|
buttonAction: () => Navigator.of(context).pop(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -390,8 +390,10 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
return MaterialPageRoute<void>(
|
return MaterialPageRoute<void>(
|
||||||
builder: (_) => getIt.get<OrderDetailsPage>(param1: settings.arguments as Order));
|
builder: (_) => getIt.get<OrderDetailsPage>(param1: settings.arguments as Order));
|
||||||
|
|
||||||
case Routes.buy:
|
case Routes.buySellPage:
|
||||||
return MaterialPageRoute<void>(builder: (_) => getIt.get<BuyOptionsPage>());
|
final args = settings.arguments as bool;
|
||||||
|
return MaterialPageRoute<void>(
|
||||||
|
builder: (_) => getIt.get<BuySellOptionsPage>(param1: args));
|
||||||
|
|
||||||
case Routes.buyWebView:
|
case Routes.buyWebView:
|
||||||
final args = settings.arguments as List;
|
final args = settings.arguments as List;
|
||||||
|
|
|
@ -55,7 +55,7 @@ class Routes {
|
||||||
static const supportLiveChat = '/support/live_chat';
|
static const supportLiveChat = '/support/live_chat';
|
||||||
static const supportOtherLinks = '/support/other';
|
static const supportOtherLinks = '/support/other';
|
||||||
static const orderDetails = '/order_details';
|
static const orderDetails = '/order_details';
|
||||||
static const buy = '/buy';
|
static const buySellPage = '/buy_sell_page';
|
||||||
static const buyWebView = '/buy_web_view';
|
static const buyWebView = '/buy_web_view';
|
||||||
static const unspentCoinsList = '/unspent_coins_list';
|
static const unspentCoinsList = '/unspent_coins_list';
|
||||||
static const unspentCoinsDetails = '/unspent_coins_details';
|
static const unspentCoinsDetails = '/unspent_coins_details';
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
import 'package:cake_wallet/buy/dfx/dfx_buy_provider.dart';
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
|
|
||||||
import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart';
|
|
||||||
import 'package:cake_wallet/di.dart';
|
|
||||||
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
|
@ -11,19 +8,14 @@ import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
|
||||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class BuyOptionsPage extends BasePage {
|
class BuySellOptionsPage extends BasePage {
|
||||||
BuyOptionsPage(this.dashboardViewModel);
|
BuySellOptionsPage(this.dashboardViewModel, this.isBuyAction);
|
||||||
|
|
||||||
final DashboardViewModel dashboardViewModel;
|
final DashboardViewModel dashboardViewModel;
|
||||||
final iconDarkRobinhood = 'assets/images/robinhood_dark.png';
|
final bool isBuyAction;
|
||||||
final iconLightRobinhood = 'assets/images/robinhood_light.png';
|
|
||||||
final iconDarkOnramper = 'assets/images/onramper_dark.png';
|
|
||||||
final iconLightOnramper = 'assets/images/onramper_light.png';
|
|
||||||
final iconDarkDFX = 'assets/images/dfx_dark.png';
|
|
||||||
final iconLightDFX = 'assets/images/dfx_light.png';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get title => S.current.buy;
|
String get title => isBuyAction ? S.current.buy : S.current.sell;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
AppBarStyle get appBarStyle => AppBarStyle.regular;
|
AppBarStyle get appBarStyle => AppBarStyle.regular;
|
||||||
|
@ -32,17 +24,9 @@ class BuyOptionsPage extends BasePage {
|
||||||
Widget body(BuildContext context) {
|
Widget body(BuildContext context) {
|
||||||
final isLightMode =
|
final isLightMode =
|
||||||
Theme.of(context).extension<OptionTileTheme>()?.useDarkImage ?? false;
|
Theme.of(context).extension<OptionTileTheme>()?.useDarkImage ?? false;
|
||||||
final iconRobinhood = Image.asset(
|
final availableProviders = isBuyAction
|
||||||
isLightMode ? iconLightRobinhood : iconDarkRobinhood,
|
? dashboardViewModel.availableBuyProviders
|
||||||
height: 40,
|
: dashboardViewModel.availableSellProviders;
|
||||||
width: 40);
|
|
||||||
final iconOnramper = Image.asset(
|
|
||||||
isLightMode ? iconLightOnramper : iconDarkOnramper,
|
|
||||||
height: 40,
|
|
||||||
width: 40);
|
|
||||||
final iconDFX = Image.asset(isLightMode ? iconLightDFX : iconDarkDFX,
|
|
||||||
height: 40, width: 40);
|
|
||||||
final availableProviders = dashboardViewModel.availableProviders;
|
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
child: Center(
|
child: Center(
|
||||||
|
@ -50,57 +34,43 @@ class BuyOptionsPage extends BasePage {
|
||||||
constraints: BoxConstraints(maxWidth: 330),
|
constraints: BoxConstraints(maxWidth: 330),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
if (availableProviders.contains(BuyProviderType.Onramper))
|
...availableProviders.map((provider) {
|
||||||
Padding(
|
final icon = Image.asset(
|
||||||
|
isLightMode ? provider.lightIcon : provider.darkIcon,
|
||||||
|
height: 40,
|
||||||
|
width: 40,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Padding(
|
||||||
padding: EdgeInsets.only(top: 24),
|
padding: EdgeInsets.only(top: 24),
|
||||||
child: OptionTile(
|
child: OptionTile(
|
||||||
image: iconOnramper,
|
image: icon,
|
||||||
title: "Onramper",
|
title: provider.toString(),
|
||||||
description: S.of(context).onramper_option_description,
|
description: isBuyAction
|
||||||
onPressed: () async => await getIt
|
? provider.buyOptionDescription
|
||||||
.get<OnRamperBuyProvider>()
|
: provider.sellOptionDescription,
|
||||||
.launchProvider(context),
|
onPressed: () =>
|
||||||
|
provider.launchProvider(context, isBuyAction),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
if (availableProviders.contains(BuyProviderType.Robinhood))
|
}).toList(),
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.only(top: 24),
|
|
||||||
child: OptionTile(
|
|
||||||
image: iconRobinhood,
|
|
||||||
title: "Robinhood Connect",
|
|
||||||
description: S.of(context).robinhood_option_description,
|
|
||||||
onPressed: () async => await getIt
|
|
||||||
.get<RobinhoodBuyProvider>()
|
|
||||||
.launchProvider(context),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (availableProviders.contains(BuyProviderType.DFX))
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.only(top: 24),
|
|
||||||
child: OptionTile(
|
|
||||||
image: iconDFX,
|
|
||||||
title: "DFX Connect",
|
|
||||||
description: S.of(context).dfx_option_description,
|
|
||||||
onPressed: () async => await getIt
|
|
||||||
.get<DFXBuyProvider>()
|
|
||||||
.launchProvider(context),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Spacer(),
|
Spacer(),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
|
padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
|
||||||
child: Text(
|
child: Text(
|
||||||
S.of(context).select_buy_provider_notice,
|
isBuyAction
|
||||||
textAlign: TextAlign.center,
|
? S.of(context).select_buy_provider_notice
|
||||||
style: TextStyle(
|
: S.of(context).select_sell_provider_notice,
|
||||||
fontSize: 14,
|
textAlign: TextAlign.center,
|
||||||
fontWeight: FontWeight.normal,
|
style: TextStyle(
|
||||||
color: Theme.of(context)
|
fontSize: 14,
|
||||||
.extension<TransactionTradeTheme>()!
|
fontWeight: FontWeight.normal,
|
||||||
.detailsTitlesColor,
|
color: Theme.of(context)
|
||||||
|
.extension<TransactionTradeTheme>()!
|
||||||
|
.detailsTitlesColor,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -29,11 +29,10 @@ class BuyListItem extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final isSelected = selectedProvider?.description == provider.description;
|
final isSelected = selectedProvider?.buyOptionDescription == provider.buyOptionDescription;
|
||||||
final iconColor = isSelected ? Colors.white : Colors.black;
|
final iconColor = isSelected ? Colors.white : Colors.black;
|
||||||
|
|
||||||
final providerIcon = getBuyProviderIcon(provider.description,
|
final providerIcon = Image.asset('assets/images/wyre-icon.png', width: 36, height: 36);
|
||||||
iconColor: iconColor)!;
|
|
||||||
|
|
||||||
final backgroundColor = isSelected
|
final backgroundColor = isSelected
|
||||||
? Palette.greyBlueCraiola
|
? Palette.greyBlueCraiola
|
||||||
|
@ -76,7 +75,7 @@ class BuyListItem extends StatelessWidget {
|
||||||
padding: EdgeInsets.only(right: 10),
|
padding: EdgeInsets.only(right: 10),
|
||||||
child: providerIcon),
|
child: providerIcon),
|
||||||
Text(
|
Text(
|
||||||
provider.description.title,
|
provider.title,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: secondaryTextColor,
|
color: secondaryTextColor,
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
|
|
|
@ -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/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/screens/wallet_connect/widgets/modals/bottom_sheet_listener.dart';
|
||||||
import 'package:cake_wallet/src/widgets/gradient_background.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/themes/extensions/sync_indicator_theme.dart';
|
||||||
import 'package:cake_wallet/utils/device_info.dart';
|
import 'package:cake_wallet/utils/device_info.dart';
|
||||||
import 'package:cake_wallet/utils/version_comparator.dart';
|
import 'package:cake_wallet/utils/version_comparator.dart';
|
||||||
|
@ -60,7 +61,8 @@ class DashboardPage extends StatelessWidget {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (DeviceInfo.instance.isDesktop) {
|
if (DeviceInfo.instance.isDesktop) {
|
||||||
if (responsiveLayoutUtil.screenWidth > ResponsiveLayoutUtilBase.kDesktopMaxDashBoardWidthConstraint) {
|
if (responsiveLayoutUtil.screenWidth >
|
||||||
|
ResponsiveLayoutUtilBase.kDesktopMaxDashBoardWidthConstraint) {
|
||||||
return getIt.get<DesktopSidebarWrapper>();
|
return getIt.get<DesktopSidebarWrapper>();
|
||||||
} else {
|
} else {
|
||||||
return dashboardPageView;
|
return dashboardPageView;
|
||||||
|
@ -295,6 +297,8 @@ class _DashboardPageView extends BasePage {
|
||||||
|
|
||||||
_showReleaseNotesPopup(context);
|
_showReleaseNotesPopup(context);
|
||||||
|
|
||||||
|
_showVulnerableSeedsPopup(context);
|
||||||
|
|
||||||
var needToPresentYat = false;
|
var needToPresentYat = false;
|
||||||
var isInactive = false;
|
var isInactive = false;
|
||||||
|
|
||||||
|
@ -354,4 +358,22 @@ class _DashboardPageView extends BasePage {
|
||||||
sharedPrefs.setInt(PreferencesKey.lastSeenAppVersion, currentAppVersion);
|
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/routes.dart';
|
||||||
import 'package:cake_wallet/src/screens/release_notes/release_notes_screen.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/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/show_pop_up.dart';
|
||||||
import 'package:cake_wallet/utils/version_comparator.dart';
|
import 'package:cake_wallet/utils/version_comparator.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -110,5 +111,25 @@ class DesktopDashboardPage extends StatelessWidget {
|
||||||
} else if (isNewInstall!) {
|
} else if (isNewInstall!) {
|
||||||
sharedPrefs.setInt(PreferencesKey.lastSeenAppVersion, currentAppVersion);
|
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,
|
Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor,
|
||||||
height: 1,
|
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: [
|
tabs: [
|
||||||
Tab(text: 'My Crypto'),
|
Tab(text: 'My Crypto'),
|
||||||
Tab(text: 'My NFTs'),
|
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) {
|
reaction((_) => exchangeViewModel.isReceiveAmountEditable, (bool isReceiveAmountEditable) {
|
||||||
receiveKey.currentState!.isAmountEditable(isEditable: isReceiveAmountEditable);
|
receiveKey.currentState!.isAmountEditable(isEditable: isReceiveAmountEditable);
|
||||||
});
|
});
|
||||||
|
@ -670,7 +666,6 @@ class ExchangePage extends BasePage {
|
||||||
? exchangeViewModel.wallet.walletAddresses.address
|
? exchangeViewModel.wallet.walletAddresses.address
|
||||||
: exchangeViewModel.receiveAddress,
|
: exchangeViewModel.receiveAddress,
|
||||||
initialIsAmountEditable: exchangeViewModel.isReceiveAmountEditable,
|
initialIsAmountEditable: exchangeViewModel.isReceiveAmountEditable,
|
||||||
initialIsAddressEditable: exchangeViewModel.isReceiveAddressEnabled,
|
|
||||||
isAmountEstimated: true,
|
isAmountEstimated: true,
|
||||||
isMoneroWallet: exchangeViewModel.isMoneroWallet,
|
isMoneroWallet: exchangeViewModel.isMoneroWallet,
|
||||||
currencies: exchangeViewModel.receiveCurrencies,
|
currencies: exchangeViewModel.receiveCurrencies,
|
||||||
|
|
|
@ -174,8 +174,6 @@ class ExchangeTemplatePage extends BasePage {
|
||||||
? exchangeViewModel.wallet.walletAddresses.address
|
? exchangeViewModel.wallet.walletAddresses.address
|
||||||
: exchangeViewModel.receiveAddress,
|
: exchangeViewModel.receiveAddress,
|
||||||
initialIsAmountEditable: false,
|
initialIsAmountEditable: false,
|
||||||
initialIsAddressEditable:
|
|
||||||
exchangeViewModel.isReceiveAddressEnabled,
|
|
||||||
isAmountEstimated: true,
|
isAmountEstimated: true,
|
||||||
isMoneroWallet: exchangeViewModel.isMoneroWallet,
|
isMoneroWallet: exchangeViewModel.isMoneroWallet,
|
||||||
currencies: exchangeViewModel.receiveCurrencies,
|
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) {
|
reaction((_) => exchangeViewModel.provider, (ExchangeProvider? provider) {
|
||||||
receiveKey.currentState!.isAmountEditable(isEditable: false);
|
receiveKey.currentState!.isAmountEditable(isEditable: false);
|
||||||
});
|
});
|
||||||
|
|
|
@ -23,7 +23,6 @@ class ExchangeCard extends StatefulWidget {
|
||||||
required this.initialAddress,
|
required this.initialAddress,
|
||||||
required this.initialWalletName,
|
required this.initialWalletName,
|
||||||
required this.initialIsAmountEditable,
|
required this.initialIsAmountEditable,
|
||||||
required this.initialIsAddressEditable,
|
|
||||||
required this.isAmountEstimated,
|
required this.isAmountEstimated,
|
||||||
required this.currencies,
|
required this.currencies,
|
||||||
required this.onCurrencySelected,
|
required this.onCurrencySelected,
|
||||||
|
@ -31,6 +30,7 @@ class ExchangeCard extends StatefulWidget {
|
||||||
this.currencyValueValidator,
|
this.currencyValueValidator,
|
||||||
this.addressTextFieldValidator,
|
this.addressTextFieldValidator,
|
||||||
this.title = '',
|
this.title = '',
|
||||||
|
this.initialIsAddressEditable = true,
|
||||||
this.hasRefundAddress = false,
|
this.hasRefundAddress = false,
|
||||||
this.isMoneroWallet = false,
|
this.isMoneroWallet = false,
|
||||||
this.currencyButtonColor = Colors.transparent,
|
this.currencyButtonColor = Colors.transparent,
|
||||||
|
|
|
@ -43,10 +43,18 @@ class OtherSettingsPage extends BasePage {
|
||||||
if(_otherSettingsViewModel.isEnabledBuyAction)
|
if(_otherSettingsViewModel.isEnabledBuyAction)
|
||||||
SettingsPickerCell(
|
SettingsPickerCell(
|
||||||
title: S.current.default_buy_provider,
|
title: S.current.default_buy_provider,
|
||||||
items: _otherSettingsViewModel.availableBuyProviders,
|
items: _otherSettingsViewModel.availableBuyProvidersTypes,
|
||||||
displayItem: _otherSettingsViewModel.getBuyProviderType,
|
displayItem: _otherSettingsViewModel.getBuyProviderType,
|
||||||
selectedItem: _otherSettingsViewModel.buyProviderType,
|
selectedItem: _otherSettingsViewModel.buyProviderType,
|
||||||
onItemSelected: _otherSettingsViewModel.onBuyProviderTypeSelected,
|
onItemSelected: _otherSettingsViewModel.onBuyProviderTypeSelected
|
||||||
|
),
|
||||||
|
if(_otherSettingsViewModel.isEnabledSellAction)
|
||||||
|
SettingsPickerCell(
|
||||||
|
title: S.current.default_sell_provider,
|
||||||
|
items: _otherSettingsViewModel.availableSellProvidersTypes,
|
||||||
|
displayItem: _otherSettingsViewModel.getSellProviderType,
|
||||||
|
selectedItem: _otherSettingsViewModel.sellProviderType,
|
||||||
|
onItemSelected: _otherSettingsViewModel.onSellProviderTypeSelected,
|
||||||
),
|
),
|
||||||
SettingsCellWithArrow(
|
SettingsCellWithArrow(
|
||||||
title: S.current.settings_terms_and_conditions,
|
title: S.current.settings_terms_and_conditions,
|
||||||
|
|
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;
|
AuthenticationStore authenticationStore;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>?
|
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>? wallet;
|
||||||
wallet;
|
|
||||||
|
|
||||||
WalletListStore walletList;
|
WalletListStore walletList;
|
||||||
|
|
||||||
|
@ -36,16 +35,16 @@ abstract class AppStoreBase with Store {
|
||||||
NodeListStore nodeListStore;
|
NodeListStore nodeListStore;
|
||||||
|
|
||||||
@action
|
@action
|
||||||
void changeCurrentWallet(
|
Future<void> changeCurrentWallet(
|
||||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>,
|
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet) async {
|
||||||
TransactionInfo>
|
|
||||||
wallet) {
|
|
||||||
this.wallet?.close();
|
this.wallet?.close();
|
||||||
this.wallet = wallet;
|
this.wallet = wallet;
|
||||||
this.wallet!.setExceptionHandler(ExceptionHandler.onError);
|
this.wallet!.setExceptionHandler(ExceptionHandler.onError);
|
||||||
|
|
||||||
if (isEVMCompatibleChain(wallet.type)) {
|
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/bitcoin.dart';
|
||||||
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
||||||
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
|
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
|
||||||
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
||||||
import 'package:cake_wallet/entities/cake_2fa_preset_options.dart';
|
import 'package:cake_wallet/entities/cake_2fa_preset_options.dart';
|
||||||
|
@ -147,7 +148,9 @@ abstract class SettingsStoreBase with Store {
|
||||||
initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
||||||
currentSyncMode = initialSyncMode,
|
currentSyncMode = initialSyncMode,
|
||||||
currentSyncAll = initialSyncAll,
|
currentSyncAll = initialSyncAll,
|
||||||
priority = ObservableMap<WalletType, TransactionPriority>() {
|
priority = ObservableMap<WalletType, TransactionPriority>(),
|
||||||
|
defaultBuyProviders = ObservableMap<WalletType, BuyProviderType>(),
|
||||||
|
defaultSellProviders = ObservableMap<WalletType, BuyProviderType>() {
|
||||||
//this.nodes = ObservableMap<WalletType, Node>.of(nodes);
|
//this.nodes = ObservableMap<WalletType, Node>.of(nodes);
|
||||||
|
|
||||||
if (initialMoneroTransactionPriority != null) {
|
if (initialMoneroTransactionPriority != null) {
|
||||||
|
@ -181,9 +184,25 @@ abstract class SettingsStoreBase with Store {
|
||||||
initializeTrocadorProviderStates();
|
initializeTrocadorProviderStates();
|
||||||
|
|
||||||
WalletType.values.forEach((walletType) {
|
WalletType.values.forEach((walletType) {
|
||||||
final key = 'defaultBuyProvider_${walletType.toString()}';
|
final key = 'buyProvider_${walletType.toString()}';
|
||||||
final providerIndex = sharedPreferences.getInt(key);
|
final providerId = sharedPreferences.getString(key);
|
||||||
defaultBuyProviders[walletType] = providerIndex != null ? BuyProviderType.values[providerIndex] : BuyProviderType.AskEachTime;
|
if (providerId != null) {
|
||||||
|
defaultBuyProviders[walletType] = BuyProviderType.values
|
||||||
|
.firstWhere((provider) => provider.id == providerId, orElse: () => BuyProviderType.askEachTime);
|
||||||
|
} else {
|
||||||
|
defaultBuyProviders[walletType] = BuyProviderType.askEachTime;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
WalletType.values.forEach((walletType) {
|
||||||
|
final key = 'sellProvider_${walletType.toString()}';
|
||||||
|
final providerId = sharedPreferences.getString(key);
|
||||||
|
if (providerId != null) {
|
||||||
|
defaultSellProviders[walletType] = BuyProviderType.values
|
||||||
|
.firstWhere((provider) => provider.id == providerId, orElse: () => BuyProviderType.askEachTime);
|
||||||
|
} else {
|
||||||
|
defaultSellProviders[walletType] = BuyProviderType.askEachTime;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
reaction(
|
reaction(
|
||||||
|
@ -196,6 +215,20 @@ abstract class SettingsStoreBase with Store {
|
||||||
(bool shouldShowYatPopup) =>
|
(bool shouldShowYatPopup) =>
|
||||||
sharedPreferences.setBool(PreferencesKey.shouldShowYatPopup, shouldShowYatPopup));
|
sharedPreferences.setBool(PreferencesKey.shouldShowYatPopup, shouldShowYatPopup));
|
||||||
|
|
||||||
|
defaultBuyProviders.observe((change) {
|
||||||
|
final String key = 'buyProvider_${change.key.toString()}';
|
||||||
|
if (change.newValue != null) {
|
||||||
|
sharedPreferences.setString(key, change.newValue!.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
defaultSellProviders.observe((change) {
|
||||||
|
final String key = 'sellProvider_${change.key.toString()}';
|
||||||
|
if (change.newValue != null) {
|
||||||
|
sharedPreferences.setString(key, change.newValue!.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
priority.observe((change) {
|
priority.observe((change) {
|
||||||
final String? key;
|
final String? key;
|
||||||
switch (change.key) {
|
switch (change.key) {
|
||||||
|
@ -251,16 +284,6 @@ abstract class SettingsStoreBase with Store {
|
||||||
(bool disableSell) =>
|
(bool disableSell) =>
|
||||||
sharedPreferences.setBool(PreferencesKey.disableSellKey, disableSell));
|
sharedPreferences.setBool(PreferencesKey.disableSellKey, disableSell));
|
||||||
|
|
||||||
reaction(
|
|
||||||
(_) => defaultBuyProviders.asObservable(),
|
|
||||||
(ObservableMap<WalletType, BuyProviderType> providers) {
|
|
||||||
providers.forEach((walletType, provider) {
|
|
||||||
final key = 'defaultBuyProvider_${walletType.toString()}';
|
|
||||||
sharedPreferences.setInt(key, provider.index);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
reaction(
|
reaction(
|
||||||
(_) => walletListOrder,
|
(_) => walletListOrder,
|
||||||
(WalletListOrderType walletListOrder) =>
|
(WalletListOrderType walletListOrder) =>
|
||||||
|
@ -594,7 +617,10 @@ abstract class SettingsStoreBase with Store {
|
||||||
ObservableMap<String, bool> trocadorProviderStates = ObservableMap<String, bool>();
|
ObservableMap<String, bool> trocadorProviderStates = ObservableMap<String, bool>();
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
ObservableMap<WalletType, BuyProviderType> defaultBuyProviders = ObservableMap<WalletType, BuyProviderType>();
|
ObservableMap<WalletType, BuyProviderType> defaultBuyProviders;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
ObservableMap<WalletType, BuyProviderType> defaultSellProviders;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
SortBalanceBy sortBalanceBy;
|
SortBalanceBy sortBalanceBy;
|
||||||
|
|
|
@ -61,8 +61,7 @@ abstract class BuyViewModelBase with Store {
|
||||||
String _url = '';
|
String _url = '';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_url = await selectedProvider
|
_url = await selectedProvider!.requestUrl(doubleAmount.toString(), fiatCurrency.title);
|
||||||
!.requestUrl(doubleAmount.toString(), fiatCurrency.title);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e.toString());
|
print(e.toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,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/auto_generate_subaddress_status.dart';
|
||||||
import 'package:cake_wallet/entities/balance_display_mode.dart';
|
import 'package:cake_wallet/entities/balance_display_mode.dart';
|
||||||
import 'package:cake_wallet/entities/buy_provider_types.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/dashboard/transaction_list_item.dart';
|
||||||
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
|
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
|
||||||
import 'package:cake_wallet/wallet_type_utils.dart';
|
import 'package:cake_wallet/wallet_type_utils.dart';
|
||||||
|
import 'package:cryptography/cryptography.dart';
|
||||||
import 'package:cw_core/balance.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/sync_status.dart';
|
||||||
import 'package:cw_core/transaction_history.dart';
|
import 'package:cw_core/transaction_history.dart';
|
||||||
import 'package:cw_core/transaction_info.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_base.dart';
|
||||||
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_core/wallet_type.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:mobx/mobx.dart';
|
||||||
|
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
||||||
|
|
||||||
part 'dashboard_view_model.g.dart';
|
part 'dashboard_view_model.g.dart';
|
||||||
|
|
||||||
|
@ -46,7 +58,8 @@ abstract class DashboardViewModelBase with Store {
|
||||||
required this.settingsStore,
|
required this.settingsStore,
|
||||||
required this.yatStore,
|
required this.yatStore,
|
||||||
required this.ordersStore,
|
required this.ordersStore,
|
||||||
required this.anonpayTransactionsStore})
|
required this.anonpayTransactionsStore,
|
||||||
|
required this.keyService})
|
||||||
: hasSellAction = false,
|
: hasSellAction = false,
|
||||||
hasBuyAction = false,
|
hasBuyAction = false,
|
||||||
hasExchangeAction = false,
|
hasExchangeAction = false,
|
||||||
|
@ -262,6 +275,8 @@ abstract class DashboardViewModelBase with Store {
|
||||||
|
|
||||||
bool get hasRescan => wallet.type == WalletType.monero || wallet.type == WalletType.haven;
|
bool get hasRescan => wallet.type == WalletType.monero || wallet.type == WalletType.haven;
|
||||||
|
|
||||||
|
final KeyService keyService;
|
||||||
|
|
||||||
BalanceViewModel balanceViewModel;
|
BalanceViewModel balanceViewModel;
|
||||||
|
|
||||||
AppStore appStore;
|
AppStore appStore;
|
||||||
|
@ -282,13 +297,31 @@ abstract class DashboardViewModelBase with Store {
|
||||||
|
|
||||||
Map<String, List<FilterItem>> filterItems;
|
Map<String, List<FilterItem>> filterItems;
|
||||||
|
|
||||||
BuyProviderType get defaultBuyProvider =>
|
BuyProvider? get defaultBuyProvider => BuyProviderHelper.getProviderByType(
|
||||||
settingsStore.defaultBuyProviders[wallet.type] ??
|
settingsStore.defaultBuyProviders[wallet.type] ?? BuyProviderType.askEachTime);
|
||||||
BuyProviderType.AskEachTime;
|
|
||||||
|
BuyProvider? get defaultSellProvider => BuyProviderHelper.getProviderByType(
|
||||||
|
settingsStore.defaultSellProviders[wallet.type] ?? BuyProviderType.askEachTime);
|
||||||
|
|
||||||
bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled;
|
bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled;
|
||||||
|
|
||||||
List<BuyProviderType> get availableProviders => 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;
|
bool get shouldShowYatPopup => settingsStore.shouldShowYatPopup;
|
||||||
|
|
||||||
|
@ -302,16 +335,15 @@ abstract class DashboardViewModelBase with Store {
|
||||||
bool hasExchangeAction;
|
bool hasExchangeAction;
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
bool get isEnabledBuyAction => !settingsStore.disableBuy && wallet.type != WalletType.haven;
|
bool get isEnabledBuyAction =>
|
||||||
|
!settingsStore.disableBuy && availableBuyProviders.isNotEmpty;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
bool hasBuyAction;
|
bool hasBuyAction;
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
bool get isEnabledSellAction =>
|
bool get isEnabledSellAction =>
|
||||||
!settingsStore.disableSell &&
|
!settingsStore.disableSell && availableSellProviders.isNotEmpty;
|
||||||
wallet.type != WalletType.haven &&
|
|
||||||
wallet.type != WalletType.monero;
|
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
bool hasSellAction;
|
bool hasSellAction;
|
||||||
|
@ -433,4 +465,32 @@ abstract class DashboardViewModelBase with Store {
|
||||||
|
|
||||||
@action
|
@action
|
||||||
void setSyncAll(bool value) => settingsStore.currentSyncAll = value;
|
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 = '',
|
receiveAddress = '',
|
||||||
depositAddress = '',
|
depositAddress = '',
|
||||||
isDepositAddressEnabled = false,
|
isDepositAddressEnabled = false,
|
||||||
isReceiveAddressEnabled = false,
|
|
||||||
isReceiveAmountEditable = false,
|
isReceiveAmountEditable = false,
|
||||||
_useTorOnly = false,
|
_useTorOnly = false,
|
||||||
receiveCurrencies = <CryptoCurrency>[],
|
receiveCurrencies = <CryptoCurrency>[],
|
||||||
|
@ -108,7 +107,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||||
bestRateSync = Timer.periodic(Duration(seconds: 10), (timer) => _calculateBestRate());
|
bestRateSync = Timer.periodic(Duration(seconds: 10), (timer) => _calculateBestRate());
|
||||||
|
|
||||||
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
||||||
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
|
|
||||||
depositAmount = '';
|
depositAmount = '';
|
||||||
receiveAmount = '';
|
receiveAmount = '';
|
||||||
receiveAddress = '';
|
receiveAddress = '';
|
||||||
|
@ -201,9 +199,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||||
@observable
|
@observable
|
||||||
bool isDepositAddressEnabled;
|
bool isDepositAddressEnabled;
|
||||||
|
|
||||||
@observable
|
|
||||||
bool isReceiveAddressEnabled;
|
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
bool isReceiveAmountEntered;
|
bool isReceiveAmountEntered;
|
||||||
|
|
||||||
|
@ -315,7 +310,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||||
isFixedRateMode = false;
|
isFixedRateMode = false;
|
||||||
_onPairChange();
|
_onPairChange();
|
||||||
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
||||||
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
@ -324,7 +318,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||||
isFixedRateMode = false;
|
isFixedRateMode = false;
|
||||||
_onPairChange();
|
_onPairChange();
|
||||||
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
||||||
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
@ -535,7 +528,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||||
depositAddress = depositCurrency == wallet.currency ? wallet.walletAddresses.address : '';
|
depositAddress = depositCurrency == wallet.currency ? wallet.walletAddresses.address : '';
|
||||||
receiveAddress = receiveCurrency == wallet.currency ? wallet.walletAddresses.address : '';
|
receiveAddress = receiveCurrency == wallet.currency ? wallet.walletAddresses.address : '';
|
||||||
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
||||||
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
|
|
||||||
isFixedRateMode = false;
|
isFixedRateMode = false;
|
||||||
_onPairChange();
|
_onPairChange();
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,8 +50,10 @@ abstract class OrderDetailsViewModelBase with Store {
|
||||||
@action
|
@action
|
||||||
Future<void> _updateOrder() async {
|
Future<void> _updateOrder() async {
|
||||||
try {
|
try {
|
||||||
if (_provider != null) {
|
if (_provider != null && (_provider is MoonPayBuyProvider || _provider is WyreBuyProvider)) {
|
||||||
final updatedOrder = await _provider!.findOrderById(order.id);
|
final updatedOrder = _provider is MoonPayBuyProvider
|
||||||
|
? await (_provider as MoonPayBuyProvider).findOrderById(order.id)
|
||||||
|
: await (_provider as WyreBuyProvider).findOrderById(order.id);
|
||||||
updatedOrder.from = order.from;
|
updatedOrder.from = order.from;
|
||||||
updatedOrder.to = order.to;
|
updatedOrder.to = order.to;
|
||||||
updatedOrder.receiveAddress = order.receiveAddress;
|
updatedOrder.receiveAddress = order.receiveAddress;
|
||||||
|
@ -87,19 +89,26 @@ abstract class OrderDetailsViewModelBase with Store {
|
||||||
value: order.provider.title)
|
value: order.provider.title)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (_provider?.trackUrl.isNotEmpty ?? false) {
|
if (_provider != null && (_provider is MoonPayBuyProvider || _provider is WyreBuyProvider)) {
|
||||||
final buildURL = _provider!.trackUrl + '${order.transferId}';
|
|
||||||
items.add(
|
final trackUrl = _provider is MoonPayBuyProvider
|
||||||
TrackTradeListItem(
|
? (_provider as MoonPayBuyProvider).trackUrl
|
||||||
title: 'Track',
|
: (_provider as WyreBuyProvider).trackUrl;
|
||||||
value: buildURL,
|
|
||||||
onTap: () {
|
if (trackUrl.isNotEmpty ?? false) {
|
||||||
try {
|
final buildURL = trackUrl + '${order.transferId}';
|
||||||
launch(buildURL);
|
items.add(
|
||||||
} catch (e) {}
|
TrackTradeListItem(
|
||||||
}
|
title: 'Track',
|
||||||
)
|
value: buildURL,
|
||||||
);
|
onTap: () {
|
||||||
|
try {
|
||||||
|
launch(buildURL);
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
items.add(
|
items.add(
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||||
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
||||||
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
|
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/store/settings_store.dart';
|
import 'package:cake_wallet/store/settings_store.dart';
|
||||||
import 'package:cw_core/balance.dart';
|
import 'package:cw_core/balance.dart';
|
||||||
import 'package:cw_core/transaction_history.dart';
|
import 'package:cw_core/transaction_history.dart';
|
||||||
|
@ -59,12 +60,24 @@ abstract class OtherSettingsViewModelBase with Store {
|
||||||
bool get isEnabledBuyAction =>
|
bool get isEnabledBuyAction =>
|
||||||
!_settingsStore.disableBuy && _wallet.type != WalletType.haven;
|
!_settingsStore.disableBuy && _wallet.type != WalletType.haven;
|
||||||
|
|
||||||
List<BuyProviderType> get availableBuyProviders =>
|
@computed
|
||||||
BuyProviderType.getAvailableProviders(walletType);
|
bool get isEnabledSellAction =>
|
||||||
|
!_settingsStore.disableSell && _wallet.type != WalletType.haven;
|
||||||
|
|
||||||
|
List<BuyProviderType> get availableBuyProvidersTypes {
|
||||||
|
return BuyProviderHelper.getAvailableBuyProviderTypes(walletType);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<BuyProviderType> get availableSellProvidersTypes =>
|
||||||
|
BuyProviderHelper.getAvailableSellProviderTypes(walletType);
|
||||||
|
|
||||||
BuyProviderType get buyProviderType =>
|
BuyProviderType get buyProviderType =>
|
||||||
_settingsStore.defaultBuyProviders[walletType] ??
|
_settingsStore.defaultBuyProviders[walletType] ??
|
||||||
BuyProviderType.AskEachTime;
|
BuyProviderType.askEachTime;
|
||||||
|
|
||||||
|
BuyProviderType get sellProviderType =>
|
||||||
|
_settingsStore.defaultSellProviders[walletType] ??
|
||||||
|
BuyProviderType.askEachTime;
|
||||||
|
|
||||||
String getDisplayPriority(dynamic priority) {
|
String getDisplayPriority(dynamic priority) {
|
||||||
final _priority = priority as TransactionPriority;
|
final _priority = priority as TransactionPriority;
|
||||||
|
@ -81,13 +94,27 @@ abstract class OtherSettingsViewModelBase with Store {
|
||||||
|
|
||||||
String getBuyProviderType(dynamic buyProviderType) {
|
String getBuyProviderType(dynamic buyProviderType) {
|
||||||
final _buyProviderType = buyProviderType as BuyProviderType;
|
final _buyProviderType = buyProviderType as BuyProviderType;
|
||||||
|
return _buyProviderType == BuyProviderType.askEachTime
|
||||||
|
? S.current.ask_each_time
|
||||||
|
: _buyProviderType.name;
|
||||||
|
}
|
||||||
|
|
||||||
return _buyProviderType.toString();
|
String getSellProviderType(dynamic sellProviderType) {
|
||||||
|
final _sellProviderType = sellProviderType as BuyProviderType;
|
||||||
|
return _sellProviderType == BuyProviderType.askEachTime
|
||||||
|
? S.current.ask_each_time
|
||||||
|
: _sellProviderType.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onDisplayPrioritySelected(TransactionPriority priority) =>
|
void onDisplayPrioritySelected(TransactionPriority priority) =>
|
||||||
_settingsStore.priority[_wallet.type] = priority;
|
_settingsStore.priority[_wallet.type] = priority;
|
||||||
|
|
||||||
void onBuyProviderTypeSelected(BuyProviderType buyProviderType) =>
|
@action
|
||||||
|
BuyProviderType onBuyProviderTypeSelected(BuyProviderType buyProviderType) =>
|
||||||
_settingsStore.defaultBuyProviders[walletType] = buyProviderType;
|
_settingsStore.defaultBuyProviders[walletType] = buyProviderType;
|
||||||
|
|
||||||
|
@action
|
||||||
|
BuyProviderType onSellProviderTypeSelected(
|
||||||
|
BuyProviderType sellProviderType) =>
|
||||||
|
_settingsStore.defaultSellProviders[walletType] = sellProviderType;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ abstract class WalletCreationVMBase with Store {
|
||||||
: await process(credentials);
|
: await process(credentials);
|
||||||
walletInfo.address = wallet.walletAddresses.address;
|
walletInfo.address = wallet.walletAddresses.address;
|
||||||
await _walletInfoSource.add(walletInfo);
|
await _walletInfoSource.add(walletInfo);
|
||||||
_appStore.changeCurrentWallet(wallet);
|
await _appStore.changeCurrentWallet(wallet);
|
||||||
getIt.get<BackgroundTasks>().registerSyncTask();
|
getIt.get<BackgroundTasks>().registerSyncTask();
|
||||||
_appStore.authenticationStore.allowed();
|
_appStore.authenticationStore.allowed();
|
||||||
state = ExecutedSuccessfullyState();
|
state = ExecutedSuccessfullyState();
|
||||||
|
|
|
@ -45,7 +45,7 @@ abstract class WalletListViewModelBase with Store {
|
||||||
@action
|
@action
|
||||||
Future<void> loadWallet(WalletListItem walletItem) async {
|
Future<void> loadWallet(WalletListItem walletItem) async {
|
||||||
final wallet = await _walletLoadingService.load(walletItem.type, walletItem.name);
|
final wallet = await _walletLoadingService.load(walletItem.type, walletItem.name);
|
||||||
_appStore.changeCurrentWallet(wallet);
|
await _appStore.changeCurrentWallet(wallet);
|
||||||
}
|
}
|
||||||
|
|
||||||
WalletListOrderType? get orderType => _appStore.settingsStore.walletListOrder;
|
WalletListOrderType? get orderType => _appStore.settingsStore.walletListOrder;
|
||||||
|
|
|
@ -41,7 +41,6 @@ PODS:
|
||||||
- shared_preferences_foundation (0.0.1):
|
- shared_preferences_foundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- tor (0.0.1)
|
|
||||||
- url_launcher_macos (0.0.1):
|
- url_launcher_macos (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- wakelock_plus (0.0.1):
|
- wakelock_plus (0.0.1):
|
||||||
|
@ -60,7 +59,6 @@ DEPENDENCIES:
|
||||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
- share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`)
|
- share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`)
|
||||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- 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`)
|
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||||
- wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/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
|
:path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
||||||
tor:
|
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/tor/macos
|
|
||||||
url_launcher_macos:
|
url_launcher_macos:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||||
wakelock_plus:
|
wakelock_plus:
|
||||||
|
@ -102,7 +98,7 @@ EXTERNAL SOURCES:
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308
|
connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308
|
||||||
cw_monero: f8b7f104508efba2591548e76b5c058d05cba3f0
|
cw_monero: ec03de55a19c4a2b174ea687e0f4202edc716fa4
|
||||||
device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
|
device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
|
||||||
devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225
|
devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225
|
||||||
flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
|
flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
|
||||||
|
@ -114,7 +110,6 @@ SPEC CHECKSUMS:
|
||||||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||||
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
|
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
|
||||||
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
|
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
|
||||||
tor: 2138c48428e696b83eacdda404de6d5574932e26
|
|
||||||
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
|
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
|
||||||
wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269
|
wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269
|
||||||
|
|
||||||
|
|
|
@ -756,6 +756,8 @@
|
||||||
"dfx_option_description": "ﺎﺑﻭﺭﻭﺃ ﻲﻓ ﺕﺎﻛﺮﺸﻟﺍﻭ ﺔﺋﺰﺠﺘﻟﺍ ءﻼﻤﻌﻟ .ﻲﻓﺎﺿﺇ KYC ﻥﻭﺪﺑ ﻭﺭﻮﻳ 990 ﻰﻟﺇ ﻞﺼﻳ ﺎﻣ .ﻱﺮﺴﻳﻮﺴﻟﺍ",
|
"dfx_option_description": "ﺎﺑﻭﺭﻭﺃ ﻲﻓ ﺕﺎﻛﺮﺸﻟﺍﻭ ﺔﺋﺰﺠﺘﻟﺍ ءﻼﻤﻌﻟ .ﻲﻓﺎﺿﺇ KYC ﻥﻭﺪﺑ ﻭﺭﻮﻳ 990 ﻰﻟﺇ ﻞﺼﻳ ﺎﻣ .ﻱﺮﺴﻳﻮﺴﻟﺍ",
|
||||||
"polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ",
|
"polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ",
|
||||||
"wallet_seed_legacy": "بذرة محفظة قديمة",
|
"wallet_seed_legacy": "بذرة محفظة قديمة",
|
||||||
|
"default_sell_provider": " ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ",
|
||||||
|
"select_sell_provider_notice": ".ﻖﻴﺒﻄﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻚﺑ ﺹﺎﺨﻟﺍ ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ ﻦﻴﻴﻌﺗ ﻖﻳﺮﻃ ﻦﻋ ﺔﺷﺎﺸﻟﺍ ﻩﺬﻫ ﻲﻄﺨﺗ",
|
||||||
"custom_drag": "مخصص (عقد وسحب)",
|
"custom_drag": "مخصص (عقد وسحب)",
|
||||||
"switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ"
|
"switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ"
|
||||||
}
|
}
|
||||||
|
|
|
@ -752,6 +752,8 @@
|
||||||
"dfx_option_description": "Купете крипто с EUR и CHF. До 990 € без допълнителен KYC. За клиенти на дребно и корпоративни клиенти в Европа",
|
"dfx_option_description": "Купете крипто с EUR и CHF. До 990 € без допълнителен KYC. За клиенти на дребно и корпоративни клиенти в Европа",
|
||||||
"polygonscan_history": "История на PolygonScan",
|
"polygonscan_history": "История на PolygonScan",
|
||||||
"wallet_seed_legacy": "Наследено портфейл семе",
|
"wallet_seed_legacy": "Наследено портфейл семе",
|
||||||
|
"default_sell_provider": "Доставчик за продажба по подразбиране",
|
||||||
|
"select_sell_provider_notice": "Изберете доставчик на продажба по-горе. Можете да пропуснете този екран, като зададете своя доставчик на продажба по подразбиране в настройките на приложението.",
|
||||||
"custom_drag": "Персонализиране (задръжте и плъзнете)",
|
"custom_drag": "Персонализиране (задръжте и плъзнете)",
|
||||||
"switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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ě",
|
"dfx_option_description": "Nakupujte kryptoměny za EUR a CHF. Až 990 € bez dalších KYC. Pro maloobchodní a firemní zákazníky v Evropě",
|
||||||
"polygonscan_history": "Historie PolygonScan",
|
"polygonscan_history": "Historie PolygonScan",
|
||||||
"wallet_seed_legacy": "Starší semeno peněženky",
|
"wallet_seed_legacy": "Starší semeno peněženky",
|
||||||
|
"default_sell_provider": "Výchozí poskytovatel prodeje",
|
||||||
|
"select_sell_provider_notice": "Výše vyberte poskytovatele prodeje. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele prodeje v nastavení aplikace.",
|
||||||
"custom_drag": "Custom (Hold and Drag)",
|
"custom_drag": "Custom (Hold and Drag)",
|
||||||
"switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
"dfx_option_description": "Krypto mit EUR und CHF kaufen. Bis zu 990€ ohne zusätzliches KYC. Für Privat- und Firmenkunden in Europa",
|
||||||
"polygonscan_history": "PolygonScan-Verlauf",
|
"polygonscan_history": "PolygonScan-Verlauf",
|
||||||
"wallet_seed_legacy": "Legacy Wallet Seed",
|
"wallet_seed_legacy": "Legacy Wallet Seed",
|
||||||
|
"default_sell_provider": "Standard-Verkaufsanbieter",
|
||||||
|
"select_sell_provider_notice": "Wählen Sie oben einen Verkaufsanbieter aus. Sie können diesen Bildschirm überspringen, indem Sie in den App-Einstellungen Ihren Standard-Verkaufsanbieter festlegen.",
|
||||||
"custom_drag": "Custom (Hold and Drag)",
|
"custom_drag": "Custom (Hold and Drag)",
|
||||||
"switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
"dfx_option_description": "Buy crypto with EUR & CHF. Up to 990€ without additional KYC. For retail and corporate customers in Europe",
|
||||||
"polygonscan_history": "PolygonScan history",
|
"polygonscan_history": "PolygonScan history",
|
||||||
"wallet_seed_legacy": "Legacy wallet seed",
|
"wallet_seed_legacy": "Legacy wallet seed",
|
||||||
|
"default_sell_provider": "Default Sell Provider",
|
||||||
|
"select_sell_provider_notice": "Select a sell provider above. You can skip this screen by setting your default sell provider in app settings.",
|
||||||
"custom_drag": "Custom (Hold and Drag)",
|
"custom_drag": "Custom (Hold and Drag)",
|
||||||
"switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -760,6 +760,8 @@
|
||||||
"seed_language_chinese_traditional": "Chino (tradicional)",
|
"seed_language_chinese_traditional": "Chino (tradicional)",
|
||||||
"polygonscan_history": "Historial de PolygonScan",
|
"polygonscan_history": "Historial de PolygonScan",
|
||||||
"wallet_seed_legacy": "Semilla de billetera heredada",
|
"wallet_seed_legacy": "Semilla de billetera heredada",
|
||||||
|
"default_sell_provider": "Proveedor de venta predeterminado",
|
||||||
|
"select_sell_provider_notice": "Seleccione un proveedor de venta arriba. Puede omitir esta pantalla configurando su proveedor de venta predeterminado en la configuración de la aplicación.",
|
||||||
"custom_drag": "Custom (mantenía y arrastre)",
|
"custom_drag": "Custom (mantenía y arrastre)",
|
||||||
"switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
"dfx_option_description": "Achetez des crypto-monnaies avec EUR et CHF. Jusqu'à 990€ sans KYC supplémentaire. Pour les clients particuliers et entreprises en Europe",
|
||||||
"polygonscan_history": "Historique de PolygonScan",
|
"polygonscan_history": "Historique de PolygonScan",
|
||||||
"wallet_seed_legacy": "Graine de portefeuille hérité",
|
"wallet_seed_legacy": "Graine de portefeuille hérité",
|
||||||
|
"default_sell_provider": "Fournisseur de vente par défaut",
|
||||||
|
"select_sell_provider_notice": "Sélectionnez un fournisseur de vente ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur de vente par défaut dans les paramètres de l'application.",
|
||||||
"custom_drag": "Custom (maintenir et traîner)",
|
"custom_drag": "Custom (maintenir et traîner)",
|
||||||
"switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -742,6 +742,8 @@
|
||||||
"polygonscan_history": "PolygonScan tarihin kowane zamani",
|
"polygonscan_history": "PolygonScan tarihin kowane zamani",
|
||||||
"wallet_seed_legacy": "Tallarin walat walat",
|
"wallet_seed_legacy": "Tallarin walat walat",
|
||||||
"setup_totp_recommended": "Saita TOTP",
|
"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)",
|
"custom_drag": "Al'ada (riƙe da ja)",
|
||||||
"switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -760,6 +760,8 @@
|
||||||
"dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। अतिरिक्त केवाईसी के बिना 990€ तक। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए",
|
"dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। अतिरिक्त केवाईसी के बिना 990€ तक। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए",
|
||||||
"polygonscan_history": "पॉलीगॉनस्कैन इतिहास",
|
"polygonscan_history": "पॉलीगॉनस्कैन इतिहास",
|
||||||
"wallet_seed_legacy": "विरासत बटुए बीज",
|
"wallet_seed_legacy": "विरासत बटुए बीज",
|
||||||
|
"default_sell_provider": "डिफ़ॉल्ट विक्रय प्रदाता",
|
||||||
|
"select_sell_provider_notice": "ऊपर एक विक्रय प्रदाता का चयन करें। आप ऐप सेटिंग में अपना डिफ़ॉल्ट विक्रय प्रदाता सेट करके इस स्क्रीन को छोड़ सकते हैं।",
|
||||||
"custom_drag": "कस्टम (पकड़ और खींचें)",
|
"custom_drag": "कस्टम (पकड़ और खींचें)",
|
||||||
"switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)"
|
"switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
"dfx_option_description": "Kupujte kripto s EUR i CHF. Do 990 € bez dodatnog KYC-a. Za maloprodajne i poslovne korisnike u Europi",
|
||||||
"polygonscan_history": "Povijest PolygonScan",
|
"polygonscan_history": "Povijest PolygonScan",
|
||||||
"wallet_seed_legacy": "Sjeme naslijeđenog novčanika",
|
"wallet_seed_legacy": "Sjeme naslijeđenog novčanika",
|
||||||
|
"default_sell_provider": "Zadani dobavljač prodaje",
|
||||||
|
"select_sell_provider_notice": "Gore odaberite pružatelja usluga prodaje. Ovaj zaslon možete preskočiti postavljanjem zadanog pružatelja usluga prodaje u postavkama aplikacije.",
|
||||||
"custom_drag": "Prilagođeni (držite i povucite)",
|
"custom_drag": "Prilagođeni (držite i povucite)",
|
||||||
"switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -748,6 +748,8 @@
|
||||||
"dfx_option_description": "Beli kripto dengan EUR & CHF. Hingga 990€ tanpa KYC tambahan. Untuk pelanggan ritel dan korporat di Eropa",
|
"dfx_option_description": "Beli kripto dengan EUR & CHF. Hingga 990€ tanpa KYC tambahan. Untuk pelanggan ritel dan korporat di Eropa",
|
||||||
"polygonscan_history": "Sejarah PolygonScan",
|
"polygonscan_history": "Sejarah PolygonScan",
|
||||||
"wallet_seed_legacy": "Biji dompet warisan",
|
"wallet_seed_legacy": "Biji dompet warisan",
|
||||||
|
"default_sell_provider": "Penyedia Penjualan Default",
|
||||||
|
"select_sell_provider_notice": "Pilih penyedia jual di atas. Anda dapat melewati layar ini dengan mengatur penyedia penjualan default Anda di pengaturan aplikasi.",
|
||||||
"custom_drag": "Khusus (tahan dan seret)",
|
"custom_drag": "Khusus (tahan dan seret)",
|
||||||
"switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
"dfx_option_description": "Acquista criptovalute con EUR e CHF. Fino a 990€ senza KYC aggiuntivi. Per clienti al dettaglio e aziendali in Europa",
|
||||||
"polygonscan_history": "Cronologia PolygonScan",
|
"polygonscan_history": "Cronologia PolygonScan",
|
||||||
"wallet_seed_legacy": "Seme di portafoglio legacy",
|
"wallet_seed_legacy": "Seme di portafoglio legacy",
|
||||||
|
"default_sell_provider": "Fornitore di vendita predefinito",
|
||||||
|
"select_sell_provider_notice": "Seleziona un fornitore di vendita sopra. Puoi saltare questa schermata impostando il tuo fornitore di vendita predefinito nelle impostazioni dell'app.",
|
||||||
"custom_drag": "Custom (Hold and Drag)",
|
"custom_drag": "Custom (Hold and Drag)",
|
||||||
"switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -760,6 +760,8 @@
|
||||||
"dfx_option_description": "EUR と CHF で暗号通貨を購入します。追加のKYCなしで最大990ユーロ。ヨーロッパの小売および法人顧客向け",
|
"dfx_option_description": "EUR と CHF で暗号通貨を購入します。追加のKYCなしで最大990ユーロ。ヨーロッパの小売および法人顧客向け",
|
||||||
"polygonscan_history": "ポリゴンスキャン履歴",
|
"polygonscan_history": "ポリゴンスキャン履歴",
|
||||||
"wallet_seed_legacy": "レガシーウォレットシード",
|
"wallet_seed_legacy": "レガシーウォレットシード",
|
||||||
|
"default_sell_provider": "デフォルトの販売プロバイダー",
|
||||||
|
"select_sell_provider_notice": "上記の販売プロバイダーを選択してください。アプリ設定でデフォルトの販売プロバイダーを設定することで、この画面をスキップできます。",
|
||||||
"custom_drag": "カスタム(ホールドとドラッグ)",
|
"custom_drag": "カスタム(ホールドとドラッグ)",
|
||||||
"switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)"
|
"switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,6 +758,8 @@
|
||||||
"dfx_option_description": "EUR 및 CHF로 암호화폐를 구매하세요. 추가 KYC 없이 최대 990€. 유럽의 소매 및 기업 고객용",
|
"dfx_option_description": "EUR 및 CHF로 암호화폐를 구매하세요. 추가 KYC 없이 최대 990€. 유럽의 소매 및 기업 고객용",
|
||||||
"polygonscan_history": "다각형 스캔 기록",
|
"polygonscan_history": "다각형 스캔 기록",
|
||||||
"wallet_seed_legacy": "레거시 지갑 시드",
|
"wallet_seed_legacy": "레거시 지갑 시드",
|
||||||
|
"default_sell_provider": "기본 판매 공급자",
|
||||||
|
"select_sell_provider_notice": "위에서 판매 공급자를 선택하세요. 앱 설정에서 기본 판매 공급자를 설정하면 이 화면을 건너뛸 수 있습니다.",
|
||||||
"custom_drag": "사용자 정의 (홀드 앤 드래그)",
|
"custom_drag": "사용자 정의 (홀드 앤 드래그)",
|
||||||
"switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)"
|
"switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,6 +758,8 @@
|
||||||
"dfx_option_description": "EUR & CHF ဖြင့် crypto ကိုဝယ်ပါ။ အပို KYC မပါဘဲ 990€ အထိ။ ဥရောပရှိ လက်လီရောင်းချသူများနှင့် ကော်ပိုရိတ်ဖောက်သည်များအတွက်",
|
"dfx_option_description": "EUR & CHF ဖြင့် crypto ကိုဝယ်ပါ။ အပို KYC မပါဘဲ 990€ အထိ။ ဥရောပရှိ လက်လီရောင်းချသူများနှင့် ကော်ပိုရိတ်ဖောက်သည်များအတွက်",
|
||||||
"polygonscan_history": "PolygonScan မှတ်တမ်း",
|
"polygonscan_history": "PolygonScan မှတ်တမ်း",
|
||||||
"wallet_seed_legacy": "အမွေအနှစ်ပိုက်ဆံအိတ်မျိုးစေ့",
|
"wallet_seed_legacy": "အမွေအနှစ်ပိုက်ဆံအိတ်မျိုးစေ့",
|
||||||
|
"default_sell_provider": "ပုံသေရောင်းချပေးသူ",
|
||||||
|
"select_sell_provider_notice": "အထက်ဖော်ပြပါ အရောင်းဝန်ဆောင်မှုပေးသူကို ရွေးပါ။ အက်ပ်ဆက်တင်များတွင် သင်၏မူလရောင်းချပေးသူကို သတ်မှတ်ခြင်းဖြင့် ဤစခရင်ကို ကျော်နိုင်သည်။",
|
||||||
"custom_drag": "စိတ်ကြိုက် (Drag)",
|
"custom_drag": "စိတ်ကြိုက် (Drag)",
|
||||||
"switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)"
|
"switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -760,6 +760,8 @@
|
||||||
"dfx_option_description": "Koop crypto met EUR & CHF. Tot 990€ zonder extra KYC. Voor particuliere en zakelijke klanten in Europa",
|
"dfx_option_description": "Koop crypto met EUR & CHF. Tot 990€ zonder extra KYC. Voor particuliere en zakelijke klanten in Europa",
|
||||||
"polygonscan_history": "PolygonScan-geschiedenis",
|
"polygonscan_history": "PolygonScan-geschiedenis",
|
||||||
"wallet_seed_legacy": "Legacy portemonnee zaad",
|
"wallet_seed_legacy": "Legacy portemonnee zaad",
|
||||||
|
"default_sell_provider": "Standaard verkoopaanbieder",
|
||||||
|
"select_sell_provider_notice": "Selecteer hierboven een verkoopaanbieder. U kunt dit scherm overslaan door uw standaardverkoopprovider in te stellen in de app-instellingen.",
|
||||||
"custom_drag": "Custom (vasthouden en slepen)",
|
"custom_drag": "Custom (vasthouden en slepen)",
|
||||||
"switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
"dfx_option_description": "Kupuj kryptowaluty za EUR i CHF. Do 990 € bez dodatkowego KYC. Dla klientów detalicznych i korporacyjnych w Europie",
|
||||||
"polygonscan_history": "Historia PolygonScan",
|
"polygonscan_history": "Historia PolygonScan",
|
||||||
"wallet_seed_legacy": "Dziedziczne ziarno portfela",
|
"wallet_seed_legacy": "Dziedziczne ziarno portfela",
|
||||||
|
"default_sell_provider": "Domyślny dostawca sprzedaży",
|
||||||
|
"select_sell_provider_notice": "Wybierz dostawcę sprzedaży powyżej. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę sprzedaży w ustawieniach aplikacji.",
|
||||||
"custom_drag": "Niestandardowe (trzymaj i przeciągnij)",
|
"custom_drag": "Niestandardowe (trzymaj i przeciągnij)",
|
||||||
"switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
"dfx_option_description": "Compre criptografia com EUR e CHF. Até 990€ sem KYC adicional. Para clientes de varejo e corporativos na Europa",
|
||||||
"polygonscan_history": "História do PolygonScan",
|
"polygonscan_history": "História do PolygonScan",
|
||||||
"wallet_seed_legacy": "Semente de carteira herdada",
|
"wallet_seed_legacy": "Semente de carteira herdada",
|
||||||
|
"default_sell_provider": "Provedor de venda padrão",
|
||||||
|
"select_sell_provider_notice": "Selecione um fornecedor de venda acima. Você pode pular esta tela definindo seu provedor de venda padrão nas configurações do aplicativo.",
|
||||||
"custom_drag": "Personalizado (segure e arraste)",
|
"custom_drag": "Personalizado (segure e arraste)",
|
||||||
"switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -760,6 +760,8 @@
|
||||||
"dfx_option_description": "Покупайте криптовалюту за EUR и CHF. До 990€ без дополнительного KYC. Для розничных и корпоративных клиентов в Европе",
|
"dfx_option_description": "Покупайте криптовалюту за EUR и CHF. До 990€ без дополнительного KYC. Для розничных и корпоративных клиентов в Европе",
|
||||||
"polygonscan_history": "История PolygonScan",
|
"polygonscan_history": "История PolygonScan",
|
||||||
"wallet_seed_legacy": "Наследие семя кошелька",
|
"wallet_seed_legacy": "Наследие семя кошелька",
|
||||||
|
"default_sell_provider": "Поставщик продаж по умолчанию",
|
||||||
|
"select_sell_provider_notice": "Выберите поставщика услуг продажи выше. Вы можете пропустить этот экран, установив поставщика услуг продаж по умолчанию в настройках приложения.",
|
||||||
"custom_drag": "Пользователь (удерживайте и перетаскивайте)",
|
"custom_drag": "Пользователь (удерживайте и перетаскивайте)",
|
||||||
"switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon)."
|
"switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon)."
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,6 +758,8 @@
|
||||||
"dfx_option_description": "ซื้อ crypto ด้วย EUR และ CHF สูงถึง 990€ โดยไม่มี KYC เพิ่มเติม สำหรับลูกค้ารายย่อยและลูกค้าองค์กรในยุโรป",
|
"dfx_option_description": "ซื้อ crypto ด้วย EUR และ CHF สูงถึง 990€ โดยไม่มี KYC เพิ่มเติม สำหรับลูกค้ารายย่อยและลูกค้าองค์กรในยุโรป",
|
||||||
"polygonscan_history": "ประวัติ PolygonScan",
|
"polygonscan_history": "ประวัติ PolygonScan",
|
||||||
"wallet_seed_legacy": "เมล็ดกระเป๋าเงินมรดก",
|
"wallet_seed_legacy": "เมล็ดกระเป๋าเงินมรดก",
|
||||||
|
"default_sell_provider": "ผู้ให้บริการการขายเริ่มต้น",
|
||||||
|
"select_sell_provider_notice": "เลือกผู้ให้บริการการขายด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการการขายเริ่มต้นในการตั้งค่าแอป",
|
||||||
"custom_drag": "กำหนดเอง (ค้างและลาก)",
|
"custom_drag": "กำหนดเอง (ค้างและลาก)",
|
||||||
"switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
"dfx_option_description": "Bumili ng crypto gamit ang EUR at CHF. Hanggang 990€ nang walang karagdagang KYC. Para sa retail at corporate na mga customer sa Europe",
|
||||||
"polygonscan_history": "Kasaysayan ng PolygonScan",
|
"polygonscan_history": "Kasaysayan ng PolygonScan",
|
||||||
"wallet_seed_legacy": "Legacy wallet seed",
|
"wallet_seed_legacy": "Legacy wallet seed",
|
||||||
|
"default_sell_provider": "Default na Sell Provider",
|
||||||
|
"select_sell_provider_notice": "Pumili ng provider ng nagbebenta sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na sell provider sa mga setting ng app.",
|
||||||
"custom_drag": "Pasadyang (hawakan at i -drag)",
|
"custom_drag": "Pasadyang (hawakan at i -drag)",
|
||||||
"switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
"dfx_option_description": "EUR ve CHF ile kripto satın alın. Ek KYC olmadan 990 €'ya kadar. Avrupa'daki perakende ve kurumsal müşteriler için",
|
||||||
"polygonscan_history": "PolygonScan geçmişi",
|
"polygonscan_history": "PolygonScan geçmişi",
|
||||||
"wallet_seed_legacy": "Eski cüzdan tohumu",
|
"wallet_seed_legacy": "Eski cüzdan tohumu",
|
||||||
|
"default_sell_provider": "Varsayılan Satış Sağlayıcısı",
|
||||||
|
"select_sell_provider_notice": "Yukarıdan bir satış sağlayıcısı seçin. Uygulama ayarlarında varsayılan satış sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.",
|
||||||
"custom_drag": "Özel (Bekle ve Sürükle)",
|
"custom_drag": "Özel (Bekle ve Sürükle)",
|
||||||
"switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -760,6 +760,8 @@
|
||||||
"seed_language_chinese_traditional": "Китайський (традиційний)",
|
"seed_language_chinese_traditional": "Китайський (традиційний)",
|
||||||
"polygonscan_history": "Історія PolygonScan",
|
"polygonscan_history": "Історія PolygonScan",
|
||||||
"wallet_seed_legacy": "Спадець насіння гаманця",
|
"wallet_seed_legacy": "Спадець насіння гаманця",
|
||||||
|
"default_sell_provider": "Постачальник продажу за замовчуванням",
|
||||||
|
"select_sell_provider_notice": "Виберіть вище постачальника послуг продажу. Ви можете пропустити цей екран, встановивши постачальника послуг продажу за умовчанням у налаштуваннях програми.",
|
||||||
"custom_drag": "На замовлення (утримуйте та перетягується)",
|
"custom_drag": "На замовлення (утримуйте та перетягується)",
|
||||||
"switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -752,6 +752,8 @@
|
||||||
"dfx_option_description": "EUR ﺭﻭﺍ CHF ﯽﻓﺎﺿﺍ ۔ﮟﯾﺪﯾﺮﺧ ﻮﭩﭘﺮﮐ ﮫﺗﺎﺳ ﮯﮐ KYC ﮯﯿﻟ ﮯﮐ ﻦﯿﻓﺭﺎﺻ ﭧﯾﺭﻮﭘﺭﺎﮐ ﺭﻭﺍ ﮦﺩﺭﻮﺧ ﮟ",
|
"dfx_option_description": "EUR ﺭﻭﺍ CHF ﯽﻓﺎﺿﺍ ۔ﮟﯾﺪﯾﺮﺧ ﻮﭩﭘﺮﮐ ﮫﺗﺎﺳ ﮯﮐ KYC ﮯﯿﻟ ﮯﮐ ﻦﯿﻓﺭﺎﺻ ﭧﯾﺭﻮﭘﺭﺎﮐ ﺭﻭﺍ ﮦﺩﺭﻮﺧ ﮟ",
|
||||||
"polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ",
|
"polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ",
|
||||||
"wallet_seed_legacy": "میراثی پرس کا بیج",
|
"wallet_seed_legacy": "میراثی پرس کا بیج",
|
||||||
|
"default_sell_provider": " ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ",
|
||||||
|
"select_sell_provider_notice": "۔ﮟﯿﮨ ﮯﺘﮑﺳ ﮌﻮﮭﭼ ﻮﮐ ﻦﯾﺮﮑﺳﺍ ﺱﺍ ﺮﮐ ﮮﺩ ﺐﯿﺗﺮﺗ ﻮﮐ ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ ﮯﻨﭘﺍ ﮟﯿﻣ ﺕﺎﺒ",
|
||||||
"custom_drag": "کسٹم (ہولڈ اینڈ ڈریگ)",
|
"custom_drag": "کسٹم (ہولڈ اینڈ ڈریگ)",
|
||||||
"switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ "
|
"switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ "
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
"dfx_option_description": "Ra crypto pẹlu EUR & CHF. Titi di 990 € laisi afikun KYC. Fun soobu ati awọn onibara ile-iṣẹ ni Yuroopu",
|
||||||
"polygonscan_history": "PolygonScan itan",
|
"polygonscan_history": "PolygonScan itan",
|
||||||
"wallet_seed_legacy": "Irugbin akole",
|
"wallet_seed_legacy": "Irugbin akole",
|
||||||
|
"default_sell_provider": "Aiyipada Olupese Tita",
|
||||||
|
"select_sell_provider_notice": "Yan olupese ti o ta loke. O le foju iboju yii nipa tito olupese iṣẹ tita aiyipada rẹ ni awọn eto app.",
|
||||||
"custom_drag": "Aṣa (mu ati fa)",
|
"custom_drag": "Aṣa (mu ati fa)",
|
||||||
"switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)"
|
"switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -759,6 +759,8 @@
|
||||||
"dfx_option_description": "用欧元和瑞士法郎购买加密货币。高达 990 欧元,无需额外 KYC。对于欧洲的零售和企业客户",
|
"dfx_option_description": "用欧元和瑞士法郎购买加密货币。高达 990 欧元,无需额外 KYC。对于欧洲的零售和企业客户",
|
||||||
"polygonscan_history": "多边形扫描历史",
|
"polygonscan_history": "多边形扫描历史",
|
||||||
"wallet_seed_legacy": "旧的钱包种子",
|
"wallet_seed_legacy": "旧的钱包种子",
|
||||||
|
"default_sell_provider": "默认销售提供商",
|
||||||
|
"select_sell_provider_notice": "选择上面的销售提供商。您可以通过在应用程序设置中设置默认销售提供商来跳过此屏幕。",
|
||||||
"custom_drag": "定制(保持和拖动)",
|
"custom_drag": "定制(保持和拖动)",
|
||||||
"switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)"
|
"switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
|
||||||
APP_ANDROID_TYPE=$1
|
APP_ANDROID_TYPE=$1
|
||||||
|
|
||||||
MONERO_COM_NAME="Monero.com"
|
MONERO_COM_NAME="Monero.com"
|
||||||
MONERO_COM_VERSION="1.8.0"
|
MONERO_COM_VERSION="1.9.0"
|
||||||
MONERO_COM_BUILD_NUMBER=69
|
MONERO_COM_BUILD_NUMBER=71
|
||||||
MONERO_COM_BUNDLE_ID="com.monero.app"
|
MONERO_COM_BUNDLE_ID="com.monero.app"
|
||||||
MONERO_COM_PACKAGE="com.monero.app"
|
MONERO_COM_PACKAGE="com.monero.app"
|
||||||
MONERO_COM_SCHEME="monero.com"
|
MONERO_COM_SCHEME="monero.com"
|
||||||
|
|
||||||
CAKEWALLET_NAME="Cake Wallet"
|
CAKEWALLET_NAME="Cake Wallet"
|
||||||
CAKEWALLET_VERSION="4.11.0"
|
CAKEWALLET_VERSION="4.12.1"
|
||||||
CAKEWALLET_BUILD_NUMBER=184
|
CAKEWALLET_BUILD_NUMBER=188
|
||||||
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
|
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
|
||||||
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
|
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
|
||||||
CAKEWALLET_SCHEME="cakewallet"
|
CAKEWALLET_SCHEME="cakewallet"
|
||||||
|
|
|
@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
|
||||||
APP_IOS_TYPE=$1
|
APP_IOS_TYPE=$1
|
||||||
|
|
||||||
MONERO_COM_NAME="Monero.com"
|
MONERO_COM_NAME="Monero.com"
|
||||||
MONERO_COM_VERSION="1.8.0"
|
MONERO_COM_VERSION="1.9.0"
|
||||||
MONERO_COM_BUILD_NUMBER=67
|
MONERO_COM_BUILD_NUMBER=69
|
||||||
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
|
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
|
||||||
|
|
||||||
CAKEWALLET_NAME="Cake Wallet"
|
CAKEWALLET_NAME="Cake Wallet"
|
||||||
CAKEWALLET_VERSION="4.11.0"
|
CAKEWALLET_VERSION="4.12.1"
|
||||||
CAKEWALLET_BUILD_NUMBER=202
|
CAKEWALLET_BUILD_NUMBER=206
|
||||||
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
||||||
|
|
||||||
HAVEN_NAME="Haven"
|
HAVEN_NAME="Haven"
|
||||||
|
|
|
@ -15,8 +15,8 @@ if [ -n "$1" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CAKEWALLET_NAME="Cake Wallet"
|
CAKEWALLET_NAME="Cake Wallet"
|
||||||
CAKEWALLET_VERSION="1.4.0"
|
CAKEWALLET_VERSION="1.5.1"
|
||||||
CAKEWALLET_BUILD_NUMBER=45
|
CAKEWALLET_BUILD_NUMBER=48
|
||||||
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
||||||
|
|
||||||
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then
|
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then
|
||||||
|
|
Loading…
Reference in a new issue