mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-22 02:34:59 +00:00
Merge remote-tracking branch 'origin/main' into CW-453-bitcoin-silent-payments
This commit is contained in:
commit
fe5f0018b6
116 changed files with 2964 additions and 972 deletions
3
.github/workflows/pr_test_build.yml
vendored
3
.github/workflows/pr_test_build.yml
vendored
|
@ -38,6 +38,8 @@ jobs:
|
|||
sudo mkdir -p /opt/android
|
||||
sudo chown $USER /opt/android
|
||||
cd /opt/android
|
||||
-y curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
cargo install cargo-ndk
|
||||
git clone https://github.com/cake-tech/cake_wallet.git --branch $GITHUB_HEAD_REF
|
||||
cd cake_wallet/scripts/android/
|
||||
./install_ndk.sh
|
||||
|
@ -134,6 +136,7 @@ jobs:
|
|||
echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart
|
||||
echo "const robinhoodCIdApiSecret = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> lib/.secrets.g.dart
|
||||
echo "const walletConnectProjectId = '${{ secrets.WALLET_CONNECT_PROJECT_ID }}';" >> lib/.secrets.g.dart
|
||||
echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> lib/.secrets.g.dart
|
||||
|
||||
- name: Rename app
|
||||
run: echo -e "id=com.cakewallet.test\nname=$GITHUB_HEAD_REF" > /opt/android/cake_wallet/android/app.properties
|
||||
|
|
|
@ -1,4 +1,2 @@
|
|||
UI enhancements
|
||||
Privacy settings enhancements
|
||||
Tablet/iPad fixes
|
||||
Bug fixes
|
||||
Monero Polyseed support, under Advanced privacy settings, create and restore from a 16 words phrase and without the need to remember the wallet creation date
|
||||
Minor bug fixes and enhancements
|
|
@ -1,5 +1,3 @@
|
|||
WalletConnect enhancements
|
||||
UI enhancements
|
||||
Privacy settings enhancements
|
||||
Tablet/iPad fixes
|
||||
Bug fixes
|
||||
Monero Polyseed support, under Advanced privacy settings, create and restore from a 16 words phrase and without the need to remember the wallet creation date
|
||||
Add Ethereum NFTs tab to see all of your purchased NFTs
|
||||
Minor bug fixes and enhancements
|
|
@ -2,6 +2,7 @@ cd scripts/android
|
|||
source ./app_env.sh cakewallet
|
||||
./app_config.sh
|
||||
cd ../.. && flutter pub get
|
||||
flutter packages pub run tool/generate_localization.dart
|
||||
cd cw_core && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd ..
|
||||
cd cw_monero && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd ..
|
||||
cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd ..
|
||||
|
|
|
@ -633,6 +633,14 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
socks5_proxy:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: socks5_proxy
|
||||
sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
source_gen:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -713,6 +721,15 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
tor:
|
||||
dependency: transitive
|
||||
description:
|
||||
path: "."
|
||||
ref: main
|
||||
resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5"
|
||||
url: "https://github.com/cake-tech/tor.git"
|
||||
source: git
|
||||
version: "0.0.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
||||
#define GENERATED_PLUGIN_REGISTRANT_
|
||||
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
|
||||
// Registers Flutter plugins.
|
||||
void fl_register_plugins(FlPluginRegistry* registry);
|
||||
|
||||
#endif // GENERATED_PLUGIN_REGISTRANT_
|
|
@ -1,23 +0,0 @@
|
|||
#
|
||||
# Generated file, do not edit.
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
||||
endforeach(plugin)
|
||||
|
||||
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
||||
endforeach(ffi_plugin)
|
|
@ -1,12 +0,0 @@
|
|||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import path_provider_foundation
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
// This is a generated file; do not edit or check into version control.
|
||||
FLUTTER_ROOT=C:\Users\borod\flutter
|
||||
FLUTTER_APPLICATION_PATH=C:\cake_wallet\cw_bitcoin_cash
|
||||
COCOAPODS_PARALLEL_CODE_SIGN=true
|
||||
FLUTTER_BUILD_DIR=build
|
||||
FLUTTER_BUILD_NAME=0.0.1
|
||||
FLUTTER_BUILD_NUMBER=0.0.1
|
||||
DART_OBFUSCATION=false
|
||||
TRACK_WIDGET_CREATION=true
|
||||
TREE_SHAKE_ICONS=false
|
||||
PACKAGE_CONFIG=.dart_tool/package_config.json
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/sh
|
||||
# This is a generated file; do not edit or check into version control.
|
||||
export "FLUTTER_ROOT=C:\Users\borod\flutter"
|
||||
export "FLUTTER_APPLICATION_PATH=C:\cake_wallet\cw_bitcoin_cash"
|
||||
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
|
||||
export "FLUTTER_BUILD_DIR=build"
|
||||
export "FLUTTER_BUILD_NAME=0.0.1"
|
||||
export "FLUTTER_BUILD_NUMBER=0.0.1"
|
||||
export "DART_OBFUSCATION=false"
|
||||
export "TRACK_WIDGET_CREATION=true"
|
||||
export "TREE_SHAKE_ICONS=false"
|
||||
export "PACKAGE_CONFIG=.dart_tool/package_config.json"
|
|
@ -1,11 +0,0 @@
|
|||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
||||
#define GENERATED_PLUGIN_REGISTRANT_
|
||||
|
||||
#include <flutter/plugin_registry.h>
|
||||
|
||||
// Registers Flutter plugins.
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry);
|
||||
|
||||
#endif // GENERATED_PLUGIN_REGISTRANT_
|
|
@ -1,23 +0,0 @@
|
|||
#
|
||||
# Generated file, do not edit.
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
||||
endforeach(plugin)
|
||||
|
||||
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
||||
endforeach(ffi_plugin)
|
|
@ -84,7 +84,41 @@ final dates = {
|
|||
"2020-8": 2153983,
|
||||
"2020-9": 2176466,
|
||||
"2020-10": 2198453,
|
||||
"2020-11": 2220000
|
||||
"2020-11": 2220000,
|
||||
"2020-12": 2242240,
|
||||
"2021-1": 2264584,
|
||||
"2021-2": 2286892,
|
||||
"2021-3": 2307079,
|
||||
"2021-4": 2329385,
|
||||
"2021-5": 2351004,
|
||||
"2021-6": 2373306,
|
||||
"2021-7": 2394882,
|
||||
"2021-8": 2417162,
|
||||
"2021-9": 2439490,
|
||||
"2021-10": 2461020,
|
||||
"2021-11": 2483377,
|
||||
"2021-12": 2504932,
|
||||
"2022-1": 2527316,
|
||||
"2022-2": 2549605,
|
||||
"2022-3": 2569711,
|
||||
"2022-4": 2591995,
|
||||
"2022-5": 2613603,
|
||||
"2022-6": 2635840,
|
||||
"2022-7": 2657395,
|
||||
"2022-8": 2679705,
|
||||
"2022-9": 2701991,
|
||||
"2022-10": 2723607,
|
||||
"2022-11": 2745899,
|
||||
"2022-12": 2767427,
|
||||
"2023-1": 2789763,
|
||||
"2023-2": 2811996,
|
||||
"2023-3": 2832118,
|
||||
"2023-4": 2854365,
|
||||
"2023-5": 2875972,
|
||||
"2023-6": 2898234,
|
||||
"2023-7": 2919771,
|
||||
"2023-8": 2942045,
|
||||
"2023-9": 2964280
|
||||
};
|
||||
|
||||
int getMoneroHeigthByDate({required DateTime date}) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:hive/hive.dart';
|
|||
import 'package:cw_core/hive_type_ids.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:http/io_client.dart' as ioc;
|
||||
import 'package:tor/tor.dart';
|
||||
|
||||
part 'node.g.dart';
|
||||
|
||||
|
@ -92,6 +93,8 @@ class Node extends HiveObject with Keyable {
|
|||
}
|
||||
}
|
||||
|
||||
bool get isValidProxyAddress => socksProxyAddress?.contains(':') ?? false;
|
||||
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
other is Node &&
|
||||
|
@ -129,9 +132,7 @@ class Node extends HiveObject with Keyable {
|
|||
try {
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return useSocksProxy
|
||||
? requestNodeWithProxy(socksProxyAddress ?? '')
|
||||
: requestMoneroNode();
|
||||
return requestMoneroNode();
|
||||
case WalletType.bitcoin:
|
||||
return requestElectrumServer();
|
||||
case WalletType.litecoin:
|
||||
|
@ -154,6 +155,9 @@ class Node extends HiveObject with Keyable {
|
|||
}
|
||||
|
||||
Future<bool> requestMoneroNode() async {
|
||||
if (uri.toString().contains(".onion") || useSocksProxy) {
|
||||
return await requestNodeWithProxy();
|
||||
}
|
||||
final path = '/json_rpc';
|
||||
final rpcUri = isSSL ? Uri.https(uri.authority, path) : Uri.http(uri.authority, path);
|
||||
final realm = 'monero-rpc';
|
||||
|
@ -205,11 +209,17 @@ class Node extends HiveObject with Keyable {
|
|||
}
|
||||
}
|
||||
|
||||
Future<bool> requestNodeWithProxy(String proxy) async {
|
||||
if (proxy.isEmpty || !proxy.contains(':')) {
|
||||
Future<bool> requestNodeWithProxy() async {
|
||||
if (!isValidProxyAddress && !Tor.instance.enabled) {
|
||||
return false;
|
||||
}
|
||||
final proxyAddress = proxy.split(':')[0];
|
||||
|
||||
String? proxy = socksProxyAddress;
|
||||
|
||||
if ((proxy?.isEmpty ?? true) && Tor.instance.enabled) {
|
||||
proxy = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}";
|
||||
}
|
||||
final proxyAddress = proxy!.split(':')[0];
|
||||
final proxyPort = int.parse(proxy.split(':')[1]);
|
||||
try {
|
||||
final socket = await Socket.connect(proxyAddress, proxyPort, timeout: Duration(seconds: 5));
|
||||
|
|
|
@ -44,6 +44,8 @@ abstract class WalletBase<BalanceType extends Balance, HistoryType extends Trans
|
|||
|
||||
String? get privateKey => null;
|
||||
|
||||
String? get hexSeed => null;
|
||||
|
||||
Object get keys;
|
||||
|
||||
WalletAddresses get walletAddresses;
|
||||
|
|
|
@ -271,10 +271,10 @@ packages:
|
|||
dependency: "direct dev"
|
||||
description:
|
||||
name: hive_generator
|
||||
sha256: "81fd20125cb2ce8fd23623d7744ffbaf653aae93706c9bd3bf7019ea0ace3938"
|
||||
sha256: "06cb8f58ace74de61f63500564931f9505368f45f98958bd7a6c35ba24159db4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.3"
|
||||
version: "2.0.1"
|
||||
http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -407,50 +407,50 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95
|
||||
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.12"
|
||||
version: "2.1.1"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e
|
||||
sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.22"
|
||||
version: "2.2.1"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74"
|
||||
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.3.1"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379
|
||||
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.7"
|
||||
version: "2.2.1"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76
|
||||
sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
version: "2.1.1"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c
|
||||
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
version: "2.2.1"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -528,6 +528,14 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
socks5_proxy:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: socks5_proxy
|
||||
sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
source_gen:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -608,6 +616,15 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
tor:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: main
|
||||
resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5"
|
||||
url: "https://github.com/cake-tech/tor.git"
|
||||
source: git
|
||||
version: "0.0.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -666,4 +683,4 @@ packages:
|
|||
version: "3.1.1"
|
||||
sdks:
|
||||
dart: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=3.0.0"
|
||||
flutter: ">=3.7.0"
|
||||
|
|
|
@ -19,6 +19,11 @@ dependencies:
|
|||
flutter_mobx: ^2.0.6+1
|
||||
intl: ^0.18.0
|
||||
encrypt: ^5.0.1
|
||||
socks5_proxy: ^1.0.4
|
||||
tor:
|
||||
git:
|
||||
url: https://github.com/cake-tech/tor.git
|
||||
ref: main
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -26,7 +31,7 @@ dev_dependencies:
|
|||
build_runner: ^2.1.11
|
||||
build_resolvers: ^2.0.9
|
||||
mobx_codegen: ^2.0.7
|
||||
hive_generator: ^1.1.3
|
||||
hive_generator: ^2.0.1
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
|
|
@ -17,7 +17,6 @@ dependencies:
|
|||
mobx: ^2.0.7+4
|
||||
bip39: ^1.0.6
|
||||
bip32: ^2.0.0
|
||||
ed25519_hd_key: ^2.2.0
|
||||
hex: ^0.2.0
|
||||
http: ^1.1.0
|
||||
shared_preferences: ^2.0.15
|
||||
|
|
|
@ -414,50 +414,50 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95
|
||||
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.12"
|
||||
version: "2.1.1"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e
|
||||
sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.22"
|
||||
version: "2.2.1"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74"
|
||||
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.3.1"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379
|
||||
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.7"
|
||||
version: "2.2.1"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76
|
||||
sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
version: "2.1.1"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130
|
||||
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
version: "2.2.1"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -535,6 +535,14 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
socks5_proxy:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: socks5_proxy
|
||||
sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
source_gen:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -615,6 +623,15 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
tor:
|
||||
dependency: transitive
|
||||
description:
|
||||
path: "."
|
||||
ref: main
|
||||
resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5"
|
||||
url: "https://github.com/cake-tech/tor.git"
|
||||
source: git
|
||||
version: "0.0.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -673,4 +690,4 @@ packages:
|
|||
version: "3.1.1"
|
||||
sdks:
|
||||
dart: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=3.0.0"
|
||||
flutter: ">=3.7.0"
|
||||
|
|
|
@ -237,50 +237,50 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95
|
||||
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.12"
|
||||
version: "2.1.1"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e
|
||||
sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.22"
|
||||
version: "2.2.1"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74"
|
||||
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.3.1"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379
|
||||
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.7"
|
||||
version: "2.2.1"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76
|
||||
sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
version: "2.1.1"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130
|
||||
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
version: "2.2.1"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -301,10 +301,19 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: pointycastle
|
||||
sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346
|
||||
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.6.2"
|
||||
version: "3.7.3"
|
||||
polyseed:
|
||||
dependency: transitive
|
||||
description:
|
||||
path: "."
|
||||
ref: HEAD
|
||||
resolved-ref: "504d58a5b147fccd3bc85a25f2e72fb32771ddd7"
|
||||
url: "https://github.com/cake-tech/polyseed_dart.git"
|
||||
source: git
|
||||
version: "0.0.1"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -318,6 +327,14 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
socks5_proxy:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: socks5_proxy
|
||||
sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -366,6 +383,15 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.1"
|
||||
tor:
|
||||
dependency: transitive
|
||||
description:
|
||||
path: "."
|
||||
ref: main
|
||||
resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5"
|
||||
url: "https://github.com/cake-tech/tor.git"
|
||||
source: git
|
||||
version: "0.0.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -399,5 +425,5 @@ packages:
|
|||
source: hosted
|
||||
version: "0.2.0+3"
|
||||
sdks:
|
||||
dart: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=3.0.0"
|
||||
dart: ">=3.0.6 <4.0.0"
|
||||
flutter: ">=3.7.0"
|
||||
|
|
|
@ -374,6 +374,35 @@ extern "C"
|
|||
return true;
|
||||
}
|
||||
|
||||
bool restore_wallet_from_spend_key(char *path, char *password, char *seed, char *language, char *spendKey, int32_t networkType, uint64_t restoreHeight, char *error)
|
||||
{
|
||||
Monero::NetworkType _networkType = static_cast<Monero::NetworkType>(networkType);
|
||||
Monero::Wallet *wallet = Monero::WalletManagerFactory::getWalletManager()->createDeterministicWalletFromSpendKey(
|
||||
std::string(path),
|
||||
std::string(password),
|
||||
std::string(language),
|
||||
_networkType,
|
||||
(uint64_t)restoreHeight,
|
||||
std::string(spendKey));
|
||||
|
||||
int status;
|
||||
std::string errorString;
|
||||
|
||||
wallet->statusWithErrorString(status, errorString);
|
||||
|
||||
if (status != Monero::Wallet::Status_Ok || !errorString.empty())
|
||||
{
|
||||
error = strdup(errorString.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cache Raw to support Polyseed
|
||||
wallet->setCacheAttribute("cakewallet.seed", std::string(seed));
|
||||
|
||||
change_current_wallet(wallet);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool load_wallet(char *path, char *password, int32_t nettype)
|
||||
{
|
||||
nice(19);
|
||||
|
@ -438,6 +467,11 @@ extern "C"
|
|||
|
||||
const char *seed()
|
||||
{
|
||||
std::string _rawSeed = get_current_wallet()->getCacheAttribute("cakewallet.seed");
|
||||
if (!_rawSeed.empty())
|
||||
{
|
||||
return strdup(_rawSeed.c_str());
|
||||
}
|
||||
return strdup(get_current_wallet()->seed().c_str());
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,9 @@ typedef restore_wallet_from_seed = Int8 Function(
|
|||
typedef restore_wallet_from_keys = Int8 Function(Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>,
|
||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>);
|
||||
|
||||
typedef restore_wallet_from_spend_key = Int8 Function(Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>,
|
||||
Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>);
|
||||
|
||||
typedef is_wallet_exist = Int8 Function(Pointer<Utf8>);
|
||||
|
||||
typedef load_wallet = Int8 Function(Pointer<Utf8>, Pointer<Utf8>, Int8);
|
||||
|
|
|
@ -14,6 +14,9 @@ typedef RestoreWalletFromSeed = int Function(
|
|||
typedef RestoreWalletFromKeys = int Function(Pointer<Utf8>, Pointer<Utf8>,
|
||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, int, int, Pointer<Utf8>);
|
||||
|
||||
typedef RestoreWalletFromSpendKey = int Function(Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>,
|
||||
Pointer<Utf8>, Pointer<Utf8>, int, int, Pointer<Utf8>);
|
||||
|
||||
typedef IsWalletExist = int Function(Pointer<Utf8>);
|
||||
|
||||
typedef LoadWallet = int Function(Pointer<Utf8>, Pointer<Utf8>, int);
|
||||
|
|
|
@ -5,7 +5,6 @@ import 'package:cw_monero/api/convert_utf8_to_string.dart';
|
|||
import 'package:cw_monero/api/signatures.dart';
|
||||
import 'package:cw_monero/api/types.dart';
|
||||
import 'package:cw_monero/api/monero_api.dart';
|
||||
import 'package:cw_monero/api/wallet.dart';
|
||||
import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart';
|
||||
import 'package:cw_monero/api/exceptions/wallet_creation_exception.dart';
|
||||
import 'package:cw_monero/api/exceptions/wallet_restore_from_keys_exception.dart';
|
||||
|
@ -25,6 +24,11 @@ final restoreWalletFromKeysNative = moneroApi
|
|||
'restore_wallet_from_keys')
|
||||
.asFunction<RestoreWalletFromKeys>();
|
||||
|
||||
final restoreWalletFromSpendKeyNative = moneroApi
|
||||
.lookup<NativeFunction<restore_wallet_from_spend_key>>(
|
||||
'restore_wallet_from_spend_key')
|
||||
.asFunction<RestoreWalletFromSpendKey>();
|
||||
|
||||
final isWalletExistNative = moneroApi
|
||||
.lookup<NativeFunction<is_wallet_exist>>('is_wallet_exist')
|
||||
.asFunction<IsWalletExist>();
|
||||
|
@ -141,6 +145,42 @@ void restoreWalletFromKeysSync(
|
|||
}
|
||||
}
|
||||
|
||||
void restoreWalletFromSpendKeySync(
|
||||
{required String path,
|
||||
required String password,
|
||||
required String seed,
|
||||
required String language,
|
||||
required String spendKey,
|
||||
int nettype = 0,
|
||||
int restoreHeight = 0}) {
|
||||
final pathPointer = path.toNativeUtf8();
|
||||
final passwordPointer = password.toNativeUtf8();
|
||||
final seedPointer = seed.toNativeUtf8();
|
||||
final languagePointer = language.toNativeUtf8();
|
||||
final spendKeyPointer = spendKey.toNativeUtf8();
|
||||
final errorMessagePointer = ''.toNativeUtf8();
|
||||
final isWalletRestored = restoreWalletFromSpendKeyNative(
|
||||
pathPointer,
|
||||
passwordPointer,
|
||||
seedPointer,
|
||||
languagePointer,
|
||||
spendKeyPointer,
|
||||
nettype,
|
||||
restoreHeight,
|
||||
errorMessagePointer) !=
|
||||
0;
|
||||
|
||||
calloc.free(pathPointer);
|
||||
calloc.free(passwordPointer);
|
||||
calloc.free(languagePointer);
|
||||
calloc.free(spendKeyPointer);
|
||||
|
||||
if (!isWalletRestored) {
|
||||
throw WalletRestoreFromKeysException(
|
||||
message: convertUTF8ToString(pointer: errorMessagePointer));
|
||||
}
|
||||
}
|
||||
|
||||
void loadWallet({
|
||||
required String path,
|
||||
required String password,
|
||||
|
@ -194,6 +234,23 @@ void _restoreFromKeys(Map<String, dynamic> args) {
|
|||
spendKey: spendKey);
|
||||
}
|
||||
|
||||
void _restoreFromSpendKey(Map<String, dynamic> args) {
|
||||
final path = args['path'] as String;
|
||||
final password = args['password'] as String;
|
||||
final seed = args['seed'] as String;
|
||||
final language = args['language'] as String;
|
||||
final spendKey = args['spendKey'] as String;
|
||||
final restoreHeight = args['restoreHeight'] as int;
|
||||
|
||||
restoreWalletFromSpendKeySync(
|
||||
path: path,
|
||||
password: password,
|
||||
seed: seed,
|
||||
language: language,
|
||||
restoreHeight: restoreHeight,
|
||||
spendKey: spendKey);
|
||||
}
|
||||
|
||||
Future<void> _openWallet(Map<String, String> args) async =>
|
||||
loadWallet(path: args['path'] as String, password: args['password'] as String);
|
||||
|
||||
|
@ -251,4 +308,22 @@ Future<void> restoreFromKeys(
|
|||
'restoreHeight': restoreHeight
|
||||
});
|
||||
|
||||
Future<void> restoreFromSpendKey(
|
||||
{required String path,
|
||||
required String password,
|
||||
required String seed,
|
||||
required String language,
|
||||
required String spendKey,
|
||||
int nettype = 0,
|
||||
int restoreHeight = 0}) async =>
|
||||
compute<Map<String, Object>, void>(_restoreFromSpendKey, {
|
||||
'path': path,
|
||||
'password': password,
|
||||
'seed': seed,
|
||||
'language': language,
|
||||
'spendKey': spendKey,
|
||||
'nettype': nettype,
|
||||
'restoreHeight': restoreHeight
|
||||
});
|
||||
|
||||
Future<bool> isWalletExist({required String path}) => compute(_isWalletExist, path);
|
||||
|
|
|
@ -29,6 +29,7 @@ import 'package:cw_monero/monero_transaction_info.dart';
|
|||
import 'package:cw_monero/monero_unspent.dart';
|
||||
import 'package:cw_monero/monero_wallet_addresses.dart';
|
||||
import 'package:cw_monero/pending_monero_transaction.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
|
@ -78,6 +79,8 @@ abstract class MoneroWalletBase
|
|||
|
||||
Box<UnspentCoinsInfo> unspentCoinsInfo;
|
||||
|
||||
void Function(FlutterErrorDetails)? _onError;
|
||||
|
||||
@override
|
||||
late MoneroWalletAddresses walletAddresses;
|
||||
|
||||
|
@ -388,46 +391,59 @@ abstract class MoneroWalletBase
|
|||
}
|
||||
|
||||
Future<void> updateUnspent() async {
|
||||
refreshCoins(walletAddresses.account!.id);
|
||||
try {
|
||||
refreshCoins(walletAddresses.account!.id);
|
||||
|
||||
unspentCoins.clear();
|
||||
unspentCoins.clear();
|
||||
|
||||
final coinCount = countOfCoins();
|
||||
for (var i = 0; i < coinCount; i++) {
|
||||
final coin = getCoin(i);
|
||||
if (coin.spent == 0) {
|
||||
final unspent = MoneroUnspent.fromCoinsInfoRow(coin);
|
||||
unspent.isChange = transaction_history.getTransaction(unspent.hash).direction == 1;
|
||||
unspentCoins.add(unspent);
|
||||
}
|
||||
}
|
||||
|
||||
if (unspentCoinsInfo.isEmpty) {
|
||||
unspentCoins.forEach((coin) => _addCoinInfo(coin));
|
||||
return;
|
||||
}
|
||||
|
||||
if (unspentCoins.isNotEmpty) {
|
||||
unspentCoins.forEach((coin) {
|
||||
final coinInfoList = unspentCoinsInfo.values.where((element) =>
|
||||
element.walletId.contains(id) &&
|
||||
element.accountIndex == walletAddresses.account!.id &&
|
||||
element.keyImage!.contains(coin.keyImage!));
|
||||
|
||||
if (coinInfoList.isNotEmpty) {
|
||||
final coinInfo = coinInfoList.first;
|
||||
|
||||
coin.isFrozen = coinInfo.isFrozen;
|
||||
coin.isSending = coinInfo.isSending;
|
||||
coin.note = coinInfo.note;
|
||||
} else {
|
||||
_addCoinInfo(coin);
|
||||
final coinCount = countOfCoins();
|
||||
for (var i = 0; i < coinCount; i++) {
|
||||
final coin = getCoin(i);
|
||||
if (coin.spent == 0) {
|
||||
final unspent = MoneroUnspent.fromCoinsInfoRow(coin);
|
||||
if (unspent.hash.isNotEmpty) {
|
||||
unspent.isChange = transaction_history
|
||||
.getTransaction(unspent.hash)
|
||||
.direction == 1;
|
||||
}
|
||||
unspentCoins.add(unspent);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await _refreshUnspentCoinsInfo();
|
||||
_askForUpdateBalance();
|
||||
if (unspentCoinsInfo.isEmpty) {
|
||||
unspentCoins.forEach((coin) => _addCoinInfo(coin));
|
||||
return;
|
||||
}
|
||||
|
||||
if (unspentCoins.isNotEmpty) {
|
||||
unspentCoins.forEach((coin) {
|
||||
final coinInfoList = unspentCoinsInfo.values.where((element) =>
|
||||
element.walletId.contains(id) &&
|
||||
element.accountIndex == walletAddresses.account!.id &&
|
||||
element.keyImage!.contains(coin.keyImage!));
|
||||
|
||||
if (coinInfoList.isNotEmpty) {
|
||||
final coinInfo = coinInfoList.first;
|
||||
|
||||
coin.isFrozen = coinInfo.isFrozen;
|
||||
coin.isSending = coinInfo.isSending;
|
||||
coin.note = coinInfo.note;
|
||||
} else {
|
||||
_addCoinInfo(coin);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await _refreshUnspentCoinsInfo();
|
||||
_askForUpdateBalance();
|
||||
} catch (e, s) {
|
||||
print(e.toString());
|
||||
_onError?.call(FlutterErrorDetails(
|
||||
exception: e,
|
||||
stack: s,
|
||||
library: this.runtimeType.toString(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _addCoinInfo(MoneroUnspent coin) async {
|
||||
|
@ -632,4 +648,7 @@ abstract class MoneroWalletBase
|
|||
walletAddresses.updateSubaddressList(accountIndex: account?.id ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void setExceptionHandler(void Function(FlutterErrorDetails) onError) => _onError = onError;
|
||||
}
|
||||
|
|
|
@ -7,16 +7,20 @@ import 'package:cw_core/wallet_credentials.dart';
|
|||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_service.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_core/get_height_by_date.dart';
|
||||
import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart';
|
||||
import 'package:cw_monero/api/wallet_manager.dart' as monero_wallet_manager;
|
||||
import 'package:cw_monero/monero_wallet.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:polyseed/polyseed.dart';
|
||||
import 'package:polyseed/src/utils/key_utils.dart';
|
||||
|
||||
class MoneroNewWalletCredentials extends WalletCredentials {
|
||||
MoneroNewWalletCredentials({required String name, required this.language, String? password})
|
||||
MoneroNewWalletCredentials({required String name, required this.language, required this.isPolyseed, String? password})
|
||||
: super(name: name, password: password);
|
||||
|
||||
final String language;
|
||||
final bool isPolyseed;
|
||||
}
|
||||
|
||||
class MoneroRestoreWalletFromSeedCredentials extends WalletCredentials {
|
||||
|
@ -68,10 +72,17 @@ class MoneroWalletService extends WalletService<
|
|||
Future<MoneroWallet> create(MoneroNewWalletCredentials credentials, {bool? isTestnet}) async {
|
||||
try {
|
||||
final path = await pathForWallet(name: credentials.name, type: getType());
|
||||
|
||||
if (credentials.isPolyseed) {
|
||||
final polyseed = Polyseed.create();
|
||||
final lang = PolyseedLang.getByEnglishName(credentials.language);
|
||||
|
||||
return _restoreFromPolyseed(
|
||||
path, credentials.password!, polyseed, credentials.walletInfo!, lang);
|
||||
}
|
||||
|
||||
await monero_wallet_manager.createWallet(
|
||||
path: path,
|
||||
password: credentials.password!,
|
||||
language: credentials.language);
|
||||
path: path, password: credentials.password!, language: credentials.language);
|
||||
final wallet = MoneroWallet(
|
||||
walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource);
|
||||
await wallet.init();
|
||||
|
@ -215,6 +226,12 @@ class MoneroWalletService extends WalletService<
|
|||
@override
|
||||
Future<MoneroWallet> restoreFromSeed(
|
||||
MoneroRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async {
|
||||
|
||||
// Restore from Polyseed
|
||||
if (Polyseed.isValidSeed(credentials.mnemonic)) {
|
||||
return restoreFromPolyseed(credentials);
|
||||
}
|
||||
|
||||
try {
|
||||
final path = await pathForWallet(name: credentials.name, type: getType());
|
||||
await monero_wallet_manager.restoreFromSeed(
|
||||
|
@ -234,6 +251,45 @@ class MoneroWalletService extends WalletService<
|
|||
}
|
||||
}
|
||||
|
||||
Future<MoneroWallet> restoreFromPolyseed(MoneroRestoreWalletFromSeedCredentials credentials) async {
|
||||
try {
|
||||
final path = await pathForWallet(name: credentials.name, type: getType());
|
||||
final polyseedCoin = PolyseedCoin.POLYSEED_MONERO;
|
||||
final lang = PolyseedLang.getByPhrase(credentials.mnemonic);
|
||||
final polyseed = Polyseed.decode(credentials.mnemonic, lang, polyseedCoin);
|
||||
|
||||
return _restoreFromPolyseed(path, credentials.password!, polyseed, credentials.walletInfo!, lang);
|
||||
} catch (e) {
|
||||
// TODO: Implement Exception for wallet list service.
|
||||
print('MoneroWalletsManager Error: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<MoneroWallet> _restoreFromPolyseed(String path, String password, Polyseed polyseed,
|
||||
WalletInfo walletInfo, PolyseedLang lang,
|
||||
{PolyseedCoin coin = PolyseedCoin.POLYSEED_MONERO}) async {
|
||||
final height = getMoneroHeigthByDate(
|
||||
date: DateTime.fromMillisecondsSinceEpoch(polyseed.birthday * 1000));
|
||||
final spendKey = keyToHexString(polyseed.generateKey(coin, 32));
|
||||
|
||||
walletInfo.isRecovery = true;
|
||||
walletInfo.restoreHeight = height;
|
||||
|
||||
await monero_wallet_manager.restoreFromSpendKey(
|
||||
path: path,
|
||||
password: password,
|
||||
seed: polyseed.encode(lang, coin),
|
||||
language: lang.nameEnglish,
|
||||
restoreHeight: height,
|
||||
spendKey: spendKey);
|
||||
final wallet = MoneroWallet(
|
||||
walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource);
|
||||
await wallet.init();
|
||||
|
||||
return wallet;
|
||||
}
|
||||
|
||||
Future<void> repairOldAndroidWallet(String name) async {
|
||||
try {
|
||||
if (!Platform.isAndroid) {
|
||||
|
|
|
@ -234,7 +234,6 @@ extern "C"
|
|||
}
|
||||
|
||||
void setUnlocked(bool unlocked);
|
||||
|
||||
};
|
||||
|
||||
Monero::Coins *m_coins;
|
||||
|
@ -375,6 +374,35 @@ extern "C"
|
|||
return true;
|
||||
}
|
||||
|
||||
bool restore_wallet_from_spend_key(char *path, char *password, char *seed, char *language, char *spendKey, int32_t networkType, uint64_t restoreHeight, char *error)
|
||||
{
|
||||
Monero::NetworkType _networkType = static_cast<Monero::NetworkType>(networkType);
|
||||
Monero::Wallet *wallet = Monero::WalletManagerFactory::getWalletManager()->createDeterministicWalletFromSpendKey(
|
||||
std::string(path),
|
||||
std::string(password),
|
||||
std::string(language),
|
||||
_networkType,
|
||||
(uint64_t)restoreHeight,
|
||||
std::string(spendKey));
|
||||
|
||||
int status;
|
||||
std::string errorString;
|
||||
|
||||
wallet->statusWithErrorString(status, errorString);
|
||||
|
||||
if (status != Monero::Wallet::Status_Ok || !errorString.empty())
|
||||
{
|
||||
error = strdup(errorString.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cache Raw to support Polyseed
|
||||
wallet->setCacheAttribute("cakewallet.seed", std::string(seed));
|
||||
|
||||
change_current_wallet(wallet);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool load_wallet(char *path, char *password, int32_t nettype)
|
||||
{
|
||||
nice(19);
|
||||
|
@ -439,6 +467,11 @@ extern "C"
|
|||
|
||||
const char *seed()
|
||||
{
|
||||
std::string _rawSeed = get_current_wallet()->getCacheAttribute("cakewallet.seed");
|
||||
if (!_rawSeed.empty())
|
||||
{
|
||||
return strdup(_rawSeed.c_str());
|
||||
}
|
||||
return strdup(get_current_wallet()->seed().c_str());
|
||||
}
|
||||
|
||||
|
@ -842,6 +875,12 @@ extern "C"
|
|||
return m_transaction_history->count();
|
||||
}
|
||||
|
||||
TransactionInfoRow* get_transaction(char * txId)
|
||||
{
|
||||
Monero::TransactionInfo *row = m_transaction_history->transaction(std::string(txId));
|
||||
return new TransactionInfoRow(row);
|
||||
}
|
||||
|
||||
int LedgerExchange(
|
||||
unsigned char *command,
|
||||
unsigned int cmd_len,
|
||||
|
@ -971,6 +1010,15 @@ extern "C"
|
|||
return result;
|
||||
}
|
||||
|
||||
void freeze_coin(int index)
|
||||
{
|
||||
m_coins->setFrozen(index);
|
||||
}
|
||||
|
||||
void thaw_coin(int index)
|
||||
{
|
||||
m_coins->thaw(index);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -414,50 +414,50 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95
|
||||
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.12"
|
||||
version: "2.1.1"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e
|
||||
sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.22"
|
||||
version: "2.2.1"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74"
|
||||
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.3.1"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379
|
||||
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.7"
|
||||
version: "2.2.1"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76
|
||||
sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
version: "2.1.1"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130
|
||||
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
version: "2.2.1"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -478,10 +478,19 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: pointycastle
|
||||
sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346
|
||||
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.6.2"
|
||||
version: "3.7.3"
|
||||
polyseed:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: HEAD
|
||||
resolved-ref: "504d58a5b147fccd3bc85a25f2e72fb32771ddd7"
|
||||
url: "https://github.com/cake-tech/polyseed_dart.git"
|
||||
source: git
|
||||
version: "0.0.1"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -535,6 +544,14 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
socks5_proxy:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: socks5_proxy
|
||||
sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
source_gen:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -615,6 +632,15 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
tor:
|
||||
dependency: transitive
|
||||
description:
|
||||
path: "."
|
||||
ref: main
|
||||
resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5"
|
||||
url: "https://github.com/cake-tech/tor.git"
|
||||
source: git
|
||||
version: "0.0.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -672,5 +698,5 @@ packages:
|
|||
source: hosted
|
||||
version: "3.1.1"
|
||||
sdks:
|
||||
dart: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=3.0.0"
|
||||
dart: ">=3.0.6 <4.0.0"
|
||||
flutter: ">=3.7.0"
|
||||
|
|
|
@ -19,6 +19,9 @@ dependencies:
|
|||
flutter_mobx: ^2.0.6+1
|
||||
intl: ^0.18.0
|
||||
encrypt: ^5.0.1
|
||||
polyseed:
|
||||
git:
|
||||
url: https://github.com/cake-tech/polyseed_dart.git
|
||||
cw_core:
|
||||
path: ../cw_core
|
||||
|
||||
|
|
|
@ -58,13 +58,13 @@ abstract class NanoWalletBase
|
|||
}
|
||||
}
|
||||
|
||||
final String _mnemonic;
|
||||
String _mnemonic;
|
||||
final String _password;
|
||||
final DerivationType _derivationType;
|
||||
DerivationType _derivationType;
|
||||
|
||||
String? _privateKey;
|
||||
String? _publicAddress;
|
||||
String? _seedKey;
|
||||
String? _hexSeed;
|
||||
|
||||
String? _representativeAddress;
|
||||
Timer? _receiveTimer;
|
||||
|
@ -85,22 +85,26 @@ abstract class NanoWalletBase
|
|||
|
||||
// initialize the different forms of private / public key we'll need:
|
||||
Future<void> init() async {
|
||||
if (_derivationType == DerivationType.unknown) {
|
||||
_derivationType = DerivationType.nano;
|
||||
}
|
||||
final String type = (_derivationType == DerivationType.nano) ? "standard" : "hd";
|
||||
|
||||
// our "mnemonic" is actually a seedkey:
|
||||
// our "mnemonic" is actually a hex form seed:
|
||||
if (!_mnemonic.contains(' ')) {
|
||||
_seedKey = _mnemonic;
|
||||
_hexSeed = _mnemonic;
|
||||
_mnemonic = "";
|
||||
}
|
||||
|
||||
if (_seedKey == null) {
|
||||
if (_hexSeed == null) {
|
||||
if (_derivationType == DerivationType.nano) {
|
||||
_seedKey = bip39.mnemonicToEntropy(_mnemonic).toUpperCase();
|
||||
_hexSeed = bip39.mnemonicToEntropy(_mnemonic).toUpperCase();
|
||||
} else {
|
||||
_seedKey = await NanoUtil.hdMnemonicListToSeed(_mnemonic.split(' '));
|
||||
_hexSeed = await NanoUtil.hdMnemonicListToSeed(_mnemonic.split(' '));
|
||||
}
|
||||
}
|
||||
_privateKey = await NanoUtil.uniSeedToPrivate(_seedKey!, 0, type);
|
||||
_publicAddress = await NanoUtil.uniSeedToAddress(_seedKey!, 0, type);
|
||||
_privateKey = await NanoUtil.uniSeedToPrivate(_hexSeed!, 0, type);
|
||||
_publicAddress = await NanoUtil.uniSeedToAddress(_hexSeed!, 0, type);
|
||||
this.walletInfo.address = _publicAddress!;
|
||||
|
||||
await walletAddresses.init();
|
||||
|
@ -182,9 +186,9 @@ abstract class NanoWalletBase
|
|||
|
||||
final block = await _client.constructSendBlock(
|
||||
amountRaw: amt.toString(),
|
||||
destinationAddress: credentials.outputs.first.isParsedAddress
|
||||
? credentials.outputs.first.extractedAddress!
|
||||
: credentials.outputs.first.address,
|
||||
destinationAddress: txOut.isParsedAddress
|
||||
? txOut.extractedAddress!
|
||||
: txOut.address,
|
||||
privateKey: _privateKey!,
|
||||
balanceAfterTx: runningBalance,
|
||||
previousHash: previousHash,
|
||||
|
@ -275,11 +279,11 @@ abstract class NanoWalletBase
|
|||
|
||||
@override
|
||||
NanoWalletKeys get keys {
|
||||
return NanoWalletKeys(seedKey: _seedKey!);
|
||||
return NanoWalletKeys(seedKey: _hexSeed!);
|
||||
}
|
||||
|
||||
@override
|
||||
String? get privateKey => _seedKey!;
|
||||
String? get privateKey => _privateKey!;
|
||||
|
||||
@override
|
||||
Future<void> rescan({required int height}) async {
|
||||
|
@ -297,7 +301,9 @@ abstract class NanoWalletBase
|
|||
}
|
||||
|
||||
@override
|
||||
String get seed => _mnemonic;
|
||||
String? get seed => _mnemonic.isNotEmpty ? _mnemonic : null;
|
||||
|
||||
String get hexSeed => _hexSeed!;
|
||||
|
||||
String get representative => _representativeAddress ?? "";
|
||||
|
||||
|
@ -330,7 +336,7 @@ abstract class NanoWalletBase
|
|||
Future<String> makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type);
|
||||
|
||||
String toJSON() => json.encode({
|
||||
'seedKey': _seedKey,
|
||||
'seedKey': _hexSeed,
|
||||
'mnemonic': _mnemonic,
|
||||
'currentBalance': balance[currency]?.currentBalance.toString() ?? "0",
|
||||
'receivableBalance': balance[currency]?.receivableBalance.toString() ?? "0",
|
||||
|
@ -351,9 +357,9 @@ abstract class NanoWalletBase
|
|||
formattedCurrentBalance: data['currentBalance'] as String? ?? "0",
|
||||
formattedReceivableBalance: data['receivableBalance'] as String? ?? "0");
|
||||
|
||||
DerivationType derivationType = DerivationType.bip39;
|
||||
if (data['derivationType'] == "DerivationType.nano") {
|
||||
derivationType = DerivationType.nano;
|
||||
DerivationType derivationType = DerivationType.nano;
|
||||
if (data['derivationType'] == "DerivationType.bip39") {
|
||||
derivationType = DerivationType.bip39;
|
||||
}
|
||||
|
||||
walletInfo.derivationType = derivationType;
|
||||
|
@ -390,9 +396,9 @@ abstract class NanoWalletBase
|
|||
Future<void> regenerateAddress() async {
|
||||
final String type = (_derivationType == DerivationType.nano) ? "standard" : "hd";
|
||||
_privateKey =
|
||||
await NanoUtil.uniSeedToPrivate(_seedKey!, this.walletAddresses.account!.id, type);
|
||||
await NanoUtil.uniSeedToPrivate(_hexSeed!, this.walletAddresses.account!.id, type);
|
||||
_publicAddress =
|
||||
await NanoUtil.uniSeedToAddress(_seedKey!, this.walletAddresses.account!.id, type);
|
||||
await NanoUtil.uniSeedToAddress(_hexSeed!, this.walletAddresses.account!.id, type);
|
||||
|
||||
this.walletInfo.address = _publicAddress!;
|
||||
this.walletAddresses.address = _publicAddress!;
|
||||
|
|
|
@ -491,50 +491,50 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2"
|
||||
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.15"
|
||||
version: "2.1.1"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86"
|
||||
sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.27"
|
||||
version: "2.2.1"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "916731ccbdce44d545414dd9961f26ba5fbaa74bcbb55237d8e65a623a8c7297"
|
||||
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.4"
|
||||
version: "2.3.1"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57
|
||||
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.11"
|
||||
version: "2.2.1"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec"
|
||||
sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.6"
|
||||
version: "2.1.1"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96"
|
||||
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.7"
|
||||
version: "2.2.1"
|
||||
pinenacl:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -676,6 +676,14 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
socks5_proxy:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: socks5_proxy
|
||||
sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
source_gen:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -756,6 +764,15 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
tor:
|
||||
dependency: transitive
|
||||
description:
|
||||
path: "."
|
||||
ref: main
|
||||
resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5"
|
||||
url: "https://github.com/cake-tech/tor.git"
|
||||
source: git
|
||||
version: "0.0.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -63,8 +63,6 @@ PODS:
|
|||
- Flutter
|
||||
- device_display_brightness (0.0.1):
|
||||
- Flutter
|
||||
- device_info (0.0.1):
|
||||
- Flutter
|
||||
- device_info_plus (0.0.1):
|
||||
- Flutter
|
||||
- devicelocale (0.0.1):
|
||||
|
@ -124,15 +122,13 @@ PODS:
|
|||
- Flutter
|
||||
- MTBBarcodeScanner (5.0.11)
|
||||
- OrderedSet (5.0.0)
|
||||
- package_info (0.0.1):
|
||||
- package_info_plus (0.4.5):
|
||||
- Flutter
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- permission_handler_apple (9.1.1):
|
||||
- Flutter
|
||||
- platform_device_id (0.0.1):
|
||||
- Flutter
|
||||
- ReachabilitySwift (5.0.0)
|
||||
- SDWebImage (5.16.0):
|
||||
- SDWebImage/Core (= 5.16.0)
|
||||
|
@ -147,6 +143,8 @@ PODS:
|
|||
- SwiftProtobuf (1.22.0)
|
||||
- SwiftyGif (5.4.4)
|
||||
- Toast (4.0.0)
|
||||
- tor (0.0.1):
|
||||
- Flutter
|
||||
- uni_links (0.0.1):
|
||||
- Flutter
|
||||
- UnstoppableDomainsResolution (4.0.0):
|
||||
|
@ -154,7 +152,7 @@ PODS:
|
|||
- CryptoSwift
|
||||
- url_launcher_ios (0.0.1):
|
||||
- Flutter
|
||||
- wakelock (0.0.1):
|
||||
- wakelock_plus (0.0.1):
|
||||
- Flutter
|
||||
- workmanager (0.0.1):
|
||||
- Flutter
|
||||
|
@ -167,7 +165,6 @@ DEPENDENCIES:
|
|||
- cw_monero (from `.symlinks/plugins/cw_monero/ios`)
|
||||
- cw_shared_external (from `.symlinks/plugins/cw_shared_external/ios`)
|
||||
- device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`)
|
||||
- device_info (from `.symlinks/plugins/device_info/ios`)
|
||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
|
||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||
|
@ -178,17 +175,17 @@ DEPENDENCIES:
|
|||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
||||
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
|
||||
- local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`)
|
||||
- package_info (from `.symlinks/plugins/package_info/ios`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||
- platform_device_id (from `.symlinks/plugins/platform_device_id/ios`)
|
||||
- sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`)
|
||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- tor (from `.symlinks/plugins/tor/ios`)
|
||||
- uni_links (from `.symlinks/plugins/uni_links/ios`)
|
||||
- UnstoppableDomainsResolution (~> 4.0.0)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
- wakelock (from `.symlinks/plugins/wakelock/ios`)
|
||||
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
|
||||
- workmanager (from `.symlinks/plugins/workmanager/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
|
@ -219,8 +216,6 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/cw_shared_external/ios"
|
||||
device_display_brightness:
|
||||
:path: ".symlinks/plugins/device_display_brightness/ios"
|
||||
device_info:
|
||||
:path: ".symlinks/plugins/device_info/ios"
|
||||
device_info_plus:
|
||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||
devicelocale:
|
||||
|
@ -241,26 +236,26 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/in_app_review/ios"
|
||||
local_auth_ios:
|
||||
:path: ".symlinks/plugins/local_auth_ios/ios"
|
||||
package_info:
|
||||
:path: ".symlinks/plugins/package_info/ios"
|
||||
package_info_plus:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
path_provider_foundation:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
permission_handler_apple:
|
||||
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||
platform_device_id:
|
||||
:path: ".symlinks/plugins/platform_device_id/ios"
|
||||
sensitive_clipboard:
|
||||
:path: ".symlinks/plugins/sensitive_clipboard/ios"
|
||||
share_plus:
|
||||
:path: ".symlinks/plugins/share_plus/ios"
|
||||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
tor:
|
||||
:path: ".symlinks/plugins/tor/ios"
|
||||
uni_links:
|
||||
:path: ".symlinks/plugins/uni_links/ios"
|
||||
url_launcher_ios:
|
||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||
wakelock:
|
||||
:path: ".symlinks/plugins/wakelock/ios"
|
||||
wakelock_plus:
|
||||
:path: ".symlinks/plugins/wakelock_plus/ios"
|
||||
workmanager:
|
||||
:path: ".symlinks/plugins/workmanager/ios"
|
||||
|
||||
|
@ -273,12 +268,11 @@ SPEC CHECKSUMS:
|
|||
cw_monero: 4cf3b96f2da8e95e2ef7d6703dd4d2c509127b7d
|
||||
cw_shared_external: 2972d872b8917603478117c9957dfca611845a92
|
||||
device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7
|
||||
device_info: d7d233b645a32c40dfdc212de5cf646ca482f175
|
||||
device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed
|
||||
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
|
||||
devicelocale: b22617f40038496deffba44747101255cee005b0
|
||||
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
|
||||
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
|
||||
file_picker: ce3938a0df3cc1ef404671531facef740d03f920
|
||||
file_picker: 15fd9539e4eb735dc54bae8c0534a7a9511a03de
|
||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||
flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf
|
||||
flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83
|
||||
|
@ -288,10 +282,9 @@ SPEC CHECKSUMS:
|
|||
local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605
|
||||
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
||||
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
||||
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
|
||||
package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
|
||||
platform_device_id: 81b3e2993881f87d0c82ef151dc274df4869aef5
|
||||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||
SDWebImage: 2aea163b50bfcb569a2726b6a754c54a4506fcf6
|
||||
sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986
|
||||
|
@ -300,10 +293,11 @@ SPEC CHECKSUMS:
|
|||
SwiftProtobuf: 40bd808372cb8706108f22d28f8ab4a6b9bc6989
|
||||
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
|
||||
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
||||
tor: 662a9f5b980b5c86decb8ba611de9bcd4c8286eb
|
||||
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
||||
UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841
|
||||
url_launcher_ios: 68d46cc9766d0c41dbdc884310529557e3cd7a86
|
||||
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
|
||||
url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b
|
||||
wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47
|
||||
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6
|
||||
|
||||
PODFILE CHECKSUM: 09df1114e7c360f55770d35a79356bf5446e0100
|
||||
|
|
|
@ -436,6 +436,7 @@ class BackupService {
|
|||
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
|
||||
final backupPassword = keychainJSON[backupPasswordKey] as String;
|
||||
|
||||
await _flutterSecureStorage.delete(key: backupPasswordKey);
|
||||
await _flutterSecureStorage.write(key: backupPasswordKey, value: backupPassword);
|
||||
|
||||
keychainWalletsInfo.forEach((dynamic rawInfo) async {
|
||||
|
@ -443,6 +444,7 @@ class BackupService {
|
|||
await importWalletKeychainInfo(info);
|
||||
});
|
||||
|
||||
await _flutterSecureStorage.delete(key: pinCodeKey);
|
||||
await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
|
||||
|
||||
keychainDumpFile.deleteSync();
|
||||
|
@ -462,6 +464,7 @@ class BackupService {
|
|||
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
|
||||
final backupPassword = keychainJSON[backupPasswordKey] as String;
|
||||
|
||||
await _flutterSecureStorage.delete(key: backupPasswordKey);
|
||||
await _flutterSecureStorage.write(key: backupPasswordKey, value: backupPassword);
|
||||
|
||||
keychainWalletsInfo.forEach((dynamic rawInfo) async {
|
||||
|
@ -469,6 +472,7 @@ class BackupService {
|
|||
await importWalletKeychainInfo(info);
|
||||
});
|
||||
|
||||
await _flutterSecureStorage.delete(key: pinCodeKey);
|
||||
await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
|
||||
|
||||
keychainDumpFile.deleteSync();
|
||||
|
|
|
@ -19,6 +19,7 @@ class KeyService {
|
|||
key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
|
||||
final encodedPassword = encodeWalletPassword(password: password);
|
||||
|
||||
await _secureStorage.delete(key: key);
|
||||
await _secureStorage.write(key: key, value: encodedPassword);
|
||||
}
|
||||
|
||||
|
|
13
lib/di.dart
13
lib/di.dart
|
@ -27,7 +27,7 @@ import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sideba
|
|||
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/edit_token_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/home_settings_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/pages/transactions_page.dart';
|
||||
import 'package:cake_wallet/src/screens/nano/nano_change_rep_page.dart';
|
||||
import 'package:cake_wallet/src/screens/nano_accounts/nano_account_edit_or_create_page.dart';
|
||||
import 'package:cake_wallet/src/screens/nano_accounts/nano_account_list_page.dart';
|
||||
|
@ -46,6 +46,7 @@ import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.
|
|||
import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/tor_page.dart';
|
||||
import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart';
|
||||
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart';
|
||||
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart';
|
||||
|
@ -64,6 +65,7 @@ import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart';
|
|||
import 'package:cake_wallet/view_model/anonpay_details_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/home_settings_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/ionia/ionia_auth_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/ionia/ionia_buy_card_view_model.dart';
|
||||
|
@ -79,7 +81,7 @@ import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_cards_page.dar
|
|||
import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_page.dart';
|
||||
import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_tip_page.dart';
|
||||
import 'package:cake_wallet/src/screens/ionia/ionia.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/pages/balance_page.dart';
|
||||
import 'package:cake_wallet/view_model/ionia/ionia_account_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/ionia/ionia_gift_cards_list_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/ionia/ionia_purchase_merch_view_model.dart';
|
||||
|
@ -211,7 +213,7 @@ import 'package:cake_wallet/store/templates/exchange_template_store.dart';
|
|||
import 'package:cake_wallet/entities/template.dart';
|
||||
import 'package:cake_wallet/exchange/exchange_template.dart';
|
||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/address_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/pages/address_page.dart';
|
||||
import 'package:cake_wallet/anypay/anypay_api.dart';
|
||||
import 'package:cake_wallet/view_model/ionia/ionia_gift_card_details_view_model.dart';
|
||||
import 'package:cake_wallet/src/screens/ionia/cards/ionia_payment_status_page.dart';
|
||||
|
@ -482,6 +484,7 @@ Future<void> setup({
|
|||
});
|
||||
|
||||
getIt.registerFactory(() => BalancePage(
|
||||
nftViewModel: getIt.get<NFTViewModel>(),
|
||||
dashboardViewModel: getIt.get<DashboardViewModel>(),
|
||||
settingsStore: getIt.get<SettingsStore>()));
|
||||
|
||||
|
@ -1177,5 +1180,9 @@ Future<void> setup({
|
|||
getIt.registerFactory(
|
||||
() => WalletConnectConnectionsView(web3walletService: getIt.get<Web3WalletService>()));
|
||||
|
||||
getIt.registerFactory(() => NFTViewModel(appStore, getIt.get<BottomSheetService>()));
|
||||
|
||||
getIt.registerFactory<TorPage>(() => TorPage(getIt.get<AppStore>()));
|
||||
|
||||
_isSetupFinished = true;
|
||||
}
|
||||
|
|
|
@ -496,6 +496,7 @@ Future<void> generateBackupPassword(FlutterSecureStorage secureStorage) async {
|
|||
}
|
||||
|
||||
final password = encrypt.Key.fromSecureRandom(32).base16;
|
||||
await secureStorage.delete(key: key);
|
||||
await secureStorage.write(key: key, value: password);
|
||||
}
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@ Future<void> ios_migrate_pin() async {
|
|||
|
||||
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
||||
final encodedPassword = encodedPinCode(pin: pinPassword);
|
||||
await flutterSecureStorage.delete(key: key);
|
||||
await flutterSecureStorage.write(key: key, value: encodedPassword);
|
||||
await prefs.setBool('ios_migration_pin_completed', true);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,9 @@ Future<List<int>> getEncryptionKey(
|
|||
if (stringifiedKey == null) {
|
||||
key = CakeHive.generateSecureKey();
|
||||
final keyStringified = key.join(',');
|
||||
await secureStorage.write(key: 'transactionDescriptionsBoxKey', value: keyStringified);
|
||||
String storageKey = 'transactionDescriptionsBoxKey';
|
||||
await secureStorage.delete(key: storageKey);
|
||||
await secureStorage.write(key: storageKey, value: keyStringified);
|
||||
} else {
|
||||
key = stringifiedKey.split(',').map((i) => int.parse(i)).toList();
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ class PreferencesKey {
|
|||
|
||||
static const exchangeProvidersSelection = 'exchange-providers-selection';
|
||||
static const autoGenerateSubaddressStatusKey = 'auto_generate_subaddress_status';
|
||||
static const moneroSeedType = 'monero_seed_type';
|
||||
static const clearnetDonationLink = 'clearnet_donation_link';
|
||||
static const onionDonationLink = 'onion_donation_link';
|
||||
static const lastSeenAppVersion = 'last_seen_app_version';
|
||||
|
|
36
lib/entities/seed_type.dart
Normal file
36
lib/entities/seed_type.dart
Normal file
|
@ -0,0 +1,36 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cw_core/enumerable_item.dart';
|
||||
|
||||
class SeedType extends EnumerableItem<int> with Serializable<int> {
|
||||
const SeedType({required String title, required int raw}) : super(title: title, raw: raw);
|
||||
|
||||
static const all = [SeedType.legacy, SeedType.polyseed];
|
||||
|
||||
static const defaultSeedType = legacy;
|
||||
|
||||
static const legacy = SeedType(raw: 0, title: 'Legacy (25 words)');
|
||||
static const polyseed = SeedType(raw: 1, title: 'Polyseed (16 words)');
|
||||
|
||||
static SeedType deserialize({required int raw}) {
|
||||
switch (raw) {
|
||||
case 0:
|
||||
return legacy;
|
||||
case 1:
|
||||
return polyseed;
|
||||
default:
|
||||
throw Exception('Unexpected token: $raw for SeedType deserialize');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
switch (this) {
|
||||
case SeedType.legacy:
|
||||
return S.current.seedtype_legacy;
|
||||
case SeedType.polyseed:
|
||||
return S.current.seedtype_polyseed;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
95
lib/entities/wallet_nft_response.dart
Normal file
95
lib/entities/wallet_nft_response.dart
Normal file
|
@ -0,0 +1,95 @@
|
|||
class WalletNFTsResponseModel {
|
||||
final int? page;
|
||||
final int? pageSize;
|
||||
|
||||
final List<NFTAssetModel>? result;
|
||||
final String? status;
|
||||
|
||||
WalletNFTsResponseModel({this.page, this.pageSize, this.result, this.status});
|
||||
|
||||
factory WalletNFTsResponseModel.fromJson(Map<String, dynamic> json) {
|
||||
return WalletNFTsResponseModel(
|
||||
page: json['page'] as int?,
|
||||
pageSize: json['page_size'] as int?,
|
||||
result: (json['result'] as List?)
|
||||
?.map((x) => NFTAssetModel.fromJson(x as Map<String, dynamic>))
|
||||
.toList(),
|
||||
status: json['status'] as String?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class NFTAssetModel {
|
||||
final String? tokenAddress;
|
||||
final String? tokenId;
|
||||
final String? contractType;
|
||||
final String? name;
|
||||
final String? symbol;
|
||||
NormalizedMetadata? normalizedMetadata;
|
||||
|
||||
NFTAssetModel(
|
||||
{this.tokenAddress,
|
||||
this.tokenId,
|
||||
this.contractType,
|
||||
this.name,
|
||||
this.symbol,
|
||||
this.normalizedMetadata});
|
||||
|
||||
factory NFTAssetModel.fromJson(Map<String, dynamic> json) {
|
||||
return NFTAssetModel(
|
||||
tokenAddress: json['token_address'] as String?,
|
||||
tokenId: json['token_id'] as String?,
|
||||
contractType: json['contract_type'] as String?,
|
||||
name: json['name'] as String?,
|
||||
symbol: json['symbol'] as String?,
|
||||
normalizedMetadata: json['normalized_metadata'] != null
|
||||
? new NormalizedMetadata.fromJson(
|
||||
json['normalized_metadata'] as Map<String, dynamic>)
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class NormalizedMetadata {
|
||||
final String? name;
|
||||
final String? description;
|
||||
final String? image;
|
||||
NormalizedMetadata({
|
||||
this.name,
|
||||
this.description,
|
||||
this.image,
|
||||
});
|
||||
|
||||
factory NormalizedMetadata.fromJson(Map<String, dynamic> json) {
|
||||
return NormalizedMetadata(
|
||||
name: json['name'] as String?,
|
||||
description: json['description'] as String?,
|
||||
image: json['image'] as String?,
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
String? get imageUrl {
|
||||
if (image == null) return image;
|
||||
|
||||
if (image!.contains('ipfs.io')) return image;
|
||||
|
||||
if (!image!.contains('ipfs')) return image;
|
||||
|
||||
// IPFS public gateway provided by Cloudflare is https://cloudflare-ipfs.com/ipfs/
|
||||
//
|
||||
// Here is an example of an ipfs image link:
|
||||
//
|
||||
// [ipfs://bafkreia2i2ctfexpovgzfff66wqhbmwwpvqjvozan7ioifzcnq76jharwu]
|
||||
|
||||
//https://ipfs.io/ipfs/QmTRcRXo6cXByjHYHTVxGpag6vpocrG3rxjPC9PxKAArR9/1620.png
|
||||
|
||||
const String ipfsPublicGateway = 'https://cloudflare-ipfs.com/ipfs/';
|
||||
|
||||
final ipfsPath = image?.split('//')[1];
|
||||
|
||||
final imageLink = '$ipfsPublicGateway$ipfsPath';
|
||||
|
||||
return imageLink;
|
||||
}
|
||||
}
|
|
@ -166,6 +166,10 @@ class CWMonero extends Monero {
|
|||
|
||||
@override
|
||||
List<String> getMoneroWordList(String language) {
|
||||
if (language.startsWith("POLYSEED_")) {
|
||||
final lang = language.replaceAll("POLYSEED_", "");
|
||||
return PolyseedLang.getByEnglishName(lang).words;
|
||||
}
|
||||
switch (language.toLowerCase()) {
|
||||
case 'english':
|
||||
return EnglishMnemonics.words;
|
||||
|
@ -223,8 +227,10 @@ class CWMonero extends Monero {
|
|||
WalletCredentials createMoneroNewWalletCredentials({
|
||||
required String name,
|
||||
required String language,
|
||||
required bool isPolyseed,
|
||||
String? password}) =>
|
||||
MoneroNewWalletCredentials(name: name, password: password, language: language);
|
||||
MoneroNewWalletCredentials(
|
||||
name: name, password: password, language: language, isPolyseed: isPolyseed);
|
||||
|
||||
@override
|
||||
Map<String, String> getKeys(Object wallet) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart';
|
|||
import 'package:cake_wallet/entities/contact_record.dart';
|
||||
import 'package:cake_wallet/buy/order.dart';
|
||||
import 'package:cake_wallet/entities/qr_view_data.dart';
|
||||
import 'package:cake_wallet/entities/wallet_nft_response.dart';
|
||||
import 'package:cake_wallet/src/screens/anonpay_details/anonpay_details_page.dart';
|
||||
import 'package:cake_wallet/src/screens/backup/backup_page.dart';
|
||||
import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart';
|
||||
|
@ -13,6 +14,7 @@ import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart';
|
|||
import 'package:cake_wallet/src/screens/buy/webview_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/edit_token_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/home_settings_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/pages/nft_details_page.dart';
|
||||
import 'package:cake_wallet/src/screens/nano/nano_change_rep_page.dart';
|
||||
import 'package:cake_wallet/src/screens/nano_accounts/nano_account_edit_or_create_page.dart';
|
||||
import 'package:cake_wallet/src/screens/nodes/pow_node_create_or_edit_page.dart';
|
||||
|
@ -20,7 +22,7 @@ import 'package:cake_wallet/src/screens/restore/sweeping_wallet_page.dart';
|
|||
import 'package:cake_wallet/src/screens/receive/anonpay_invoice_page.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/anonpay_receive_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/pages/transactions_page.dart';
|
||||
import 'package:cake_wallet/src/screens/restore/wallet_restore_choose_derivation.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/desktop_settings/desktop_settings_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/display_settings_page.dart';
|
||||
|
@ -43,6 +45,7 @@ import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart';
|
|||
import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/tor_page.dart';
|
||||
import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart';
|
||||
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart';
|
||||
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart';
|
||||
|
@ -53,8 +56,10 @@ import 'package:cake_wallet/src/screens/support_other_links/support_other_links_
|
|||
import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart';
|
||||
import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/utils/payment_request.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart';
|
||||
import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
|
||||
|
@ -83,7 +88,6 @@ import 'package:cake_wallet/src/screens/setup_pin_code/setup_pin_code.dart';
|
|||
import 'package:cake_wallet/src/screens/restore/restore_options_page.dart';
|
||||
import 'package:cake_wallet/src/screens/send/send_page.dart';
|
||||
import 'package:cake_wallet/src/screens/disclaimer/disclaimer_page.dart';
|
||||
import 'package:cake_wallet/src/screens/seed_language/seed_language_page.dart';
|
||||
import 'package:cake_wallet/src/screens/transaction_details/transaction_details_page.dart';
|
||||
import 'package:cake_wallet/src/screens/monero_accounts/monero_account_edit_or_create_page.dart';
|
||||
import 'package:cake_wallet/src/screens/contact/contact_list_page.dart';
|
||||
|
@ -101,7 +105,7 @@ import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dar
|
|||
import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_page.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:cake_wallet/wallet_types.g.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/address_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/pages/address_page.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart';
|
||||
import 'package:cake_wallet/src/screens/ionia/ionia.dart';
|
||||
import 'package:cake_wallet/src/screens/ionia/cards/ionia_payment_status_page.dart';
|
||||
|
@ -110,6 +114,8 @@ import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart';
|
|||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/node.dart';
|
||||
|
||||
import 'src/screens/dashboard/pages/nft_import_page.dart';
|
||||
|
||||
late RouteSettings currentRouteSettings;
|
||||
|
||||
Route<dynamic> createRoute(RouteSettings settings) {
|
||||
|
@ -141,8 +147,9 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
case Routes.newWallet:
|
||||
final type = settings.arguments as WalletType;
|
||||
final walletNewVM = getIt.get<WalletNewVM>(param1: type);
|
||||
final settingsStore = getIt.get<SettingsStore>();
|
||||
|
||||
return CupertinoPageRoute<void>(builder: (_) => NewWalletPage(walletNewVM));
|
||||
return CupertinoPageRoute<void>(builder: (_) => NewWalletPage(walletNewVM, settingsStore));
|
||||
|
||||
case Routes.setupPin:
|
||||
Function(PinCodeState<PinCodeWidget>, String)? callback;
|
||||
|
@ -258,17 +265,6 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
case Routes.changeRep:
|
||||
return CupertinoPageRoute<void>(builder: (_) => getIt.get<NanoChangeRepPage>());
|
||||
|
||||
case Routes.seedLanguage:
|
||||
final args = settings.arguments as List<dynamic>;
|
||||
final type = args.first as WalletType;
|
||||
final redirectRoute = args[1] as String;
|
||||
|
||||
return CupertinoPageRoute<void>(builder: (_) {
|
||||
return SeedLanguage(
|
||||
onConfirm: (context, lang) =>
|
||||
Navigator.of(context).popAndPushNamed(redirectRoute, arguments: [type, lang]));
|
||||
});
|
||||
|
||||
case Routes.walletList:
|
||||
return MaterialPageRoute<void>(
|
||||
fullscreenDialog: true, builder: (_) => getIt.get<WalletListPage>());
|
||||
|
@ -615,6 +611,25 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
web3walletService: getIt.get<Web3WalletService>(),
|
||||
launchUri: settings.arguments as Uri?,
|
||||
));
|
||||
|
||||
case Routes.nftDetailsPage:
|
||||
return MaterialPageRoute<void>(
|
||||
builder: (_) => NFTDetailsPage(
|
||||
nftAsset: settings.arguments as NFTAssetModel,
|
||||
dashboardViewModel: getIt.get<DashboardViewModel>(),
|
||||
),
|
||||
);
|
||||
|
||||
case Routes.importNFTPage:
|
||||
return MaterialPageRoute<void>(
|
||||
builder: (_) => ImportNFTPage(
|
||||
nftViewModel: settings.arguments as NFTViewModel,
|
||||
),
|
||||
);
|
||||
|
||||
case Routes.torPage:
|
||||
return MaterialPageRoute<void>(builder: (_) => getIt.get<TorPage>());
|
||||
|
||||
default:
|
||||
return MaterialPageRoute<void>(
|
||||
builder: (_) => Scaffold(
|
||||
|
|
|
@ -7,7 +7,8 @@ class Routes {
|
|||
static const restoreOptions = '/restore_options';
|
||||
static const restoreWalletFromSeedKeys = '/restore_wallet_from_seeds_keys';
|
||||
static const restoreWalletTypeFromQR = '/restore_wallet_from_qr_code';
|
||||
static const restoreWalletChooseDerivation = '/restore_wallet_choose_derivation';
|
||||
static const restoreWalletChooseDerivation =
|
||||
'/restore_wallet_choose_derivation';
|
||||
static const dashboard = '/dashboard';
|
||||
static const send = '/send';
|
||||
static const transactionDetails = '/transaction_info';
|
||||
|
@ -17,7 +18,6 @@ class Routes {
|
|||
static const disclaimer = '/disclaimer';
|
||||
static const readDisclaimer = '/read_disclaimer';
|
||||
static const changeRep = '/change_representative';
|
||||
static const seedLanguage = '/seed_language';
|
||||
static const walletList = '/view_model.wallet_list';
|
||||
static const auth = '/auth';
|
||||
static const newNode = '/new_node_list';
|
||||
|
@ -100,5 +100,9 @@ class Routes {
|
|||
static const editToken = '/edit_token';
|
||||
static const manageNodes = '/manage_nodes';
|
||||
static const managePowNodes = '/manage_pow_nodes';
|
||||
static const walletConnectConnectionsListing = '/wallet-connect-connections-listing';
|
||||
static const walletConnectConnectionsListing =
|
||||
'/wallet-connect-connections-listing';
|
||||
static const nftDetailsPage = '/nft_details_page';
|
||||
static const importNFTPage = '/import_nft_page';
|
||||
static const torPage = '/tor_page';
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import 'dart:async';
|
||||
import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/entities/main_actions.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/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/widgets/gradient_background.dart';
|
||||
import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
|
||||
|
@ -15,7 +14,6 @@ import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart';
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/yat_emoji_id.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -23,8 +21,8 @@ import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
|||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/menu_widget.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/action_button.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/pages/balance_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/pages/transactions_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
import 'dart:async';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/release_notes/release_notes_screen.dart';
|
||||
import 'package:cake_wallet/src/screens/yat_emoji_id.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/utils/version_comparator.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/pages/balance_page.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/main.dart';
|
||||
import 'package:cake_wallet/router.dart' as Router;
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/entities/main_actions.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_action_button.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/market_place_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/pages/market_place_page.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
|
@ -6,10 +6,8 @@ import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart';
|
|||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/entities/receive_page_option.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/present_receive_option_picker.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/src/widgets/gradient_background.dart';
|
||||
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
|
||||
import 'package:cake_wallet/themes/extensions/receive_page_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
|
@ -26,7 +24,6 @@ import 'package:flutter_mobx/flutter_mobx.dart';
|
|||
import 'package:keyboard_actions/keyboard_actions.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/balance_page_theme.dart';
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||
|
||||
|
@ -192,8 +189,7 @@ class AddressPage extends BasePage {
|
|||
? S.of(context).accounts_subaddresses
|
||||
: S.of(context).addresses;
|
||||
|
||||
if (!addressListViewModel.hasSilentAddresses &&
|
||||
dashboardViewModel.isAutoGenerateSubaddressesEnabled) {
|
||||
if (dashboardViewModel.isAutoGenerateSubaddressesEnabled) {
|
||||
label = addressListViewModel.hasAccounts
|
||||
? S.of(context).accounts
|
||||
: S.of(context).account;
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:auto_size_text/auto_size_text.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/pages/nft_listing_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/home_screen_account_widget.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/introducing_card.dart';
|
||||
|
@ -11,15 +12,80 @@ import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
|
|||
import 'package:cake_wallet/utils/feature_flag.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/nft_view_model.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
class BalancePage extends StatelessWidget {
|
||||
BalancePage({required this.dashboardViewModel, required this.settingsStore});
|
||||
BalancePage({
|
||||
required this.dashboardViewModel,
|
||||
required this.settingsStore,
|
||||
required this.nftViewModel,
|
||||
});
|
||||
|
||||
final DashboardViewModel dashboardViewModel;
|
||||
final NFTViewModel nftViewModel;
|
||||
final SettingsStore settingsStore;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Observer(
|
||||
builder: (context) {
|
||||
final isEthereumWallet = dashboardViewModel.type == WalletType.ethereum;
|
||||
return DefaultTabController(
|
||||
length: isEthereumWallet ? 2 : 1,
|
||||
child: Column(
|
||||
children: [
|
||||
if (isEthereumWallet)
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 8),
|
||||
child: TabBar(
|
||||
indicatorSize: TabBarIndicatorSize.label,
|
||||
isScrollable: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
labelStyle: TextStyle(
|
||||
fontSize: 18,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w600,
|
||||
color:
|
||||
Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor,
|
||||
height: 1,
|
||||
),
|
||||
tabs: [
|
||||
Tab(text: 'My Crypto'),
|
||||
Tab(text: 'My NFTs'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
children: [
|
||||
CryptoBalanceWidget(dashboardViewModel: dashboardViewModel),
|
||||
if (isEthereumWallet) NFTListingPage(nftViewModel: nftViewModel)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CryptoBalanceWidget extends StatelessWidget {
|
||||
const CryptoBalanceWidget({
|
||||
super.key,
|
||||
required this.dashboardViewModel,
|
||||
});
|
||||
|
||||
final DashboardViewModel dashboardViewModel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
|
@ -38,7 +104,7 @@ class BalancePage extends StatelessWidget {
|
|||
accountName: dashboardViewModel.subname)
|
||||
: Column(
|
||||
children: [
|
||||
SizedBox(height: 56),
|
||||
SizedBox(height: 16),
|
||||
Container(
|
||||
margin: const EdgeInsets.only(left: 24, bottom: 16),
|
||||
child: Observer(
|
||||
|
@ -105,8 +171,7 @@ class BalancePage extends StatelessWidget {
|
|||
itemBuilder: (__, index) {
|
||||
final balance =
|
||||
dashboardViewModel.balanceViewModel.formattedBalances.elementAt(index);
|
||||
return buildBalanceRow(
|
||||
context,
|
||||
return BalanceRowWidget(
|
||||
availableBalanceLabel:
|
||||
'${dashboardViewModel.balanceViewModel.availableBalanceLabel}',
|
||||
availableBalance: balance.availableBalance,
|
||||
|
@ -130,20 +195,44 @@ class BalancePage extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget buildBalanceRow(
|
||||
BuildContext context, {
|
||||
required String availableBalanceLabel,
|
||||
required String availableBalance,
|
||||
required String availableFiatBalance,
|
||||
required String additionalBalanceLabel,
|
||||
required String additionalBalance,
|
||||
required String additionalFiatBalance,
|
||||
required String frozenBalance,
|
||||
required String frozenFiatBalance,
|
||||
required String currency,
|
||||
required bool hasAdditionalBalance,
|
||||
}) {
|
||||
class BalanceRowWidget extends StatelessWidget {
|
||||
const BalanceRowWidget({
|
||||
required this.availableBalanceLabel,
|
||||
required this.availableBalance,
|
||||
required this.availableFiatBalance,
|
||||
required this.additionalBalanceLabel,
|
||||
required this.additionalBalance,
|
||||
required this.additionalFiatBalance,
|
||||
required this.frozenBalance,
|
||||
required this.frozenFiatBalance,
|
||||
required this.currency,
|
||||
required this.hasAdditionalBalance,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final String availableBalanceLabel;
|
||||
final String availableBalance;
|
||||
final String availableFiatBalance;
|
||||
final String additionalBalanceLabel;
|
||||
final String additionalBalance;
|
||||
final String additionalFiatBalance;
|
||||
final String frozenBalance;
|
||||
final String frozenFiatBalance;
|
||||
final String currency;
|
||||
final bool hasAdditionalBalance;
|
||||
|
||||
// void _showBalanceDescription(BuildContext context) {
|
||||
// showPopUp<void>(
|
||||
// context: context,
|
||||
// builder: (_) =>
|
||||
// InformationPage(information: S.current.available_balance_description),
|
||||
// );
|
||||
// }
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(left: 16, right: 16),
|
||||
decoration: BoxDecoration(
|
||||
|
@ -165,8 +254,9 @@ class BalancePage extends StatelessWidget {
|
|||
children: [
|
||||
GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: hasAdditionalBalance ? () =>
|
||||
_showBalanceDescription(context, S.current.available_balance_description)
|
||||
onTap: hasAdditionalBalance
|
||||
? () =>
|
||||
_showBalanceDescription(context, S.current.available_balance_description)
|
||||
: null,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
@ -229,8 +319,9 @@ class BalancePage extends StatelessWidget {
|
|||
if (frozenBalance.isNotEmpty)
|
||||
GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: hasAdditionalBalance ?
|
||||
() => _showBalanceDescription(context, S.current.unavailable_balance_description)
|
||||
onTap: hasAdditionalBalance
|
||||
? () =>
|
||||
_showBalanceDescription(context, S.current.unavailable_balance_description)
|
||||
: null,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
@ -253,9 +344,8 @@ class BalancePage extends StatelessWidget {
|
|||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Icon(Icons.help_outline,
|
||||
size: 16,
|
||||
color: Theme.of(context)
|
||||
.extension<BalancePageTheme>()!
|
||||
.labelTextColor),
|
||||
color:
|
||||
Theme.of(context).extension<BalancePageTheme>()!.labelTextColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -337,8 +427,6 @@ class BalancePage extends StatelessWidget {
|
|||
}
|
||||
|
||||
void _showBalanceDescription(BuildContext context, String content) {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) => InformationPage(information: content));
|
||||
showPopUp<void>(context: context, builder: (_) => InformationPage(information: content));
|
||||
}
|
||||
}
|
178
lib/src/screens/dashboard/pages/nft_details_page.dart
Normal file
178
lib/src/screens/dashboard/pages/nft_details_page.dart
Normal file
|
@ -0,0 +1,178 @@
|
|||
import 'package:cake_wallet/entities/wallet_nft_response.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/menu_widget.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/nft_image_tile_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/gradient_background.dart';
|
||||
import 'package:cake_wallet/themes/extensions/balance_page_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class NFTDetailsPage extends BasePage {
|
||||
NFTDetailsPage({required this.dashboardViewModel, required this.nftAsset});
|
||||
|
||||
final DashboardViewModel dashboardViewModel;
|
||||
final NFTAssetModel nftAsset;
|
||||
|
||||
@override
|
||||
bool get gradientBackground => true;
|
||||
|
||||
@override
|
||||
Widget Function(BuildContext, Widget) get rootWrapper =>
|
||||
(BuildContext context, Widget scaffold) =>
|
||||
GradientBackground(scaffold: scaffold);
|
||||
|
||||
@override
|
||||
bool get resizeToAvoidBottomInset => false;
|
||||
|
||||
@override
|
||||
Widget get endDrawer => MenuWidget(dashboardViewModel);
|
||||
|
||||
@override
|
||||
Widget trailing(BuildContext context) {
|
||||
final menuButton = Image.asset(
|
||||
'assets/images/menu.png',
|
||||
color:
|
||||
Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor,
|
||||
);
|
||||
|
||||
return Container(
|
||||
alignment: Alignment.centerRight,
|
||||
width: 40,
|
||||
child: TextButton(
|
||||
// FIX-ME: Style
|
||||
//highlightColor: Colors.transparent,
|
||||
//splashColor: Colors.transparent,
|
||||
//padding: EdgeInsets.all(0),
|
||||
onPressed: () => onOpenEndDrawer(),
|
||||
child: Semantics(label: S.of(context).wallet_menu, child: menuButton),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(30.0),
|
||||
border: Border.all(
|
||||
color: Theme.of(context)
|
||||
.extension<BalancePageTheme>()!
|
||||
.cardBorderColor,
|
||||
width: 1,
|
||||
),
|
||||
color: Theme.of(context)
|
||||
.extension<SyncIndicatorTheme>()!
|
||||
.syncedBackgroundColor,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
height: MediaQuery.sizeOf(context).height / 2.5,
|
||||
width: double.infinity,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
margin: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(16.0),
|
||||
border: Border.all(
|
||||
color: Theme.of(context)
|
||||
.extension<BalancePageTheme>()!
|
||||
.cardBorderColor,
|
||||
width: 1,
|
||||
),
|
||||
color: Theme.of(context)
|
||||
.extension<SyncIndicatorTheme>()!
|
||||
.syncedBackgroundColor,
|
||||
|
||||
),
|
||||
child: NFTImageWidget(
|
||||
imageUrl: nftAsset.normalizedMetadata?.imageUrl,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
_NFTSingleInfoTile(
|
||||
infoType: S.current.name,
|
||||
infoValue: nftAsset.normalizedMetadata?.name ?? '',
|
||||
),
|
||||
|
||||
if (nftAsset.normalizedMetadata?.description != null) ...[
|
||||
SizedBox(height: 16),
|
||||
_NFTSingleInfoTile(
|
||||
infoType: 'Description',
|
||||
infoValue: nftAsset.normalizedMetadata?.description ?? '',
|
||||
),
|
||||
],
|
||||
|
||||
SizedBox(height: 16),
|
||||
_NFTSingleInfoTile(
|
||||
infoType: 'Contract Name',
|
||||
infoValue: nftAsset.name ?? '',
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
_NFTSingleInfoTile(
|
||||
infoType: 'Contract Symbol',
|
||||
infoValue: nftAsset.symbol ?? '',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _NFTSingleInfoTile extends StatelessWidget {
|
||||
const _NFTSingleInfoTile({
|
||||
required this.infoType,
|
||||
required this.infoValue,
|
||||
});
|
||||
|
||||
final String infoType;
|
||||
final String infoValue;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
infoType,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context)
|
||||
.extension<BalancePageTheme>()!
|
||||
.labelTextColor,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Text(
|
||||
infoValue,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context)
|
||||
.extension<BalancePageTheme>()!
|
||||
.assetTitleColor,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
168
lib/src/screens/dashboard/pages/nft_import_page.dart
Normal file
168
lib/src/screens/dashboard/pages/nft_import_page.dart
Normal file
|
@ -0,0 +1,168 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/address_text_field.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
class ImportNFTPage extends StatefulWidget {
|
||||
const ImportNFTPage({required this.nftViewModel, super.key});
|
||||
|
||||
final NFTViewModel nftViewModel;
|
||||
|
||||
@override
|
||||
State<ImportNFTPage> createState() => _ImportNFTPageState();
|
||||
}
|
||||
|
||||
class _ImportNFTPageState extends State<ImportNFTPage> {
|
||||
late TextEditingController tokenAddressController;
|
||||
late TextEditingController tokenIDController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
tokenAddressController = TextEditingController();
|
||||
tokenIDController = TextEditingController();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
tokenAddressController.dispose();
|
||||
tokenIDController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _ImportNFTPage(
|
||||
nftViewModel: widget.nftViewModel,
|
||||
tokenAddressController: tokenAddressController,
|
||||
tokenIDController: tokenIDController,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ImportNFTPage extends BasePage {
|
||||
_ImportNFTPage({
|
||||
required this.tokenIDController,
|
||||
required this.tokenAddressController,
|
||||
required this.nftViewModel,
|
||||
});
|
||||
|
||||
final NFTViewModel nftViewModel;
|
||||
final TextEditingController tokenIDController;
|
||||
final TextEditingController tokenAddressController;
|
||||
|
||||
@override
|
||||
String? get title => S.current.import;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
||||
Text(
|
||||
S.current.address,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w800,
|
||||
color:
|
||||
Theme.of(context).extension<SeedWidgetTheme>()!.hintTextColor,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
AddressTextField(
|
||||
controller: tokenAddressController,
|
||||
options: [AddressTextFieldOption.paste],
|
||||
onPushPasteButton: (context) async {
|
||||
final clipboard = await Clipboard.getData('text/plain');
|
||||
final tokenAddress = clipboard?.text ?? '';
|
||||
|
||||
if (tokenAddress.isNotEmpty) {
|
||||
tokenAddressController.text = tokenAddress;
|
||||
}
|
||||
},
|
||||
borderColor: Theme.of(context)
|
||||
.extension<CakeTextTheme>()!
|
||||
.textfieldUnderlineColor,
|
||||
iconColor: Theme.of(context).primaryColor,
|
||||
placeholder: '0x...',
|
||||
textStyle: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: PaletteDark.darkCyanBlue,
|
||||
),
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: PaletteDark.darkCyanBlue,
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 48),
|
||||
Text(
|
||||
S.current.tokenID,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w800,
|
||||
color: Theme.of(context).extension<SeedWidgetTheme>()!.hintTextColor,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
AddressTextField(
|
||||
controller: tokenIDController,
|
||||
options: [AddressTextFieldOption.paste],
|
||||
onPushPasteButton: (context) async {
|
||||
final clipboard = await Clipboard.getData('text/plain');
|
||||
final tokenID = clipboard?.text ?? '';
|
||||
|
||||
if (tokenID.isNotEmpty) {
|
||||
tokenIDController.text = tokenID;
|
||||
}
|
||||
},
|
||||
borderColor: Theme.of(context)
|
||||
.extension<CakeTextTheme>()!
|
||||
.textfieldUnderlineColor,
|
||||
iconColor: Theme.of(context).primaryColor,
|
||||
placeholder: S.current.enterTokenID,
|
||||
textStyle: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: PaletteDark.darkCyanBlue,
|
||||
),
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: PaletteDark.darkCyanBlue,
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
Observer(builder: (context) {
|
||||
return LoadingPrimaryButton(
|
||||
isLoading: nftViewModel.isImportNFTLoading,
|
||||
text: S.current.import,
|
||||
color: Theme.of(context).primaryColor,
|
||||
textColor: Colors.white,
|
||||
onPressed: () async {
|
||||
await nftViewModel.importNFT(tokenAddressController.text, tokenIDController.text);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
84
lib/src/screens/dashboard/pages/nft_listing_page.dart
Normal file
84
lib/src/screens/dashboard/pages/nft_listing_page.dart
Normal file
|
@ -0,0 +1,84 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/nft_tile_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
class NFTListingPage extends StatelessWidget {
|
||||
final NFTViewModel nftViewModel;
|
||||
|
||||
const NFTListingPage({super.key, required this.nftViewModel});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Observer(
|
||||
builder: (context) {
|
||||
return Column(
|
||||
children: [
|
||||
SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 16, right: 16, bottom: 16),
|
||||
child: PrimaryButton(
|
||||
text: S.current.import,
|
||||
color: Theme.of(context)
|
||||
.extension<SyncIndicatorTheme>()!
|
||||
.syncedBackgroundColor,
|
||||
textColor: Colors.white,
|
||||
onPressed: () => Navigator.pushNamed(
|
||||
context,
|
||||
Routes.importNFTPage,
|
||||
arguments: nftViewModel,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (nftViewModel.isLoading)
|
||||
Expanded(
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(
|
||||
backgroundColor: Theme.of(context).extension<DashboardPageTheme>()!.textColor,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
Theme.of(context)
|
||||
.extension<ExchangePageTheme>()!
|
||||
.firstGradientBottomPanelColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (!nftViewModel.isLoading)
|
||||
Expanded(
|
||||
child: nftViewModel.nftAssetByWalletModels.isEmpty
|
||||
? Center(
|
||||
child: Text(
|
||||
S.current.noNFTYet,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context)
|
||||
.extension<DashboardPageTheme>()!
|
||||
.pageTitleTextColor,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
)
|
||||
: ListView.separated(
|
||||
padding: EdgeInsets.symmetric(horizontal: 4, vertical: 16),
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8),
|
||||
itemCount: nftViewModel.nftAssetByWalletModels.length,
|
||||
itemBuilder: (context, index) {
|
||||
final nftAsset = nftViewModel.nftAssetByWalletModels[index];
|
||||
return NFTTileWidget(nftAsset: nftAsset);
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
|
@ -46,9 +46,11 @@ class TransactionsPage extends StatelessWidget {
|
|||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 0, 24, 8),
|
||||
child: DashBoardRoundedCardWidget(
|
||||
onTap: () => Navigator.of(context).pushNamed(
|
||||
Routes.webViewPage,
|
||||
arguments: ['', Uri.parse('https://guides.cakewallet.com/docs/bugs-service-status/why_are_my_funds_not_appearing/')]),
|
||||
onTap: () => Navigator.of(context).pushNamed(Routes.webViewPage, arguments: [
|
||||
'',
|
||||
Uri.parse(
|
||||
'https://guides.cakewallet.com/docs/bugs-service-status/why_are_my_funds_not_appearing/')
|
||||
]),
|
||||
title: S.of(context).syncing_wallet_alert_title,
|
||||
subTitle: S.of(context).syncing_wallet_alert_content,
|
||||
),
|
||||
|
@ -76,40 +78,34 @@ class TransactionsPage extends StatelessWidget {
|
|||
|
||||
return Observer(
|
||||
builder: (_) => TransactionRow(
|
||||
onTap: () => Navigator.of(context).pushNamed(
|
||||
Routes.transactionDetails,
|
||||
arguments: transaction),
|
||||
onTap: () => Navigator.of(context)
|
||||
.pushNamed(Routes.transactionDetails, arguments: transaction),
|
||||
direction: transaction.direction,
|
||||
formattedDate: DateFormat('HH:mm')
|
||||
.format(transaction.date),
|
||||
formattedDate: DateFormat('HH:mm').format(transaction.date),
|
||||
formattedAmount: item.formattedCryptoAmount,
|
||||
formattedFiatAmount: dashboardViewModel
|
||||
.balanceViewModel.isFiatDisabled
|
||||
? ''
|
||||
: item.formattedFiatAmount,
|
||||
formattedFiatAmount:
|
||||
dashboardViewModel.balanceViewModel.isFiatDisabled
|
||||
? ''
|
||||
: item.formattedFiatAmount,
|
||||
isPending: transaction.isPending,
|
||||
title: item.formattedTitle +
|
||||
item.formattedStatus));
|
||||
title: item.formattedTitle + item.formattedStatus));
|
||||
}
|
||||
|
||||
if (item is AnonpayTransactionListItem) {
|
||||
final transactionInfo = item.transaction;
|
||||
|
||||
return AnonpayTransactionRow(
|
||||
onTap: () => Navigator.of(context).pushNamed(
|
||||
Routes.anonPayDetailsPage,
|
||||
arguments: transactionInfo),
|
||||
onTap: () => Navigator.of(context)
|
||||
.pushNamed(Routes.anonPayDetailsPage, arguments: transactionInfo),
|
||||
currency: transactionInfo.fiatAmount != null
|
||||
? transactionInfo.fiatEquiv ?? ''
|
||||
: CryptoCurrency.fromFullName(
|
||||
transactionInfo.coinTo)
|
||||
: CryptoCurrency.fromFullName(transactionInfo.coinTo)
|
||||
.name
|
||||
.toUpperCase(),
|
||||
provider: transactionInfo.provider,
|
||||
amount: transactionInfo.fiatAmount?.toString() ??
|
||||
(transactionInfo.amountTo?.toString() ?? ''),
|
||||
createdAt: DateFormat('HH:mm')
|
||||
.format(transactionInfo.createdAt),
|
||||
createdAt: DateFormat('HH:mm').format(transactionInfo.createdAt),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -118,17 +114,14 @@ class TransactionsPage extends StatelessWidget {
|
|||
|
||||
return Observer(
|
||||
builder: (_) => TradeRow(
|
||||
onTap: () => Navigator.of(context).pushNamed(
|
||||
Routes.tradeDetails,
|
||||
arguments: trade),
|
||||
onTap: () => Navigator.of(context)
|
||||
.pushNamed(Routes.tradeDetails, arguments: trade),
|
||||
provider: trade.provider,
|
||||
from: trade.from,
|
||||
to: trade.to,
|
||||
createdAtFormattedDate:
|
||||
trade.createdAt != null
|
||||
? DateFormat('HH:mm')
|
||||
.format(trade.createdAt!)
|
||||
: null,
|
||||
createdAtFormattedDate: trade.createdAt != null
|
||||
? DateFormat('HH:mm').format(trade.createdAt!)
|
||||
: null,
|
||||
formattedAmount: item.tradeFormattedAmount));
|
||||
}
|
||||
|
||||
|
@ -138,13 +131,12 @@ class TransactionsPage extends StatelessWidget {
|
|||
return Observer(
|
||||
builder: (_) => OrderRow(
|
||||
onTap: () => Navigator.of(context)
|
||||
.pushNamed(Routes.orderDetails,
|
||||
arguments: order),
|
||||
.pushNamed(Routes.orderDetails, arguments: order),
|
||||
provider: order.provider,
|
||||
from: order.from!,
|
||||
to: order.to!,
|
||||
createdAtFormattedDate: DateFormat('HH:mm')
|
||||
.format(order.createdAt),
|
||||
createdAtFormattedDate:
|
||||
DateFormat('HH:mm').format(order.createdAt),
|
||||
formattedAmount: item.orderFormattedAmount,
|
||||
));
|
||||
}
|
37
lib/src/screens/dashboard/widgets/nft_image_tile_widget.dart
Normal file
37
lib/src/screens/dashboard/widgets/nft_image_tile_widget.dart
Normal file
|
@ -0,0 +1,37 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
class NFTImageWidget extends StatelessWidget {
|
||||
const NFTImageWidget({
|
||||
required this.imageUrl,
|
||||
});
|
||||
|
||||
final String? imageUrl;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
try {
|
||||
if (imageUrl == null) return Icon(Icons.error);
|
||||
|
||||
if (imageUrl!.contains('.svg')) {
|
||||
return SvgPicture.network(imageUrl!);
|
||||
}
|
||||
|
||||
return Image.network(
|
||||
imageUrl!,
|
||||
fit: BoxFit.cover,
|
||||
loadingBuilder: (BuildContext _, Widget child, ImageChunkEvent? loadingProgress) {
|
||||
if (loadingProgress == null) {
|
||||
return child;
|
||||
} else {
|
||||
return CupertinoActivityIndicator(animating: true);
|
||||
}
|
||||
},
|
||||
errorBuilder: (_, __, ___) => Icon(Icons.error),
|
||||
);
|
||||
} catch (_) {
|
||||
return Icon(Icons.error);
|
||||
}
|
||||
}
|
||||
}
|
95
lib/src/screens/dashboard/widgets/nft_tile_widget.dart
Normal file
95
lib/src/screens/dashboard/widgets/nft_tile_widget.dart
Normal file
|
@ -0,0 +1,95 @@
|
|||
import 'package:cake_wallet/entities/wallet_nft_response.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/nft_image_tile_widget.dart';
|
||||
import 'package:cake_wallet/themes/extensions/balance_page_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class NFTTileWidget extends StatelessWidget {
|
||||
const NFTTileWidget({super.key, required this.nftAsset});
|
||||
|
||||
final NFTAssetModel nftAsset;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
onTap: () => Navigator.pushNamed(context, Routes.nftDetailsPage,
|
||||
arguments: nftAsset),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.only(left: 16, right: 16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(30.0),
|
||||
border: Border.all(
|
||||
color: Theme.of(context)
|
||||
.extension<BalancePageTheme>()!
|
||||
.cardBorderColor,
|
||||
width: 1,
|
||||
),
|
||||
color: Theme.of(context)
|
||||
.extension<SyncIndicatorTheme>()!
|
||||
.syncedBackgroundColor,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
height: 100,
|
||||
width: 100,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
margin: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(16.0),
|
||||
border: Border.all(
|
||||
color: Theme.of(context)
|
||||
.extension<BalancePageTheme>()!
|
||||
.cardBorderColor,
|
||||
width: 1,
|
||||
),
|
||||
color: Theme.of(context)
|
||||
.extension<SyncIndicatorTheme>()!
|
||||
.syncedBackgroundColor,
|
||||
),
|
||||
child: NFTImageWidget(
|
||||
imageUrl: nftAsset.normalizedMetadata?.imageUrl,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${nftAsset.name ?? ''} - ${nftAsset.symbol ?? ''}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context)
|
||||
.extension<BalancePageTheme>()!
|
||||
.labelTextColor,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Text(
|
||||
nftAsset.normalizedMetadata?.name ?? nftAsset.name ?? "",
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w900,
|
||||
color: Theme.of(context)
|
||||
.extension<BalancePageTheme>()!
|
||||
.assetTitleColor,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/seed_phrase_length.dart';
|
||||
import 'package:cake_wallet/entities/seed_type.dart';
|
||||
import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
|
||||
|
@ -97,16 +98,27 @@ class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBod
|
|||
);
|
||||
}),
|
||||
if (widget.privacySettingsViewModel.hasSeedPhraseLengthOption)
|
||||
Observer(builder: (_) {
|
||||
return SettingsPickerCell<SeedPhraseLength>(
|
||||
title: S.current.seed_phrase_length,
|
||||
items: SeedPhraseLength.values,
|
||||
selectedItem: widget.privacySettingsViewModel.seedPhraseLength,
|
||||
onItemSelected: (SeedPhraseLength length) {
|
||||
widget.privacySettingsViewModel.setSeedPhraseLength(length);
|
||||
},
|
||||
);
|
||||
}),
|
||||
Observer(builder: (_) {
|
||||
return SettingsPickerCell<SeedPhraseLength>(
|
||||
title: S.current.seed_phrase_length,
|
||||
items: SeedPhraseLength.values,
|
||||
selectedItem: widget.privacySettingsViewModel.seedPhraseLength,
|
||||
onItemSelected: (SeedPhraseLength length) {
|
||||
widget.privacySettingsViewModel.setSeedPhraseLength(length);
|
||||
},
|
||||
);
|
||||
}),
|
||||
if (widget.privacySettingsViewModel.hasSeedTypeOption)
|
||||
Observer(builder: (_) {
|
||||
return SettingsChoicesCell(
|
||||
ChoicesListItem<SeedType>(
|
||||
title: S.current.seedtype,
|
||||
items: SeedType.all,
|
||||
selectedItem: widget.privacySettingsViewModel.seedType,
|
||||
onItemSelected: widget.privacySettingsViewModel.setSeedType,
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
bottomSectionPadding: EdgeInsets.all(24),
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import 'package:cake_wallet/entities/generate_name.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker.dart';
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:cake_wallet/main.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
|
@ -15,17 +17,20 @@ import 'package:cake_wallet/src/widgets/seed_language_selector.dart';
|
|||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
|
||||
import 'package:cake_wallet/src/widgets/seed_language_picker.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/core/execution_state.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_new_vm.dart';
|
||||
import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
|
||||
import 'package:cake_wallet/entities/seed_type.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
|
||||
class NewWalletPage extends BasePage {
|
||||
NewWalletPage(this._walletNewVM);
|
||||
NewWalletPage(this._walletNewVM, this._settingsStore);
|
||||
|
||||
final WalletNewVM _walletNewVM;
|
||||
final SettingsStore _settingsStore;
|
||||
|
||||
final walletNameImage = Image.asset('assets/images/wallet_name.png');
|
||||
|
||||
|
@ -36,14 +41,15 @@ class NewWalletPage extends BasePage {
|
|||
|
||||
@override
|
||||
Widget body(BuildContext context) => WalletNameForm(
|
||||
_walletNewVM, currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage);
|
||||
_walletNewVM, currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage, _settingsStore);
|
||||
}
|
||||
|
||||
class WalletNameForm extends StatefulWidget {
|
||||
WalletNameForm(this._walletNewVM, this.walletImage);
|
||||
WalletNameForm(this._walletNewVM, this.walletImage, this._settingsStore);
|
||||
|
||||
final WalletNewVM _walletNewVM;
|
||||
final Image walletImage;
|
||||
final SettingsStore _settingsStore;
|
||||
|
||||
@override
|
||||
_WalletNameFormState createState() => _WalletNameFormState(_walletNewVM);
|
||||
|
@ -85,6 +91,8 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
|||
});
|
||||
}
|
||||
});
|
||||
|
||||
_setSeedType(SeedType.defaultSeedType);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
@ -180,22 +188,40 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
|||
),
|
||||
),
|
||||
),
|
||||
|
||||
if (_walletNewVM.hasLanguageSelector) ...[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 40),
|
||||
child: Text(
|
||||
S.of(context).seed_language_choose,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
|
||||
if (_walletNewVM.hasSeedType) ...[
|
||||
Observer(
|
||||
builder: (BuildContext build) => Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: SelectButton(
|
||||
text: widget._settingsStore.moneroSeedType.title,
|
||||
onTap: () async {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) => Picker(
|
||||
items: SeedType.all,
|
||||
selectedAtIndex: isPolyseed ? 1 : 0,
|
||||
onItemSelected: _setSeedType,
|
||||
isSeparated: false,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
Observer(
|
||||
builder: (BuildContext build) => Padding(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: SeedLanguageSelector(
|
||||
key: _languageSelectorKey,
|
||||
initialSelected: defaultSeedLanguage,
|
||||
seedType: _walletNewVM.hasSeedType
|
||||
? widget._settingsStore.moneroSeedType
|
||||
: SeedType.legacy,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: SeedLanguageSelector(
|
||||
key: _languageSelectorKey, initialSelected: defaultSeedLanguage),
|
||||
)
|
||||
],
|
||||
Observer(builder: (context) {
|
||||
|
@ -229,7 +255,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
|||
Navigator.of(context)
|
||||
.pushNamed(Routes.advancedPrivacySettings, arguments: _walletNewVM.type);
|
||||
},
|
||||
child: Text(S.of(context).advanced_privacy_settings),
|
||||
child: Text(S.of(context).advanced_settings),
|
||||
),
|
||||
],
|
||||
)),
|
||||
|
@ -253,8 +279,15 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
|||
} else {
|
||||
_walletNewVM.create(
|
||||
options: _walletNewVM.hasLanguageSelector
|
||||
? _languageSelectorKey.currentState!.selected
|
||||
? [_languageSelectorKey.currentState!.selected, isPolyseed]
|
||||
: null);
|
||||
}
|
||||
}
|
||||
|
||||
bool get isPolyseed => widget._settingsStore.moneroSeedType == SeedType.polyseed;
|
||||
|
||||
void _setSeedType(SeedType item) {
|
||||
widget._settingsStore.moneroSeedType = item;
|
||||
_languageSelectorKey.currentState?.selected = defaultSeedLanguage; // Reset Seed language
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ class WalletRestoreFromKeysFromState extends State<WalletRestoreFromKeysFrom> {
|
|||
widget.walletRestoreViewModel.type == WalletType.banano;
|
||||
return AddressTextField(
|
||||
controller: privateKeyController,
|
||||
placeholder: nanoBased ? S.of(context).seed_key : S.of(context).private_key,
|
||||
placeholder: nanoBased ? S.of(context).seed_hex_form : S.of(context).private_key,
|
||||
options: [AddressTextFieldOption.paste],
|
||||
buttonColor: Theme.of(context).hintColor,
|
||||
onPushPasteButton: (_) {
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
import 'package:cake_wallet/core/wallet_name_validator.dart';
|
||||
import 'package:cake_wallet/entities/generate_name.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
|
||||
import 'package:cake_wallet/src/widgets/seed_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||
import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/core/wallet_name_validator.dart';
|
||||
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:cake_wallet/entities/seed_type.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker.dart';
|
||||
import 'package:cake_wallet/src/widgets/seed_language_picker.dart';
|
||||
import 'package:polyseed/polyseed.dart';
|
||||
|
||||
class WalletRestoreFromSeedForm extends StatefulWidget {
|
||||
WalletRestoreFromSeedForm({
|
||||
|
@ -47,21 +50,35 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
|||
blockchainHeightKey = GlobalKey<BlockchainHeightState>(),
|
||||
formKey = GlobalKey<FormState>(),
|
||||
languageController = TextEditingController(),
|
||||
nameTextEditingController = TextEditingController();
|
||||
nameTextEditingController = TextEditingController(),
|
||||
seedTypeController = TextEditingController();
|
||||
|
||||
final GlobalKey<SeedWidgetState> seedWidgetStateKey;
|
||||
final GlobalKey<BlockchainHeightState> blockchainHeightKey;
|
||||
final TextEditingController languageController;
|
||||
final TextEditingController nameTextEditingController;
|
||||
final TextEditingController seedTypeController;
|
||||
final GlobalKey<FormState> formKey;
|
||||
String language;
|
||||
bool isPolyseed = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_setLanguageLabel(language);
|
||||
_setSeedType(SeedType.defaultSeedType);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void onSeedChange(String seed) {
|
||||
if (widget.type == WalletType.monero && Polyseed.isValidSeed(seed)) {
|
||||
final lang = PolyseedLang.getByPhrase(seed);
|
||||
|
||||
_changeSeedType(SeedType.polyseed);
|
||||
_changeLanguage(lang.nameEnglish);
|
||||
}
|
||||
widget.onSeedChange?.call(seed);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
|
@ -111,24 +128,58 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
|||
key: seedWidgetStateKey,
|
||||
language: language,
|
||||
type: widget.type,
|
||||
onSeedChange: widget.onSeedChange),
|
||||
onSeedChange: onSeedChange),
|
||||
if (widget.type == WalletType.monero)
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) => Picker(
|
||||
items: SeedType.all,
|
||||
selectedAtIndex: isPolyseed ? 1 : 0,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
onItemSelected: _changeSeedType,
|
||||
isSeparated: false,
|
||||
));
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
padding: EdgeInsets.only(top: 20.0),
|
||||
child: IgnorePointer(
|
||||
child: BaseTextFormField(
|
||||
controller: seedTypeController,
|
||||
enableInteractiveSelection: false,
|
||||
readOnly: true,
|
||||
suffixIcon: expandIcon,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.displayLanguageSelector)
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) =>
|
||||
SeedLanguagePicker(selected: language, onItemSelected: _changeLanguage));
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
padding: EdgeInsets.only(top: 20.0),
|
||||
child: IgnorePointer(
|
||||
child: BaseTextFormField(
|
||||
controller: languageController,
|
||||
enableInteractiveSelection: false,
|
||||
readOnly: true)))),
|
||||
if (widget.displayBlockHeightSelector)
|
||||
onTap: () async {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) => SeedLanguagePicker(
|
||||
selected: language,
|
||||
onItemSelected: _changeLanguage,
|
||||
seedType: isPolyseed ? SeedType.polyseed : SeedType.legacy,
|
||||
));
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
padding: EdgeInsets.only(top: 20.0),
|
||||
child: IgnorePointer(
|
||||
child: BaseTextFormField(
|
||||
controller: languageController,
|
||||
enableInteractiveSelection: false,
|
||||
readOnly: true,
|
||||
suffixIcon: expandIcon,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (!isPolyseed && widget.displayBlockHeightSelector)
|
||||
BlockchainHeightWidget(
|
||||
focusNode: widget.blockHeightFocusNode,
|
||||
key: blockchainHeightKey,
|
||||
|
@ -143,14 +194,37 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
|||
]));
|
||||
}
|
||||
|
||||
Widget get expandIcon => Container(
|
||||
padding: EdgeInsets.all(18),
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: Image.asset(
|
||||
'assets/images/arrow_bottom_purple_icon.png',
|
||||
height: 8,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
);
|
||||
|
||||
void _changeLanguage(String language) {
|
||||
final setLang = isPolyseed ? "POLYSEED_$language" : language;
|
||||
setState(() {
|
||||
this.language = language;
|
||||
seedWidgetStateKey.currentState!.changeSeedLanguage(language);
|
||||
_setLanguageLabel(language);
|
||||
widget.onLanguageChange?.call(language);
|
||||
this.language = setLang;
|
||||
seedWidgetStateKey.currentState!.changeSeedLanguage(setLang);
|
||||
_setLanguageLabel(setLang);
|
||||
widget.onLanguageChange?.call(setLang);
|
||||
});
|
||||
}
|
||||
|
||||
void _setLanguageLabel(String language) => languageController.text = '$language (Seed language)';
|
||||
void _setLanguageLabel(String language) =>
|
||||
languageController.text = '${language.replaceAll("POLYSEED_", "")} (Seed language)';
|
||||
|
||||
void _changeSeedType(SeedType item) {
|
||||
_setSeedType(item);
|
||||
_changeLanguage('English');
|
||||
}
|
||||
|
||||
void _setSeedType(SeedType item) {
|
||||
setState(() => isPolyseed = item == SeedType.polyseed);
|
||||
seedTypeController.text = item.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +1,30 @@
|
|||
import 'package:cake_wallet/core/execution_state.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/restore/wallet_restore_from_keys_form.dart';
|
||||
import 'package:cake_wallet/src/screens/restore/wallet_restore_from_seed_form.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
|
||||
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
|
||||
import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_restore_view_model.dart';
|
||||
import 'package:cw_core/nano_account_info_response.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:keyboard_actions/keyboard_actions.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:polyseed/polyseed.dart';
|
||||
import 'package:smooth_page_indicator/smooth_page_indicator.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/core/execution_state.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_restore_view_model.dart';
|
||||
import 'package:cake_wallet/src/screens/restore/wallet_restore_from_keys_form.dart';
|
||||
import 'package:cake_wallet/src/screens/restore/wallet_restore_from_seed_form.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
|
||||
import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart';
|
||||
|
||||
class WalletRestorePage extends BasePage {
|
||||
WalletRestorePage(this.walletRestoreViewModel)
|
||||
|
@ -50,27 +51,13 @@ class WalletRestorePage extends BasePage {
|
|||
}
|
||||
},
|
||||
onSeedChange: (String seed) {
|
||||
if (walletRestoreViewModel.hasBlockchainHeightLanguageSelector) {
|
||||
final hasHeight = walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey
|
||||
.currentState!.restoreHeightController.text.isNotEmpty;
|
||||
if (hasHeight) {
|
||||
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
|
||||
}
|
||||
} else {
|
||||
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
|
||||
}
|
||||
final isPolyseed =
|
||||
walletRestoreViewModel.type == WalletType.monero && Polyseed.isValidSeed(seed);
|
||||
_validateOnChange(isPolyseed: isPolyseed);
|
||||
},
|
||||
onLanguageChange: (_) {
|
||||
if (walletRestoreViewModel.hasBlockchainHeightLanguageSelector) {
|
||||
final hasHeight = walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey
|
||||
.currentState!.restoreHeightController.text.isNotEmpty;
|
||||
|
||||
if (hasHeight) {
|
||||
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
|
||||
}
|
||||
} else {
|
||||
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
|
||||
}
|
||||
onLanguageChange: (String language) {
|
||||
final isPolyseed = language.startsWith("POLYSEED_");
|
||||
_validateOnChange(isPolyseed: isPolyseed);
|
||||
}));
|
||||
break;
|
||||
case WalletRestoreMode.keys:
|
||||
|
@ -225,7 +212,7 @@ class WalletRestorePage extends BasePage {
|
|||
Navigator.of(context).pushNamed(Routes.advancedPrivacySettings,
|
||||
arguments: walletRestoreViewModel.type);
|
||||
},
|
||||
child: Text(S.of(context).advanced_privacy_settings),
|
||||
child: Text(S.of(context).advanced_settings),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -238,9 +225,26 @@ class WalletRestorePage extends BasePage {
|
|||
);
|
||||
}
|
||||
|
||||
void _validateOnChange({bool isPolyseed = false}) {
|
||||
if (!isPolyseed && walletRestoreViewModel.hasBlockchainHeightLanguageSelector) {
|
||||
final hasHeight = walletRestoreFromSeedFormKey
|
||||
.currentState?.blockchainHeightKey.currentState?.restoreHeightController.text.isNotEmpty;
|
||||
|
||||
if (hasHeight == true) {
|
||||
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
|
||||
}
|
||||
} else {
|
||||
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
|
||||
}
|
||||
}
|
||||
|
||||
bool _isValidSeed() {
|
||||
final seedWords =
|
||||
walletRestoreFromSeedFormKey.currentState!.seedWidgetStateKey.currentState!.text.split(' ');
|
||||
final seedPhrase =
|
||||
walletRestoreFromSeedFormKey.currentState!.seedWidgetStateKey.currentState!.text;
|
||||
if (walletRestoreViewModel.type == WalletType.monero && Polyseed.isValidSeed(seedPhrase))
|
||||
return true;
|
||||
|
||||
final seedWords = seedPhrase.split(' ');
|
||||
|
||||
if ((walletRestoreViewModel.type == WalletType.monero ||
|
||||
walletRestoreViewModel.type == WalletType.haven) &&
|
||||
|
@ -285,7 +289,8 @@ class WalletRestorePage extends BasePage {
|
|||
|
||||
if (walletRestoreViewModel.hasBlockchainHeightLanguageSelector) {
|
||||
credentials['height'] =
|
||||
walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey.currentState!.height;
|
||||
walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey.currentState?.height ??
|
||||
-1;
|
||||
}
|
||||
|
||||
credentials['name'] =
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/src/widgets/seed_language_selector.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
|
||||
|
||||
class SeedLanguage extends BasePage {
|
||||
SeedLanguage({required this.onConfirm});
|
||||
|
||||
final Function(BuildContext, String) onConfirm;
|
||||
|
||||
final walletNameImage = Image.asset('assets/images/wallet_name.png');
|
||||
final walletNameLightImage =
|
||||
Image.asset('assets/images/wallet_name_light.png');
|
||||
|
||||
@override
|
||||
String get title => S.current.wallet_list_restore_wallet;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) =>
|
||||
SeedLanguageForm(
|
||||
onConfirm: onConfirm,
|
||||
walletImage: currentTheme.type == ThemeType.dark
|
||||
? walletNameImage : walletNameLightImage);
|
||||
}
|
||||
|
||||
class SeedLanguageForm extends StatefulWidget {
|
||||
SeedLanguageForm({required this.onConfirm, required this.walletImage});
|
||||
|
||||
final Function(BuildContext, String) onConfirm;
|
||||
final Image walletImage;
|
||||
|
||||
@override
|
||||
SeedLanguageFormState createState() => SeedLanguageFormState();
|
||||
}
|
||||
|
||||
class SeedLanguageFormState extends State<SeedLanguageForm> {
|
||||
static const aspectRatioImage = 1.22;
|
||||
final _languageSelectorKey = GlobalKey<SeedLanguageSelectorState>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: ScrollableWithBottomSection(
|
||||
contentPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
||||
content:
|
||||
Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 12, right: 12),
|
||||
child: AspectRatio(
|
||||
aspectRatio: aspectRatioImage,
|
||||
child: FittedBox(child: widget.walletImage,
|
||||
fit: BoxFit.fill)),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 40),
|
||||
child: Text(
|
||||
S.of(context).seed_language_choose,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
color:
|
||||
Theme.of(context).extension<CakeTextTheme>()!.titleColor),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: SeedLanguageSelector(
|
||||
key: _languageSelectorKey,
|
||||
initialSelected: defaultSeedLanguage),
|
||||
)
|
||||
]),
|
||||
bottomSectionPadding:
|
||||
EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
||||
bottomSection: Observer(
|
||||
builder: (context) {
|
||||
return PrimaryButton(
|
||||
onPressed: () => widget.onConfirm(
|
||||
context, _languageSelectorKey.currentState!.selected),
|
||||
text: S.of(context).seed_language_next,
|
||||
color: Colors.green,
|
||||
textColor: Colors.white);
|
||||
},
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
||||
List<Image> flagImages = [
|
||||
Image.asset('assets/images/flags/usa.png'),
|
||||
Image.asset('assets/images/flags/chn.png'),
|
||||
Image.asset('assets/images/flags/nld.png'),
|
||||
Image.asset('assets/images/flags/deu.png'),
|
||||
Image.asset('assets/images/flags/jpn.png'),
|
||||
Image.asset('assets/images/flags/prt.png'),
|
||||
Image.asset('assets/images/flags/rus.png'),
|
||||
Image.asset('assets/images/flags/esp.png'),
|
||||
Image.asset('assets/images/flags/fra.png'),
|
||||
Image.asset('assets/images/flags/ita.png'),
|
||||
];
|
||||
|
||||
const List<String> languageCodes = [
|
||||
'Eng',
|
||||
'Chi',
|
||||
'Ned',
|
||||
'Ger',
|
||||
'Jap',
|
||||
'Por',
|
||||
'Rus',
|
||||
'Esp',
|
||||
'Fre',
|
||||
'Ita',
|
||||
];
|
||||
|
||||
const defaultSeedLanguage = 'English';
|
||||
|
||||
const List<String> seedLanguages = [
|
||||
defaultSeedLanguage,
|
||||
'Chinese (simplified)',
|
||||
'Dutch',
|
||||
'German',
|
||||
'Japanese',
|
||||
'Portuguese',
|
||||
'Russian',
|
||||
'Spanish',
|
||||
'French',
|
||||
'Italian',
|
||||
];
|
||||
|
||||
enum Places { topLeft, topRight, bottomLeft, bottomRight, inside }
|
||||
|
||||
class SeedLanguagePicker extends StatefulWidget {
|
||||
SeedLanguagePicker({Key? key, this.selected = defaultSeedLanguage, required this.onItemSelected})
|
||||
: super(key: key);
|
||||
|
||||
final String selected;
|
||||
final Function(String) onItemSelected;
|
||||
|
||||
@override
|
||||
SeedLanguagePickerState createState() =>
|
||||
SeedLanguagePickerState(selected: selected, onItemSelected: onItemSelected);
|
||||
}
|
||||
|
||||
class SeedLanguagePickerState extends State<SeedLanguagePicker> {
|
||||
SeedLanguagePickerState({required this.selected, required this.onItemSelected});
|
||||
|
||||
final String selected;
|
||||
final Function(String) onItemSelected;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Picker(
|
||||
selectedAtIndex: seedLanguages.indexOf(selected),
|
||||
items: seedLanguages,
|
||||
images: flagImages,
|
||||
isGridView: true,
|
||||
title: S.of(context).seed_choose,
|
||||
hintText: S.of(context).seed_choose,
|
||||
matchingCriteria: (String language, String searchText) {
|
||||
return language.toLowerCase().contains(searchText);
|
||||
},
|
||||
onItemSelected: onItemSelected,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -3,8 +3,8 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arro
|
|||
import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/wallet_connect_button.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:cake_wallet/utils/feature_flag.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/settings/sync_mode.dart';
|
||||
|
@ -90,7 +90,12 @@ class ConnectionSyncPage extends BasePage {
|
|||
onTap: () => Navigator.of(context).pushNamed(Routes.walletConnectConnectionsListing),
|
||||
),
|
||||
const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||
]
|
||||
],
|
||||
if (FeatureFlag.isInAppTorEnabled)
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.tor_connection,
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.torPage),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
@ -22,81 +22,83 @@ class PrivacyPage extends BasePage {
|
|||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Observer(builder: (_) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SettingsChoicesCell(
|
||||
ChoicesListItem<FiatApiMode>(
|
||||
title: S.current.fiat_api,
|
||||
items: FiatApiMode.all,
|
||||
selectedItem: _privacySettingsViewModel.fiatApiMode,
|
||||
onItemSelected: (FiatApiMode fiatApiMode) =>
|
||||
_privacySettingsViewModel.setFiatMode(fiatApiMode),
|
||||
return SingleChildScrollView(
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Observer(builder: (_) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SettingsChoicesCell(
|
||||
ChoicesListItem<FiatApiMode>(
|
||||
title: S.current.fiat_api,
|
||||
items: FiatApiMode.all,
|
||||
selectedItem: _privacySettingsViewModel.fiatApiMode,
|
||||
onItemSelected: (FiatApiMode fiatApiMode) =>
|
||||
_privacySettingsViewModel.setFiatMode(fiatApiMode),
|
||||
),
|
||||
),
|
||||
),
|
||||
SettingsChoicesCell(
|
||||
ChoicesListItem<ExchangeApiMode>(
|
||||
title: S.current.exchange,
|
||||
items: ExchangeApiMode.all,
|
||||
selectedItem: _privacySettingsViewModel.exchangeStatus,
|
||||
onItemSelected: (ExchangeApiMode mode) =>
|
||||
_privacySettingsViewModel.setExchangeApiMode(mode),
|
||||
SettingsChoicesCell(
|
||||
ChoicesListItem<ExchangeApiMode>(
|
||||
title: S.current.exchange,
|
||||
items: ExchangeApiMode.all,
|
||||
selectedItem: _privacySettingsViewModel.exchangeStatus,
|
||||
onItemSelected: (ExchangeApiMode mode) =>
|
||||
_privacySettingsViewModel.setExchangeApiMode(mode),
|
||||
),
|
||||
),
|
||||
),
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.settings_save_recipient_address,
|
||||
value: _privacySettingsViewModel.shouldSaveRecipientAddress,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setShouldSaveRecipientAddress(value);
|
||||
}),
|
||||
if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.auto_generate_subaddresses,
|
||||
value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setAutoGenerateSubaddresses(value);
|
||||
},
|
||||
),
|
||||
if (DeviceInfo.instance.isMobile)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.prevent_screenshots,
|
||||
value: _privacySettingsViewModel.isAppSecure,
|
||||
title: S.current.settings_save_recipient_address,
|
||||
value: _privacySettingsViewModel.shouldSaveRecipientAddress,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setIsAppSecure(value);
|
||||
_privacySettingsViewModel.setShouldSaveRecipientAddress(value);
|
||||
}),
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.disable_buy,
|
||||
value: _privacySettingsViewModel.disableBuy,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setDisableBuy(value);
|
||||
}),
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.disable_sell,
|
||||
value: _privacySettingsViewModel.disableSell,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setDisableSell(value);
|
||||
}),
|
||||
if (_privacySettingsViewModel.canUseEtherscan)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.etherscan_history,
|
||||
value: _privacySettingsViewModel.useEtherscan,
|
||||
if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.auto_generate_subaddresses,
|
||||
value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setUseEtherscan(value);
|
||||
_privacySettingsViewModel.setAutoGenerateSubaddresses(value);
|
||||
},
|
||||
),
|
||||
if (DeviceInfo.instance.isMobile)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.prevent_screenshots,
|
||||
value: _privacySettingsViewModel.isAppSecure,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setIsAppSecure(value);
|
||||
}),
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.disable_buy,
|
||||
value: _privacySettingsViewModel.disableBuy,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setDisableBuy(value);
|
||||
}),
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.domain_looks_up,
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage),
|
||||
),
|
||||
SettingsCellWithArrow(
|
||||
title: 'Trocador providers',
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.trocadorProvidersPage),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.disable_sell,
|
||||
value: _privacySettingsViewModel.disableSell,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setDisableSell(value);
|
||||
}),
|
||||
if (_privacySettingsViewModel.canUseEtherscan)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.etherscan_history,
|
||||
value: _privacySettingsViewModel.useEtherscan,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setUseEtherscan(value);
|
||||
}),
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.domain_looks_up,
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage),
|
||||
),
|
||||
SettingsCellWithArrow(
|
||||
title: 'Trocador providers',
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.trocadorProvidersPage),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
267
lib/src/screens/settings/tor_page.dart
Normal file
267
lib/src/screens/settings/tor_page.dart
Normal file
|
@ -0,0 +1,267 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tor/tor.dart';
|
||||
|
||||
class TorPage extends BasePage {
|
||||
final AppStore appStore;
|
||||
|
||||
TorPage(this.appStore);
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return TorPageBody(appStore);
|
||||
}
|
||||
}
|
||||
|
||||
class TorPageBody extends StatefulWidget {
|
||||
final AppStore appStore;
|
||||
|
||||
const TorPageBody(this.appStore, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<TorPageBody> createState() => _TorPageBodyState();
|
||||
}
|
||||
|
||||
class _TorPageBodyState extends State<TorPageBody> {
|
||||
bool torEnabled = false;
|
||||
bool connecting = false;
|
||||
|
||||
// Set the default text for the host input field.
|
||||
final hostController = TextEditingController(text: 'https://icanhazip.com/');
|
||||
|
||||
// https://check.torproject.org is another good option.
|
||||
|
||||
Future<void> startTor() async {
|
||||
setState(() {
|
||||
connecting = true; // Update flag
|
||||
});
|
||||
|
||||
await Tor.init();
|
||||
|
||||
// Start the proxy
|
||||
await Tor.instance.start();
|
||||
|
||||
// Toggle started flag.
|
||||
setState(() {
|
||||
torEnabled = Tor.instance.enabled; // Update flag
|
||||
connecting = false;
|
||||
});
|
||||
|
||||
final node = widget.appStore.settingsStore.getCurrentNode(widget.appStore.wallet!.type);
|
||||
if (node.socksProxyAddress?.isEmpty ?? true) {
|
||||
node.socksProxyAddress = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}";
|
||||
}
|
||||
widget.appStore.wallet!.connectToNode(node: node);
|
||||
|
||||
print('Done awaiting; tor should be running');
|
||||
}
|
||||
|
||||
Future<void> endTor() async {
|
||||
// Start the proxy
|
||||
Tor.instance.disable();
|
||||
|
||||
// Toggle started flag.
|
||||
setState(() {
|
||||
torEnabled = Tor.instance.enabled; // Update flag
|
||||
});
|
||||
|
||||
print('Done awaiting; tor should be stopped');
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
torEnabled = Tor.instance.enabled;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// Clean up the controller when the widget is disposed.
|
||||
hostController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: connecting
|
||||
? ConnectingScreen()
|
||||
: torEnabled
|
||||
? DisconnectScreen(disconnect: endTor)
|
||||
: ConnectScreen(connect: startTor),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ConnectScreen extends StatelessWidget {
|
||||
final Function() connect;
|
||||
|
||||
const ConnectScreen({super.key, required this.connect});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: 200,
|
||||
height: 200,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.blue,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.lock,
|
||||
color: Colors.white,
|
||||
size: 100,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Text(
|
||||
'Connect to Tor',
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Text(
|
||||
'Your connection to the Tor network ensures privacy and security.',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.grey,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 30),
|
||||
ElevatedButton(
|
||||
onPressed: connect,
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: Colors.blue,
|
||||
padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
'Connect',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class DisconnectScreen extends StatelessWidget {
|
||||
final Function() disconnect;
|
||||
|
||||
const DisconnectScreen({super.key, required this.disconnect});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: 200,
|
||||
height: 200,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.green,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.check,
|
||||
color: Colors.white,
|
||||
size: 100,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Text(
|
||||
'Connected to Tor',
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Text(
|
||||
'You are currently connected to the Tor network.',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.grey,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 30),
|
||||
ElevatedButton(
|
||||
onPressed: disconnect,
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: Colors.red,
|
||||
padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
'Disconnect',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ConnectingScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: 200,
|
||||
height: 200,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.yellow,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.hourglass_bottom,
|
||||
color: Colors.white,
|
||||
size: 100,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Text(
|
||||
'Connecting...',
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -57,6 +57,8 @@ class ChatwootWidgetState extends State<ChatwootWidget> {
|
|||
return true;
|
||||
}
|
||||
|
||||
Future<void> storeCookie(String value) async =>
|
||||
await widget.secureStorage.write(key: COOKIE_KEY, value: value);
|
||||
Future<void> storeCookie(String value) async {
|
||||
await widget.secureStorage.delete(key: COOKIE_KEY);
|
||||
await widget.secureStorage.write(key: COOKIE_KEY, value: value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ class WalletConnectConnectionsView extends StatelessWidget {
|
|||
|
||||
final actualLinkList = launchUri.query.split("uri=");
|
||||
|
||||
if (actualLinkList.length <= 1) return;
|
||||
|
||||
final query = actualLinkList[1];
|
||||
|
||||
final uri = Uri.decodeComponent(query);
|
||||
|
|
|
@ -68,13 +68,16 @@ class AddressTextField extends StatelessWidget {
|
|||
enabled: isActive,
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
|
||||
style: textStyle ??
|
||||
TextStyle(
|
||||
fontSize: 16, color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
|
||||
decoration: InputDecoration(
|
||||
|
||||
suffixIcon: SizedBox(
|
||||
width: prefixIconWidth * options.length + (spaceBetweenPrefixIcons * options.length),
|
||||
),
|
||||
|
||||
hintStyle: hintStyle ?? TextStyle(fontSize: 16, color: Theme.of(context).hintColor),
|
||||
hintText: placeholder ?? S.current.widgets_address,
|
||||
focusedBorder: isBorderExist
|
||||
|
|
93
lib/src/widgets/seed_language_picker.dart
Normal file
93
lib/src/widgets/seed_language_picker.dart
Normal file
|
@ -0,0 +1,93 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
||||
import 'package:cake_wallet/entities/seed_type.dart';
|
||||
|
||||
class SeedLanguagePickerOption {
|
||||
SeedLanguagePickerOption(this.name, this.nameLocalized, this.image, this.supportedSeedTypes);
|
||||
|
||||
final String name;
|
||||
final String nameLocalized;
|
||||
final Image image;
|
||||
final List<SeedType> supportedSeedTypes;
|
||||
}
|
||||
|
||||
final List<SeedLanguagePickerOption> seedLanguages = [
|
||||
SeedLanguagePickerOption('English', S.current.seed_language_english,
|
||||
Image.asset('assets/images/flags/usa.png'), [SeedType.legacy, SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Chinese (simplified)', S.current.seed_language_chinese,
|
||||
Image.asset('assets/images/flags/chn.png'), [SeedType.legacy, SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Chinese (Traditional)', S.current.seed_language_chinese_traditional,
|
||||
Image.asset('assets/images/flags/chn.png'), [SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Dutch', S.current.seed_language_dutch,
|
||||
Image.asset('assets/images/flags/nld.png'), [SeedType.legacy]),
|
||||
SeedLanguagePickerOption('German', S.current.seed_language_german,
|
||||
Image.asset('assets/images/flags/deu.png'), [SeedType.legacy]),
|
||||
SeedLanguagePickerOption('Japanese', S.current.seed_language_japanese,
|
||||
Image.asset('assets/images/flags/jpn.png'), [SeedType.legacy, SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Korean', S.current.seed_language_korean,
|
||||
Image.asset('assets/images/flags/kor.png'), [SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Portuguese', S.current.seed_language_portuguese,
|
||||
Image.asset('assets/images/flags/prt.png'), [SeedType.legacy, SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Russian', S.current.seed_language_russian,
|
||||
Image.asset('assets/images/flags/rus.png'), [SeedType.legacy]),
|
||||
SeedLanguagePickerOption('Czech', S.current.seed_language_czech,
|
||||
Image.asset('assets/images/flags/czk.png'), [SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Spanish', S.current.seed_language_spanish,
|
||||
Image.asset('assets/images/flags/esp.png'), [SeedType.legacy, SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('French', S.current.seed_language_french,
|
||||
Image.asset('assets/images/flags/fra.png'), [SeedType.legacy, SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Italian', S.current.seed_language_italian,
|
||||
Image.asset('assets/images/flags/ita.png'), [SeedType.legacy, SeedType.polyseed]),
|
||||
];
|
||||
|
||||
const defaultSeedLanguage = 'English';
|
||||
|
||||
enum Places { topLeft, topRight, bottomLeft, bottomRight, inside }
|
||||
|
||||
class SeedLanguagePicker extends StatefulWidget {
|
||||
SeedLanguagePicker(
|
||||
{Key? key,
|
||||
this.selected = defaultSeedLanguage,
|
||||
this.seedType = SeedType.defaultSeedType,
|
||||
required this.onItemSelected})
|
||||
: super(key: key);
|
||||
|
||||
final SeedType seedType;
|
||||
final String selected;
|
||||
final Function(String) onItemSelected;
|
||||
|
||||
@override
|
||||
SeedLanguagePickerState createState() => SeedLanguagePickerState(
|
||||
selected: selected, onItemSelected: onItemSelected, seedType: seedType);
|
||||
}
|
||||
|
||||
class SeedLanguagePickerState extends State<SeedLanguagePicker> {
|
||||
SeedLanguagePickerState(
|
||||
{required this.selected, required this.onItemSelected, required this.seedType});
|
||||
|
||||
final SeedType seedType;
|
||||
final String selected;
|
||||
final Function(String) onItemSelected;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final availableSeedLanguages = seedLanguages
|
||||
.where((SeedLanguagePickerOption e) => e.supportedSeedTypes.contains(seedType));
|
||||
|
||||
return Picker(
|
||||
selectedAtIndex: availableSeedLanguages.map((e) => e.name).toList().indexOf(selected),
|
||||
items: availableSeedLanguages.map((e) => e.name).toList(),
|
||||
images: availableSeedLanguages.map((e) => e.image).toList(),
|
||||
isGridView: true,
|
||||
title: S.of(context).seed_choose,
|
||||
hintText: S.of(context).seed_choose,
|
||||
matchingCriteria: (String language, String searchText) {
|
||||
return language.toLowerCase().contains(searchText);
|
||||
},
|
||||
onItemSelected: onItemSelected,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,49 +1,42 @@
|
|||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/entities/seed_type.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
|
||||
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
|
||||
import 'package:cake_wallet/src/widgets/seed_language_picker.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SeedLanguageSelector extends StatefulWidget {
|
||||
SeedLanguageSelector({Key? key, required this.initialSelected})
|
||||
SeedLanguageSelector(
|
||||
{Key? key, required this.initialSelected, this.seedType = SeedType.defaultSeedType})
|
||||
: super(key: key);
|
||||
|
||||
final String initialSelected;
|
||||
final SeedType seedType;
|
||||
|
||||
@override
|
||||
SeedLanguageSelectorState createState() =>
|
||||
SeedLanguageSelectorState(selected: initialSelected);
|
||||
SeedLanguageSelectorState createState() => SeedLanguageSelectorState(selected: initialSelected);
|
||||
}
|
||||
|
||||
class SeedLanguageSelectorState extends State<SeedLanguageSelector> {
|
||||
SeedLanguageSelectorState({required this.selected});
|
||||
|
||||
final seedLocales = [
|
||||
S.current.seed_language_english,
|
||||
S.current.seed_language_chinese,
|
||||
S.current.seed_language_dutch,
|
||||
S.current.seed_language_german,
|
||||
S.current.seed_language_japanese,
|
||||
S.current.seed_language_portuguese,
|
||||
S.current.seed_language_russian,
|
||||
S.current.seed_language_spanish,
|
||||
S.current.seed_language_french,
|
||||
S.current.seed_language_italian,
|
||||
];
|
||||
String selected;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SelectButton(
|
||||
image: null,
|
||||
text: seedLocales[seedLanguages.indexOf(selected)],
|
||||
text:
|
||||
"${seedLanguages.firstWhere((e) => e.name == selected).nameLocalized} (${S.of(context).seed_language})",
|
||||
onTap: () async {
|
||||
await showPopUp<String>(
|
||||
context: context,
|
||||
builder: (_) => SeedLanguagePicker(
|
||||
selected: this.selected,
|
||||
onItemSelected: (String selected) =>
|
||||
setState(() => this.selected = selected)));
|
||||
context: context,
|
||||
builder: (_) => SeedLanguagePicker(
|
||||
selected: this.selected,
|
||||
seedType: widget.seedType,
|
||||
onItemSelected: (String selected) => setState(() => this.selected = selected),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
|||
import 'package:cake_wallet/entities/pin_code_required_duration.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/entities/seed_phrase_length.dart';
|
||||
import 'package:cake_wallet/entities/seed_type.dart';
|
||||
import 'package:cake_wallet/entities/sort_balance_types.dart';
|
||||
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
|
||||
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
|
||||
|
@ -48,6 +49,7 @@ abstract class SettingsStoreBase with Store {
|
|||
required BalanceDisplayMode initialBalanceDisplayMode,
|
||||
required bool initialSaveRecipientAddress,
|
||||
required AutoGenerateSubaddressStatus initialAutoGenerateSubaddressStatus,
|
||||
required SeedType initialMoneroSeedType,
|
||||
required bool initialAppSecure,
|
||||
required bool initialDisableBuy,
|
||||
required bool initialDisableSell,
|
||||
|
@ -108,6 +110,7 @@ abstract class SettingsStoreBase with Store {
|
|||
balanceDisplayMode = initialBalanceDisplayMode,
|
||||
shouldSaveRecipientAddress = initialSaveRecipientAddress,
|
||||
autoGenerateSubaddressStatus = initialAutoGenerateSubaddressStatus,
|
||||
moneroSeedType = initialMoneroSeedType,
|
||||
fiatApiMode = initialFiatMode,
|
||||
allowBiometricalAuthentication = initialAllowBiometricalAuthentication,
|
||||
selectedCake2FAPreset = initialCake2FAPresetOptions,
|
||||
|
@ -240,6 +243,11 @@ abstract class SettingsStoreBase with Store {
|
|||
(AutoGenerateSubaddressStatus autoGenerateSubaddressStatus) => sharedPreferences.setInt(
|
||||
PreferencesKey.autoGenerateSubaddressStatusKey, autoGenerateSubaddressStatus.value));
|
||||
|
||||
reaction(
|
||||
(_) => moneroSeedType,
|
||||
(SeedType moneroSeedType) => sharedPreferences.setInt(
|
||||
PreferencesKey.moneroSeedType, moneroSeedType.raw));
|
||||
|
||||
reaction(
|
||||
(_) => fiatApiMode,
|
||||
(FiatApiMode mode) =>
|
||||
|
@ -435,6 +443,7 @@ abstract class SettingsStoreBase with Store {
|
|||
static const defaultPinCodeTimeOutDuration = PinCodeRequiredDuration.tenminutes;
|
||||
static const defaultAutoGenerateSubaddressStatus = AutoGenerateSubaddressStatus.initialized;
|
||||
static const defaultSeedPhraseLength = SeedPhraseLength.twelveWords;
|
||||
static const defaultMoneroSeedType = SeedType.defaultSeedType;
|
||||
|
||||
@observable
|
||||
FiatCurrency fiatCurrency;
|
||||
|
@ -460,6 +469,9 @@ abstract class SettingsStoreBase with Store {
|
|||
@observable
|
||||
AutoGenerateSubaddressStatus autoGenerateSubaddressStatus;
|
||||
|
||||
@observable
|
||||
SeedType moneroSeedType;
|
||||
|
||||
@observable
|
||||
bool isAppSecure;
|
||||
|
||||
|
@ -775,12 +787,20 @@ abstract class SettingsStoreBase with Store {
|
|||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
final deviceName = await _getDeviceName() ?? '';
|
||||
final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true;
|
||||
|
||||
final generateSubaddresses =
|
||||
sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey);
|
||||
|
||||
final autoGenerateSubaddressStatus = generateSubaddresses != null
|
||||
? AutoGenerateSubaddressStatus.deserialize(raw: generateSubaddresses)
|
||||
: defaultAutoGenerateSubaddressStatus;
|
||||
|
||||
final _moneroSeedType = sharedPreferences.getInt(PreferencesKey.moneroSeedType);
|
||||
|
||||
final moneroSeedType = _moneroSeedType != null
|
||||
? SeedType.deserialize(raw: _moneroSeedType)
|
||||
: defaultMoneroSeedType;
|
||||
|
||||
final nodes = <WalletType, Node>{};
|
||||
final powNodes = <WalletType, Node>{};
|
||||
|
||||
|
@ -833,27 +853,27 @@ abstract class SettingsStoreBase with Store {
|
|||
initialBalanceDisplayMode: currentBalanceDisplayMode,
|
||||
initialSaveRecipientAddress: shouldSaveRecipientAddress,
|
||||
initialAutoGenerateSubaddressStatus: autoGenerateSubaddressStatus,
|
||||
initialAppSecure: isAppSecure,
|
||||
initialDisableBuy: disableBuy,
|
||||
initialDisableSell: disableSell,
|
||||
initialDefaultBuyProvider: defaultBuyProvider,
|
||||
initialFiatMode: currentFiatApiMode,
|
||||
initialAllowBiometricalAuthentication: allowBiometricalAuthentication,
|
||||
initialCake2FAPresetOptions: selectedCake2FAPreset,
|
||||
initialUseTOTP2FA: useTOTP2FA,
|
||||
initialTotpSecretKey: totpSecretKey,
|
||||
initialFailedTokenTrial: tokenTrialNumber,
|
||||
initialExchangeStatus: exchangeStatus,
|
||||
initialTheme: savedTheme,
|
||||
actionlistDisplayMode: actionListDisplayMode,
|
||||
initialPinLength: pinLength,
|
||||
pinTimeOutDuration: pinCodeTimeOutDuration,
|
||||
seedPhraseLength: seedPhraseWordCount,
|
||||
initialLanguageCode: savedLanguageCode,
|
||||
sortBalanceBy: sortBalanceBy,
|
||||
pinNativeTokenAtTop: pinNativeTokenAtTop,
|
||||
useEtherscan: useEtherscan,
|
||||
defaultNanoRep: defaultNanoRep,
|
||||
initialMoneroSeedType: moneroSeedType,
|
||||
initialAppSecure: isAppSecure,
|
||||
initialDisableBuy: disableBuy,
|
||||
initialDisableSell: disableSell,
|
||||
initialDefaultBuyProvider: defaultBuyProvider,
|
||||
initialFiatMode: currentFiatApiMode,
|
||||
initialAllowBiometricalAuthentication: allowBiometricalAuthentication,
|
||||
initialCake2FAPresetOptions: selectedCake2FAPreset,
|
||||
initialUseTOTP2FA: useTOTP2FA,
|
||||
initialTotpSecretKey: totpSecretKey,
|
||||
initialFailedTokenTrial: tokenTrialNumber,
|
||||
initialExchangeStatus: exchangeStatus,
|
||||
initialTheme: savedTheme,
|
||||
actionlistDisplayMode: actionListDisplayMode,
|
||||
initialPinLength: pinLength,
|
||||
pinTimeOutDuration: pinCodeTimeOutDuration,
|
||||
seedPhraseLength: seedPhraseWordCount,initialLanguageCode: savedLanguageCode,
|
||||
sortBalanceBy: sortBalanceBy,
|
||||
pinNativeTokenAtTop: pinNativeTokenAtTop,
|
||||
useEtherscan: useEtherscan,
|
||||
defaultNanoRep: defaultNanoRep,
|
||||
defaultBananoRep: defaultBananoRep,
|
||||
lookupsTwitter: lookupsTwitter,
|
||||
lookupsMastodon: lookupsMastodon,
|
||||
|
@ -862,10 +882,10 @@ abstract class SettingsStoreBase with Store {
|
|||
lookupsOpenAlias: lookupsOpenAlias,
|
||||
lookupsENS: lookupsENS,
|
||||
initialMoneroTransactionPriority: moneroTransactionPriority,
|
||||
initialBitcoinTransactionPriority: bitcoinTransactionPriority,
|
||||
initialHavenTransactionPriority: havenTransactionPriority,
|
||||
initialLitecoinTransactionPriority: litecoinTransactionPriority,
|
||||
initialBitcoinCashTransactionPriority: bitcoinCashTransactionPriority,
|
||||
initialBitcoinTransactionPriority: bitcoinTransactionPriority,
|
||||
initialHavenTransactionPriority: havenTransactionPriority,
|
||||
initialLitecoinTransactionPriority: litecoinTransactionPriority,
|
||||
initialBitcoinCashTransactionPriority: bitcoinCashTransactionPriority,
|
||||
initialShouldRequireTOTP2FAForAccessingWallet: shouldRequireTOTP2FAForAccessingWallet,
|
||||
initialShouldRequireTOTP2FAForSendsToContact: shouldRequireTOTP2FAForSendsToContact,
|
||||
initialShouldRequireTOTP2FAForSendsToNonContact: shouldRequireTOTP2FAForSendsToNonContact,
|
||||
|
@ -927,6 +947,12 @@ abstract class SettingsStoreBase with Store {
|
|||
? AutoGenerateSubaddressStatus.deserialize(raw: generateSubaddresses)
|
||||
: defaultAutoGenerateSubaddressStatus;
|
||||
|
||||
final _moneroSeedType = sharedPreferences.getInt(PreferencesKey.moneroSeedType);
|
||||
|
||||
moneroSeedType = _moneroSeedType != null
|
||||
? SeedType.deserialize(raw: _moneroSeedType)
|
||||
: defaultMoneroSeedType;
|
||||
|
||||
balanceDisplayMode = BalanceDisplayMode.deserialize(
|
||||
raw: sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey)!);
|
||||
shouldSaveRecipientAddress =
|
||||
|
|
|
@ -162,6 +162,7 @@ class ExceptionHandler {
|
|||
"Error while launching http",
|
||||
"OS Error: Network is unreachable",
|
||||
"ClientException: Write failed, uri=http",
|
||||
"Connection terminated during handshake",
|
||||
];
|
||||
|
||||
static Future<void> _addDeviceInfo(File file) async {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
class FeatureFlag {
|
||||
static const bool isCakePayEnabled = false;
|
||||
static const bool isExolixEnabled = false;
|
||||
static const bool isInAppTorEnabled = false;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/seed_phrase_length.dart';
|
||||
import 'package:cake_wallet/entities/seed_type.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
@ -19,6 +20,9 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
|
|||
@computed
|
||||
FiatApiMode get fiatApiMode => _settingsStore.fiatApiMode;
|
||||
|
||||
@computed
|
||||
SeedType get seedType => _settingsStore.moneroSeedType;
|
||||
|
||||
@observable
|
||||
bool _addCustomNode = false;
|
||||
|
||||
|
@ -29,6 +33,8 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
|
|||
bool get hasSeedPhraseLengthOption =>
|
||||
type == WalletType.bitcoinCash || type == WalletType.ethereum;
|
||||
|
||||
bool get hasSeedTypeOption => type == WalletType.monero;
|
||||
|
||||
@computed
|
||||
bool get addCustomNode => _addCustomNode;
|
||||
|
||||
|
@ -38,6 +44,9 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
|
|||
@action
|
||||
void setFiatApiMode(FiatApiMode fiatApiMode) => _settingsStore.fiatApiMode = fiatApiMode;
|
||||
|
||||
@action
|
||||
void setSeedType(SeedType seedType) => _settingsStore.moneroSeedType = seedType;
|
||||
|
||||
@action
|
||||
void setExchangeApiMode(ExchangeApiMode value) => _settingsStore.exchangeStatus = value;
|
||||
|
||||
|
|
142
lib/view_model/dashboard/nft_view_model.dart
Normal file
142
lib/view_model/dashboard/nft_view_model.dart
Normal file
|
@ -0,0 +1,142 @@
|
|||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_widget.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||
|
||||
import 'package:cake_wallet/entities/wallet_nft_response.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
|
||||
part 'nft_view_model.g.dart';
|
||||
|
||||
class NFTViewModel = NFTViewModelBase with _$NFTViewModel;
|
||||
|
||||
abstract class NFTViewModelBase with Store {
|
||||
NFTViewModelBase(this.appStore, this.bottomSheetService)
|
||||
: isLoading = false,
|
||||
isImportNFTLoading = false,
|
||||
nftAssetByWalletModels = ObservableList() {
|
||||
getNFTAssetByWallet();
|
||||
|
||||
reaction((_) => appStore.wallet, (_) => getNFTAssetByWallet());
|
||||
}
|
||||
|
||||
final AppStore appStore;
|
||||
final BottomSheetService bottomSheetService;
|
||||
|
||||
@observable
|
||||
bool isLoading;
|
||||
|
||||
@observable
|
||||
bool isImportNFTLoading;
|
||||
|
||||
ObservableList<NFTAssetModel> nftAssetByWalletModels;
|
||||
|
||||
@action
|
||||
Future<void> getNFTAssetByWallet() async {
|
||||
if (appStore.wallet!.type != WalletType.ethereum) return;
|
||||
|
||||
final walletAddress = appStore.wallet!.walletInfo.address;
|
||||
log('Fetching wallet NFTs for $walletAddress');
|
||||
|
||||
// the [chain] refers to the chain network that the nft is on
|
||||
// the [format] refers to the number format type of the responses
|
||||
// the [normalizedMetadata] field is a boolean that determines if
|
||||
// the response would include a json string of the NFT Metadata that can be decoded
|
||||
// and used within the wallet
|
||||
final uri = Uri.https(
|
||||
'deep-index.moralis.io',
|
||||
'/api/v2.2/$walletAddress/nft',
|
||||
{
|
||||
"chain": "eth",
|
||||
"format": "decimal",
|
||||
"media_items": "false",
|
||||
"normalizeMetadata": "true",
|
||||
},
|
||||
);
|
||||
|
||||
try {
|
||||
isLoading = true;
|
||||
|
||||
final response = await http.get(
|
||||
uri,
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"X-API-Key": secrets.moralisApiKey,
|
||||
},
|
||||
);
|
||||
|
||||
final decodedResponse = jsonDecode(response.body) as Map<String, dynamic>;
|
||||
|
||||
final result = WalletNFTsResponseModel.fromJson(decodedResponse).result ?? [];
|
||||
|
||||
nftAssetByWalletModels.clear();
|
||||
|
||||
nftAssetByWalletModels.addAll(result);
|
||||
|
||||
isLoading = false;
|
||||
} catch (e) {
|
||||
isLoading = false;
|
||||
log(e.toString());
|
||||
bottomSheetService.queueBottomSheet(
|
||||
isModalDismissible: true,
|
||||
widget: BottomSheetMessageDisplayWidget(
|
||||
message: e.toString(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> importNFT(String tokenAddress, String tokenId) async {
|
||||
|
||||
// the [chain] refers to the chain network that the nft is on
|
||||
// the [format] refers to the number format type of the responses
|
||||
// the [normalizedMetadata] field is a boolean that determines if
|
||||
// the response would include a json string of the NFT Metadata that can be decoded
|
||||
// and used within the wallet
|
||||
final uri = Uri.https(
|
||||
'deep-index.moralis.io',
|
||||
'/api/v2.2/nft/$tokenAddress/$tokenId',
|
||||
{
|
||||
"chain": "eth",
|
||||
"format": "decimal",
|
||||
"media_items": "false",
|
||||
"normalizeMetadata": "true",
|
||||
},
|
||||
);
|
||||
|
||||
try {
|
||||
isImportNFTLoading = true;
|
||||
|
||||
final response = await http.get(
|
||||
uri,
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"X-API-Key": secrets.moralisApiKey,
|
||||
},
|
||||
);
|
||||
|
||||
final decodedResponse = jsonDecode(response.body) as Map<String, dynamic>;
|
||||
|
||||
final nftAsset = NFTAssetModel.fromJson(decodedResponse);
|
||||
|
||||
nftAssetByWalletModels.add(nftAsset);
|
||||
|
||||
isImportNFTLoading = false;
|
||||
} catch (e) {
|
||||
isImportNFTLoading = false;
|
||||
bottomSheetService.queueBottomSheet(
|
||||
isModalDismissible: true,
|
||||
widget: BottomSheetMessageDisplayWidget(
|
||||
message: e.toString(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,6 +37,7 @@ abstract class EditBackupPasswordViewModelBase with Store {
|
|||
@action
|
||||
Future<void> save() async {
|
||||
final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
|
||||
await secureStorage.delete(key: key);
|
||||
await secureStorage.write(key: key, value: backupPassword);
|
||||
secretStore.write(key: key, value: backupPassword);
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ class RestoredWallet {
|
|||
factory RestoredWallet.fromSeed(Map<String, dynamic> json) {
|
||||
final height = json['height'] as String?;
|
||||
final mnemonic_seed = json['mnemonic_seed'] as String?;
|
||||
final seed = json['seed'] as String?;
|
||||
final seed = json['seed'] as String? ?? json['hexSeed'] as String?;
|
||||
return RestoredWallet(
|
||||
restoreMode: json['mode'] as WalletRestoreMode,
|
||||
type: json['type'] as WalletType,
|
||||
|
|
|
@ -10,6 +10,7 @@ import 'package:cw_core/wallet_type.dart';
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:polyseed/polyseed.dart';
|
||||
|
||||
class WalletRestoreFromQRCode {
|
||||
WalletRestoreFromQRCode();
|
||||
|
@ -51,7 +52,7 @@ class WalletRestoreFromQRCode {
|
|||
RegExp _getPattern(int wordCount) =>
|
||||
RegExp(r'(?<=\W|^)((?:\w+\s+){' + (wordCount - 1).toString() + r'}\w+)(?=\W|$)');
|
||||
|
||||
List<int> patternCounts = walletType == WalletType.monero ? [25, 14, 13] : [24, 18, 12];
|
||||
List<int> patternCounts = walletType == WalletType.monero ? [25, 16, 14, 13] : [24, 18, 12];
|
||||
|
||||
for (final count in patternCounts) {
|
||||
final pattern = _getPattern(count);
|
||||
|
@ -123,12 +124,17 @@ class WalletRestoreFromQRCode {
|
|||
}
|
||||
|
||||
if (credentials['seed'] != null) {
|
||||
final seedValue = credentials['seed'];
|
||||
final seedValue = credentials['seed'] as String;
|
||||
final words = SeedValidator.getWordList(type: type, language: 'english');
|
||||
|
||||
if (type == WalletType.monero && Polyseed.isValidSeed(seedValue)) {
|
||||
return WalletRestoreMode.seed;
|
||||
}
|
||||
|
||||
seedValue.split(' ').forEach((element) {
|
||||
if (!words.contains(element)) {
|
||||
throw Exception(
|
||||
'Unexpected restore mode: mnemonic_seed is invalid or does\'t match wallet type');
|
||||
"Unexpected restore mode: mnemonic_seed is invalid or doesn't match wallet type");
|
||||
}
|
||||
});
|
||||
return WalletRestoreMode.seed;
|
||||
|
@ -151,6 +157,14 @@ class WalletRestoreFromQRCode {
|
|||
return WalletRestoreMode.keys;
|
||||
}
|
||||
|
||||
if ((type == WalletType.nano || type == WalletType.banano) && credentials.containsKey('hexSeed')) {
|
||||
final hexSeed = credentials['hexSeed'] as String;
|
||||
if (hexSeed.isEmpty) {
|
||||
throw Exception('Unexpected restore mode: hexSeed');
|
||||
}
|
||||
return WalletRestoreMode.seed;
|
||||
}
|
||||
|
||||
throw Exception('Unexpected restore mode: restore params are invalid');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,19 +107,18 @@ abstract class WalletKeysViewModelBase with Store {
|
|||
]);
|
||||
}
|
||||
|
||||
if (_appStore.wallet!.type == WalletType.nano || _appStore.wallet!.type == WalletType.banano) {
|
||||
bool nanoBased =
|
||||
_appStore.wallet!.type == WalletType.nano || _appStore.wallet!.type == WalletType.banano;
|
||||
|
||||
// we don't necessarily have the seed phrase for nano / banano:
|
||||
if (_appStore.wallet!.seed != null) {
|
||||
items.addAll([
|
||||
StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!),
|
||||
]);
|
||||
}
|
||||
|
||||
// we always have the hex version of the seed:
|
||||
if (nanoBased) {
|
||||
// we always have the hex version of the seed and private key:
|
||||
items.addAll([
|
||||
if (_appStore.wallet!.seed != null)
|
||||
StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!),
|
||||
if (_appStore.wallet!.hexSeed != null)
|
||||
StandartListItem(title: S.current.seed_hex_form, value: _appStore.wallet!.hexSeed!),
|
||||
if (_appStore.wallet!.privateKey != null)
|
||||
StandartListItem(title: S.current.spend_key_private, value: _appStore.wallet!.privateKey!),
|
||||
StandartListItem(title: S.current.private_key, value: _appStore.wallet!.privateKey!),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -172,7 +171,10 @@ abstract class WalletKeysViewModelBase with Store {
|
|||
final restoreHeightResult = await restoreHeight;
|
||||
return {
|
||||
if (_appStore.wallet!.seed != null) 'seed': _appStore.wallet!.seed!,
|
||||
if (_appStore.wallet!.privateKey != null) 'private_key': _appStore.wallet!.privateKey!,
|
||||
if (_appStore.wallet!.seed == null && _appStore.wallet!.hexSeed != null)
|
||||
'hexSeed': _appStore.wallet!.hexSeed!,
|
||||
if (_appStore.wallet!.seed == null && _appStore.wallet!.privateKey != null)
|
||||
'private_key': _appStore.wallet!.privateKey!,
|
||||
if (restoreHeightResult != null) ...{'height': restoreHeightResult}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
@ -32,17 +30,22 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
|
|||
|
||||
bool get hasLanguageSelector => type == WalletType.monero || type == WalletType.haven;
|
||||
|
||||
bool get hasSeedType => type == WalletType.monero;
|
||||
|
||||
@override
|
||||
WalletCredentials getCredentials(dynamic options) {
|
||||
WalletCredentials getCredentials(dynamic _options) {
|
||||
final options = _options as List<dynamic>?;
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return monero!.createMoneroNewWalletCredentials(name: name, language: options as String);
|
||||
return monero!.createMoneroNewWalletCredentials(
|
||||
name: name, language: options!.first as String, isPolyseed: options.last as bool);
|
||||
case WalletType.bitcoin:
|
||||
return bitcoin!.createBitcoinNewWalletCredentials(name: name);
|
||||
case WalletType.litecoin:
|
||||
return bitcoin!.createBitcoinNewWalletCredentials(name: name);
|
||||
case WalletType.haven:
|
||||
return haven!.createHavenNewWalletCredentials(name: name, language: options as String);
|
||||
return haven!
|
||||
.createHavenNewWalletCredentials(name: name, language: options!.first as String);
|
||||
case WalletType.ethereum:
|
||||
return ethereum!.createEthereumNewWalletCredentials(name: name);
|
||||
case WalletType.bitcoinCash:
|
||||
|
|
|
@ -30,13 +30,11 @@ PODS:
|
|||
- FlutterMacOS
|
||||
- package_info (0.0.1):
|
||||
- FlutterMacOS
|
||||
- package_info_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- platform_device_id (0.0.1):
|
||||
- FlutterMacOS
|
||||
- platform_device_id_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- ReachabilitySwift (5.0.0)
|
||||
- share_plus_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
|
@ -45,7 +43,7 @@ PODS:
|
|||
- FlutterMacOS
|
||||
- url_launcher_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- wakelock_macos (0.0.1):
|
||||
- wakelock_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
|
@ -57,13 +55,12 @@ DEPENDENCIES:
|
|||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`)
|
||||
- package_info (from `Flutter/ephemeral/.symlinks/plugins/package_info/macos`)
|
||||
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
|
||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- platform_device_id (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos`)
|
||||
- platform_device_id_macos (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id_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`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
- wakelock_macos (from `Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos`)
|
||||
- wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
|
@ -86,20 +83,18 @@ EXTERNAL SOURCES:
|
|||
:path: Flutter/ephemeral/.symlinks/plugins/in_app_review/macos
|
||||
package_info:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/package_info/macos
|
||||
package_info_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
|
||||
path_provider_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
||||
platform_device_id:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos
|
||||
platform_device_id_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/platform_device_id_macos/macos
|
||||
share_plus_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos
|
||||
shared_preferences_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
||||
url_launcher_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||
wakelock_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos
|
||||
wakelock_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308
|
||||
|
@ -110,14 +105,13 @@ SPEC CHECKSUMS:
|
|||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0
|
||||
package_info: 6eba2fd8d3371dda2d85c8db6fe97488f24b74b2
|
||||
package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
platform_device_id: 3e414428f45df149bbbfb623e2c0ca27c545b763
|
||||
platform_device_id_macos: f763bb55f088be804d61b96eb4710b8ab6598e94
|
||||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
|
||||
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
|
||||
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
|
||||
wakelock_macos: bc3f2a9bd8d2e6c89fee1e1822e7ddac3bd004a9
|
||||
wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269
|
||||
|
||||
PODFILE CHECKSUM: 5107934592df7813b33d744aebc8ddc6b5a5445f
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ dependencies:
|
|||
ref: main
|
||||
version: 1.0.0
|
||||
flutter_plugin_android_lifecycle: 2.0.9
|
||||
path_provider_android: 2.0.24
|
||||
path_provider_android: ^2.2.1
|
||||
shared_preferences_android: 2.0.17
|
||||
url_launcher_android: 6.0.24
|
||||
sensitive_clipboard: ^1.0.0
|
||||
|
@ -98,6 +98,15 @@ dependencies:
|
|||
url: https://github.com/cake-tech/bitcoin_flutter.git
|
||||
ref: silent-payments
|
||||
fluttertoast: 8.1.4
|
||||
tor:
|
||||
git:
|
||||
url: https://github.com/cake-tech/tor.git
|
||||
ref: main
|
||||
socks5_proxy: ^1.0.4
|
||||
flutter_svg: ^2.0.9
|
||||
polyseed:
|
||||
git:
|
||||
url: https://github.com/cake-tech/polyseed_dart.git
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"seed_title": "سييد",
|
||||
"seed_share": "شارك السييد",
|
||||
"copy": "نسخ",
|
||||
"seed_language_choose": "الرجاء اختيار لغة السييد:",
|
||||
"seed_language": "لغة البذور",
|
||||
"seed_choose": "اختر لغة السييد",
|
||||
"seed_language_next": "التالي",
|
||||
"seed_language_english": "إنجليزي",
|
||||
|
@ -383,7 +383,7 @@
|
|||
"change_backup_password_alert": "لن تكون ملفات النسخ الاحتياطي السابقة متاحة للاستيراد بكلمة مرور نسخ احتياطي جديدة. سيتم استخدام كلمة مرور النسخ الاحتياطي الجديدة لملفات النسخ الاحتياطي الجديدة فقط. هل أنت متأكد أنك تريد تغيير كلمة المرور الاحتياطية؟",
|
||||
"enter_backup_password": "أدخل كلمة المرور الاحتياطية هنا",
|
||||
"select_backup_file": "حدد ملف النسخ الاحتياطي",
|
||||
"import": "اختيار ملف",
|
||||
"import": "ﺩﺭﻮﺘﺴﻳ",
|
||||
"please_select_backup_file": "الرجاء تحديد ملف النسخ الاحتياطي وإدخال كلمة مرور النسخ الاحتياطي.",
|
||||
"fixed_rate": "السعر الثابت",
|
||||
"fixed_rate_alert": "ستتمكن من إدخال مبلغ الاستلام عند تشغيل وضع السعر الثابت. هل تريد التبديل إلى وضع السعر الثابت؟",
|
||||
|
@ -569,7 +569,7 @@
|
|||
"always": "دائماً",
|
||||
"minutes_to_pin_code": "${minutes} دقيقة",
|
||||
"disable_exchange": "تعطيل التبادل",
|
||||
"advanced_privacy_settings": "إعدادات الخصوصية المتقدمة",
|
||||
"advanced_settings": "إعدادات متقدمة",
|
||||
"settings_can_be_changed_later": "يمكن تغيير هذه الإعدادات لاحقًا في إعدادات التطبيق",
|
||||
"add_custom_node": "إضافة عقدة مخصصة جديدة",
|
||||
"disable_fiat": "تعطيل fiat",
|
||||
|
@ -727,11 +727,26 @@
|
|||
"require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ",
|
||||
"camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ",
|
||||
"switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ",
|
||||
"seed_phrase_length": " ﺭﻭﺬﺒﻟﺍ ﺓﺭﺎﺒﻌﻟﺍ ﻝﻮﻃ",
|
||||
"unavailable_balance": " ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ",
|
||||
"importNFTs": "NFTs ﺩﺍﺮﻴﺘﺳﺍ",
|
||||
"noNFTYet": "ﻥﻵﺍ ﻰﺘﺣ NFTs ﺪﺟﻮﻳ ﻻ",
|
||||
"address": " ﻥﺍﻮﻨﻋ",
|
||||
"enterTokenID": "ﺰﻴﻤﻤﻟﺍ ﺰﻣﺮﻟﺍ ﻑﺮﻌﻣ ﻞﺧﺩﺃ",
|
||||
"tokenID": "ﻒﻳﺮﻌﺗ ﺔﻗﺎﻄﺑ",
|
||||
"name": "ﻢﺳﺍ",
|
||||
"symbol": "ﺰﻣﺭ",
|
||||
"seed_phrase_length": "ﺭﻭﺬﺒﻟﺍ ﺓﺭﺎﺒﻌﻟﺍ ﻝﻮﻃ",
|
||||
"unavailable_balance": "ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ",
|
||||
"unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ",
|
||||
"unspent_change": "يتغير",
|
||||
"Block_remaining": "${status} كتلة متبقية",
|
||||
"labeled_silent_addresses": "العناوين الصامتة المسمى",
|
||||
"use_testnet": "استخدم testnet"
|
||||
}
|
||||
"use_testnet": "استخدم testnet",
|
||||
"seed_hex_form": "بذور المحفظة (شكل عرافة)",
|
||||
"tor_connection": "ﺭﻮﺗ ﻝﺎﺼﺗﺍ",
|
||||
"seedtype": "البذور",
|
||||
"seedtype_legacy": "إرث (25 كلمة)",
|
||||
"seedtype_polyseed": "بوليسيد (16 كلمة)",
|
||||
"seed_language_czech": "التشيكية",
|
||||
"seed_language_korean": "الكورية",
|
||||
"seed_language_chinese_traditional": "تقاليد صينية)"
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"seed_title": "Seed",
|
||||
"seed_share": "Споделяне на seed",
|
||||
"copy": "Копиране",
|
||||
"seed_language_choose": "Моля, изберете език на seed-а:",
|
||||
"seed_language": "Език на семената",
|
||||
"seed_choose": "Изберете език на seed-а",
|
||||
"seed_language_next": "Следващ",
|
||||
"seed_language_english": "Английски",
|
||||
|
@ -569,7 +569,7 @@
|
|||
"always": "Винаги",
|
||||
"minutes_to_pin_code": "${minute} минути",
|
||||
"disable_exchange": "Деактивиране на борса",
|
||||
"advanced_privacy_settings": "Допълнителни настройки за поверителност",
|
||||
"advanced_settings": "Разширени настройки",
|
||||
"settings_can_be_changed_later": "Тези настройки могат да бъдат променени по-късно от приложението",
|
||||
"add_custom_node": "Добавяне на нов персонализиран Node",
|
||||
"disable_fiat": "Деактивиране на fiat",
|
||||
|
@ -723,11 +723,26 @@
|
|||
"require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли",
|
||||
"camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.",
|
||||
"switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново",
|
||||
"importNFTs": "Импортирайте NFT",
|
||||
"noNFTYet": "Все още няма NFT",
|
||||
"address": "Адрес",
|
||||
"enterTokenID": "Въведете идентификатора на токена",
|
||||
"tokenID": "документ за самоличност",
|
||||
"name": "Име",
|
||||
"symbol": "Символ",
|
||||
"seed_phrase_length": "Дължина на началната фраза",
|
||||
"unavailable_balance": "Неналично салдо",
|
||||
"unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.",
|
||||
"unspent_change": "Промяна",
|
||||
"Block_remaining": "${status} останал блок",
|
||||
"labeled_silent_addresses": "Етикетирани безшумни адреси",
|
||||
"use_testnet": "Използвайте TestNet"
|
||||
}
|
||||
"use_testnet": "Използвайте TestNet",
|
||||
"tor_connection": "Tor връзка",
|
||||
"seed_hex_form": "Семена от портфейл (шестнадесетична форма)",
|
||||
"seedtype": "Семенна тип",
|
||||
"seedtype_legacy": "Наследство (25 думи)",
|
||||
"seedtype_polyseed": "Поли семе (16 думи)",
|
||||
"seed_language_czech": "Чех",
|
||||
"seed_language_korean": "Корейски",
|
||||
"seed_language_chinese_traditional": "Традиционен китайски)"
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"seed_title": "Seed",
|
||||
"seed_share": "Sdílet seed",
|
||||
"copy": "Kopírovat",
|
||||
"seed_language_choose": "Prosím zvolte si jazyk seedu:",
|
||||
"seed_language": "Jazyk semen",
|
||||
"seed_choose": "Zvolte si jazyk seedu",
|
||||
"seed_language_next": "Další",
|
||||
"seed_language_english": "Angličtina",
|
||||
|
@ -383,7 +383,7 @@
|
|||
"change_backup_password_alert": "Vaše předchozí soubory se zálohami nebude možné naimportovat s novým heslem. Nové heslo bude použito pouze pro nové zálohy. Opravdu chcete změnit heslo pro zálohy?",
|
||||
"enter_backup_password": "Zde zadejte své heslo pro zálohy",
|
||||
"select_backup_file": "Vybrat soubor se zálohou",
|
||||
"import": "Importovat",
|
||||
"import": "Import",
|
||||
"please_select_backup_file": "Prosím vyberte soubor se zálohou a zadejte heslo pro zálohy.",
|
||||
"fixed_rate": "Pevný kurz",
|
||||
"fixed_rate_alert": "Když je zvolený pevný kurz, můžete zadat konkrétní částku, kterou chcete dostat. Chcete se přepnout do režimu s pevným kurzem?",
|
||||
|
@ -569,7 +569,7 @@
|
|||
"always": "Vždy",
|
||||
"minutes_to_pin_code": "${minute} minutách",
|
||||
"disable_exchange": "Zakázat směnárny",
|
||||
"advanced_privacy_settings": "Pokročilá nastavení soukromí",
|
||||
"advanced_settings": "Pokročilé nastavení",
|
||||
"settings_can_be_changed_later": "Tato nastavení mohou být změněna později v nastavení v této aplikaci",
|
||||
"add_custom_node": "Přidat vlastní uzel",
|
||||
"disable_fiat": "Zakázat fiat",
|
||||
|
@ -723,11 +723,26 @@
|
|||
"require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek",
|
||||
"camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.",
|
||||
"switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu",
|
||||
"importNFTs": "Importujte NFT",
|
||||
"noNFTYet": "Zatím žádné NFT",
|
||||
"address": "Adresa",
|
||||
"enterTokenID": "Zadejte ID tokenu",
|
||||
"tokenID": "ID",
|
||||
"name": "název",
|
||||
"symbol": "Symbol",
|
||||
"seed_phrase_length": "Délka fráze semene",
|
||||
"unavailable_balance": "Nedostupný zůstatek",
|
||||
"unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.",
|
||||
"unspent_change": "Změna",
|
||||
"Block_remaining": "${status} Blok zbývající",
|
||||
"labeled_silent_addresses": "Označené tiché adresy",
|
||||
"use_testnet": "Použijte testNet"
|
||||
}
|
||||
"use_testnet": "Použijte testNet",
|
||||
"tor_connection": "Připojení Tor",
|
||||
"seed_hex_form": "Semeno peněženky (hex formulář)",
|
||||
"seedtype": "SeedType",
|
||||
"seedtype_legacy": "Legacy (25 slov)",
|
||||
"seedtype_polyseed": "Polyseed (16 slov)",
|
||||
"seed_language_czech": "čeština",
|
||||
"seed_language_korean": "korejština",
|
||||
"seed_language_chinese_traditional": "Číňan (tradiční)"
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"seed_title": "Seed",
|
||||
"seed_share": "Seed teilen",
|
||||
"copy": "Kopieren",
|
||||
"seed_language_choose": "Bitte wählen Sie die Sprache des Seeds:",
|
||||
"seed_language": "Seed-Sprache",
|
||||
"seed_choose": "Seed-Sprache auswählen",
|
||||
"seed_language_next": "Weiter",
|
||||
"seed_language_english": "Englisch",
|
||||
|
@ -571,7 +571,7 @@
|
|||
"always": "immer",
|
||||
"minutes_to_pin_code": "${minute} Minuten",
|
||||
"disable_exchange": "Exchange deaktivieren",
|
||||
"advanced_privacy_settings": "Erweiterte Datenschutzeinstellungen",
|
||||
"advanced_settings": "Erweiterte Einstellungen",
|
||||
"settings_can_be_changed_later": "Diese Einstellungen können später in den App-Einstellungen geändert werden",
|
||||
"add_custom_node": "Neuen benutzerdefinierten Knoten hinzufügen",
|
||||
"disable_fiat": "Fiat deaktivieren",
|
||||
|
@ -722,20 +722,35 @@
|
|||
"awaitDAppProcessing": "Bitte warten Sie, bis die dApp die Verarbeitung abgeschlossen hat.",
|
||||
"copyWalletConnectLink": "Kopieren Sie den WalletConnect-Link von dApp und fügen Sie ihn hier ein",
|
||||
"enterWalletConnectURI": "Geben Sie den WalletConnect-URI ein",
|
||||
"seed_key": "Samenschlüssel",
|
||||
"enter_seed_phrase": "Geben Sie Ihre Samenphrase ein",
|
||||
"change_rep_successful": "Erfolgreich veränderte Vertreter",
|
||||
"seed_key": "Seed-Schlüssel",
|
||||
"enter_seed_phrase": "Geben Sie Ihre Seed-Phrase ein",
|
||||
"change_rep_successful": "Vertreter erfolgreich gerändert",
|
||||
"add_contact": "Kontakt hinzufügen",
|
||||
"exchange_provider_unsupported": "${providerName} wird nicht mehr unterstützt!",
|
||||
"domain_looks_up": "Domain-Suchen",
|
||||
"require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets",
|
||||
"camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.",
|
||||
"switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut",
|
||||
"importNFTs": "NFTs importieren",
|
||||
"noNFTYet": "Noch keine NFTs",
|
||||
"address": "Adresse",
|
||||
"enterTokenID": "Geben Sie die Token-ID ein",
|
||||
"tokenID": "AUSWEIS",
|
||||
"name": "Name",
|
||||
"symbol": "Symbol",
|
||||
"seed_phrase_length": "Länge der Seed-Phrase",
|
||||
"unavailable_balance": "Nicht verfügbares Guthaben",
|
||||
"unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.",
|
||||
"unspent_change": "Wechselgeld",
|
||||
"Block_remaining": "${status} Block verbleibend",
|
||||
"labeled_silent_addresses": "Bezeichnete stille Adressen",
|
||||
"use_testnet": "TESTNET verwenden"
|
||||
}
|
||||
"use_testnet": "TESTNET verwenden",
|
||||
"tor_connection": "Tor-Verbindung",
|
||||
"seed_hex_form": "Brieftaschensamen (Sechskantform)",
|
||||
"seedtype": "Seedtyp",
|
||||
"seedtype_legacy": "Veraltet (25 Wörter)",
|
||||
"seedtype_polyseed": "Polyseed (16 Wörter)",
|
||||
"seed_language_czech": "Tschechisch",
|
||||
"seed_language_korean": "Koreanisch",
|
||||
"seed_language_chinese_traditional": "Chinesisch (Traditionell)"
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"seed_title": "Seed",
|
||||
"seed_share": "Share seed",
|
||||
"copy": "Copy",
|
||||
"seed_language_choose": "Please choose seed language:",
|
||||
"seed_language": "Seed language",
|
||||
"seed_choose": "Choose seed language",
|
||||
"seed_language_next": "Next",
|
||||
"seed_language_english": "English",
|
||||
|
@ -572,7 +572,7 @@
|
|||
"always": "Always",
|
||||
"minutes_to_pin_code": "${minute} minutes",
|
||||
"disable_exchange": "Disable exchange",
|
||||
"advanced_privacy_settings": "Advanced Privacy Settings",
|
||||
"advanced_settings": "Advanced Settings",
|
||||
"settings_can_be_changed_later": "These settings can be changed later in the app settings",
|
||||
"add_custom_node": "Add New Custom Node",
|
||||
"disable_fiat": "Disable fiat",
|
||||
|
@ -732,11 +732,26 @@
|
|||
"require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets",
|
||||
"camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.",
|
||||
"switchToETHWallet": "Please switch to an Ethereum wallet and try again",
|
||||
"importNFTs": "Import NFTs",
|
||||
"noNFTYet": "No NFTs yet",
|
||||
"address": "Address",
|
||||
"enterTokenID": "Enter the token ID",
|
||||
"tokenID": "ID",
|
||||
"name": "Name",
|
||||
"symbol": "Symbol",
|
||||
"seed_phrase_length": "Seed phrase length",
|
||||
"unavailable_balance": "Unavailable balance",
|
||||
"unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.",
|
||||
"unspent_change": "Change",
|
||||
"Block_remaining": "${status} Block Remaining",
|
||||
"labeled_silent_addresses": "Labeled Silent Addresses",
|
||||
"use_testnet": "Use testnet"
|
||||
}
|
||||
"use_testnet": "Use testnet",
|
||||
"tor_connection": "Tor connection",
|
||||
"seed_hex_form": "Wallet seed (hex form)",
|
||||
"seedtype": "Seedtype",
|
||||
"seedtype_legacy": "Legacy (25 words)",
|
||||
"seedtype_polyseed": "Polyseed (16 words)",
|
||||
"seed_language_czech": "Czech",
|
||||
"seed_language_korean": "Korean",
|
||||
"seed_language_chinese_traditional": "Chinese (Traditional)"
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"seed_title": "Semilla",
|
||||
"seed_share": "Compartir semillas",
|
||||
"copy": "Dupdo",
|
||||
"seed_language_choose": "Por favor elija el idioma semilla:",
|
||||
"seed_language": "Lenguaje de semillas",
|
||||
"seed_choose": "Elige el idioma semilla",
|
||||
"seed_language_next": "Próximo",
|
||||
"seed_language_english": "Inglés",
|
||||
|
@ -571,7 +571,7 @@
|
|||
"always": "siempre",
|
||||
"minutes_to_pin_code": "${minute} minutos",
|
||||
"disable_exchange": "Deshabilitar intercambio",
|
||||
"advanced_privacy_settings": "Configuración avanzada de privacidad",
|
||||
"advanced_settings": "Ajustes avanzados",
|
||||
"settings_can_be_changed_later": "Estas configuraciones se pueden cambiar más tarde en la configuración de la aplicación",
|
||||
"add_custom_node": "Agregar nuevo nodo personalizado",
|
||||
"disable_fiat": "Deshabilitar fiat",
|
||||
|
@ -731,11 +731,26 @@
|
|||
"require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas",
|
||||
"camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.",
|
||||
"switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente.",
|
||||
"importNFTs": "Importar NFT",
|
||||
"noNFTYet": "Aún no hay NFT",
|
||||
"address": "DIRECCIÓN",
|
||||
"enterTokenID": "Ingrese el ID del token",
|
||||
"tokenID": "IDENTIFICACIÓN",
|
||||
"name": "Nombre",
|
||||
"symbol": "Símbolo",
|
||||
"seed_phrase_length": "Longitud de la frase inicial",
|
||||
"unavailable_balance": "Saldo no disponible",
|
||||
"unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.",
|
||||
"unspent_change": "Cambiar",
|
||||
"Block_remaining": "${status} bloque restante",
|
||||
"labeled_silent_addresses": "Direcciones silenciosas etiquetadas",
|
||||
"use_testnet": "Use TestNet"
|
||||
}
|
||||
"use_testnet": "Use TestNet",
|
||||
"tor_connection": "conexión tor",
|
||||
"seed_hex_form": "Semilla de billetera (forma hexadecimal)",
|
||||
"seedtype": "Type de semillas",
|
||||
"seedtype_legacy": "Legado (25 palabras)",
|
||||
"seedtype_polyseed": "Polieta (16 palabras)",
|
||||
"seed_language_czech": "checo",
|
||||
"seed_language_korean": "coreano",
|
||||
"seed_language_chinese_traditional": "Chino (tradicional)"
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"seed_title": "Phrase secrète (seed)",
|
||||
"seed_share": "Partager la phrase secrète (seed)",
|
||||
"copy": "Copier",
|
||||
"seed_language_choose": "Merci de choisir la langue de la phrase secrète (seed) :",
|
||||
"seed_language": "Langage de la phrase secrète",
|
||||
"seed_choose": "Choisissez la langue de la phrase secrète (seed)",
|
||||
"seed_language_next": "Suivant",
|
||||
"seed_language_english": "Anglais",
|
||||
|
@ -571,7 +571,7 @@
|
|||
"always": "toujours",
|
||||
"minutes_to_pin_code": "${minute} minutes",
|
||||
"disable_exchange": "Désactiver l'échange",
|
||||
"advanced_privacy_settings": "Paramètres de confidentialité avancés",
|
||||
"advanced_settings": "Réglages avancés",
|
||||
"settings_can_be_changed_later": "Ces paramètres peuvent être modifiés ultérieurement dans les paramètres de l'application",
|
||||
"add_custom_node": "Ajouter un nouveau nœud personnalisé",
|
||||
"disable_fiat": "Désactiver les montants en fiat",
|
||||
|
@ -729,6 +729,15 @@
|
|||
"exchange_provider_unsupported": "${providerName} n'est plus pris en charge !",
|
||||
"domain_looks_up": "Résolution de nom",
|
||||
"require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes",
|
||||
"camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.",
|
||||
"switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer",
|
||||
"importNFTs": "Importer des NFT",
|
||||
"noNFTYet": "Pas encore de NFT",
|
||||
"address": "Adresse",
|
||||
"enterTokenID": "Entrez l'ID du jeton",
|
||||
"tokenID": "IDENTIFIANT",
|
||||
"name": "Nom",
|
||||
"symbol": "Symbole",
|
||||
"seed_phrase_length": "Longueur de la phrase de départ",
|
||||
"unavailable_balance": "Solde indisponible",
|
||||
"unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.",
|
||||
|
@ -737,5 +746,14 @@
|
|||
"unspent_change": "Changement",
|
||||
"Block_remaining": "${status} bloc restant",
|
||||
"labeled_silent_addresses": "Adresses silencieuses étiquetées",
|
||||
"use_testnet": "Utiliser TestNet"
|
||||
}
|
||||
"use_testnet": "Utiliser TestNet",
|
||||
"unspent_change": "Changement",
|
||||
"tor_connection": "Connexion Tor",
|
||||
"seed_hex_form": "Graine du portefeuille (forme hexagonale)",
|
||||
"seedtype": "Type de type graine",
|
||||
"seedtype_legacy": "Héritage (25 mots)",
|
||||
"seedtype_polyseed": "Polyseed (16 mots)",
|
||||
"seed_language_czech": "tchèque",
|
||||
"seed_language_korean": "coréen",
|
||||
"seed_language_chinese_traditional": "Chinois (Traditionnel)"
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"seed_title": "iri",
|
||||
"seed_share": "Raba iri",
|
||||
"copy": "Kwafi",
|
||||
"seed_language_choose": "Don Allah zaɓi harshen seed:",
|
||||
"seed_language": "Harshen Magani",
|
||||
"seed_choose": "Zaɓi harshen seed",
|
||||
"seed_language_next": "Na gaba",
|
||||
"seed_language_english": "Ingilishi",
|
||||
|
@ -570,7 +570,7 @@
|
|||
"always": "Koyaushe",
|
||||
"minutes_to_pin_code": "${minute} minti",
|
||||
"disable_exchange": "Kashe musanya",
|
||||
"advanced_privacy_settings": "Babban Saitunan Sirri",
|
||||
"advanced_settings": "Saitunan ci gaba",
|
||||
"settings_can_be_changed_later": "Ana iya canza waɗannan saitunan daga baya a cikin saitunan app",
|
||||
"add_custom_node": "Ƙara Sabon Kulli na Custom",
|
||||
"disable_fiat": "Dakatar da fiat",
|
||||
|
@ -709,11 +709,26 @@
|
|||
"require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje",
|
||||
"camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.",
|
||||
"switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa",
|
||||
"importNFTs": "Shigo da NFTs",
|
||||
"noNFTYet": "Babu NFTs tukuna",
|
||||
"address": "Adireshi",
|
||||
"enterTokenID": "Shigar da alamar alama",
|
||||
"tokenID": "ID",
|
||||
"name": "Suna",
|
||||
"symbol": "Alama",
|
||||
"seed_phrase_length": "Tsawon jimlar iri",
|
||||
"unavailable_balance": "Ma'aunin da ba ya samuwa",
|
||||
"unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.",
|
||||
"unspent_change": "Canza",
|
||||
"Block_remaining": "${status} toshe ragowar",
|
||||
"labeled_silent_addresses": "Mai labarar adireshin shiru",
|
||||
"use_testnet": "Amfani da gwaji"
|
||||
}
|
||||
"use_testnet": "Amfani da gwaji",
|
||||
"tor_connection": "Tor haɗin gwiwa",
|
||||
"seed_hex_form": "Gany Sero (form form)",
|
||||
"seedtype": "Seedtype",
|
||||
"seedtype_legacy": "Legacy (25 kalmomi)",
|
||||
"seedtype_polyseed": "Polyseed (16 kalmomi)",
|
||||
"seed_language_czech": "Czech",
|
||||
"seed_language_korean": "Yaren Koriya",
|
||||
"seed_language_chinese_traditional": "Sinanci (na gargajiya)"
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"seed_title": "बीज",
|
||||
"seed_share": "बीज साझा करें",
|
||||
"copy": "प्रतिलिपि",
|
||||
"seed_language_choose": "कृपया बीज भाषा चुनें:",
|
||||
"seed_language": "बीज",
|
||||
"seed_choose": "बीज भाषा चुनें",
|
||||
"seed_language_next": "आगामी",
|
||||
"seed_language_english": "अंग्रेज़ी",
|
||||
|
@ -571,7 +571,7 @@
|
|||
"always": "हमेशा",
|
||||
"minutes_to_pin_code": "${minute} मिनट",
|
||||
"disable_exchange": "एक्सचेंज अक्षम करें",
|
||||
"advanced_privacy_settings": "उन्नत गोपनीयता सेटिंग्स",
|
||||
"advanced_settings": "एडवांस सेटिंग",
|
||||
"settings_can_be_changed_later": "इन सेटिंग्स को बाद में ऐप सेटिंग में बदला जा सकता है",
|
||||
"add_custom_node": "नया कस्टम नोड जोड़ें",
|
||||
"disable_fiat": "िएट को अक्षम करें",
|
||||
|
@ -731,11 +731,26 @@
|
|||
"require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है",
|
||||
"camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।",
|
||||
"switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें",
|
||||
"importNFTs": "एनएफटी आयात करें",
|
||||
"noNFTYet": "अभी तक कोई एनएफटी नहीं",
|
||||
"address": "पता",
|
||||
"enterTokenID": "टोकन आईडी दर्ज करें",
|
||||
"tokenID": "पहचान",
|
||||
"name": "नाम",
|
||||
"symbol": "प्रतीक",
|
||||
"seed_phrase_length": "बीज वाक्यांश की लंबाई",
|
||||
"unavailable_balance": "अनुपलब्ध शेष",
|
||||
"unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।",
|
||||
"unspent_change": "परिवर्तन",
|
||||
"Block_remaining": "${status} शेष ब्लॉक",
|
||||
"labeled_silent_addresses": "मूक पते लेबल",
|
||||
"use_testnet": "टेस्टनेट का उपयोग करें"
|
||||
}
|
||||
"use_testnet": "टेस्टनेट का उपयोग करें",
|
||||
"tor_connection": "टोर कनेक्शन",
|
||||
"seed_hex_form": "वॉलेट सीड (हेक्स फॉर्म)",
|
||||
"seedtype": "बीज",
|
||||
"seedtype_legacy": "विरासत (25 शब्द)",
|
||||
"seedtype_polyseed": "पॉलीसीड (16 शब्द)",
|
||||
"seed_language_czech": "चेक",
|
||||
"seed_language_korean": "कोरियाई",
|
||||
"seed_language_chinese_traditional": "चीनी पारंपरिक)"
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"seed_title": "Prisupni izraz",
|
||||
"seed_share": "Podijeli pristupni izraz",
|
||||
"copy": "Kopiraj",
|
||||
"seed_language_choose": "Molimo odaberite jezik pristupnog izraza:",
|
||||
"seed_language": "Sjemeni jezik",
|
||||
"seed_choose": "Odaberi jezik pristupnog izraza",
|
||||
"seed_language_next": "Dalje",
|
||||
"seed_language_english": "Engleski",
|
||||
|
@ -383,7 +383,7 @@
|
|||
"change_backup_password_alert": "Nećemo moći uvesti Vaše prethodne datoteke sigurnosne kopije s novom lozinkom za sigurnosnu kopiju. Novu lozinku za sigurnosnu kopiju moći ćete koristiti samo za nove datoteke sigurnosne kopije. Jeste li sigurni da želite promijeniti lozinku za sigurnosnu kopiju?",
|
||||
"enter_backup_password": "Unesite svoju lozinku za sigurnosnu kopiju ovdje",
|
||||
"select_backup_file": "Odaberite datoteku sigurnosne kopije",
|
||||
"import": "Uvezi",
|
||||
"import": "Uvoz",
|
||||
"please_select_backup_file": "Molimo odaberite datoteku sigurnosne kopije i unesite lozinku za sigurnosnu kopiju.",
|
||||
"fixed_rate": "Fiksna stopa",
|
||||
"fixed_rate_alert": "Moći ćete unijeti iznos koji želite primiti nakon što označite način rada fiksne stope. Želite li se prebaciti na način rada fiksne stope?",
|
||||
|
@ -571,7 +571,7 @@
|
|||
"always": "Uvijek",
|
||||
"minutes_to_pin_code": "${minute} minuta",
|
||||
"disable_exchange": "Onemogući exchange",
|
||||
"advanced_privacy_settings": "Napredne postavke privatnosti",
|
||||
"advanced_settings": "Napredne postavke",
|
||||
"settings_can_be_changed_later": "Te se postavke mogu promijeniti kasnije u postavkama aplikacije",
|
||||
"add_custom_node": "Dodaj novi prilagođeni čvor",
|
||||
"disable_fiat": "Isključi, fiat",
|
||||
|
@ -729,11 +729,26 @@
|
|||
"require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike",
|
||||
"camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.",
|
||||
"switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno",
|
||||
"importNFTs": "Uvoz NFT-ova",
|
||||
"noNFTYet": "Još nema NFT-ova",
|
||||
"address": "Adresa",
|
||||
"enterTokenID": "Unesite ID tokena",
|
||||
"tokenID": "iskaznica",
|
||||
"name": "Ime",
|
||||
"symbol": "Simbol",
|
||||
"seed_phrase_length": "Duljina početne fraze",
|
||||
"unavailable_balance": "Nedostupno stanje",
|
||||
"unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.",
|
||||
"unspent_change": "Promijeniti",
|
||||
"Block_remaining": "${status} ostao blok",
|
||||
"labeled_silent_addresses": "Označene tihe adrese",
|
||||
"use_testnet": "Koristite TestNet"
|
||||
}
|
||||
"use_testnet": "Koristite TestNet",
|
||||
"tor_connection": "Tor veza",
|
||||
"seed_hex_form": "Sjeme novčanika (šesterokutni oblik)",
|
||||
"seedtype": "Sjemenska vrsta",
|
||||
"seedtype_legacy": "Nasljeđe (25 riječi)",
|
||||
"seedtype_polyseed": "Poliseed (16 riječi)",
|
||||
"seed_language_czech": "češki",
|
||||
"seed_language_korean": "korejski",
|
||||
"seed_language_chinese_traditional": "Kinesko (tradicionalno)"
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"seed_title": "Bibit",
|
||||
"seed_share": "Bagikan bibit",
|
||||
"copy": "Salin",
|
||||
"seed_language_choose": "Silakan pilih bahasa bibit:",
|
||||
"seed_language": "Bahasa benih",
|
||||
"seed_choose": "Pilih bahasa bibit",
|
||||
"seed_language_next": "Selanjutnya",
|
||||
"seed_language_english": "Inggris",
|
||||
|
@ -570,7 +570,7 @@
|
|||
"always": "Selalu",
|
||||
"minutes_to_pin_code": "${minute} menit",
|
||||
"disable_exchange": "Nonaktifkan pertukaran",
|
||||
"advanced_privacy_settings": "Pengaturan Privasi Lanjutan",
|
||||
"advanced_settings": "Pengaturan lanjutan",
|
||||
"settings_can_be_changed_later": "Pengaturan ini dapat diubah nanti di pengaturan aplikasi",
|
||||
"add_custom_node": "Tambahkan Node Kustom Baru",
|
||||
"disable_fiat": "Nonaktifkan fiat",
|
||||
|
@ -719,11 +719,26 @@
|
|||
"require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal",
|
||||
"camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.",
|
||||
"switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi",
|
||||
"importNFTs": "Impor NFT",
|
||||
"noNFTYet": "Belum ada NFT",
|
||||
"address": "Alamat",
|
||||
"enterTokenID": "Masukkan ID tokennya",
|
||||
"tokenID": "PENGENAL",
|
||||
"name": "Nama",
|
||||
"symbol": "Simbol",
|
||||
"seed_phrase_length": "Panjang frase benih",
|
||||
"unavailable_balance": "Saldo tidak tersedia",
|
||||
"unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.",
|
||||
"unspent_change": "Mengubah",
|
||||
"Block_remaining": "${status} blok tersisa",
|
||||
"labeled_silent_addresses": "Label alamat diam",
|
||||
"use_testnet": "Gunakan TestNet"
|
||||
}
|
||||
"use_testnet": "Gunakan TestNet",
|
||||
"tor_connection": "koneksi Tor",
|
||||
"seed_hex_form": "Biji dompet (bentuk hex)",
|
||||
"seedtype": "Seedtype",
|
||||
"seedtype_legacy": "Legacy (25 kata)",
|
||||
"seedtype_polyseed": "Polyseed (16 kata)",
|
||||
"seed_language_czech": "Ceko",
|
||||
"seed_language_korean": "Korea",
|
||||
"seed_language_chinese_traditional": "Cina (tradisional)"
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"seed_title": "Seme",
|
||||
"seed_share": "Condividi seme",
|
||||
"copy": "Copia",
|
||||
"seed_language_choose": "Gentilmente scegli la lingua del seme:",
|
||||
"seed_language": "Linguaggio di semi",
|
||||
"seed_choose": "Scegli la lingua del seme",
|
||||
"seed_language_next": "Prossimo",
|
||||
"seed_language_english": "Inglese",
|
||||
|
@ -383,7 +383,7 @@
|
|||
"change_backup_password_alert": "I precedenti file di backup non potranno essere importati con la nuova password di backup. La nuova password di backup verrà usata soltanto per i nuovi file di backup. Sei sicuro di voler cambiare la tua password di backup?",
|
||||
"enter_backup_password": "Inserisci la password di backup qui",
|
||||
"select_backup_file": "Seleziona file di backup",
|
||||
"import": "Importa",
|
||||
"import": "Importare",
|
||||
"please_select_backup_file": "Gentilmente seleziona il file di backup e inserisci la password di backup.",
|
||||
"fixed_rate": "Tasso fisso",
|
||||
"fixed_rate_alert": "Potrai inserire l'ammontare da ricevere quando il tasso è fisso. Vuoi cambiare alla modalità tasso fisso?",
|
||||
|
@ -571,7 +571,7 @@
|
|||
"always": "sempre",
|
||||
"minutes_to_pin_code": "${minute} minuti",
|
||||
"disable_exchange": "Disabilita scambio",
|
||||
"advanced_privacy_settings": "Impostazioni avanzate sulla privacy",
|
||||
"advanced_settings": "Impostazioni avanzate",
|
||||
"settings_can_be_changed_later": "Queste impostazioni possono essere modificate in seguito nelle impostazioni dell'app",
|
||||
"add_custom_node": "Aggiungi nuovo nodo personalizzato",
|
||||
"disable_fiat": "Disabilita fiat",
|
||||
|
@ -731,11 +731,26 @@
|
|||
"require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni",
|
||||
"camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.",
|
||||
"switchToETHWallet": "Passa a un portafoglio Ethereum e riprova",
|
||||
"importNFTs": "Importa NFT",
|
||||
"noNFTYet": "Nessun NFT ancora",
|
||||
"address": "Indirizzo",
|
||||
"enterTokenID": "Inserisci l'ID del token",
|
||||
"tokenID": "ID",
|
||||
"name": "Nome",
|
||||
"symbol": "Simbolo",
|
||||
"seed_phrase_length": "Lunghezza della frase seed",
|
||||
"unavailable_balance": "Saldo non disponibile",
|
||||
"unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.",
|
||||
"unspent_change": "Modifica",
|
||||
"Block_remaining": "${status} blocco rimanente",
|
||||
"labeled_silent_addresses": "Indirizzi silenziosi etichettati",
|
||||
"use_testnet": "Usa TestNet"
|
||||
}
|
||||
"use_testnet": "Usa TestNet",
|
||||
"tor_connection": "Connessione Tor",
|
||||
"seed_hex_form": "Seme di portafoglio (forma esadecimale)",
|
||||
"seedtype": "Seedtype",
|
||||
"seedtype_legacy": "Legacy (25 parole)",
|
||||
"seedtype_polyseed": "Polyseed (16 parole)",
|
||||
"seed_language_czech": "ceco",
|
||||
"seed_language_korean": "coreano",
|
||||
"seed_language_chinese_traditional": "Cinese tradizionale)"
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"seed_title": "シード",
|
||||
"seed_share": "シードを共有する",
|
||||
"copy": "コピー",
|
||||
"seed_language_choose": "シード言語を選択してください:",
|
||||
"seed_language": "シード言語",
|
||||
"seed_choose": "シード言語を選択してください",
|
||||
"seed_language_next": "次",
|
||||
"seed_language_english": "英語",
|
||||
|
@ -383,7 +383,7 @@
|
|||
"change_backup_password_alert": "以前のバックアップファイルは、新しいバックアップパスワードでインポートできなくなります。 新しいバックアップパスワードは、新しいバックアップファイルにのみ使用されます。 バックアップパスワードを変更してもよろしいですか?",
|
||||
"enter_backup_password": "ここにバックアップパスワードを入力してください",
|
||||
"select_backup_file": "バックアップファイルを選択",
|
||||
"import": "インポート",
|
||||
"import": "輸入",
|
||||
"please_select_backup_file": "バックアップファイルを選択し、バックアップパスワードを入力してください。",
|
||||
"fixed_rate": "固定金利",
|
||||
"fixed_rate_alert": "固定金利モードにチェックを入れると、受取額を入力できるようになります。 固定金利モードに切り替えますか?",
|
||||
|
@ -571,7 +571,7 @@
|
|||
"always": "いつも",
|
||||
"minutes_to_pin_code": "${minute} 分",
|
||||
"disable_exchange": "交換を無効にする",
|
||||
"advanced_privacy_settings": "高度なプライバシー設定",
|
||||
"advanced_settings": "高度な設定",
|
||||
"settings_can_be_changed_later": "これらの設定は、後でアプリの設定で変更できます",
|
||||
"add_custom_node": "新しいカスタム ノードを追加",
|
||||
"disable_fiat": "フィアットを無効にする",
|
||||
|
@ -731,11 +731,26 @@
|
|||
"require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要",
|
||||
"camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。",
|
||||
"switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください",
|
||||
"importNFTs": "NFTのインポート",
|
||||
"noNFTYet": "NFTはまだありません",
|
||||
"address": "住所",
|
||||
"enterTokenID": "トークンIDを入力してください",
|
||||
"tokenID": "ID",
|
||||
"name": "名前",
|
||||
"symbol": "シンボル",
|
||||
"seed_phrase_length": "シードフレーズの長さ",
|
||||
"unavailable_balance": "利用できない残高",
|
||||
"unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。",
|
||||
"unspent_change": "変化",
|
||||
"Block_remaining": "${status}ブロックの残り",
|
||||
"labeled_silent_addresses": "サイレントアドレスとラベル付けされています",
|
||||
"use_testnet": "TestNetを使用します"
|
||||
}
|
||||
"use_testnet": "TestNetを使用します",
|
||||
"tor_connection": "Tor接続",
|
||||
"seed_hex_form": "ウォレットシード(ヘックスフォーム)",
|
||||
"seedtype": "SeedType",
|
||||
"seedtype_legacy": "レガシー(25語)",
|
||||
"seedtype_polyseed": "ポリシード(16語)",
|
||||
"seed_language_czech": "チェコ",
|
||||
"seed_language_korean": "韓国語",
|
||||
"seed_language_chinese_traditional": "中国の伝統的な)"
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"seed_title": "씨",
|
||||
"seed_share": "시드 공유",
|
||||
"copy": "부",
|
||||
"seed_language_choose": "종자 언어를 선택하십시오:",
|
||||
"seed_language": "종자 언어",
|
||||
"seed_choose": "시드 언어를 선택하십시오",
|
||||
"seed_language_next": "다음 것",
|
||||
"seed_language_english": "영어",
|
||||
|
@ -571,7 +571,7 @@
|
|||
"always": "언제나",
|
||||
"minutes_to_pin_code": "${minute}분",
|
||||
"disable_exchange": "교환 비활성화",
|
||||
"advanced_privacy_settings": "고급 개인 정보 설정",
|
||||
"advanced_settings": "고급 설정",
|
||||
"settings_can_be_changed_later": "이 설정은 나중에 앱 설정에서 변경할 수 있습니다.",
|
||||
"add_custom_node": "새 사용자 정의 노드 추가",
|
||||
"disable_fiat": "법정화폐 비활성화",
|
||||
|
@ -729,11 +729,26 @@
|
|||
"require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요",
|
||||
"camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.",
|
||||
"switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요.",
|
||||
"importNFTs": "NFT 가져오기",
|
||||
"noNFTYet": "아직 NFT가 없습니다",
|
||||
"address": "주소",
|
||||
"enterTokenID": "토큰 ID를 입력하세요",
|
||||
"tokenID": "ID",
|
||||
"name": "이름",
|
||||
"symbol": "상징",
|
||||
"seed_phrase_length": "시드 문구 길이",
|
||||
"unavailable_balance": "사용할 수 없는 잔액",
|
||||
"unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.",
|
||||
"unspent_change": "변화",
|
||||
"Block_remaining": "${status} 나머지 블록",
|
||||
"labeled_silent_addresses": "라벨링 된 무음 주소",
|
||||
"use_testnet": "TestNet을 사용하십시오"
|
||||
}
|
||||
"use_testnet": "TestNet을 사용하십시오",
|
||||
"tor_connection": "토르 연결",
|
||||
"seed_hex_form": "지갑 씨앗 (16 진 양식)",
|
||||
"seedtype": "시드 타입",
|
||||
"seedtype_legacy": "레거시 (25 단어)",
|
||||
"seedtype_polyseed": "다문 (16 단어)",
|
||||
"seed_language_czech": "체코 사람",
|
||||
"seed_language_korean": "한국인",
|
||||
"seed_language_chinese_traditional": "중국 전통)"
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"seed_title": "မျိုးစေ့",
|
||||
"seed_share": "မျိုးစေ့မျှဝေပါ။",
|
||||
"copy": "ကော်ပီ",
|
||||
"seed_language_choose": "ကျေးဇူးပြု၍ မျိုးစေ့ဘာသာစကားကို ရွေးပါ-",
|
||||
"seed_language": "မျိုးစေ့ဘာသာ",
|
||||
"seed_choose": "မျိုးစေ့ဘာသာစကားကို ရွေးချယ်ပါ။",
|
||||
"seed_language_next": "နောက်တစ်ခု",
|
||||
"seed_language_english": "အင်္ဂလိပ်စာ",
|
||||
|
@ -569,7 +569,7 @@
|
|||
"always": "အမြဲတမ်း",
|
||||
"minutes_to_pin_code": "${minute} မိနစ်",
|
||||
"disable_exchange": "လဲလှယ်မှုကို ပိတ်ပါ။",
|
||||
"advanced_privacy_settings": "အဆင့်မြင့် ကိုယ်ရေးကိုယ်တာ ဆက်တင်များ",
|
||||
"advanced_settings": "အဆင့်မြင့်ချိန်ညှိချက်များ",
|
||||
"settings_can_be_changed_later": "အက်ပ်ဆက်တင်များတွင် ဤဆက်တင်များကို နောက်ပိုင်းတွင် ပြောင်းလဲနိုင်သည်။",
|
||||
"add_custom_node": "စိတ်ကြိုက် Node အသစ်ကို ထည့်ပါ။",
|
||||
"disable_fiat": "Fiat ကိုပိတ်ပါ။",
|
||||
|
@ -729,11 +729,26 @@
|
|||
"require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။",
|
||||
"camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။",
|
||||
"switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။",
|
||||
"importNFTs": "NFTs များကို တင်သွင်းပါ။",
|
||||
"noNFTYet": "NFTs မရှိသေးပါ။",
|
||||
"address": "လိပ်စာ",
|
||||
"enterTokenID": "တိုကင် ID ကိုထည့်ပါ။",
|
||||
"tokenID": "အမှတ်သညာ",
|
||||
"name": "နာမည်",
|
||||
"symbol": "သင်္ကေတ",
|
||||
"seed_phrase_length": "မျိုးစေ့စာပိုဒ်တိုအရှည်",
|
||||
"unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။",
|
||||
"unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။",
|
||||
"unspent_change": "ပေြာင်းလဲခြင်း",
|
||||
"Block_remaining": "ကျန်ရှိသော ${status}",
|
||||
"labeled_silent_addresses": "အသံတိတ်အသံတိတ်လိပ်စာများတံဆိပ်ကပ်",
|
||||
"use_testnet": "testnet ကိုသုံးပါ"
|
||||
}
|
||||
"use_testnet": "testnet ကိုသုံးပါ",
|
||||
"tor_connection": "Tor ချိတ်ဆက်မှု",
|
||||
"seed_hex_form": "ပိုက်ဆံအိတ်မျိုးစေ့ (Hex Form)",
|
||||
"seedtype": "မျိုးပွားခြင်း",
|
||||
"seedtype_legacy": "အမွေအနှစ် (စကားလုံး 25 လုံး)",
|
||||
"seedtype_polyseed": "polyseed (စကားလုံး 16 လုံး)",
|
||||
"seed_language_czech": "ချက်",
|
||||
"seed_language_korean": "ကိုးရီးယား",
|
||||
"seed_language_chinese_traditional": "တရုတ်ရိုးရာ)"
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue