Added the project

M committed Jan 4, 2020 at 21:31 UTC 69f4c127abc81a7f6105534044497e052ea9cec8
417 files changed +33436
.metadata new
+10
@@ -0,0 +1,10 @@
1 +# This file tracks properties of this Flutter project.
2 +# Used by Flutter tool to assess capabilities and perform upgrades etc.
3 +#
4 +# This file should be version controlled and should not be manually edited.
5 +
6 +version:
7 + revision: 20e59316b8b8474554b38493b8ca888794b0234a
8 + channel: stable
9 +
10 +project_type: app
LICENSE.md new
+21
@@ -0,0 +1,21 @@
1 +MIT License
2 +
3 +Copyright (c) 2020 Cake Technologies LLC
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in all
13 +copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 +SOFTWARE.
README.md new
+5
@@ -0,0 +1,5 @@
1 +# Cake Wallet
2 +
3 +The project description, motivation, build scripts, instructions, tests will be added soon (Jan-Feb 2020);
4 +
5 +Copyright (c) 2020 Cake Technologies LLC.
\ No newline at end of file
analysis_options.yaml new
+64
@@ -0,0 +1,64 @@
1 +include: package:pedantic/analysis_options.yaml
2 +
3 +analyzer:
4 + strong-mode:
5 + implicit-casts: false
6 + implicit-dynamic: false
7 + exclude:
8 + - **/*.yaml
9 + - build/**
10 + - **/*.g.dart
11 + - lib/generated/*.dart
12 +
13 +linter:
14 + rules:
15 + - always_declare_return_types
16 + - always_specify_types
17 + - annotate_overrides
18 + - avoid_as
19 + - avoid_empty_else
20 + - avoid_init_to_null
21 + - avoid_return_types_on_setters
22 + - await_only_futures
23 + - camel_case_types
24 + - cancel_subscriptions
25 + - close_sinks
26 + - comment_references
27 + - constant_identifier_names
28 + - control_flow_in_finally
29 + - empty_catches
30 + - empty_constructor_bodies
31 + - empty_statements
32 + - hash_and_equals
33 + - implementation_imports
34 + - invariant_booleans
35 + - iterable_contains_unrelated_type
36 + - library_names
37 + - library_prefixes
38 + - list_remove_unrelated_type
39 + - literal_only_boolean_expressions
40 + - non_constant_identifier_names
41 + - one_member_abstracts
42 + - only_throw_errors
43 + - overridden_fields
44 + - package_api_docs
45 + - package_names
46 + - package_prefixed_library_names
47 + - parameter_assignments
48 + - prefer_final_fields
49 + - prefer_final_locals
50 + - prefer_is_not_empty
51 + - public_member_api_docs
52 + - slash_for_doc_comments
53 + - sort_constructors_first
54 + - sort_unnamed_constructors_first
55 + - super_goes_last
56 + - test_types_in_equals
57 + - throw_in_finally
58 + - type_annotate_public_apis
59 + - type_init_formals
60 + - unawaited_futures
61 + - unnecessary_brace_in_string_interp
62 + - unnecessary_getters_setters
63 + - unrelated_type_equality_checks
64 + - valid_regexps
\ No newline at end of file
android/.gitignore new
+7
@@ -0,0 +1,7 @@
1 +gradle-wrapper.jar
2 +/.gradle
3 +/captures/
4 +/gradlew
5 +/gradlew.bat
6 +/local.properties
7 +GeneratedPluginRegistrant.java
android/app/build.gradle new
+86
@@ -0,0 +1,86 @@
1 +def localProperties = new Properties()
2 +def localPropertiesFile = rootProject.file('local.properties')
3 +if (localPropertiesFile.exists()) {
4 + localPropertiesFile.withReader('UTF-8') { reader ->
5 + localProperties.load(reader)
6 + }
7 +}
8 +
9 +def flutterRoot = localProperties.getProperty('flutter.sdk')
10 +if (flutterRoot == null) {
11 + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 +}
13 +
14 +def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 +if (flutterVersionCode == null) {
16 + flutterVersionCode = '1'
17 +}
18 +
19 +def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 +if (flutterVersionName == null) {
21 + flutterVersionName = '1.0'
22 +}
23 +
24 +apply plugin: 'com.android.application'
25 +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
26 +
27 +def keystoreProperties = new Properties()
28 +def keystorePropertiesFile = rootProject.file('key.properties')
29 +if (keystorePropertiesFile.exists()) {
30 + keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
31 +}
32 +
33 +android {
34 + compileSdkVersion 28
35 +
36 + lintOptions {
37 + disable 'InvalidPackage'
38 + }
39 +
40 + defaultConfig {
41 + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
42 + applicationId "com.cakewallet.cake_wallet"
43 + minSdkVersion 21
44 + targetSdkVersion 28
45 + versionCode flutterVersionCode.toInteger()
46 + versionName flutterVersionName
47 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
48 +
49 + externalNativeBuild {
50 + cmake {
51 + cppFlags "-std=c++11"
52 + arguments '-DANDROID_STL=c++_shared', '-DBUILD_TESTING=OFF'
53 + version "3.10.2"
54 + }
55 + }
56 + }
57 +
58 + signingConfigs {
59 + release {
60 + keyAlias keystoreProperties['keyAlias']
61 + keyPassword keystoreProperties['keyPassword']
62 + storeFile file(keystoreProperties['storeFile'])
63 + storePassword keystoreProperties['storePassword']
64 + }
65 + }
66 + buildTypes {
67 + release {
68 + signingConfig signingConfigs.release
69 +
70 + minifyEnabled true
71 + useProguard true
72 +
73 + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
74 + }
75 + }
76 +}
77 +
78 +flutter {
79 + source '../..'
80 +}
81 +
82 +dependencies {
83 + testImplementation 'junit:junit:4.12'
84 + androidTestImplementation 'androidx.test:runner:1.1.1'
85 + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
86 +}
android/app/proguard-rules.pro new
+8
@@ -0,0 +1,8 @@
1 +## Flutter wrapper
2 +-keep class io.flutter.app.** { *; }
3 +-keep class io.flutter.plugin.** { *; }
4 +-keep class io.flutter.util.** { *; }
5 +-keep class io.flutter.view.** { *; }
6 +-keep class io.flutter.** { *; }
7 +-keep class io.flutter.plugins.** { *; }
8 +-dontwarn io.flutter.embedding.**
\ No newline at end of file
android/app/src/debug/AndroidManifest.xml new
+7
@@ -0,0 +1,7 @@
1 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2 + package="com.cakewallet.cake_wallet">
3 + <!-- Flutter needs it to communicate with the running application
4 + to allow setting breakpoints, to provide hot reload, etc.
5 + -->
6 + <uses-permission android:name="android.permission.INTERNET"/>
7 +</manifest>
android/app/src/main/AndroidManifest.xml new
+36
@@ -0,0 +1,36 @@
1 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2 + package="com.cakewallet.cake_wallet">
3 + <!-- io.flutter.app.FlutterApplication is an android.app.Application that
4 + calls FlutterMain.startInitialization(this); in its onCreate method.
5 + In most cases you can leave this as-is, but you if you want to provide
6 + additional functionality it is fine to subclass or reimplement
7 + FlutterApplication and put your custom class here. -->
8 +
9 + <uses-permission android:name="android.permission.INTERNET"/>
10 +
11 + <application
12 + android:name="io.flutter.app.FlutterApplication"
13 + android:label="Cake Wallet"
14 + android:icon="@mipmap/ic_launcher">
15 + <activity
16 + android:name=".MainActivity"
17 + android:launchMode="singleTop"
18 + android:theme="@style/LaunchTheme"
19 + android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
20 + android:hardwareAccelerated="true"
21 + android:windowSoftInputMode="adjustResize"
22 + android:screenOrientation="portrait">
23 + <!-- This keeps the window background of the activity showing
24 + until Flutter renders its first frame. It can be removed if
25 + there is no splash screen (such as the default splash screen
26 + defined in @style/LaunchTheme). -->
27 + <meta-data
28 + android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
29 + android:value="true" />
30 + <intent-filter>
31 + <action android:name="android.intent.action.MAIN"/>
32 + <category android:name="android.intent.category.LAUNCHER"/>
33 + </intent-filter>
34 + </activity>
35 + </application>
36 +</manifest>
android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java new
+13
@@ -0,0 +1,13 @@
1 +package com.cakewallet.cake_wallet;
2 +
3 +import android.os.Bundle;
4 +import io.flutter.app.FlutterActivity;
5 +import io.flutter.plugins.GeneratedPluginRegistrant;
6 +
7 +public class MainActivity extends FlutterActivity {
8 + @Override
9 + protected void onCreate(Bundle savedInstanceState) {
10 + super.onCreate(savedInstanceState);
11 + GeneratedPluginRegistrant.registerWith(this);
12 + }
13 +}
android/app/src/main/res/drawable/launch_background.xml new
+12
@@ -0,0 +1,12 @@
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<!-- Modify this file to customize your launch splash screen -->
3 +<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
4 + <item android:drawable="@android:color/white" />
5 +
6 + <!-- You can insert your own image assets here -->
7 + <!-- <item>
8 + <bitmap
9 + android:gravity="center"
10 + android:src="@mipmap/launch_image" />
11 + </item> -->
12 +</layer-list>
android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
android/app/src/main/res/values/styles.xml new
+8
@@ -0,0 +1,8 @@
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<resources>
3 + <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
4 + <!-- Show a splash screen on the activity. Automatically removed when
5 + Flutter draws its first frame -->
6 + <item name="android:windowBackground">@drawable/launch_background</item>
7 + </style>
8 +</resources>
android/app/src/profile/AndroidManifest.xml new
+7
@@ -0,0 +1,7 @@
1 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2 + package="com.cakewallet.cake_wallet">
3 + <!-- Flutter needs it to communicate with the running application
4 + to allow setting breakpoints, to provide hot reload, etc.
5 + -->
6 + <uses-permission android:name="android.permission.INTERNET"/>
7 +</manifest>
android/build.gradle new
+29
@@ -0,0 +1,29 @@
1 +buildscript {
2 + repositories {
3 + google()
4 + jcenter()
5 + }
6 +
7 + dependencies {
8 + classpath 'com.android.tools.build:gradle:3.5.0'
9 + }
10 +}
11 +
12 +allprojects {
13 + repositories {
14 + google()
15 + jcenter()
16 + }
17 +}
18 +
19 +rootProject.buildDir = '../build'
20 +subprojects {
21 + project.buildDir = "${rootProject.buildDir}/${project.name}"
22 +}
23 +subprojects {
24 + project.evaluationDependsOn(':app')
25 +}
26 +
27 +task clean(type: Delete) {
28 + delete rootProject.buildDir
29 +}
android/gradle.properties new
+4
@@ -0,0 +1,4 @@
1 +org.gradle.jvmargs=-Xmx1536M
2 +android.enableR8=true
3 +android.useAndroidX=true
4 +android.enableJetifier=true
android/gradle/wrapper/gradle-wrapper.properties new
+6
@@ -0,0 +1,6 @@
1 +#Fri Jun 23 08:50:38 CEST 2017
2 +distributionBase=GRADLE_USER_HOME
3 +distributionPath=wrapper/dists
4 +zipStoreBase=GRADLE_USER_HOME
5 +zipStorePath=wrapper/dists
6 +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
android/settings.gradle new
+15
@@ -0,0 +1,15 @@
1 +include ':app'
2 +
3 +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 +
5 +def plugins = new Properties()
6 +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 +if (pluginsFile.exists()) {
8 + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 +}
10 +
11 +plugins.each { name, path ->
12 + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 + include ":$name"
14 + project(":$name").projectDir = pluginDirectory
15 +}
assets/faq/faq_de.json new
+58
@@ -0,0 +1,58 @@
1 +[
2 + {
3 + "question" : "Was ist der Unterschied zwischen verfügbarem Guthaben und vollständigem Guthaben?",
4 + "answer" : "Nachdem Sie eine Transaktion getätigt oder Monero erhalten haben, muss die Transaktion noch bestätigt werden. In ungefähr 20 Minuten sollte Ihr \"verfügbares Guthaben\" aktualisiert werden!\nWenn Sie Monero senden, verringert sich manchmal Ihr verfügbares Guthaben um mehr als den Betrag, den Sie gesendet haben. Dies ist normal und zum Schutz Ihrer Privatsphäre erforderlich. Ihr \"vollständiges Gleichgewicht\" sollte in 20 Minuten wieder normal sein.\n"
5 + },
6 + {
7 + "question" : "Wie sende ich Monero an eine Börse, für die eine Zahlungs-ID erforderlich ist?",
8 + "answer" : "Tippen Sie auf dem Wallet-Bildschirm auf die Schaltfläche \"Senden\". Kopieren Sie anschließend die Einzahlungsadresse der Börse und fügen Sie sie in das Feld \"Adresse\" ein. Kopieren Sie dann die vom Umtausch bereitgestellte Zahlungs-ID und fügen Sie sie in das Feld Zahlungs-ID ein. Geben Sie zum Schluss den Betrag ein, den Sie senden möchten, und los geht's!\n"
9 + },
10 + {
11 + "question" : "Was kann ich tun, wenn ich beim Senden von Monero an eine Börse vergessen habe, die Zahlungs-ID einzugeben?",
12 + "answer" : "Obwohl unser Support Sie bei diesem Problem nicht direkt unterstützen kann, ist es ein sehr häufiges Problem, mit dem die meisten Börsen vertraut sind. Wenden Sie sich einfach an den Support der Börse, erklären Sie, dass Sie vergessen haben, Ihre Zahlungs-ID anzugeben, und senden Sie ihnen dann Ihre Transaktions-ID als Nachweis. Sie finden die Transaktions-ID, indem Sie auf die Transaktion in Ihrem Wallet-Bildschirm tippen.\n"
13 + },
14 + {
15 + "question" : "Was bedeuten \"Samen\" und \"Schlüssel\"?",
16 + "answer" : "Ihre Schlüssel verschlüsseln die privaten Informationen in Ihrer Brieftasche und ermöglichen es Ihnen, Münzen auszugeben und eingehende Transaktionen anzuzeigen.\nIhr Startwert ist nur eine Version Ihres privaten Schlüssels, die so geschrieben wurde, dass Sie sie leichter notieren können. Ihr Same und Schlüssel sind tatsächlich dasselbe, nur in verschiedenen Formen!\nGeben Sie niemals Ihren Samen oder Schlüssel an jemanden weiter. Ihr Geld wird gestohlen, wenn Sie Ihren Samen oder Schlüssel herausgeben. Bitte notieren Sie sich jedoch Ihren Samen und bewahren Sie ihn an einem sicheren Ort auf (so können Sie Ihre Brieftasche wiederherstellen, wenn Sie Ihr Telefon verlieren.)\n"
17 + },
18 + {
19 + "question" : "Wie viele Geldbörsen kann ich erstellen?",
20 + "answer" : "Es gibt keine Grenzen! Sie können so viele Brieftaschen erstellen, wie Sie möchten.\n"
21 + },
22 + {
23 + "question" : "Wie kann ich meine Brieftasche wiederherstellen?",
24 + "answer" : "Tippen Sie auf das Menü •••, wählen Sie „Brieftaschen“ und dann „Brieftasche wiederherstellen“. Geben Sie dann Ihren Startwert (oder Ihre Schlüssel) und optional ein Datum vor der ersten Transaktion in Ihrer Brieftasche ein (dies beschleunigt den Synchronisierungsvorgang) .) Möglicherweise müssen Sie die App 15 bis 30 Minuten geöffnet lassen, um Ihr Portemonnaie vollständig wiederherzustellen.\n"
25 + },
26 + {
27 + "question" : "Was kann ich tun, wenn ich meinen Samen verliere?",
28 + "answer" : "Wenn Sie Ihren Samen vergessen haben, haben Sie ihn wahrscheinlich irgendwo aufgeschrieben. Bitte überprüfen Sie Ihre Notizen und schauen Sie sich auf Ihrem Computer um. Wenn Sie es nirgendwo finden, haben Sie möglicherweise Cake Wallet gesichert (in diesem Fall können Sie es aus diesem Backup wiederherstellen.) Wenn keines dieser Probleme auftritt, können wir leider nichts tun.\n"
29 + },
30 + {
31 + "question" : "Sammeln Sie Informationen zu meiner Brieftasche?",
32 + "answer" : "Cake Wallet sammelt oder zeichnet keine Informationen über Ihre Brieftasche auf. Ihre Privatsphäre ist uns wichtig.\n"
33 + },
34 + {
35 + "question" : "Kann ich eine Transaktion stornieren?",
36 + "answer" : "Sobald eine Transaktion an die Blockchain gesendet wurde, kann sie leider nicht mehr rückgängig gemacht werden. Sie können die Transaktion jederzeit abbrechen, bevor sie gesendet wird. Überprüfen Sie die Adresse daher immer, bevor Sie eine Transaktion senden.\n"
37 + },
38 + {
39 + "question" : "Was sind Subadressen und wie verwende ich sie?",
40 + "answer" : "Eine Unteradresse ist im Grunde eine eindeutige Adresse, die Sie jederzeit generieren können. An sie gesendete Münzen landen weiterhin in Ihrer Hauptbrieftasche, aber die Person, die die Münzen sendet, kann Ihre Hauptadresse nicht ermitteln. Unteradressen beginnen immer mit „8“.\nSie können eine neue Unteradresse im Empfangsbildschirm erstellen, indem Sie auf das „+“ neben der Schaltfläche Unteradressen tippen. Geben Sie einen Namen für die Unteradresse ein und tippen Sie auf \"Hinzufügen\". Dann tippen Sie einfach auf den Namen der Subadresse, wenn Sie ihn verwenden möchten!\nWenn Sie paranoid sind, sollten Sie wahrscheinlich jedes Mal, wenn Sie Monero erhalten, eine neue Unteradresse erstellen.\n"
41 + },
42 + {
43 + "question" : "Was ist eine Transaktions-ID?",
44 + "answer" : "Ein Transaktions-Hash oder eine Transaktions-ID ist eine eindeutige Methode, um eine Transaktion zu identifizieren. Jede Transaktion hat einen eigenen Hash. Wenn Sie jemandem einen Transaktions-Hash zur Verfügung stellen müssen, gehen Sie einfach zum Hauptbildschirm der Brieftasche, tippen Sie auf die Transaktion, halten Sie im oberen Bereich die Taste gedrückt und wählen Sie Kopieren.\n"
45 + },
46 + {
47 + "question" : "Ich habe meine XMR nicht erhalten! Was kann ich tun?",
48 + "answer" : "Wenn Sie Ihren Monero nicht erhalten haben, möchten Sie möglicherweise auf das Menü ••• tippen und auf Reconnect (Neu verbinden) klicken. Wenn dies nicht funktioniert, gehen Sie in das Einstellungsmenü, tippen Sie auf das Feld \"Aktueller Knoten\" und wählen Sie einen Knoten mit einem grünen Punkt daneben aus.\n"
49 + },
50 + {
51 + "question" : "Ich habe in der App keine Münzen aus dem Umtausch erhalten. Was kann ich tun?",
52 + "answer" : "Wenn Sie Probleme mit einem Austausch haben, wenden Sie sich am besten an den Austausch. Wir sind eine Partnerschaft mit XMR.TO, Morph und ChangeNow eingegangen. Rufen Sie daher am besten http://xmr.to, http://changenow.io oder http://morphtoken.com auf und wenden Sie sich an deren Support.\n"
53 + },
54 + {
55 + "question" : "Wie kontaktiere ich den Cake Wallet-Support?",
56 + "answer" : "Senden Sie eine E-Mail an support@cakewallet.io, schließen Sie sich dem Telegramm unter @cake_wallet an oder twittern Sie @CakeWalletXMR!\n"
57 + }
58 +]
\ No newline at end of file
assets/faq/faq_en.json new
+58
@@ -0,0 +1,58 @@
1 +[
2 + {
3 + "question" : "What’s the difference between Available Balance and Full Balance?",
4 + "answer" : "After you make a transaction or receive some Monero, the transaction still needs to be confirmed. In about 20 minutes your available balance should update!\nSometimes, when you send Monero, your available balance will decrease by more than the amount you’ve sent. This is normal, and it’s necessary in order to protect your privacy. Your full balance should be back to normal in 20 minutes.\n"
5 + },
6 + {
7 + "question" : "How do I send Monero to an exchange that requires a Payment ID?",
8 + "answer" : "Tap the send button on the Wallet screen. Next, copy the exchange deposit address and paste it into the address box. Then, copy the Payment ID provided by the exchange and paste it into the Payment ID box. Finally, enter the amount you’d like to send, and you’re good to go!\n"
9 + },
10 + {
11 + "question" : "What do I do if I forgot to enter the Payment ID when sending Monero to an exchange?",
12 + "answer" : "While our support can’t directly help you with this issue, it’s a very common problem that most exchanges are used to dealing with. Just contact the exchange support, explain that you forgot to include your Payment ID, and then send them your Transaction ID as proof. You can find the Transaction ID by tapping on the transaction in your Wallet screen.\n"
13 + },
14 + {
15 + "question" : "What do \"seed\" and \"keys\" mean?",
16 + "answer" : "Your keys encode the private information in your wallet, and are what allow you to spend coins and see incoming transactions.\nYour seed is just a version of your private key written in a way that’s easier for you to write down. Your seed and keys are actually the same thing, just in different forms!\nDO NOT ever give your seed or keys to anyone. Your funds will be stolen if you give out your seed or keys. Please write down your seed, however, and store it in a safe place (this will allow you to restore your wallet if you lose your phone.)\n"
17 + },
18 + {
19 + "question" : "How many wallets can I create?",
20 + "answer" : "There is no limit! You can create as many wallets as you want.\n"
21 + },
22 + {
23 + "question" : "How can I restore my wallet?",
24 + "answer" : "Tap the ••• menu, select Wallets, and then choose Restore Wallet. Then enter your seed (or your keys), and optionally enter a date before the first transaction in your wallet (this will speed up the syncing process.) You may need to keep the app open for 15-30 minutes in order to completely restore your wallet.\n"
25 + },
26 + {
27 + "question" : "What can I do if I lose my seed?",
28 + "answer" : "If you forgot your seed, you likely wrote it down somewhere. Please check your notes and look around on your computer. If you can’t find it anywhere, you may have backed up Cake Wallet (in which case you would be able to restore from that backup.) If none of these work, there is unfortunately nothing that we can do.\n"
29 + },
30 + {
31 + "question" : "Do you collect any information about my wallet?",
32 + "answer" : "Cake Wallet DOES NOT collect or record any information about your wallet. We care about your privacy.\n"
33 + },
34 + {
35 + "question" : "Is it possible to reverse a transaction?",
36 + "answer" : "Unfortunately, as soon as a transaction has been submitted to the blockchain, there is no way to undo it. You can always cancel the transaction before it’s sent though, so always double-check the address before you send a transaction.\n"
37 + },
38 + {
39 + "question" : "What are subaddresses, and how do I use them?",
40 + "answer" : "A subaddress is basically a unique address that you can generate at any time. Coins sent to it will still arrive in your main wallet, but the person sending the coins can’t tell what your main address is. Subaddresses always start with 8.\nYou can make a new subaddress in the Receive screen by tapping the + next to the Subaddresses button. Enter a name for the subaddress and tap Add. Then just tap on the subaddress name when you want to use it!\nIf you’re paranoid, you should probably create a new subaddress every time you receive Monero.\n"
41 + },
42 + {
43 + "question" : "What is a transaction ID?",
44 + "answer" : "A transaction hash, or transaction ID, is a unique way to identify any transaction. Each transaction has its own hash. If you need to provide a transaction hash to somebody, just go to the main Wallet screen, tap on the transaction, long-press on the top section, and select Copy.\n"
45 + },
46 + {
47 + "question" : "I didn't receive my XMR! What can I do?",
48 + "answer" : "If you didn't receive your Monero, you might want to tap the ••• menu and hit Reconnect. If that doesn't work, go into the settings menu, tap the 'Current Node' box, and select a node with a green dot next to it.\n"
49 + },
50 + {
51 + "question" : "I didn't receive my coins from the exchange in the app. What can I do?",
52 + "answer" : "If you're having issues with an exchange, the best option is to contact the exchange itself. We're partnered with XMR.TO, Morph and ChangeNow, so your best bet is to go to http://xmr.to, http://changenow.io, or http://morphtoken.com and contact their support.\n"
53 + },
54 + {
55 + "question" : "How do I contact Cake Wallet support?",
56 + "answer" : "Email support@cakewallet.io, join the Telegram at @cake_wallet, or tweet @CakeWalletXMR!\n"
57 + }
58 +]
\ No newline at end of file
assets/faq/faq_es.json new
+58
@@ -0,0 +1,58 @@
1 +[
2 + {
3 + "question" : "¿Cuál es la diferencia entre el saldo disponible y el saldo total?",
4 + "answer" : "Después de realizar una transacción o recibir algo de Monero, la transacción aún debe confirmarse. ¡En unos 20 minutos su \"saldo disponible\" debería actualizarse!\nA veces, cuando envía Monero, su saldo disponible disminuirá en más de la cantidad que envió. Esto es normal y es necesario para proteger su privacidad. Su \"saldo total\" debería volver a la normalidad en 20 minutos.\n"
5 + },
6 + {
7 + "question" : "¿Cómo envío a Monero a un intercambio que requiere una ID de pago?",
8 + "answer" : "Toque el botón \"enviar\" en la pantalla de Wallet. A continuación, copie la dirección de depósito del intercambio y péguela en el cuadro \"dirección\". Luego, copie la ID de pago proporcionada por el intercambio y péguela en el cuadro de ID de pago. Finalmente, ingrese la cantidad que desea enviar, ¡y listo!\n"
9 + },
10 + {
11 + "question" : "¿Qué debo hacer si olvidé ingresar la ID de pago al enviar Monero a un intercambio?",
12 + "answer" : "Si bien nuestro soporte no puede ayudarlo directamente con este problema, es un problema muy común que la mayoría de los intercambios están acostumbrados a resolver. Simplemente comuníquese con el soporte del intercambio, explique que olvidó incluir su ID de pago y luego envíeles su ID de transacción como prueba. Puede encontrar la ID de la transacción tocando la transacción en la pantalla de su billetera.\n"
13 + },
14 + {
15 + "question" : "¿Qué significan \"semilla\" y \"claves\"?",
16 + "answer" : "Sus claves codifican la información privada en su billetera y son las que le permiten gastar monedas y ver las transacciones entrantes.\nSu semilla es solo una versión de su clave privada escrita de una manera que le resulta más fácil de anotar. ¡Tu semilla y tus llaves son en realidad la misma cosa, solo que en diferentes formas!\nNunca le des tu semilla o llaves a nadie. Sus fondos serán robados si entrega su semilla o llaves. Sin embargo, escriba su semilla y guárdela en un lugar seguro (esto le permitirá restaurar su billetera si pierde su teléfono).\n"
17 + },
18 + {
19 + "question" : "¿Cuántas billeteras puedo crear?",
20 + "answer" : "¡No hay límite! Puede crear tantas billeteras como desee.\n"
21 + },
22 + {
23 + "question" : "¿Cómo puedo restaurar mi billetera?",
24 + "answer" : "Toque el menú •••, seleccione \"Carteras\", y luego elija \"Restaurar billetera\". Luego ingrese su semilla (o sus claves), y opcionalmente ingrese una fecha antes de la primera transacción en su billetera (esto acelerará el proceso de sincronización .) Es posible que deba mantener la aplicación abierta durante 15-30 minutos para restaurar completamente su billetera.\n"
25 + },
26 + {
27 + "question" : "¿Qué puedo hacer si pierdo mi semilla?",
28 + "answer" : "Si olvidó su semilla, probablemente la escribió en alguna parte. Verifique sus notas y mire a su alrededor en su computadora. Si no puede encontrarlo en ninguna parte, es posible que haya realizado una copia de seguridad de Cake Wallet (en cuyo caso podría restaurar desde esa copia de seguridad). Si ninguno de estos funciona, desafortunadamente no hay nada que podamos hacer.\n"
29 + },
30 + {
31 + "question" : "¿Recopila información sobre mi billetera?",
32 + "answer" : "Cake Wallet NO recopila ni registra ninguna información sobre su billetera. Nos preocupamos por su privacidad.\n"
33 + },
34 + {
35 + "question" : "¿Es posible revertir una transacción?",
36 + "answer" : "Desafortunadamente, tan pronto como se haya enviado una transacción a la cadena de bloques, no hay forma de deshacerla. Sin embargo, siempre puede cancelar la transacción antes de enviarla, así que siempre verifique la dirección antes de enviar una transacción.\n"
37 + },
38 + {
39 + "question" : "¿Qué son las \"subdirecciones\" y cómo las uso?",
40 + "answer" : "Una subdirección es básicamente una dirección única que puede generar en cualquier momento. Las monedas que se le envíen seguirán llegando a su billetera principal, pero la persona que envía las monedas no puede decir cuál es su dirección principal. Las subdirecciones siempre comienzan con \"8\".\nPuede hacer una nueva subdirección en la pantalla Recibir tocando el \"+\" al lado del botón Subdirecciones. Ingrese un nombre para la subdirección y toque “Agregar”. Luego, solo toca el nombre de la subdirección cuando quieras usarlo.\nSi eres paranoico, probablemente deberías crear una nueva subdirección cada vez que recibas Monero.\n"
41 + },
42 + {
43 + "question" : "¿Qué es una ID de transacción?",
44 + "answer" : "Un hash de transacción, o ID de transacción, es una forma única de identificar cualquier transacción. Cada transacción tiene su propio hash. Si necesita proporcionar un hash de transacción a alguien, simplemente vaya a la pantalla principal de Wallet, toque la transacción, mantenga presionada la sección superior y seleccione Copiar.\n"
45 + },
46 + {
47 + "question" : "¡No recibí mi XMR! ¿Que puedo hacer?",
48 + "answer" : "Si no recibió su Monero, puede tocar el menú ••• y presionar Volver a conectar. Si eso no funciona, vaya al menú de configuración, toque el cuadro 'Nodo actual' y seleccione un nodo con un punto verde al lado.\n"
49 + },
50 + {
51 + "question" : "No recibí mis monedas del intercambio en la aplicación. ¿Que puedo hacer?",
52 + "answer" : "Si tiene problemas con un intercambio, la mejor opción es ponerse en contacto con el intercambio en sí. Estamos asociados con XMR.TO, Morph y ChangeNow, por lo que su mejor opción es ir a http://xmr.to, http://changenow.io o http://morphtoken.com y contactar a su soporte.\n"
53 + },
54 + {
55 + "question" : "¿Cómo contacto al soporte de Cake Wallet?",
56 + "answer" : "¡Envíe un correo electrónico a support@cakewallet.io, únase al Telegram en @cake_wallet o envíe un tweet a @CakeWalletXMR!\n"
57 + }
58 +]
\ No newline at end of file
assets/faq/faq_hi.json new
+58
@@ -0,0 +1,58 @@
1 +[
2 + {
3 + "question" : "उपलब्ध शेष और पूर्ण शेष के बीच क्या अंतर है?",
4 + "answer" : "आपके द्वारा लेन-देन करने या कुछ मोनरो प्राप्त करने के बाद, लेन-देन की पुष्टि करने की आवश्यकता है। लगभग 20 मिनट में आपका \"उपलब्ध शेष\" अपडेट होना चाहिए!\nकभी-कभी, जब आप Monero भेजते हैं, तो आपका उपलब्ध शेष राशि आपके द्वारा भेजी गई राशि से अधिक घट जाएगी। यह सामान्य है, और आपकी गोपनीयता की सुरक्षा के लिए यह आवश्यक है। आपका \"पूर्ण संतुलन\" 20 मिनट में वापस सामान्य हो जाना चाहिए।\n"
5 + },
6 + {
7 + "question" : "मैं एक एक्सचेंज को एक भुगतान आईडी के लिए मोनेरो को कैसे भेजूं?",
8 + "answer" : "वॉलेट स्क्रीन पर \"भेजें\" बटन पर टैप करें। इसके बाद, एक्सचेंज के जमा पते को कॉपी करें और इसे \"एड्रेस\" बॉक्स में पेस्ट करें। फिर, एक्सचेंज द्वारा प्रदान की गई भुगतान आईडी को कॉपी करें और भुगतान आईडी बॉक्स में पेस्ट करें। अंत में, वह राशि दर्ज करें जिसे आप भेजना चाहते हैं, और आप जाना चाहते हैं!\n"
9 + },
10 + {
11 + "question" : "यदि मैं एक मुद्रा में मोनरो भेजते समय भुगतान आईडी दर्ज करना भूल गया तो मैं क्या करूँ?",
12 + "answer" : "जबकि हमारा समर्थन सीधे इस मुद्दे पर आपकी सहायता नहीं कर सकता है, यह एक बहुत ही आम समस्या है जिससे निपटने के लिए ज्यादातर एक्सचेंजों का उपयोग किया जाता है। एक्सचेंज के समर्थन से संपर्क करें, समझाएं कि आप अपनी भुगतान आईडी को शामिल करना भूल गए हैं, और फिर उन्हें प्रमाण के रूप में अपनी लेन-देन आईडी भेजें। आप अपने वॉलेट स्क्रीन में लेनदेन पर टैप करके ट्रांजेक्शन आईडी पा सकते हैं।\n"
13 + },
14 + {
15 + "question" : "\"बीज\" और \"कुंजियाँ\" का क्या अर्थ है?",
16 + "answer" : "आपकी कुंजी आपके बटुए में निजी जानकारी को कूटबद्ध करती है, और जो आपको सिक्के खर्च करने और आने वाले लेनदेन को देखने की अनुमति देती है।\nआपका बीज आपकी निजी कुंजी का एक संस्करण है जो इस तरह से लिखा गया है कि आपको लिखना आसान है। आपके बीज और चाबियाँ वास्तव में एक ही चीज़ हैं, बस अलग-अलग रूपों में!\nकभी भी अपना बीज या चाबी किसी को न दें। यदि आप अपना बीज या चाबियां देते हैं तो आपके धन की चोरी हो जाएगी। कृपया, अपने बीज को नीचे लिखें, और इसे एक सुरक्षित स्थान पर संग्रहीत करें (यदि आप अपना फोन खो देते हैं तो यह आपको अपने बटुए को पुनर्स्थापित करने की अनुमति देगा।)\n"
17 + },
18 + {
19 + "question" : "मैं कितने वॉलेट बना सकता हूं?",
20 + "answer" : "कोई सीमा नही है! आप जितने चाहें उतने पर्स बना सकते हैं।\n"
21 + },
22 + {
23 + "question" : "मैं अपना बटुआ कैसे पुनर्स्थापित कर सकता हूं?",
24 + "answer" : "••• मेनू पर टैप करें, \"वॉलेट्स\" चुनें, और फिर \"रिस्टोर वॉलेट\" चुनें। फिर अपना बीज (या अपनी चाबियाँ) दर्ज करें, और वैकल्पिक रूप से अपने वॉलेट में पहले लेनदेन से पहले एक तिथि दर्ज करें (यह सिंकिंग प्रक्रिया को गति देगा। ।) आपको अपने वॉलेट को पूरी तरह से बहाल करने के लिए ऐप को 15-30 मिनट तक खुला रखने की आवश्यकता हो सकती है।\n"
25 + },
26 + {
27 + "question" : "अगर मैं अपना बीज खो देता हूं तो मैं क्या कर सकता हूं?",
28 + "answer" : "यदि आप अपना बीज भूल गए हैं, तो आप इसे कहीं न कहीं लिख सकते हैं। कृपया अपने नोट्स देखें और अपने कंप्यूटर पर देखें। यदि आप इसे कहीं भी नहीं पा सकते हैं, तो आपने केक वॉलेट का बैकअप ले लिया होगा (जिस स्थिति में आप उस बैकअप से पुनर्स्थापित कर पाएंगे।) यदि इनमें से कोई भी काम नहीं है, तो दुर्भाग्य से ऐसा कुछ भी नहीं है जो हम कर सकते हैं।\n"
29 + },
30 + {
31 + "question" : "क्या आप मेरे बटुए के बारे में कोई जानकारी एकत्र करते हैं?",
32 + "answer" : "केक वॉलेट आपके बटुए के बारे में कोई जानकारी एकत्र या रिकॉर्ड नहीं करता है। हमें आपकी गोपनीयता का ख्याल है।\n"
33 + },
34 + {
35 + "question" : "क्या किसी लेनदेन को उल्टा करना संभव है?",
36 + "answer" : "दुर्भाग्य से, जैसे ही एक लेन-देन ब्लॉकचैन को सबमिट किया गया है, इसे पूर्ववत करने का कोई तरीका नहीं है। आप इसे भेजे जाने से पहले लेनदेन को हमेशा रद्द कर सकते हैं, इसलिए लेन-देन भेजने से पहले हमेशा पते की दोबारा जांच करें।\n"
37 + },
38 + {
39 + "question" : "\"उप-प्रजातियां\" क्या हैं, और मैं उनका उपयोग कैसे करूं?",
40 + "answer" : "एक सबड्रेस मूल रूप से एक अनूठा पता है जिसे आप किसी भी समय उत्पन्न कर सकते हैं। इसके लिए भेजे गए सिक्के अभी भी आपके मुख्य वॉलेट में आएंगे, लेकिन सिक्के भेजने वाला व्यक्ति यह नहीं बता सकता है कि आपका मुख्य पता क्या है। Subaddresses हमेशा \"8\" से शुरू होता है।\nआप Subaddresses बटन के बगल में \"+\" टैप करके प्राप्त स्क्रीन में एक नई उप-प्रसंग बना सकते हैं। सबड्रेस के लिए एक नाम दर्ज करें और \"जोड़ें\" पर टैप करें। फिर जब आप इसका उपयोग करना चाहते हैं तो बस सबड्रेस नाम पर टैप करें!\nयदि आप अपाहिज हैं, तो आपको हर बार मोनरो प्राप्त करने के लिए एक नया सबड्रेस बनाना चाहिए।\n"
41 + },
42 + {
43 + "question" : "लेनदेन आईडी क्या है?",
44 + "answer" : "लेन-देन हैश, या लेनदेन आईडी, किसी भी लेनदेन की पहचान करने का एक अनूठा तरीका है। प्रत्येक लेनदेन का अपना हैश होता है। यदि आपको किसी को लेन-देन हैश प्रदान करने की आवश्यकता है, तो बस मुख्य वॉलेट स्क्रीन पर जाएं, लेन-देन पर टैप करें, शीर्ष अनुभाग पर लंबे समय तक दबाएं और प्रतिलिपि का चयन करें।\n"
45 + },
46 + {
47 + "question" : "मैं अपने XMR प्राप्त नहीं किया! मैं क्या कर सकता हूँ?",
48 + "answer" : "यदि आपको अपना मोनरो प्राप्त नहीं हुआ, तो आप ••• मेनू पर टैप कर सकते हैं और रीकनेक्ट को हिट कर सकते हैं। यदि वह काम नहीं करता है, तो सेटिंग मेनू में जाएं, 'करंट नोड' बॉक्स पर टैप करें, और उसके बगल में हरे रंग की डॉट के साथ एक नोड चुनें।\n"
49 + },
50 + {
51 + "question" : "मुझे ऐप में एक्सचेंज से मेरे सिक्के नहीं मिले। मैं क्या कर सकता हूँ?",
52 + "answer" : "यदि आप एक एक्सचेंज के साथ समस्या कर रहे हैं, तो सबसे अच्छा विकल्प एक्सचेंज से संपर्क करना है। हम XMR.TO, Morph और ChangeNow के साथ भागीदारी कर रहे हैं, इसलिए आपका सबसे अच्छा दांव http://xmr.to, http://changenow.io, या http://morphtoken.com पर जाना है और उनके समर्थन से संपर्क करना है।\n"
53 + },
54 + {
55 + "question" : "मैं केक वॉलेट से कैसे संपर्क करूं?",
56 + "answer" : "ईमेल support@cakewallet.io, @cake_wallet पर टेलीग्राम में शामिल हों, या @CakeWalletXMR पर ट्वीट करें!\n"
57 + }
58 +]
\ No newline at end of file
assets/faq/faq_ja.json new
+58
@@ -0,0 +1,58 @@
1 +[
2 + {
3 + "question" : "Available BalanceとFull Balanceの違いは何ですか?",
4 + "answer" : "取引を行うか、Moneroを受け取った後でも、取引を確認する必要があります。 約20分で「利用可能残高」が更新されます!\nMoneroを送信すると、利用可能な残高が送信した金額よりも少なくなる場合があります。 これは正常な動作であり、プライバシーを保護するために必要です。 「フルバランス」は20分で通常に戻ります。\n"
5 + },
6 + {
7 + "question" : "支払いIDが必要な取引所にMoneroを送信するにはどうすればよいですか?",
8 + "answer" : "ウォレット画面の「送信」ボタンをタップします。 次に、取引所のデポジットアドレスをコピーして、「アドレス」ボックスに貼り付けます。 次に、取引所から提供された支払いIDをコピーして、[支払いID]ボックスに貼り付けます。 最後に、送信したい金額を入力すると、準備完了です!\n"
9 + },
10 + {
11 + "question" : "Moneroを取引所に送信するときに支払いIDの入力を忘れた場合はどうすればよいですか?",
12 + "answer" : "のサポートはこの問題を直接支援することはできませんが、ほとんどの取引所が対処に慣れている非常に一般的な問題です。交換サポートに連絡し、支払いIDを含めるのを忘れたことを説明してから、証拠としてトランザクションIDを送信してください。ウォレット画面でトランザクションをタップすると、トランザクションIDを見つけることができます。\n"
13 + },
14 + {
15 + "question" : "「シード」と「キー」はどういう意味ですか?",
16 + "answer" : "キーはウォレットの個人情報をエンコードし、コインを使って着信トランザクションを確認できるようにします。\nシードは、書きやすいように書かれた秘密鍵の単なるバージョンです。 シードとキーは実際には同じもので、異なる形式になっています!\nシードやキーを誰にも渡さないでください。 シードまたはキーを渡すと、資金が盗まれます。 ただし、シードを書き留めて安全な場所に保管してください(これにより、携帯電話を紛失した場合にウォレットを復元できます。\n"
17 + },
18 + {
19 + "question" : "いくつのウォレットを作成できますか?",
20 + "answer" : "制限はありません! ウォレットはいくつでも作成できます。\n"
21 + },
22 + {
23 + "question" : "ウォレットを復元するにはどうすればよいですか?",
24 + "answer" : "•••メニューをタップし、「ウォレット」を選択し、「ウォレットの復元」を選択します。次に、シード(またはキー)を入力し、オプションでウォレットの最初のトランザクションの前に日付を入力します(これにより同期プロセスが高速化されます) 。)ウォレットを完全に復元するには、アプリを15〜30分間開いたままにする必要がある場合があります。\n"
25 + },
26 + {
27 + "question" : "種を失ったらどうすればいいですか?",
28 + "answer" : "種を忘れた場合は、どこかに書き留めている可能性があります。 のメモを確認して、コンピューターを見てください。 どこにも見つからない場合は、Cake Walletをバックアップしている可能性があります(この場合、そのバックアップから復元できます)。これらのいずれも機能しない場合、残念ながら何もできません。\n"
29 + },
30 + {
31 + "question" : "ウォレットに関する情報を収集しますか?",
32 + "answer" : "Cake Walletは、ウォレットに関する情報を収集または記録しません。 私たちはあなたのプライバシーを大切にします。\n"
33 + },
34 + {
35 + "question" : "トランザクションを取り消すことは可能ですか?",
36 + "answer" : "残念ながら、トランザクションがブロックチェーンに送信されるとすぐに、元に戻す方法はありません。 ただし、トランザクションは送信前にいつでもキャンセルできます。したがって、トランザクションを送信する前に必ずアドレスを再確認してください。\n"
37 + },
38 + {
39 + "question" : "「サブアドレス」とは何ですか。どのように使用しますか?",
40 + "answer" : "サブアドレスは基本的に、いつでも生成できる一意のアドレスです。 送られたコインはメインのウォレットに届きますが、コインを送った人はメインの住所を知ることができません。 サブアドレスは常に「8」で始まります。\n[サブアドレス]ボタンの横にある[+]をタップすると、受信画面で新しいサブアドレスを作成できます。 サブアドレスの名前を入力し、「追加」をタップします。 次に、使用したいサブアドレス名をタップします!\n妄想している場合は、Moneroを受信するたびに新しいサブアドレスを作成する必要があります。\n"
41 + },
42 + {
43 + "question" : "トランザクションIDとは何ですか?",
44 + "answer" : "トランザクションハッシュ、またはトランザクションIDは、トランザクションを識別するユニークな方法です。 各トランザクションには独自のハッシュがあります。 誰かにトランザクションハッシュを提供する必要がある場合は、ウォレットのメイン画面に移動し、トランザクションをタップして、上部セクションを長押しし、[コピー]を選択します。\n"
45 + },
46 + {
47 + "question" : "XMRを受け取りませんでした! 私に何ができる?",
48 + "answer" : "Moneroを受け取っていない場合は、•••メニューをタップして、[再接続]を押します。 それでもうまくいかない場合は、設定メニューに移動し、「現在のノード」ボックスをタップして、横に緑色の点があるノードを選択します。\n"
49 + },
50 + {
51 + "question" : "アプリの取引所からコインを受け取りませんでした。 私に何ができる?",
52 + "answer" : "取引所に問題がある場合、最良の選択肢は取引所自体に連絡することです。 XMR.TO、Morph、ChangeNowと提携しているため、最善の策はhttp://xmr.to、http://changenow.io、またはhttp://morphtoken.comにアクセスしてサポートに連絡することです。\n"
53 + },
54 + {
55 + "question" : "Cake Walletサポートに連絡するにはどうすればよいですか?",
56 + "answer" : "support@cakewallet.ioにメールを送信するか、@ cake_walletで電報に参加するか、@ CakeWalletXMRにツイートしてください。\n"
57 + }
58 +]
\ No newline at end of file
assets/faq/faq_ko.json new
+58
@@ -0,0 +1,58 @@
1 +[
2 + {
3 + "question" : "가용 잔액과 전체 잔액의 차이점은 무엇입니까?",
4 + "answer" : "거래를하거나 일부 Monero를받은 후에도 거래를 확인해야합니다. 약 20 분 후에“사용 가능한 잔액”이 업데이트됩니다!\n때로는 Monero를 보낼 때 사용 가능한 잔액이 보낸 금액보다 많이 줄어 듭니다. 이는 정상적인 현상이며 개인 정보를 보호하기 위해 필요합니다. \"풀 밸런스\"는 20 분 후에 정상으로 돌아옵니다.\n"
5 + },
6 + {
7 + "question" : "지불 ID가 필요한 거래소에 Monero를 보내려면 어떻게해야합니까?",
8 + "answer" : "월렛 화면에서 \"보내기\"버튼을 누릅니다. 그런 다음 교환기 예금 주소를 복사하여 \"주소\"상자에 붙여 넣습니다. 그런 다음 교환에서 제공 한 지불 ID를 복사하여 지불 ID 상자에 붙여 넣으십시오. 마지막으로 송금 할 금액을 입력하면 좋습니다.\n"
9 + },
10 + {
11 + "question" : "Monero를 교환소에 보낼 때 지불 ID를 입력하지 않은 경우 어떻게해야합니까?",
12 + "answer" : "의 지원으로이 문제를 직접 해결할 수는 없지만 대부분의 거래소에서 처리하는 데 매우 일반적인 문제입니다. 거래소의 지원팀에 연락하여 결제 ID를 잊어 버렸다고 설명하고 거래 ID를 증거로 보내십시오. 월렛 화면에서 거래를 탭하여 거래 ID를 찾을 수 있습니다.\n"
13 + },
14 + {
15 + "question" : "\"씨\"와 \"키\"는 무엇을 의미합니까?",
16 + "answer" : "열쇠는 지갑에 개인 정보를 암호화하여 동전을 사용하고 들어오는 거래를 볼 수있게 해줍니다.\n귀하의 시드는 귀하가 쉽게 기록 할 수있는 방식으로 작성된 개인 키 버전입니다. 당신의 씨앗과 열쇠는 실제로는 다른 형태로 동일합니다!\n씨앗이나 열쇠를 다른 사람에게주지 마십시오. 씨앗이나 열쇠를 내면 자금이 도용됩니다. 그러나 씨앗을 기록하여 안전한 곳에 보관하십시오 (휴대 전화를 분실 한 경우 지갑을 복원 할 수 있습니다).\n"
17 + },
18 + {
19 + "question" : "몇 개의 지갑을 만들 수 있습니까?",
20 + "answer" : "제한이 없습니다! 원하는만큼 지갑을 만들 수 있습니다.\n"
21 + },
22 + {
23 + "question" : "지갑을 어떻게 복원 할 수 있습니까?",
24 + "answer" : "••• 메뉴를 탭하고 \"월렛\"을 선택한 다음 \"지갑 복원\"을 선택하십시오. 그런 다음 시드 (또는 키)를 입력하고 선택적으로 지갑의 첫 거래 전에 날짜를 입력하십시오 (동기화 속도가 빨라집니다) .) 지갑을 완전히 복원하려면 앱을 15-30 분 동안 열어 두어야합니다.\n"
25 + },
26 + {
27 + "question" : "씨앗을 잃어 버리면 어떻게해야합니까?",
28 + "answer" : "씨앗을 잊어 버렸다면 아마 어딘가에 썼을 것입니다. 메모를 확인하고 컴퓨터를 둘러보십시오. 어디에서나 찾을 수 없다면 Cake Wallet을 백업했을 수 있습니다 (이 경우 해당 백업에서 복원 할 수 있습니다). 이러한 작업이 없으면 불행히도 우리가 할 수있는 일이 없습니다.\n"
29 + },
30 + {
31 + "question" : "내 지갑에 대한 정보를 수집합니까?",
32 + "answer" : "케이크 지갑은 지갑에 대한 정보를 수집하거나 기록하지 않습니다. 우리는 당신의 프라이버시를 걱정합니다.\n"
33 + },
34 + {
35 + "question" : "거래를 취소 할 수 있습니까?",
36 + "answer" : "불행히도, 거래가 블록 체인에 제출 되 자마자 취소 할 수있는 방법이 없습니다. 거래가 전송되기 전에 언제든지 취소 할 수 있으므로 거래를 보내기 전에 항상 주소를 다시 확인하십시오.\n"
37 + },
38 + {
39 + "question" : "하위 주소 란 무엇이며 어떻게 사용합니까?",
40 + "answer" : "하위 주소는 기본적으로 언제든지 생성 할 수있는 고유 한 주소입니다. 동전은 여전히 주 지갑에 도착하지만 동전을 보낸 사람은 자신의 주 주소가 무엇인지 알 수 없습니다. 하위 주소는 항상 \"8\"로 시작합니다.\n하위 주소 버튼 옆에있는 \"+\"를 누르면 수신 화면에서 새 하위 주소를 만들 수 있습니다. 하위 주소의 이름을 입력하고 \"추가\"를 누릅니다. 그런 다음 사용하려는 하위 주소 이름을 탭하십시오!\n편집증이라면 Monero를받을 때마다 새 하위 주소를 만들어야합니다.\n"
41 + },
42 + {
43 + "question" : "거래 ID는 무엇입니까?",
44 + "answer" : "트랜잭션 해시 또는 트랜잭션 ID는 트랜잭션을 식별하는 고유 한 방법입니다. 각 트랜잭션에는 자체 해시가 있습니다. 누군가에게 거래 해시를 제공해야하는 경우 주 지갑 화면으로 이동하여 거래를 탭하고 상단 섹션을 길게 누른 다음 복사를 선택하십시오.\n"
45 + },
46 + {
47 + "question" : "XMR을받지 못했습니다! 내가 무엇을 할 수 있을지?",
48 + "answer" : "Monero를받지 못했다면 ••• 메뉴를 누르고 다시 연결을 누르십시오. 그래도 작동하지 않으면 설정 메뉴로 이동하여 '현재 노드'상자를 누르고 옆에 녹색 점이있는 노드를 선택하십시오.\n"
49 + },
50 + {
51 + "question" : "앱의 거래소에서 동전을받지 못했습니다. 내가 무엇을 할 수 있을지?",
52 + "answer" : "교환에 문제가있는 경우 교환기에 연락하는 것이 가장 좋습니다. 우리는 XMR.TO, Morph 및 ChangeNow와 파트너 관계를 맺고 있으므로 가장 좋은 방법은 http://xmr.to, http://changenow.io 또는 http://morphtoken.com으로 이동하여 지원 부서에 문의하는 것입니다.\n"
53 + },
54 + {
55 + "question" : "Cake Wallet 지원팀에 연락하려면 어떻게해야합니까?",
56 + "answer" : "support@cakewallet.io로 이메일을 보내거나 @cake_wallet에서 전보에 가입하거나 @CakeWalletXMR을 트윗하십시오!\n"
57 + }
58 +]
\ No newline at end of file
assets/faq/faq_nl.json new
+58
@@ -0,0 +1,58 @@
1 +[
2 + {
3 + "question" : "Wat is het verschil tussen beschikbaar saldo en volledig saldo?",
4 + "answer" : "Nadat u een transactie heeft uitgevoerd of wat Monero heeft ontvangen, moet de transactie nog worden bevestigd. Over ongeveer 20 minuten zou uw \"beschikbare saldo\" moeten zijn bijgewerkt!\nWanneer u Monero verzendt, daalt uw beschikbare saldo soms met meer dan het bedrag dat u heeft verzonden. Dit is normaal en dit is noodzakelijk om uw privacy te beschermen. Uw \"volledige balans\" zou binnen 20 minuten weer normaal moeten zijn.\n"
5 + },
6 + {
7 + "question" : "Hoe stuur ik Monero naar een beurs die een betalings-ID vereist?",
8 + "answer" : "Tik op de knop \"Verzenden\" op het Wallet-scherm. Kopieer vervolgens het stortingsadres van de uitwisseling en plak het in het vak \"adres\". Kopieer vervolgens de betalings-ID van de centrale en plak deze in het vak Betalings-ID. Voer ten slotte het bedrag in dat u wilt verzenden en u bent klaar om te gaan!\n"
9 + },
10 + {
11 + "question" : "Wat moet ik doen als ik ben vergeten de betalings-ID in te voeren wanneer ik Monero naar een beurs stuur?",
12 + "answer" : "Hoewel onze ondersteuning u niet rechtstreeks met dit probleem kan helpen, is het een veel voorkomend probleem dat de meeste beurzen gewend zijn aan te pakken. Neem contact op met de ondersteuning van de beurs, leg uit dat u bent vergeten uw betalings-ID op te nemen en stuur ze vervolgens uw transactie-ID als bewijs. U kunt de transactie-ID vinden door op de transactie in uw Wallet-scherm te tikken.\n"
13 + },
14 + {
15 + "question" : "Wat betekenen zaad en sleutels?",
16 + "answer" : "Uw sleutels coderen de privé-informatie in uw portemonnee en stellen u in staat munten uit te geven en inkomende transacties te bekijken.\nUw seed is slechts een versie van uw privésleutel die zo is geschreven dat u deze gemakkelijker kunt opschrijven. Je zaad en sleutels zijn eigenlijk hetzelfde, alleen in verschillende vormen!\nGeef NOOIT uw zaad of sleutels aan iemand. Je geld wordt gestolen als je je zaad of sleutels weggeeft. Schrijf uw zaad echter op en bewaar het op een veilige plaats (hiermee kunt u uw portemonnee herstellen als u uw telefoon verliest.)\n"
17 + },
18 + {
19 + "question" : "Hoeveel portefeuilles kan ik maken?",
20 + "answer" : "Er is geen limiet! U kunt zoveel portefeuilles maken als u wilt.\n"
21 + },
22 + {
23 + "question" : "Hoe kan ik mijn portemonnee herstellen?",
24 + "answer" : "Tik op het ••• menu, selecteer \"Portefeuilles\" en kies vervolgens \"Portemonnee herstellen\". Voer vervolgens uw seed (of uw sleutels) in en voer optioneel een datum in vóór de eerste transactie in uw portefeuille (dit versnelt het synchronisatieproces .) Mogelijk moet u de app 15-30 minuten open houden om uw portemonnee volledig te herstellen.\n"
25 + },
26 + {
27 + "question" : "Wat kan ik doen als ik mijn zaad verlies?",
28 + "answer" : "Als je je zaad bent vergeten, heb je het waarschijnlijk ergens opgeschreven. Controleer uw aantekeningen en kijk rond op uw computer. Als je het nergens kunt vinden, heb je misschien een back-up gemaakt van Cake Wallet (in welk geval je in staat zou zijn om vanuit die back-up te herstellen.) Als geen van deze werken, kunnen we helaas niets doen.\n"
29 + },
30 + {
31 + "question" : "Verzamel je informatie over mijn portemonnee?",
32 + "answer" : "Cake Wallet verzamelt of registreert GEEN informatie over uw portemonnee. Wij geven om uw privacy.\n"
33 + },
34 + {
35 + "question" : "Is het mogelijk om een transactie ongedaan te maken?",
36 + "answer" : "Helaas is het niet mogelijk om een transactie ongedaan te maken zodra een transactie bij de blockchain is ingediend. U kunt de transactie echter altijd annuleren voordat deze wordt verzonden, dus controleer altijd het adres voordat u een transactie verzendt.\n"
37 + },
38 + {
39 + "question" : "Wat zijn \"subadressen\" en hoe gebruik ik deze?",
40 + "answer" : "Een subadres is eigenlijk een uniek adres dat u op elk gewenst moment kunt genereren. Munten die er naartoe worden verzonden, komen nog steeds in uw hoofdportemonnee, maar de persoon die de munten verzendt, kan niet zien wat uw hoofdadres is. Subadressen beginnen altijd met \"8\".\nU kunt een nieuw subadres maken in het scherm Ontvangen door te tikken op de \"+\" naast de knop Subadressen. Voer een naam in voor het subadres en tik op \"Toevoegen\". Tik vervolgens op de naam van het subadres wanneer u deze wilt gebruiken!\nAls u paranoïde bent, moet u waarschijnlijk elke keer dat u Monero ontvangt een nieuw subadres maken.\n"
41 + },
42 + {
43 + "question" : "Wat is een transactie-ID?",
44 + "answer" : "Een transactie-hash of transactie-ID is een unieke manier om een transactie te identificeren. Elke transactie heeft zijn eigen hash. Als u iemand een transactie-hash moet geven, gaat u gewoon naar het hoofdscherm van Wallet, tikt u op de transactie, drukt u lang op het bovenste gedeelte en selecteert u Kopiëren.\n"
45 + },
46 + {
47 + "question" : "Ik heb mijn XMR niet ontvangen! Wat kan ik doen?",
48 + "answer" : "Als u uw Monero niet hebt ontvangen, wilt u misschien op het ••• menu tikken en op Opnieuw verbinden klikken. Als dat niet werkt, gaat u naar het instellingenmenu, tikt u op het vak 'Huidige knooppunt' en selecteert u een knooppunt met een groene stip ernaast.\n"
49 + },
50 + {
51 + "question" : "Ik heb mijn munten niet ontvangen van de beurs in de app. Wat kan ik doen?",
52 + "answer" : "Als u problemen ondervindt met een uitwisseling, kunt u het beste contact opnemen met de uitwisseling zelf. We werken samen met XMR.TO, Morph en ChangeNow, dus u kunt het beste naar http://xmr.to, http://changenow.io of http://morphtoken.com gaan en contact opnemen met hun ondersteuning.\n"
53 + },
54 + {
55 + "question" : "Hoe neem ik contact op met Cake Wallet-ondersteuning?",
56 + "answer" : "E-mail support@cakewallet.io, word lid van het Telegram op @cake_wallet of tweet @CakeWalletXMR!\n"
57 + }
58 +]
\ No newline at end of file
assets/faq/faq_pl.json new
+58
@@ -0,0 +1,58 @@
1 +[
2 + {
3 + "question" : "Jaka jest różnica między dostępnym saldem a pełnym saldem?",
4 + "answer" : "Po dokonaniu transakcji lub otrzymaniu Monero transakcja nadal musi zostać potwierdzona. Za około 20 minut Twoje „dostępne saldo” powinno się zaktualizować!\nCzasami po wysłaniu Monero dostępne saldo zmniejsza się o więcej niż kwota wysłana. Jest to normalne i konieczne w celu ochrony Twojej prywatności. Twoja „pełna równowaga” powinna wrócić do normy za 20 minut.\n"
5 + },
6 + {
7 + "question" : "Jak wysłać Monero na giełdę, która wymaga płatności ID?",
8 + "answer" : "Naciśnij przycisk „wyślij” na ekranie portfela. Następnie skopiuj adres depozytu giełdy i wklej go w polu „adres”. Następnie skopiuj identyfikator płatności podany przez giełdę i wklej go w polu ID płatności. Na koniec wprowadź kwotę, którą chcesz wysłać, i możesz zacząć!\n"
9 + },
10 + {
11 + "question" : "Co mam zrobić, jeśli zapomniałem wprowadzić ID płatności podczas wysyłania Monero na giełdę?",
12 + "answer" : "Chociaż nasze wsparcie nie może bezpośrednio pomóc w rozwiązaniu tego problemu, jest to bardzo częsty problem, z którym korzysta większość giełd. Wystarczy skontaktować się z obsługą giełdy, wyjaśnić, że zapomniałeś podać ID płatności, a następnie przesłać im dowód transakcji. Możesz znaleźć ID transakcji, dotykając transakcji na ekranie portfela.\n"
13 + },
14 + {
15 + "question" : "Co oznaczają słowa „seed” i „keys”?",
16 + "answer" : "Twoje klucze kodują prywatne informacje w twoim portfelu i pozwalają wydać monety i zobaczyć przychodzące transakcje.\nTwoje ziarno to tylko wersja twojego klucza prywatnego napisana w sposób, który łatwiej Ci zapisać. Wasze nasiona i klucze są w rzeczywistości takie same, tylko w różnych formach!\nNigdy nie dawaj nikomu swojego ziarna ani kluczy. Twoje fundusze zostaną skradzione, jeśli wydasz swoje nasiona lub klucze. Zapisz jednak swoje ziarno i przechowuj je w bezpiecznym miejscu (pozwoli to przywrócić portfel, jeśli zgubisz telefon).\n"
17 + },
18 + {
19 + "question" : "Ile portfeli mogę utworzyć?",
20 + "answer" : "Tu nie ma limitu! Możesz utworzyć dowolną liczbę portfeli.\n"
21 + },
22 + {
23 + "question" : "Jak mogę przywrócić mój portfel?",
24 + "answer" : "Stuknij menu •••, wybierz „Portfele”, a następnie „Przywróć portfel”. Następnie wprowadź dane początkowe (lub klucze) i opcjonalnie wprowadź datę przed pierwszą transakcją w portfelu (przyspieszy to proces synchronizacji .) Może być konieczne pozostawienie aplikacji otwartej przez 15-30 minut, aby całkowicie przywrócić portfel.\n"
25 + },
26 + {
27 + "question" : "Co mogę zrobić, jeśli stracę nasiona?",
28 + "answer" : "Jeśli zapomniałeś o nasieniu, prawdopodobnie gdzieś je zapisałeś. Sprawdź swoje notatki i rozejrzyj się po komputerze. Jeśli nie możesz go nigdzie znaleźć, być może utworzono kopię zapasową Cake Wallet (w takim przypadku będziesz mógł przywrócić dane z tej kopii zapasowej). Jeśli żadna z tych czynności nie działa, niestety nic nie możemy zrobić.\n"
29 + },
30 + {
31 + "question" : "Czy zbierasz jakieś informacje o moim portfelu?",
32 + "answer" : "Portfel Cake NIE gromadzi ani nie rejestruje żadnych informacji o Twoim portfelu. Dbamy o Twoją prywatność.\n"
33 + },
34 + {
35 + "question" : "Czy można cofnąć transakcję?",
36 + "answer" : "Niestety, jak tylko transakcja zostanie przesłana do blockchain, nie ma możliwości jej cofnięcia. Zawsze możesz jednak anulować transakcję przed jej wysłaniem, dlatego zawsze dokładnie sprawdź adres przed wysłaniem transakcji.\n"
37 + },
38 + {
39 + "question" : "Co to są „podadresy” i jak z nich korzystać?",
40 + "answer" : "Podadres jest w zasadzie unikalnym adresem, który można wygenerować w dowolnym momencie. Monety wysłane do niego nadal będą pojawiać się w głównym portfelu, ale osoba wysyłająca monety nie może podać Twojego głównego adresu. Podadresy zawsze zaczynają się od „8”.\nMożesz utworzyć nowy podadres na ekranie Odbieranie, dotykając „+” obok przycisku Podadresy. Wprowadź nazwę podadresu i dotknij „Dodaj”. Następnie dotknij nazwy podadresu, gdy chcesz go użyć!\nJeśli jesteś paranoikiem, prawdopodobnie za każdym razem, gdy otrzymasz Monero, powinieneś utworzyć nowy podadres.\n"
41 + },
42 + {
43 + "question" : "Co to jest ID transakcji?",
44 + "answer" : "Skrót transakcji lub ID transakcji to unikalny sposób identyfikowania każdej transakcji. Każda transakcja ma swój własny skrót. Jeśli chcesz podać komuś skrót transakcji, po prostu przejdź do głównego ekranu Portfela, dotknij transakcji, naciśnij długo w górnej części i wybierz Kopiuj.\n"
45 + },
46 + {
47 + "question" : "Nie otrzymałem mojego XMR! Co mogę zrobić?",
48 + "answer" : "Jeśli nie otrzymałeś Monero, możesz dotknąć menu ••• i nacisnąć Połącz ponownie. Jeśli to nie zadziała, przejdź do menu ustawień, dotknij pola „Bieżący węzeł” i wybierz węzeł z zieloną kropką obok niego.\n"
49 + },
50 + {
51 + "question" : "Nie otrzymałem moich monet z wymiany w aplikacji. Co mogę zrobić?",
52 + "answer" : "Jeśli masz problemy z wymianą, najlepszym rozwiązaniem jest skontaktowanie się z samą giełdą. Współpracujemy z XMR.TO, Morph i ChangeNow, więc najlepiej postawić się na stronie http://xmr.to, http://changenow.io lub http://morphtoken.com i skontaktować się z ich wsparciem.\n"
53 + },
54 + {
55 + "question" : "Jak skontaktować się z obsługą Cake Wallet?",
56 + "answer" : "Wyślij e-mail na adres support@cakewallet.io, dołącz do telegramu na @cake_wallet lub tweet @CakeWalletXMR!\n"
57 + }
58 +]
\ No newline at end of file
assets/faq/faq_pt.json new
+58
@@ -0,0 +1,58 @@
1 +[
2 + {
3 + "question" : "Qual é a diferença entre Saldo disponível e Saldo total?",
4 + "answer" : "Depois de fazer uma transação ou receber alguns Monero, a transação ainda precisa ser confirmada. Em cerca de 20 minutos, seu \"saldo disponível\" deve ser atualizado!\nÀs vezes, quando você envia o Monero, seu saldo disponível diminui em mais do que o valor enviado. Isso é normal e é necessário para proteger sua privacidade. Seu \"equilíbrio total\" deve voltar ao normal em 20 minutos.\n"
5 + },
6 + {
7 + "question" : "Como envio o Monero para uma troca que exige um ID de pagamento?",
8 + "answer" : "Toque no botão \"enviar\" na tela da Carteira virtual. Em seguida, copie o endereço de depósito da bolsa e cole-o na caixa \"endereço\". Em seguida, copie o ID do pagamento fornecido pela central e cole-o na caixa ID do pagamento. Por fim, insira a quantia que você deseja enviar e pronto!\n"
9 + },
10 + {
11 + "question" : "O que devo fazer se me esquecer do código de pagamento ao enviar o Monero para uma troca?",
12 + "answer" : "Embora nosso suporte não possa ajudá-lo diretamente com esse problema, é um problema muito comum com o qual a maioria das trocas está acostumada. Basta entrar em contato com o suporte da bolsa, explicar que você esqueceu de incluir seu ID de pagamento e enviar a ele seu ID de transação como prova. Você pode encontrar o ID da transação tocando na transação na tela da Carteira virtual.\n"
13 + },
14 + {
15 + "question" : "O que significam \"semente\" e \"chaves\"?",
16 + "answer" : "Suas chaves codificam as informações privadas da sua carteira e são o que permite gastar moedas e ver as transações recebidas.\nSua semente é apenas uma versão da sua chave privada escrita de uma maneira mais fácil para você escrever. Suas sementes e chaves são na verdade a mesma coisa, apenas em formas diferentes!\nNunca dê sua semente ou chave a ninguém. Seus fundos serão roubados se você der suas sementes ou chaves. No entanto, anote sua semente e guarde-a em um local seguro (isso permitirá que você restaure sua carteira se perder o telefone.)\n"
17 + },
18 + {
19 + "question" : "Quantas carteiras posso criar?",
20 + "answer" : "Não há limite! Você pode criar quantas carteiras quiser.\n"
21 + },
22 + {
23 + "question" : "Como posso restaurar minha carteira?",
24 + "answer" : "Toque no menu •••, selecione \"Carteiras\" e escolha \"Restaurar carteira\". Em seguida, insira sua semente (ou suas chaves) e, opcionalmente, insira uma data antes da primeira transação na sua carteira (isso acelerará o processo de sincronização .) Pode ser necessário manter o aplicativo aberto por 15 a 30 minutos para restaurar completamente sua carteira.\n"
25 + },
26 + {
27 + "question" : "O que posso fazer se perder minha semente?",
28 + "answer" : "Se você esqueceu sua semente, provavelmente a anotou em algum lugar. Por favor, verifique suas anotações e olhe em volta no seu computador. Se você não conseguir encontrá-lo em nenhum lugar, pode ter feito o backup da Cake Wallet (nesse caso, poderá restaurar a partir desse backup.) Se nada disso funcionar, infelizmente não há nada que possamos fazer.\n"
29 + },
30 + {
31 + "question" : "Você coleta alguma informação sobre minha carteira?",
32 + "answer" : "Cake Wallet NÃO coleta nem registra nenhuma informação sobre sua carteira. Nós nos preocupamos com sua privacidade.\n"
33 + },
34 + {
35 + "question" : "É possível reverter uma transação?",
36 + "answer" : "Infelizmente, assim que uma transação foi enviada ao blockchain, não há como desfazê-lo. No entanto, você sempre pode cancelar a transação antes de ser enviada. Verifique sempre o endereço antes de enviar uma transação.\n"
37 + },
38 + {
39 + "question" : "O que são \"sub-endereços\" e como os usamos?",
40 + "answer" : "Um sub-endereço é basicamente um endereço exclusivo que você pode gerar a qualquer momento. As moedas enviadas ainda chegarão à sua carteira principal, mas a pessoa que está enviando as moedas não sabe qual é o seu endereço principal. Os sub-endereços sempre começam com \"8\".\nVocê pode criar um novo sub-endereço na tela Receber, tocando no botão \"+\" ao lado do botão Sub-endereços. Digite um nome para o sub-endereço e toque em \"Adicionar\". Em seguida, basta tocar no nome do sub-endereço quando quiser usá-lo!\nSe você é paranóico, provavelmente deve criar um novo sub-endereço toda vez que receber o Monero.\n"
41 + },
42 + {
43 + "question" : "O que é um ID de transação?",
44 + "answer" : "Um hash de transação, ou ID da transação, é uma maneira exclusiva de identificar qualquer transação. Cada transação possui seu próprio hash. Se você precisar fornecer um hash de transação a alguém, vá para a tela principal da Carteira virtual, toque na transação, pressione e segure na seção superior e selecione Copiar.\n"
45 + },
46 + {
47 + "question" : "Não recebi meu XMR! O que eu posso fazer?",
48 + "answer" : "Se você não recebeu seu Monero, toque no menu ••• e clique em Reconectar. Se isso não funcionar, entre no menu de configurações, toque na caixa 'Nó atual' e selecione um nó com um ponto verde próximo a ele.\n"
49 + },
50 + {
51 + "question" : "Não recebi minhas moedas da troca no aplicativo. O que eu posso fazer?",
52 + "answer" : "Se você estiver tendo problemas com uma troca, a melhor opção é entrar em contato com a troca. Somos parceiros do XMR.TO, Morph e ChangeNow, portanto, sua melhor aposta é ir para http://xmr.to, http://changenow.io ou http://morphtoken.com e entrar em contato com o suporte deles.\n"
53 + },
54 + {
55 + "question" : "Como entro em contato com o suporte da Cake Wallet?",
56 + "answer" : "Envie um e-mail para support@cakewallet.io, participe do Telegram em @cake_wallet ou envie um tweet para @CakeWalletXMR!\n"
57 + }
58 +]
\ No newline at end of file
assets/faq/faq_ru.json new
+58
@@ -0,0 +1,58 @@
1 +[
2 + {
3 + "question" : "В чем разница между доступным балансом и полным балансом?",
4 + "answer" : "После того, как вы совершите транзакцию или получите какой-либо Monero, транзакция все еще нуждается в подтверждении. Примерно через 20 минут ваш «доступный баланс» должен обновиться.\nИногда, когда вы отправляете Monero, ваш доступный баланс уменьшается более чем на сумму, которую вы отправили. Это нормально и необходимо для защиты вашей конфиденциальности. Ваш «полный баланс» должен вернуться к норме через 20 минут.\n"
5 + },
6 + {
7 + "question" : "Как отправить Monero на обмен, для которого требуется идентификатор платежа?",
8 + "answer" : "Нажмите кнопку «Отправить» на экране кошелька. Затем скопируйте адрес депозита биржи и вставьте его в поле «адрес». Затем скопируйте идентификатор платежа, предоставленный провайдером обмена и вставьте его в поле идентификатора платежа. Затем ведите сумму, которую вы хотите отправить и все готово!\n"
9 + },
10 + {
11 + "question" : "Что мне делать, если я забыл ввести идентификатор платежа при отправке Monero на обмен?",
12 + "answer" : "Хотя наша поддержка не может напрямую помочь вам в этом вопросе, это очень распространенная проблема, с которой большинство бирж привыкли иметь дело. Просто свяжитесь со службой поддержки провайдера обмена и объясните, что вы забыли указать свой идентификатор платежа, а затем отправьте им свой идентификатор транзакции в качестве доказательства. Вы можете найти идентификатор транзакции, нажав на транзакцию на экране своего кошелька.\n"
13 + },
14 + {
15 + "question" : "Что означают «семена» и «ключи»?",
16 + "answer" : "Ваши ключи кодируют личную информацию в вашем кошельке и позволяют вам тратить монеты и видеть входящие транзакции.Ваше семя (код-фраза) - это просто версия вашего личного ключа, написанная так, чтобы вам было легче ее записать. Ваше семя и ключи на самом деле одно и то же, только в разных формах! Никому не передавайте свою код-фразу или ключи иначе ваши средства могут быть украдены. Однако, пожалуйста, запишите их и храните в безопасном месте (это позволит вам восстановить свой кошелек, если вы потеряете свой телефон.)\n"
17 + },
18 + {
19 + "question" : "Сколько кошельков я могу создать?",
20 + "answer" : "Там нет предела! Вы можете создать столько кошельков, сколько захотите.\n"
21 + },
22 + {
23 + "question" : "Как я могу восстановить свой кошелек?",
24 + "answer" : "Коснитесь ••• меню, выберите «Кошельки», а затем выберите «Восстановить кошелек». Затем введите свою код-фразу (или ключи) и при необходимости введите дату до первой транзакции в вашем кошельке (это ускорит процесс синхронизации .) Вам может понадобиться держать приложение открытым в течение 15-30 минут, чтобы полностью восстановить свой кошелек.\n"
25 + },
26 + {
27 + "question" : "Что мне делать, если я потеряю свою код-фразу?",
28 + "answer" : "Если вы забыли свою код-фразу, вы вероятно, где-то записали ее. Пожалуйста, проверьте свои заметки и осмотрите свой компьютер. Если вы нигде не можете найти ее, возможно, вы создали резервную копию Cake Wallet (в этом случае вы сможете восстановить данные из этой резервной копии.) К сожалению если вышеуказанные способы вам не помогли, мы ничего не можем сделать.\n"
29 + },
30 + {
31 + "question" : "Собираете ли вы какую-либо информацию о моем кошельке?",
32 + "answer" : "Cake Wallet не собирает и не записывает какую-либо информацию о вашем кошельке. Мы заботимся о вашей конфиденциальности.\n"
33 + },
34 + {
35 + "question" : "Возможно ли отменить транзакцию?",
36 + "answer" : "К сожалению, как только транзакция была передана в блокчейн, отменить ее невозможно. Вы всегда можете отменить транзакцию до ее отправки, поэтому всегда дважды проверяйте адрес перед отправкой транзакции.\n"
37 + },
38 + {
39 + "question" : "Что такое «сабадреса» и как их использовать?",
40 + "answer" : "Сабадрес - это уникальный адрес, который вы можете сгенерировать в любое время. Монеты, отправленные на него, все равно поступят на ваш основной кошелек, но человек отправляющий монеты, не может узнать ваш основной адрес. Сабадреса всегда начинаются с «8».\nВы можете создать новый сабадрес на экране получения, нажав «+» рядом с кнопкой «Сабадреса». Введите имя для дополнительного адреса и нажмите «Добавить». Затем просто нажмите на имя сабадреса, когда вы хотите его использовать!\nЕсли вы переживаете за конфединциальность, вероятно вам следует создавать новый сабадрес каждый раз, когда вы хотите получить Monero.\n"
41 + },
42 + {
43 + "question" : "Что такое ID транзакции?",
44 + "answer" : "Хэш транзакции (или ID транзакции), является уникальным способом идентификации любой транзакции. Каждая транзакция имеет свой ID. Если вам нужно предоставить ID транзакции кому-то, просто перейдите на главный экран кошелька, нажмите на транзакцию, нажмите и удерживайте поле с ID транзакции для копирования.\n"
45 + },
46 + {
47 + "question" : "Я не получил свои XMR! Что я могу сделать?",
48 + "answer" : "Если вы не получили Monero, вы можете нажать ••• меню и нажать «Переподключиться». Если это не сработает, перейдите в меню настроек, коснитесь поля «Текущий узел» и выберите узел с зеленой точкой рядом с ним.\n"
49 + },
50 + {
51 + "question" : "Я не получил свои монеты после обмена в приложении. Что я могу сделать?",
52 + "answer" : "Если у вас возникли проблемы с обменом, лучше всего связаться с провайдером обмена. Мы сотрудничаем с XMR.TO, Morph и ChangeNow, поэтому вам лучше всего зайти на http://xmr.to, http://changenow.io или http://morphtoken.com и связаться с их поддержкой.\n"
53 + },
54 + {
55 + "question" : "Как мне связаться со службой поддержки Cake Wallet?",
56 + "answer" : "По электронной почте support@cakewallet.io, присоединитесь к Telegram по адресу @cake_wallet или отправьте твит @CakeWalletXMR!\n"
57 + }
58 +]
\ No newline at end of file
assets/faq/faq_zh.json new
+58
@@ -0,0 +1,58 @@
1 +[
2 + {
3 + "question" : "可用余额和全额余额有什么区别?",
4 + "answer" : "在您进行交易或收到一些门罗币后,仍然需要确认交易。 在大约20分钟内,您的“可用余额”应该会更新!\n有时,当您发送Monero时,可用余额会减少,超过所发送的金额。 这是正常现象,因此有必要保护您的隐私。 您的“全部余额”应在20分钟内恢复正常。\n"
5 + },
6 + {
7 + "question" : "如何将Monero发送到需要付款ID的交易所?",
8 + "answer" : "点击电子钱包屏幕上的“发送”按钮。 接下来,复制交易所的存款地址,并将其粘贴到“地址”框中。 然后,复制交易所提供的付款ID,并将其粘贴到“付款ID”框中。 最后,输入您要发送的金额,一切顺利!\n"
9 + },
10 + {
11 + "question" : "如果将Monero发送到交易所时忘记输入付款ID,该怎么办?",
12 + "answer" : "尽管我们的支持无法直接为您解决此问题,但大多数交易所都习惯于处理这个非常普遍的问题。 只需联系交易所的支持人员,说明您忘记包含付款ID,然后将其交易ID发送给他们即可作为证明。 您可以通过在电子钱包屏幕中点击交易找到交易ID。\n"
13 + },
14 + {
15 + "question" : "“种子”和“钥匙”是什么意思?",
16 + "answer" : "您的密钥对钱包中的私人信息进行编码,这些密钥使您可以花费硬币并查看传入的交易。\n您的种子只是私钥的一种版本,以更容易记下来的方式编写。 您的种子和密钥实际上是同一件事,只是形式不同!\n永远不要将您的种子或钥匙交给任何人。 如果您提供种子或钥匙,您的资金将被盗。 但是,请写下您的种子,并将其存储在安全的地方(如果您丢失手机,这将使您可以恢复钱包。)\n"
17 + },
18 + {
19 + "question" : "我可以创建多少个钱包?",
20 + "answer" : "没有限制! 您可以根据需要创建任意数量的钱包。\n"
21 + },
22 + {
23 + "question" : "如何恢复我的钱包?",
24 + "answer" : "点击•••菜单,选择“钱包”,然后选择“还原钱包”。然后输入您的种子(或密钥),还可以选择在您的钱包中进行第一笔交易之前输入日期(这将加快同步过程) 。)您可能需要将应用保持打开状态15-30分钟,以完全恢复您的钱包。\n"
25 + },
26 + {
27 + "question" : "如果我种下种子了怎么办?",
28 + "answer" : "如果您忘记了种子,则可能将其写下来。 请检查笔记并在计算机上四处张望。 如果您在任何地方都找不到它,则可能已经备份了Cake Wallet(在这种情况下,您可以从该备份中还原。)如果这些都不起作用,那么很遗憾,我们无能为力。\n"
29 + },
30 + {
31 + "question" : "您是否收集有关我的钱包的任何信息?",
32 + "answer" : "Cake Wallet不会收集或记录有关您钱包的任何信息。 我们关心您的隐私。\n"
33 + },
34 + {
35 + "question" : "是否可以撤消交易?",
36 + "answer" : "不幸的是,一旦将交易提交到区块链,就无法撤消它。 不过,您始终可以在发送交易之前取消交易,因此请务必在发送交易之前仔细检查地址。\n"
37 + },
38 + {
39 + "question" : "什么是“子地址”,我该如何使用它们?",
40 + "answer" : "子地址基本上是您可以随时生成的唯一地址。 发送给它的硬币仍然会到达您的主钱包中,但是发送硬币的人无法告知您的主要地址是什么。 子地址始终以“ 8”开头。\n您可以通过点击“子地址”按钮旁边的“ +”在“接收”屏幕中创建一个新的子地址。 输入子地址的名称,然后点击“添加”。 然后,当您要使用子地址名称时,只需点击它即可!\n如果您偏执狂,您可能应该在每次收到门罗币时创建一个新的子地址。\n"
41 + },
42 + {
43 + "question" : "什么是交易编号?",
44 + "answer" : "交易哈希或交易ID是识别任何交易的唯一方式。 每个交易都有自己的哈希。 如果您需要向某人提供交易哈希,只需转到电子钱包主屏幕,点击交易,长按顶部,然后选择复制。\n"
45 + },
46 + {
47 + "question" : "我没有收到我的XMR! 我能做什么?",
48 + "answer" : "如果您未收到门罗币,则可能需要点击•••菜单,然后点击重新连接。 如果这不起作用,请进入设置菜单,点击“当前节点”框,然后选择旁边带有绿点的节点。\n"
49 + },
50 + {
51 + "question" : "我没有从应用程序中的交易所收到硬币。 我能做什么?",
52 + "answer" : "如果您对交易所有疑问,最好的选择是与交易所本身联系。 我们与XMR.TO,Morph和ChangeNow合作,因此最好的选择是访问http://xmr.to、http://changenow.io或http://morphtoken.com,并与他们的支持部门联系。\n"
53 + },
54 + {
55 + "question" : "如何联系蛋糕钱包支持?",
56 + "answer" : "电子邮件support@cakewallet.io,通过@cake_wallet加入电报,或在@CakeWalletXMR上发布推文!\n"
57 + }
58 +]
\ No newline at end of file
assets/fonts/Lato-Bold.ttf
Binary files /dev/null and b/assets/fonts/Lato-Bold.ttf differ
assets/fonts/Lato-Regular.ttf
Binary files /dev/null and b/assets/fonts/Lato-Regular.ttf differ
assets/fonts/Lato-Semibold.ttf
Binary files /dev/null and b/assets/fonts/Lato-Semibold.ttf differ
assets/images/2.0x/Telegram.png
Binary files /dev/null and b/assets/images/2.0x/Telegram.png differ
assets/images/2.0x/Twitter.png
Binary files /dev/null and b/assets/images/2.0x/Twitter.png differ
assets/images/2.0x/arrow_bottom_cake_green.png
Binary files /dev/null and b/assets/images/2.0x/arrow_bottom_cake_green.png differ
assets/images/2.0x/back_arrow.png
Binary files /dev/null and b/assets/images/2.0x/back_arrow.png differ
assets/images/2.0x/back_arrow_dark_theme.png
Binary files /dev/null and b/assets/images/2.0x/back_arrow_dark_theme.png differ
assets/images/2.0x/bitmap.png
Binary files /dev/null and b/assets/images/2.0x/bitmap.png differ
assets/images/2.0x/cake_arrow.png
Binary files /dev/null and b/assets/images/2.0x/cake_arrow.png differ
assets/images/2.0x/cake_logo.png
Binary files /dev/null and b/assets/images/2.0x/cake_logo.png differ
assets/images/2.0x/change_now.png
Binary files /dev/null and b/assets/images/2.0x/change_now.png differ
assets/images/2.0x/close_button.png
Binary files /dev/null and b/assets/images/2.0x/close_button.png differ
assets/images/2.0x/close_button_dark_theme.png
Binary files /dev/null and b/assets/images/2.0x/close_button_dark_theme.png differ
assets/images/2.0x/delete_icon.png
Binary files /dev/null and b/assets/images/2.0x/delete_icon.png differ
assets/images/2.0x/keysIco.png
Binary files /dev/null and b/assets/images/2.0x/keysIco.png differ
assets/images/2.0x/qr_code_icon.png
Binary files /dev/null and b/assets/images/2.0x/qr_code_icon.png differ
assets/images/2.0x/qr_icon.png
Binary files /dev/null and b/assets/images/2.0x/qr_icon.png differ
assets/images/2.0x/refresh_icon.png
Binary files /dev/null and b/assets/images/2.0x/refresh_icon.png differ
assets/images/2.0x/restoreSeed.png
Binary files /dev/null and b/assets/images/2.0x/restoreSeed.png differ
assets/images/2.0x/seedIco.png
Binary files /dev/null and b/assets/images/2.0x/seedIco.png differ
assets/images/2.0x/seedKeys.png
Binary files /dev/null and b/assets/images/2.0x/seedKeys.png differ
assets/images/2.0x/seed_image.png
Binary files /dev/null and b/assets/images/2.0x/seed_image.png differ
assets/images/2.0x/welcomeImg.png
Binary files /dev/null and b/assets/images/2.0x/welcomeImg.png differ
assets/images/2.0x/xmr_btc.png
Binary files /dev/null and b/assets/images/2.0x/xmr_btc.png differ
assets/images/3.0x/Telegram.png
Binary files /dev/null and b/assets/images/3.0x/Telegram.png differ
assets/images/3.0x/Twitter.png
Binary files /dev/null and b/assets/images/3.0x/Twitter.png differ
assets/images/3.0x/arrow_bottom_cake_green.png
Binary files /dev/null and b/assets/images/3.0x/arrow_bottom_cake_green.png differ
assets/images/3.0x/back_arrow.png
Binary files /dev/null and b/assets/images/3.0x/back_arrow.png differ
assets/images/3.0x/back_arrow_dark_theme.png
Binary files /dev/null and b/assets/images/3.0x/back_arrow_dark_theme.png differ
assets/images/3.0x/bitmap.png
Binary files /dev/null and b/assets/images/3.0x/bitmap.png differ
assets/images/3.0x/cake_arrow.png
Binary files /dev/null and b/assets/images/3.0x/cake_arrow.png differ
assets/images/3.0x/cake_logo.png
Binary files /dev/null and b/assets/images/3.0x/cake_logo.png differ
assets/images/3.0x/change_now.png
Binary files /dev/null and b/assets/images/3.0x/change_now.png differ
assets/images/3.0x/close_button.png
Binary files /dev/null and b/assets/images/3.0x/close_button.png differ
assets/images/3.0x/close_button_dark_theme.png
Binary files /dev/null and b/assets/images/3.0x/close_button_dark_theme.png differ
assets/images/3.0x/delete_icon.png
Binary files /dev/null and b/assets/images/3.0x/delete_icon.png differ
assets/images/3.0x/keysIco.png
Binary files /dev/null and b/assets/images/3.0x/keysIco.png differ
assets/images/3.0x/qr_code_icon.png
Binary files /dev/null and b/assets/images/3.0x/qr_code_icon.png differ
assets/images/3.0x/qr_icon.png
Binary files /dev/null and b/assets/images/3.0x/qr_icon.png differ
assets/images/3.0x/refresh_icon.png
Binary files /dev/null and b/assets/images/3.0x/refresh_icon.png differ
assets/images/3.0x/restoreSeed.png
Binary files /dev/null and b/assets/images/3.0x/restoreSeed.png differ
assets/images/3.0x/seedIco.png
Binary files /dev/null and b/assets/images/3.0x/seedIco.png differ
assets/images/3.0x/seedKeys.png
Binary files /dev/null and b/assets/images/3.0x/seedKeys.png differ
assets/images/3.0x/seed_image.png
Binary files /dev/null and b/assets/images/3.0x/seed_image.png differ
assets/images/3.0x/welcomeImg.png
Binary files /dev/null and b/assets/images/3.0x/welcomeImg.png differ
assets/images/3.0x/xmr_btc.png
Binary files /dev/null and b/assets/images/3.0x/xmr_btc.png differ
assets/images/Telegram.png
Binary files /dev/null and b/assets/images/Telegram.png differ
assets/images/Twitter.png
Binary files /dev/null and b/assets/images/Twitter.png differ
assets/images/address_book_icon.png
Binary files /dev/null and b/assets/images/address_book_icon.png differ
assets/images/app_logo.png
Binary files /dev/null and b/assets/images/app_logo.png differ
assets/images/arrow_bottom_cake_green.png
Binary files /dev/null and b/assets/images/arrow_bottom_cake_green.png differ
assets/images/arrow_bottom_purple_icon.png
Binary files /dev/null and b/assets/images/arrow_bottom_purple_icon.png differ
assets/images/back_arrow.png
Binary files /dev/null and b/assets/images/back_arrow.png differ
assets/images/back_arrow_dark_theme.png
Binary files /dev/null and b/assets/images/back_arrow_dark_theme.png differ
assets/images/bitmap.png
Binary files /dev/null and b/assets/images/bitmap.png differ
assets/images/cake_arrow.png
Binary files /dev/null and b/assets/images/cake_arrow.png differ
assets/images/cake_logo.png
Binary files /dev/null and b/assets/images/cake_logo.png differ
assets/images/change_now.png
Binary files /dev/null and b/assets/images/change_now.png differ
assets/images/close_button.png
Binary files /dev/null and b/assets/images/close_button.png differ
assets/images/close_button_dark_theme.png
Binary files /dev/null and b/assets/images/close_button_dark_theme.png differ
assets/images/delete_icon.png
Binary files /dev/null and b/assets/images/delete_icon.png differ
assets/images/exchange_icon.png
Binary files /dev/null and b/assets/images/exchange_icon.png differ
assets/images/keysIco.png
Binary files /dev/null and b/assets/images/keysIco.png differ
assets/images/more.png
Binary files /dev/null and b/assets/images/more.png differ
assets/images/paste_button.png
Binary files /dev/null and b/assets/images/paste_button.png differ
assets/images/qr_code_icon.png
Binary files /dev/null and b/assets/images/qr_code_icon.png differ
assets/images/qr_icon.png
Binary files /dev/null and b/assets/images/qr_icon.png differ
assets/images/receive_icon.png
Binary files /dev/null and b/assets/images/receive_icon.png differ
assets/images/receive_icon_raw.png
Binary files /dev/null and b/assets/images/receive_icon_raw.png differ
assets/images/refresh_icon.png
Binary files /dev/null and b/assets/images/refresh_icon.png differ
assets/images/restoreSeed.png
Binary files /dev/null and b/assets/images/restoreSeed.png differ
assets/images/seedIco.png
Binary files /dev/null and b/assets/images/seedIco.png differ
assets/images/seedKeys.png
Binary files /dev/null and b/assets/images/seedKeys.png differ
assets/images/seed_image.png
Binary files /dev/null and b/assets/images/seed_image.png differ
assets/images/send_icon.png
Binary files /dev/null and b/assets/images/send_icon.png differ
assets/images/settings_icon.png
Binary files /dev/null and b/assets/images/settings_icon.png differ
assets/images/transaction_incoming.png
Binary files /dev/null and b/assets/images/transaction_incoming.png differ
assets/images/transaction_outgoing.png
Binary files /dev/null and b/assets/images/transaction_outgoing.png differ
assets/images/wallet_icon.png
Binary files /dev/null and b/assets/images/wallet_icon.png differ
assets/images/welcomeImg.png
Binary files /dev/null and b/assets/images/welcomeImg.png differ
assets/images/x.png
Binary files /dev/null and b/assets/images/x.png differ
assets/images/xmr_btc.png
Binary files /dev/null and b/assets/images/xmr_btc.png differ
assets/node_list.yml new
+25
@@ -0,0 +1,25 @@
1 +-
2 + uri: xmr-node-uk.cakewallet.com:18081
3 + is_default: true
4 +-
5 + uri: eu-node.cakewallet.io:18081
6 + login: cake
7 + password: public_node
8 + is_default: false
9 +-
10 + uri: node.cakewallet.io:18081
11 + login: cake
12 + password: public_node
13 + is_default: false
14 +-
15 + uri: node.moneroworld.com:18089
16 + is_default: false
17 +-
18 + uri: node.xmr.pt:18081
19 + is_default: false
20 +-
21 + uri: node.xmr.ru:13666
22 + is_default: false
23 +-
24 + uri: opennode.xmr-tw.org:18089
25 + is_default: false
\ No newline at end of file
assets/text/Terms_of_Use.txt new
+25
@@ -0,0 +1,25 @@
1 +1. Use of Cake Wallet
2 +The Cake Wallet app (hereinafter, referred to as the "App") allows the use of accessing the Monero Blockchain/network. You are not authorized, and nor should you rely on the App for legal advice, business advice, or advice of any kind. You act at your own risk in reliance on the contents of the App. Should you make a decision to act or not act you should contact a licensed attorney in the relevant jurisdiction in which you want or need help. In no way are the owners of, or contributors to, the App responsible for the actions, decisions, or other behavior taken or not taken by you in reliance upon the App.
3 +2. Translations
4 +The App may contain translations of the English version of the content available on the App. These translations are provided only as a convenience. In the event of any conflict between the English language version and the translated version, the English language version shall take precedence. If you notice any inconsistency, please report them on GitHub.
5 +3. Risks related to the use of Cake Wallet.
6 +The App, the App’s owner Cake Technologies LLC and Cake Technologies owners, partners, employees, contributors, and any affiliates will not be responsible for any losses, damages or claims arising from events falling within the scope of the following five categories:
7 +1. (1) Mistakes made by the user of any Monero-related software or service, e.g., forgotten passwords, payments sent to wrong Monero addresses, and accidental deletion of wallets.
8 +2. (2) Software problems of the App and/or any Monero-related software or service, e.g., corrupted wallet file, incorrectly constructed transactions, unsafe cryptographic libraries, malware affecting the App and/or any Monero-related software or service.
9 +3. (3) Technical failures in the hardware of the user of any Monero-related software or service, e.g., data loss due to a faulty or damaged storage device.
10 +4. (4) Security problems experienced by the user of any Monero-related software or service, e.g., unauthorized access to users' wallets and/or accounts.
11 +5. (5) Actions or inactions of third parties and/or events experienced by third parties, e.g., bankruptcy of service providers, information security attacks on service providers, and fraud conducted by third parties.
12 +4. Investment risks
13 +The investment in Monero can lead to loss of money over short or even long periods. The investors in Monero should expect prices to have large range fluctuations.
14 +5. Compliance with tax obligations
15 +The users of the App are solely responsible to determinate what, if any, taxes apply to their Monero transactions. The owners of, or contributors to, the App are NOT responsible for determining the taxes that apply to Monero transactions.
16 +6. The App does not store, send, or receive Moneros
17 +The App does not store, send or receive Monero. This is because Monero exists only by virtue of the ownership record maintained in the Monero network. Any transfer of title in Moneros occurs within a decentralized Monero network, and not on the App.
18 +7. No warranties
19 +The App is provided on an "as is" basis without any warranties of any kind regarding the App and/or any content, data, materials and/or services provided on the App.
20 +8. Limitation of liability
21 +Unless otherwise required by law, in no event shall the owners of, or contributors to, the App be liable for any damages of any kind, including, but not limited to, loss of use, loss of profits, or loss of data arising out of or in any way connected with the use of the App.
22 +9. Arbitration
23 +The user of the App agrees to arbitrate any dispute arising from or in connection with the App or this disclaimer, except for disputes related to copyrights, logos, trademarks, trade names, trade secrets or patents.
24 +10. Last amendment
25 +This disclaimer was amended for the last time on January 15, 2018.
\ No newline at end of file
cw_monero/.gitignore new
+11
@@ -0,0 +1,11 @@
1 +.DS_Store
2 +.dart_tool/
3 +
4 +.packages
5 +.pub/
6 +
7 +build/
8 +
9 +ios/External/
10 +android/.externalNativeBuild/
11 +android/.cxx/
\ No newline at end of file
cw_monero/.metadata new
+10
@@ -0,0 +1,10 @@
1 +# This file tracks properties of this Flutter project.
2 +# Used by Flutter tool to assess capabilities and perform upgrades etc.
3 +#
4 +# This file should be version controlled and should not be manually edited.
5 +
6 +version:
7 + revision: 798e4272a2e43d7daab75f225a13442e384ee0cd
8 + channel: dev
9 +
10 +project_type: plugin
cw_monero/CHANGELOG.md new
+3
@@ -0,0 +1,3 @@
1 +## 0.0.1
2 +
3 +* TODO: Describe initial release.
cw_monero/LICENSE new
+1
@@ -0,0 +1 @@
1 +TODO: Add your license here.
cw_monero/README.md new
+14
@@ -0,0 +1,14 @@
1 +# cw_monero
2 +
3 +A new flutter plugin project.
4 +
5 +## Getting Started
6 +
7 +This project is a starting point for a Flutter
8 +[plug-in package](https://flutter.dev/developing-packages/),
9 +a specialized package that includes platform-specific implementation code for
10 +Android and/or iOS.
11 +
12 +For help getting started with Flutter, view our
13 +[online documentation](https://flutter.dev/docs), which offers tutorials,
14 +samples, guidance on mobile development, and a full API reference.
cw_monero/android/.gitignore new
+8
@@ -0,0 +1,8 @@
1 +*.iml
2 +.gradle
3 +/local.properties
4 +/.idea/workspace.xml
5 +/.idea/libraries
6 +.DS_Store
7 +/build
8 +/captures
cw_monero/android/CMakeLists.txt new
+218
@@ -0,0 +1,218 @@
1 +cmake_minimum_required(VERSION 3.4.1)
2 +
3 +add_library( cw_monero
4 + SHARED
5 + ./jni/monero_jni.cpp
6 + ../ios/Classes/monero_api.cpp)
7 +
8 + find_library( log-lib log )
9 +
10 +set(CMAKE_BUILD_TYPE Debug)
11 +
12 +set(EXTERNAL_LIBS_DIR ${CMAKE_SOURCE_DIR}/../ios/External/android)
13 +
14 +############
15 +# libsodium
16 +############
17 +
18 +add_library(sodium STATIC IMPORTED)
19 +set_target_properties(sodium PROPERTIES IMPORTED_LOCATION
20 + ${EXTERNAL_LIBS_DIR}/libsodium/lib/${ANDROID_ABI}/libsodium.a)
21 +
22 +############
23 +# OpenSSL
24 +############
25 +
26 +add_library(crypto STATIC IMPORTED)
27 +set_target_properties(crypto PROPERTIES IMPORTED_LOCATION
28 + ${EXTERNAL_LIBS_DIR}/openssl/lib/${ANDROID_ABI}/libcrypto.a)
29 +
30 +add_library(ssl STATIC IMPORTED)
31 +set_target_properties(ssl PROPERTIES IMPORTED_LOCATION
32 + ${EXTERNAL_LIBS_DIR}/openssl/lib/${ANDROID_ABI}/libssl.a)
33 +
34 +############
35 +# Boost
36 +############
37 +
38 +add_library(boost_chrono STATIC IMPORTED)
39 +set_target_properties(boost_chrono PROPERTIES IMPORTED_LOCATION
40 + ${EXTERNAL_LIBS_DIR}/boost/lib/${ANDROID_ABI}/libboost_chrono.a)
41 +
42 +add_library(boost_date_time STATIC IMPORTED)
43 +set_target_properties(boost_date_time PROPERTIES IMPORTED_LOCATION
44 + ${EXTERNAL_LIBS_DIR}/boost/lib/${ANDROID_ABI}/libboost_date_time.a)
45 +
46 +add_library(boost_filesystem STATIC IMPORTED)
47 +set_target_properties(boost_filesystem PROPERTIES IMPORTED_LOCATION
48 + ${EXTERNAL_LIBS_DIR}/boost/lib/${ANDROID_ABI}/libboost_filesystem.a)
49 +
50 +add_library(boost_program_options STATIC IMPORTED)
51 +set_target_properties(boost_program_options PROPERTIES IMPORTED_LOCATION
52 + ${EXTERNAL_LIBS_DIR}/boost/lib/${ANDROID_ABI}/libboost_program_options.a)
53 +
54 +add_library(boost_regex STATIC IMPORTED)
55 +set_target_properties(boost_regex PROPERTIES IMPORTED_LOCATION
56 + ${EXTERNAL_LIBS_DIR}/boost/lib/${ANDROID_ABI}/libboost_regex.a)
57 +
58 +add_library(boost_serialization STATIC IMPORTED)
59 +set_target_properties(boost_serialization PROPERTIES IMPORTED_LOCATION
60 + ${EXTERNAL_LIBS_DIR}/boost/lib/${ANDROID_ABI}/libboost_serialization.a)
61 +
62 +add_library(boost_system STATIC IMPORTED)
63 +set_target_properties(boost_system PROPERTIES IMPORTED_LOCATION
64 + ${EXTERNAL_LIBS_DIR}/boost/lib/${ANDROID_ABI}/libboost_system.a)
65 +
66 +add_library(boost_thread STATIC IMPORTED)
67 +set_target_properties(boost_thread PROPERTIES IMPORTED_LOCATION
68 + ${EXTERNAL_LIBS_DIR}/boost/lib/${ANDROID_ABI}/libboost_thread.a)
69 +
70 +add_library(boost_wserialization STATIC IMPORTED)
71 +set_target_properties(boost_wserialization PROPERTIES IMPORTED_LOCATION
72 + ${EXTERNAL_LIBS_DIR}/boost/lib/${ANDROID_ABI}/libboost_wserialization.a)
73 +
74 +#############
75 +# Monero
76 +#############
77 +
78 +add_library(wallet_api STATIC IMPORTED)
79 +set_target_properties(wallet_api PROPERTIES IMPORTED_LOCATION
80 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libwallet_api.a)
81 +
82 +add_library(wallet STATIC IMPORTED)
83 +set_target_properties(wallet PROPERTIES IMPORTED_LOCATION
84 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libwallet.a)
85 +
86 +add_library(cryptonote_core STATIC IMPORTED)
87 +set_target_properties(cryptonote_core PROPERTIES IMPORTED_LOCATION
88 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libcryptonote_core.a)
89 +
90 +add_library(cryptonote_basic STATIC IMPORTED)
91 +set_target_properties(cryptonote_basic PROPERTIES IMPORTED_LOCATION
92 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libcryptonote_basic.a)
93 +
94 +add_library(mnemonics STATIC IMPORTED)
95 +set_target_properties(mnemonics PROPERTIES IMPORTED_LOCATION
96 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libmnemonics.a)
97 +
98 +add_library(common STATIC IMPORTED)
99 +set_target_properties(common PROPERTIES IMPORTED_LOCATION
100 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libcommon.a)
101 +
102 +add_library(cncrypto STATIC IMPORTED)
103 +set_target_properties(cncrypto PROPERTIES IMPORTED_LOCATION
104 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libcncrypto.a)
105 +
106 +add_library(ringct STATIC IMPORTED)
107 +set_target_properties(ringct PROPERTIES IMPORTED_LOCATION
108 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libringct.a)
109 +
110 +add_library(ringct_basic STATIC IMPORTED)
111 +set_target_properties(ringct_basic PROPERTIES IMPORTED_LOCATION
112 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libringct_basic.a)
113 +
114 +add_library(blockchain_db STATIC IMPORTED)
115 +set_target_properties(blockchain_db PROPERTIES IMPORTED_LOCATION
116 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libblockchain_db.a)
117 +
118 +add_library(lmdb STATIC IMPORTED)
119 +set_target_properties(lmdb PROPERTIES IMPORTED_LOCATION
120 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/liblmdb.a)
121 +
122 +add_library(easylogging STATIC IMPORTED)
123 +set_target_properties(easylogging PROPERTIES IMPORTED_LOCATION
124 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libeasylogging.a)
125 +
126 +add_library(unbound STATIC IMPORTED)
127 +set_target_properties(unbound PROPERTIES IMPORTED_LOCATION
128 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libunbound.a)
129 +
130 +add_library(epee STATIC IMPORTED)
131 +set_target_properties(epee PROPERTIES IMPORTED_LOCATION
132 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libepee.a)
133 +
134 +add_library(blocks STATIC IMPORTED)
135 +set_target_properties(blocks PROPERTIES IMPORTED_LOCATION
136 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libblocks.a)
137 +
138 +add_library(checkpoints STATIC IMPORTED)
139 +set_target_properties(checkpoints PROPERTIES IMPORTED_LOCATION
140 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libcheckpoints.a)
141 +
142 +add_library(device STATIC IMPORTED)
143 +set_target_properties(device PROPERTIES IMPORTED_LOCATION
144 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libdevice.a)
145 +
146 +add_library(device_trezor STATIC IMPORTED)
147 +set_target_properties(device_trezor PROPERTIES IMPORTED_LOCATION
148 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libdevice_trezor.a)
149 +
150 +add_library(multisig STATIC IMPORTED)
151 +set_target_properties(multisig PROPERTIES IMPORTED_LOCATION
152 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libmultisig.a)
153 +
154 +add_library(version STATIC IMPORTED)
155 +set_target_properties(version PROPERTIES IMPORTED_LOCATION
156 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libversion.a)
157 +
158 +add_library(net STATIC IMPORTED)
159 +set_target_properties(net PROPERTIES IMPORTED_LOCATION
160 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libnet.a)
161 +
162 +add_library(hardforks STATIC IMPORTED)
163 +set_target_properties(hardforks PROPERTIES IMPORTED_LOCATION
164 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libhardforks.a)
165 +
166 +add_library(randomx STATIC IMPORTED)
167 +set_target_properties(randomx PROPERTIES IMPORTED_LOCATION
168 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/librandomx.a)
169 +
170 +add_library(rpc_base STATIC IMPORTED)
171 +set_target_properties(rpc_base PROPERTIES IMPORTED_LOCATION
172 + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/librpc_base.a)
173 +
174 +include_directories( ${EXTERNAL_LIBS_DIR}/monero/include )
175 +
176 +target_link_libraries( cw_monero
177 +
178 + wallet_api
179 + wallet
180 + cryptonote_core
181 + cryptonote_basic
182 + mnemonics
183 + ringct
184 + ringct_basic
185 + net
186 + common
187 + cncrypto
188 + blockchain_db
189 + lmdb
190 + easylogging
191 + unbound
192 + epee
193 + blocks
194 + checkpoints
195 + device
196 + device_trezor
197 + multisig
198 + version
199 + randomx
200 + hardforks
201 + rpc_base
202 +
203 + boost_chrono
204 + boost_date_time
205 + boost_filesystem
206 + boost_program_options
207 + boost_regex
208 + boost_serialization
209 + boost_system
210 + boost_thread
211 + boost_wserialization
212 +
213 + ssl
214 + crypto
215 +
216 + sodium
217 +
218 + ${log-lib} )
\ No newline at end of file
cw_monero/android/build.gradle new
+51
@@ -0,0 +1,51 @@
1 +group 'com.cakewallet.monero'
2 +version '1.0-SNAPSHOT'
3 +
4 +buildscript {
5 + ext.kotlin_version = '1.3.50'
6 + repositories {
7 + google()
8 + jcenter()
9 + }
10 +
11 + dependencies {
12 + classpath 'com.android.tools.build:gradle:3.5.0'
13 + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14 + }
15 +}
16 +
17 +rootProject.allprojects {
18 + repositories {
19 + google()
20 + jcenter()
21 + }
22 +}
23 +
24 +apply plugin: 'com.android.library'
25 +apply plugin: 'kotlin-android'
26 +
27 +android {
28 + compileSdkVersion 28
29 +
30 + sourceSets {
31 + main.java.srcDirs += 'src/main/kotlin'
32 + }
33 + defaultConfig {
34 + minSdkVersion 21
35 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
36 + }
37 + lintOptions {
38 + disable 'InvalidPackage'
39 + }
40 + externalNativeBuild {
41 + // Encapsulates your CMake build configurations.
42 + cmake {
43 + // Provides a relative path to your CMake build script.
44 + path "CMakeLists.txt"
45 + }
46 + }
47 +}
48 +
49 +dependencies {
50 + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
51 +}
cw_monero/android/gradle.properties new
+4
@@ -0,0 +1,4 @@
1 +org.gradle.jvmargs=-Xmx1536M
2 +android.enableR8=true
3 +android.useAndroidX=true
4 +android.enableJetifier=true
cw_monero/android/gradle/wrapper/gradle-wrapper.properties new
+5
@@ -0,0 +1,5 @@
1 +distributionBase=GRADLE_USER_HOME
2 +distributionPath=wrapper/dists
3 +zipStoreBase=GRADLE_USER_HOME
4 +zipStorePath=wrapper/dists
5 +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
cw_monero/android/jni/monero_jni.cpp new
+74
@@ -0,0 +1,74 @@
1 +#include <string.h>
2 +#include <jni.h>
3 +#include "../../ios/Classes/monero_api.h"
4 +#include <stdbool.h>
5 +
6 +#ifdef __cplusplus
7 +extern "C" {
8 +#endif
9 +
10 +JNIEXPORT void JNICALL
11 +Java_com_cakewallet_monero_MoneroApi_setNodeAddressJNI(
12 + JNIEnv *env,
13 + jobject inst,
14 + jstring uri,
15 + jstring login,
16 + jstring password,
17 + jboolean use_ssl,
18 + jboolean is_light_wallet) {
19 + const char *_uri = env->GetStringUTFChars(uri, 0);
20 + const char *_login = "";
21 + const char *_password = "";
22 + char *error;
23 +
24 + if (login != NULL) {
25 + _login = env->GetStringUTFChars(login, 0);
26 + }
27 +
28 + if (password != NULL) {
29 + _password = env->GetStringUTFChars(password, 0);
30 + }
31 + char *__uri = (char*) _uri;
32 + char *__login = (char*) _login;
33 + char *__password = (char*) _password;
34 + bool inited = setup_node(__uri, __login, __password, false, false, error);
35 +
36 + if (!inited) {
37 + env->ThrowNew(env->FindClass("java/lang/Exception"), error);
38 + }
39 +}
40 +
41 +JNIEXPORT void JNICALL
42 +Java_com_cakewallet_monero_MoneroApi_connectToNodeJNI(
43 + JNIEnv *env,
44 + jobject inst) {
45 + char *error;
46 + bool is_connected = connect_to_node(error);
47 +
48 + if (!is_connected) {
49 + env->ThrowNew(env->FindClass("java/lang/Exception"), error);
50 + }
51 +}
52 +
53 +JNIEXPORT void JNICALL
54 +Java_com_cakewallet_monero_MoneroApi_startSyncJNI(
55 + JNIEnv *env,
56 + jobject inst) {
57 + start_refresh();
58 +}
59 +
60 +JNIEXPORT void JNICALL
61 +Java_com_cakewallet_monero_MoneroApi_loadWalletJNI(
62 + JNIEnv *env,
63 + jobject inst,
64 + jstring path,
65 + jstring password) {
66 + char *_path = (char *) env->GetStringUTFChars(path, 0);
67 + char *_password = (char *) env->GetStringUTFChars(password, 0);
68 +
69 + load_wallet(_path, _password, 0);
70 +}
71 +
72 +#ifdef __cplusplus
73 +}
74 +#endif
\ No newline at end of file
cw_monero/android/settings.gradle new
+1
@@ -0,0 +1 @@
1 +rootProject.name = 'cw_monero'
cw_monero/android/src/main/AndroidManifest.xml new
+4
@@ -0,0 +1,4 @@
1 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2 + package="com.cakewallet.monero">
3 + <uses-permission android:name="android.permission.INTERNET"/>
4 +</manifest>
cw_monero/android/src/main/kotlin/com/cakewallet/monero/CwMoneroPlugin.kt new
+74
@@ -0,0 +1,74 @@
1 +package com.cakewallet.monero
2 +
3 +import android.app.Activity
4 +import android.os.AsyncTask
5 +import android.os.Looper
6 +import android.os.Handler
7 +import android.os.Process
8 +
9 +import io.flutter.plugin.common.MethodCall
10 +import io.flutter.plugin.common.MethodChannel
11 +import io.flutter.plugin.common.MethodChannel.MethodCallHandler
12 +import io.flutter.plugin.common.MethodChannel.Result
13 +import io.flutter.plugin.common.PluginRegistry.Registrar
14 +
15 +class doAsync(val handler: () -> Unit) : AsyncTask<Void, Void, Void>() {
16 + override fun doInBackground(vararg params: Void?): Void? {
17 + Process.setThreadPriority(Process.THREAD_PRIORITY_AUDIO);
18 + handler()
19 + return null
20 + }
21 +}
22 +
23 +class CwMoneroPlugin: MethodCallHandler {
24 + companion object {
25 + val moneroApi = MoneroApi()
26 + val main = Handler(Looper.getMainLooper());
27 +
28 + init {
29 + System.loadLibrary("cw_monero")
30 + }
31 +
32 + @JvmStatic
33 + fun registerWith(registrar: Registrar) {
34 + val channel = MethodChannel(registrar.messenger(), "cw_monero")
35 + channel.setMethodCallHandler(CwMoneroPlugin())
36 + }
37 + }
38 +
39 + override fun onMethodCall(call: MethodCall, result: Result) {
40 + if (call.method == "setupNode") {
41 + val uri = call.argument("address") ?: ""
42 + val login = call.argument("login") ?: ""
43 + val password = call.argument("password") ?: ""
44 + val useSSL = false
45 + val isLightWallet = false
46 + doAsync {
47 + try {
48 + moneroApi.setNodeAddressJNI(uri, login, password, useSSL, isLightWallet)
49 + main.post({
50 + result.success(true)
51 + });
52 + } catch(e: Throwable) {
53 + main.post({
54 + result.error("CONNECTION_ERROR", e.message, null)
55 + });
56 + }
57 + }.execute()
58 + }
59 + if (call.method == "startSync") {
60 + doAsync {
61 + moneroApi.startSyncJNI()
62 + main.post({
63 + result.success(true)
64 + });
65 + }.execute()
66 + }
67 + if (call.method == "loadWallet") {
68 + val path = call.argument("path") ?: ""
69 + val password = call.argument("password") ?: ""
70 + moneroApi.loadWalletJNI(path, password)
71 + result.success(true)
72 + }
73 + }
74 +}
cw_monero/android/src/main/kotlin/com/cakewallet/monero/MoneroApi.kt new
+14
@@ -0,0 +1,14 @@
1 +package com.cakewallet.monero
2 +
3 +class MoneroApi {
4 + external fun setNodeAddressJNI(uri: String, login: String, password: String, use_ssl: Boolean, is_light_wallet: Boolean)
5 + external fun connectToNodeJNI()
6 + external fun startSyncJNI()
7 + external fun loadWalletJNI(path: String, password: String)
8 +
9 + companion object {
10 + init {
11 + System.loadLibrary("cw_monero")
12 + }
13 + }
14 +}
\ No newline at end of file
cw_monero/ios/.gitignore new
+37
@@ -0,0 +1,37 @@
1 +.idea/
2 +.vagrant/
3 +.sconsign.dblite
4 +.svn/
5 +
6 +.DS_Store
7 +*.swp
8 +profile
9 +
10 +DerivedData/
11 +build/
12 +GeneratedPluginRegistrant.h
13 +GeneratedPluginRegistrant.m
14 +
15 +.generated/
16 +
17 +*.pbxuser
18 +*.mode1v3
19 +*.mode2v3
20 +*.perspectivev3
21 +
22 +!default.pbxuser
23 +!default.mode1v3
24 +!default.mode2v3
25 +!default.perspectivev3
26 +
27 +xcuserdata
28 +
29 +*.moved-aside
30 +
31 +*.pyc
32 +*sync/
33 +Icon?
34 +.tags*
35 +
36 +/Flutter/Generated.xcconfig
37 +/Flutter/flutter_export_environment.sh
\ No newline at end of file
cw_monero/ios/Assets/.gitkeep
cw_monero/ios/Classes/CwMoneroPlugin.h new
+4
@@ -0,0 +1,4 @@
1 +#import <Flutter/Flutter.h>
2 +
3 +@interface CwMoneroPlugin : NSObject<FlutterPlugin>
4 +@end
cw_monero/ios/Classes/CwMoneroPlugin.m new
+8
@@ -0,0 +1,8 @@
1 +#import "CwMoneroPlugin.h"
2 +#import <cw_monero/cw_monero-Swift.h>
3 +
4 +@implementation CwMoneroPlugin
5 ++ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
6 + [SwiftCwMoneroPlugin registerWithRegistrar:registrar];
7 +}
8 +@end
cw_monero/ios/Classes/CwWalletListener.h new
+23
@@ -0,0 +1,23 @@
1 +#include <stdint.h>
2 +
3 +struct CWMoneroWalletListener;
4 +
5 +typedef int8_t (*on_new_block_callback)(uint64_t height);
6 +typedef int8_t (*on_need_to_refresh_callback)();
7 +
8 +typedef struct CWMoneroWalletListener
9 +{
10 + // on_money_spent_callback *on_money_spent;
11 + // on_money_received_callback *on_money_received;
12 + // on_unconfirmed_money_received_callback *on_unconfirmed_money_received;
13 + // on_new_block_callback *on_new_block;
14 + // on_updated_callback *on_updated;
15 + // on_refreshed_callback *on_refreshed;
16 +
17 + on_new_block_callback on_new_block;
18 +} CWMoneroWalletListener;
19 +
20 +struct TestListener {
21 + // int8_t x;
22 + on_new_block_callback on_new_block;
23 +};
\ No newline at end of file
cw_monero/ios/Classes/SwiftCwMoneroPlugin.swift new
+14
@@ -0,0 +1,14 @@
1 +import Flutter
2 +import UIKit
3 +
4 +public class SwiftCwMoneroPlugin: NSObject, FlutterPlugin {
5 + public static func register(with registrar: FlutterPluginRegistrar) {
6 + let channel = FlutterMethodChannel(name: "cw_monero", binaryMessenger: registrar.messenger())
7 + let instance = SwiftCwMoneroPlugin()
8 + registrar.addMethodCallDelegate(instance, channel: channel)
9 + }
10 +
11 + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
12 + result("iOS " + UIDevice.current.systemVersion)
13 + }
14 +}
cw_monero/ios/Classes/monero_api.cpp new
+671
@@ -0,0 +1,671 @@
1 +#include <stdint.h>
2 +#include "cstdlib"
3 +#include <chrono>
4 +#include <functional>
5 +#include <iostream>
6 +#include <unistd.h>
7 +#include "thread"
8 +#include "../External/android/monero/include/wallet2_api.h"
9 +#include "CwWalletListener.h"
10 +
11 +using namespace std::chrono_literals;
12 +
13 +#ifdef __cplusplus
14 +extern "C"
15 +{
16 +#endif
17 +
18 + struct Utf8Box
19 + {
20 + char *value;
21 +
22 + Utf8Box(char *_value)
23 + {
24 + value = _value;
25 + }
26 + };
27 +
28 + struct SubaddressRow
29 + {
30 + uint64_t id;
31 + char *address;
32 + char *label;
33 +
34 + SubaddressRow(std::size_t _id, char *_address, char *_label)
35 + {
36 + id = static_cast<uint64_t>(_id);
37 + address = _address;
38 + label = _label;
39 + }
40 + };
41 +
42 + struct AccountRow
43 + {
44 + uint64_t id;
45 + char *label;
46 +
47 + AccountRow(std::size_t _id, char *_label)
48 + {
49 + id = static_cast<uint64_t>(_id);
50 + label = _label;
51 + }
52 + };
53 +
54 + struct MoneroWalletListener : Monero::WalletListener
55 + {
56 + uint64_t m_height;
57 + bool m_need_to_refresh;
58 + bool m_new_transaction;
59 +
60 + MoneroWalletListener()
61 + {
62 + m_height = 0;
63 + m_need_to_refresh = false;
64 + m_new_transaction = false;
65 + }
66 +
67 + void moneySpent(const std::string &txId, uint64_t amount)
68 + {
69 + m_new_transaction = true;
70 + }
71 +
72 + void moneyReceived(const std::string &txId, uint64_t amount)
73 + {
74 + m_new_transaction = true;
75 + }
76 +
77 + void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount)
78 + {
79 + m_new_transaction = true;
80 + }
81 +
82 + void newBlock(uint64_t height)
83 + {
84 + m_height = height;
85 + }
86 +
87 + void updated()
88 + {
89 + m_need_to_refresh = true;
90 + }
91 +
92 + void refreshed()
93 + {
94 + m_need_to_refresh = true;
95 + }
96 +
97 + void resetNeedToRefresh()
98 + {
99 + m_need_to_refresh = false;
100 + }
101 +
102 + bool isNeedToRefresh()
103 + {
104 + return m_need_to_refresh;
105 + }
106 +
107 + bool isNewTransactionExist()
108 + {
109 + return m_new_transaction;
110 + }
111 +
112 + void resetIsNewTransactionExist()
113 + {
114 + m_new_transaction = false;
115 + }
116 +
117 + uint64_t height()
118 + {
119 + return m_height;
120 + }
121 + };
122 +
123 + struct TransactionInfoRow
124 + {
125 + uint64_t amount;
126 + uint64_t fee;
127 + uint64_t blockHeight;
128 + uint64_t confirmations;
129 + uint32_t subaddrAccount;
130 + int8_t direction;
131 + int8_t isPending;
132 +
133 + char *hash;
134 + char *paymentId;
135 +
136 + int64_t datetime;
137 +
138 + TransactionInfoRow(Monero::TransactionInfo *transaction)
139 + {
140 + amount = transaction->amount();
141 + fee = transaction->fee();
142 + blockHeight = transaction->blockHeight();
143 + subaddrAccount = transaction->subaddrAccount();
144 + confirmations = transaction->confirmations();
145 + datetime = static_cast<int64_t>(transaction->timestamp());
146 + direction = transaction->direction();
147 + isPending = static_cast<int8_t>(transaction->isPending());
148 + std::string *hash_str = new std::string(transaction->hash());
149 + hash = strdup(hash_str->c_str());
150 + paymentId = strdup(transaction->paymentId().c_str());
151 + }
152 + };
153 +
154 + struct PendingTransactionRaw
155 + {
156 + uint64_t amount;
157 + uint64_t fee;
158 + char *hash;
159 + Monero::PendingTransaction *transaction;
160 +
161 + PendingTransactionRaw(Monero::PendingTransaction *_transaction)
162 + {
163 + transaction = _transaction;
164 + amount = _transaction->amount();
165 + fee = _transaction->fee();
166 + hash = strdup(_transaction->txid()[0].c_str());
167 + }
168 + };
169 +
170 + Monero::Wallet *m_wallet;
171 + Monero::TransactionHistory *m_transaction_history;
172 + MoneroWalletListener *m_listener;
173 + Monero::Subaddress *m_subaddress;
174 + Monero::SubaddressAccount *m_account;
175 + uint64_t m_last_known_wallet_height;
176 +
177 + void change_current_wallet(Monero::Wallet *wallet)
178 + {
179 + m_wallet = wallet;
180 + // m_listener = nullptr;
181 +
182 +
183 + if (wallet != nullptr)
184 + {
185 + m_transaction_history = wallet->history();
186 + }
187 + else
188 + {
189 + m_transaction_history = nullptr;
190 + }
191 +
192 + if (wallet != nullptr)
193 + {
194 + m_account = wallet->subaddressAccount();
195 + }
196 + else
197 + {
198 + m_account = nullptr;
199 + }
200 +
201 + if (wallet != nullptr)
202 + {
203 + m_subaddress = wallet->subaddress();
204 + }
205 + else
206 + {
207 + m_subaddress = nullptr;
208 + }
209 + }
210 +
211 + Monero::Wallet *get_current_wallet()
212 + {
213 + return m_wallet;
214 + }
215 +
216 + bool create_wallet(char *path, char *password, char *language, int32_t networkType, char *error)
217 + {
218 + Monero::NetworkType _networkType = static_cast<Monero::NetworkType>(networkType);
219 + Monero::WalletManager *walletManager = Monero::WalletManagerFactory::getWalletManager();
220 + Monero::Wallet *wallet = walletManager->createWallet(path, password, language, _networkType);
221 +
222 + int status;
223 + std::string errorString;
224 +
225 + wallet->statusWithErrorString(status, errorString);
226 +
227 + if (status != Monero::Wallet::Status_Ok)
228 + {
229 + error = strdup(errorString.c_str());
230 + return false;
231 + }
232 +
233 + change_current_wallet(wallet);
234 +
235 + return true;
236 + }
237 +
238 + bool restore_wallet_from_seed(char *path, char *password, char *seed, int32_t networkType, uint64_t restoreHeight, char *error)
239 + {
240 + Monero::NetworkType _networkType = static_cast<Monero::NetworkType>(networkType);
241 + Monero::Wallet *wallet = Monero::WalletManagerFactory::getWalletManager()->recoveryWallet(
242 + std::string(path),
243 + std::string(password),
244 + std::string(seed),
245 + _networkType,
246 + (uint64_t)restoreHeight);
247 +
248 + int status;
249 + std::string errorString;
250 +
251 + wallet->statusWithErrorString(status, errorString);
252 +
253 + if (status != Monero::Wallet::Status_Ok)
254 + {
255 + error = strdup(errorString.c_str());
256 + return false;
257 + }
258 +
259 + change_current_wallet(wallet);
260 + return true;
261 + }
262 +
263 + bool restore_wallet_from_keys(char *path, char *password, char *language, char *address, char *viewKey, char *spendKey, int32_t networkType, uint64_t restoreHeight, char *error)
264 + {
265 + Monero::NetworkType _networkType = static_cast<Monero::NetworkType>(networkType);
266 + Monero::Wallet *wallet = Monero::WalletManagerFactory::getWalletManager()->createWalletFromKeys(
267 + std::string(path),
268 + std::string(password),
269 + std::string(language),
270 + _networkType,
271 + (uint64_t)restoreHeight,
272 + std::string(address),
273 + std::string(viewKey),
274 + std::string(spendKey));
275 +
276 + int status;
277 + std::string errorString;
278 +
279 + wallet->statusWithErrorString(status, errorString);
280 +
281 + if (status != Monero::Wallet::Status_Ok)
282 + {
283 + error = strdup(errorString.c_str());
284 + return false;
285 + }
286 +
287 + change_current_wallet(wallet);
288 + return true;
289 + }
290 +
291 + void load_wallet(char *path, char *password, int32_t nettype)
292 + {
293 + Monero::NetworkType networkType = static_cast<Monero::NetworkType>(nettype);
294 + Monero::Wallet *wallet = Monero::WalletManagerFactory::getWalletManager()->openWallet(std::string(path), std::string(password), networkType);
295 + change_current_wallet(wallet);
296 + }
297 +
298 + bool is_wallet_exist(char *path)
299 + {
300 + return Monero::WalletManagerFactory::getWalletManager()->walletExists(std::string(path));
301 + }
302 +
303 + void close_current_wallet()
304 + {
305 + Monero::WalletManagerFactory::getWalletManager()->closeWallet(get_current_wallet());
306 + change_current_wallet(nullptr);
307 + }
308 +
309 + char *get_filename()
310 + {
311 + return strdup(get_current_wallet()->filename().c_str());
312 + }
313 +
314 + char *secret_view_key()
315 + {
316 + return strdup(get_current_wallet()->secretViewKey().c_str());
317 + }
318 +
319 + char *public_view_key()
320 + {
321 + return strdup(get_current_wallet()->publicViewKey().c_str());
322 + }
323 +
324 + char *secret_spend_key()
325 + {
326 + return strdup(get_current_wallet()->secretSpendKey().c_str());
327 + }
328 +
329 + char *public_spend_key()
330 + {
331 + return strdup(get_current_wallet()->publicSpendKey().c_str());
332 + }
333 +
334 + char *get_address(uint32_t account_index, uint32_t address_index)
335 + {
336 + return strdup(get_current_wallet()->address(account_index, address_index).c_str());
337 + }
338 +
339 +
340 + const char *seed()
341 + {
342 + return strdup(get_current_wallet()->seed().c_str());
343 + }
344 +
345 + uint64_t get_full_balance(uint32_t account_index)
346 + {
347 + return get_current_wallet()->balance(account_index);
348 + }
349 +
350 + uint64_t get_unlocked_balance(uint32_t account_index)
351 + {
352 + return get_current_wallet()->unlockedBalance(account_index);
353 + }
354 +
355 + uint64_t get_current_height()
356 + {
357 + return get_current_wallet()->blockChainHeight();
358 + }
359 +
360 + uint64_t get_node_height()
361 + {
362 + return get_current_wallet()->daemonBlockChainHeight();
363 + }
364 +
365 + bool connect_to_node(char *error)
366 + {
367 + bool is_connected = get_current_wallet()->connectToDaemon();
368 +
369 + if (!is_connected)
370 + {
371 + error = strdup(get_current_wallet()->errorString().c_str());
372 + }
373 +
374 + return is_connected;
375 + }
376 +
377 + bool setup_node(char *address, char *login, char *password, bool use_ssl, bool is_light_wallet, char *error)
378 + {
379 + Monero::Wallet *wallet = get_current_wallet();
380 +
381 + std::string _login = "";
382 + std::string _password = "";
383 +
384 + if (login != nullptr)
385 + {
386 + _login = std::string(login);
387 + }
388 +
389 + if (password != nullptr)
390 + {
391 + _password = std::string(password);
392 + }
393 +
394 + bool inited = wallet->init(std::string(address), 0, _login, _password, use_ssl, is_light_wallet);
395 +
396 + if (!inited)
397 + {
398 + error = strdup(wallet->errorString().c_str());
399 + } else if (!wallet->connectToDaemon()) {
400 + error = strdup(wallet->errorString().c_str());
401 + }
402 +
403 + return inited;
404 + }
405 +
406 + bool is_connected()
407 + {
408 + return get_current_wallet()->connected();
409 + }
410 +
411 + void start_refresh()
412 + {
413 + get_current_wallet()->refreshAsync();
414 + get_current_wallet()->startRefresh();
415 + }
416 +
417 + void set_refresh_from_block_height(uint64_t height)
418 + {
419 + get_current_wallet()->setRefreshFromBlockHeight(height);
420 + }
421 +
422 + void set_recovering_from_seed(bool is_recovery)
423 + {
424 + get_current_wallet()->setRecoveringFromSeed(is_recovery);
425 + }
426 +
427 + void store(char *path)
428 + {
429 + get_current_wallet()->store(std::string(path));
430 + }
431 +
432 + bool transaction_create(char *address, char *payment_id, char *amount,
433 + uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction)
434 + {
435 + nice(19);
436 +
437 + auto priority = static_cast<Monero::PendingTransaction::Priority>(priority_raw);
438 + std::string _payment_id;
439 + Monero::PendingTransaction *transaction;
440 +
441 + if (payment_id != nullptr)
442 + {
443 + _payment_id = std::string(payment_id);
444 + }
445 +
446 + if (amount != nullptr)
447 + {
448 + uint64_t _amount = Monero::Wallet::amountFromString(std::string(amount));
449 + transaction = m_wallet->createTransaction(std::string(address), _payment_id, _amount, m_wallet->defaultMixin(), priority, subaddr_account);
450 + }
451 + else
452 + {
453 + transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional<uint64_t>(), m_wallet->defaultMixin(), priority, subaddr_account);
454 + }
455 +
456 + int status = transaction->status();
457 +
458 + if (status == Monero::PendingTransaction::Status::Status_Error || status == Monero::PendingTransaction::Status::Status_Critical)
459 + {
460 + error = Utf8Box(strdup(transaction->errorString().c_str()));
461 + return false;
462 + }
463 +
464 + m_listener->m_new_transaction = true;
465 +
466 + pendingTransaction = PendingTransactionRaw(transaction);
467 + return true;
468 + }
469 +
470 + bool transaction_commit(PendingTransactionRaw *transaction, Utf8Box &error)
471 + {
472 + bool committed = transaction->transaction->commit();
473 +
474 + if (!committed)
475 + {
476 + error = Utf8Box(strdup(transaction->transaction->errorString().c_str()));
477 + } else {
478 + m_listener->m_new_transaction = true;
479 + }
480 +
481 + return committed;
482 + }
483 +
484 + uint64_t get_syncing_height()
485 + {
486 + if (m_listener == nullptr) {
487 + return 0;
488 + }
489 +
490 + uint64_t _height = m_listener->height();
491 +
492 + if (_height != m_last_known_wallet_height)
493 + {
494 + m_last_known_wallet_height = _height;
495 + }
496 +
497 + return _height;
498 + }
499 +
500 + uint64_t is_needed_to_refresh()
501 + {
502 + if (m_listener == nullptr) {
503 + return false;
504 + }
505 +
506 + bool should_refresh = m_listener->isNeedToRefresh();
507 +
508 + if (should_refresh)
509 + {
510 + m_listener->resetNeedToRefresh();
511 + }
512 +
513 + return should_refresh;
514 + }
515 +
516 + uint8_t is_new_transaction_exist()
517 + {
518 + if (m_listener == nullptr) {
519 + return false;
520 + }
521 +
522 + bool is_new_transaction_exist = m_listener->isNewTransactionExist();
523 +
524 + if (is_new_transaction_exist)
525 + {
526 + m_listener->resetIsNewTransactionExist();
527 + }
528 +
529 + return is_new_transaction_exist;
530 + }
531 +
532 + void set_listener()
533 + {
534 + m_last_known_wallet_height = 0;
535 +
536 + if (m_listener != nullptr)
537 + {
538 + free(m_listener);
539 + }
540 +
541 + m_listener = new MoneroWalletListener();
542 + get_current_wallet()->setListener(m_listener);
543 + }
544 +
545 + int64_t *subaddrress_get_all()
546 + {
547 + std::vector<Monero::SubaddressRow *> _subaddresses = m_subaddress->getAll();
548 + size_t size = _subaddresses.size();
549 + int64_t *subaddresses = (int64_t *)malloc(size * sizeof(int64_t));
550 +
551 + for (int i = 0; i < size; i++)
552 + {
553 + Monero::SubaddressRow *row = _subaddresses[i];
554 + SubaddressRow *_row = new SubaddressRow(row->getRowId(), strdup(row->getAddress().c_str()), strdup(row->getLabel().c_str()));
555 + subaddresses[i] = reinterpret_cast<int64_t>(_row);
556 + }
557 +
558 + return subaddresses;
559 + }
560 +
561 + int32_t subaddrress_size()
562 + {
563 + std::vector<Monero::SubaddressRow *> _subaddresses = m_subaddress->getAll();
564 + return _subaddresses.size();
565 + }
566 +
567 + void subaddress_add_row(uint32_t accountIndex, char *label)
568 + {
569 + m_subaddress->addRow(accountIndex, std::string(label));
570 + }
571 +
572 + void subaddress_set_label(uint32_t accountIndex, uint32_t addressIndex, char *label)
573 + {
574 + m_subaddress->setLabel(accountIndex, addressIndex, std::string(label));
575 + }
576 +
577 + void subaddress_refresh(uint32_t accountIndex)
578 + {
579 + m_subaddress->refresh(accountIndex);
580 + }
581 +
582 + int32_t account_size()
583 + {
584 + std::vector<Monero::SubaddressAccountRow *> _accocunts = m_account->getAll();
585 + return _accocunts.size();
586 + }
587 +
588 + int64_t *account_get_all()
589 + {
590 + std::vector<Monero::SubaddressAccountRow *> _accocunts = m_account->getAll();
591 + size_t size = _accocunts.size();
592 + int64_t *accocunts = (int64_t *)malloc(size * sizeof(int64_t));
593 +
594 + for (int i = 0; i < size; i++)
595 + {
596 + Monero::SubaddressAccountRow *row = _accocunts[i];
597 + AccountRow *_row = new AccountRow(row->getRowId(), strdup(row->getLabel().c_str()));
598 + accocunts[i] = reinterpret_cast<int64_t>(_row);
599 + }
600 +
601 + return accocunts;
602 + }
603 +
604 + void account_add_row(char *label)
605 + {
606 + m_account->addRow(std::string(label));
607 + }
608 +
609 + void account_set_label_row(uint32_t account_index, char *label)
610 + {
611 + m_account->setLabel(account_index, label);
612 + }
613 +
614 + void account_refresh()
615 + {
616 + m_account->refresh();
617 + }
618 +
619 + int64_t *transactions_get_all()
620 + {
621 + std::vector<Monero::TransactionInfo *> transactions = m_transaction_history->getAll();
622 + size_t size = transactions.size();
623 + int64_t *transactionAddresses = (int64_t *)malloc(size * sizeof(int64_t));
624 +
625 + for (int i = 0; i < size; i++)
626 + {
627 + Monero::TransactionInfo *row = transactions[i];
628 + TransactionInfoRow *tx = new TransactionInfoRow(row);
629 + transactionAddresses[i] = reinterpret_cast<int64_t>(tx);
630 + }
631 +
632 + return transactionAddresses;
633 + }
634 +
635 + void transactions_refresh()
636 + {
637 + m_transaction_history->refresh();
638 + }
639 +
640 + int64_t transactions_count()
641 + {
642 + return m_transaction_history->count();
643 + }
644 +
645 + int LedgerExchange(
646 + unsigned char *command,
647 + unsigned int cmd_len,
648 + unsigned char *response,
649 + unsigned int max_resp_len)
650 + {
651 + return -1;
652 + }
653 +
654 + int LedgerFind(char *buffer, size_t len)
655 + {
656 + return -1;
657 + }
658 +
659 + void on_startup()
660 + {
661 + Monero::Utils::onStartup();
662 + }
663 +
664 + void rescan_blockchain()
665 + {
666 + m_wallet->rescanBlockchainAsync();
667 + }
668 +
669 +#ifdef __cplusplus
670 +}
671 +#endif
cw_monero/ios/Classes/monero_api.h new
+35
@@ -0,0 +1,35 @@
1 +#include <stdint.h>
2 +#include <stdio.h>
3 +#include <stdbool.h>
4 +#include "CwWalletListener.h"
5 +
6 +#ifdef __cplusplus
7 +extern "C" {
8 +#endif
9 +
10 +bool create_wallet(char *path, char *password, char *language, int32_t networkType, char *error);
11 +bool restore_wallet_from_seed(char *path, char *password, char *seed, int32_t networkType, uint64_t restoreHeight, char *error);
12 +bool restore_wallet_from_keys(char *path, char *password, char *language, char *address, char *viewKey, char *spendKey, int32_t networkType, uint64_t restoreHeight, char *error);
13 +void load_wallet(char *path, char *password, int32_t nettype);
14 +bool is_wallet_exist(char *path);
15 +
16 +char *get_filename();
17 +const char *seed();
18 +char *get_address(uint32_t account_index, uint32_t address_index);
19 +uint64_t get_full_balance(uint32_t account_index);
20 +uint64_t get_unlocked_balance(uint32_t account_index);
21 +uint64_t get_current_height();
22 +uint64_t get_node_height();
23 +
24 +bool is_connected();
25 +
26 +bool setup_node(char *address, char *login, char *password, bool use_ssl, bool is_light_wallet, char *error);
27 +bool connect_to_node(char *error);
28 +void start_refresh();
29 +void set_refresh_from_block_height(uint64_t height);
30 +void set_recovering_from_seed(bool is_recovery);
31 +void store(char *path);
32 +
33 +#ifdef __cplusplus
34 +}
35 +#endif
\ No newline at end of file
cw_monero/ios/cw_monero.podspec new
+51
@@ -0,0 +1,51 @@
1 +#
2 +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
3 +# Run `pod lib lint cw_monero.podspec' to validate before publishing.
4 +#
5 +Pod::Spec.new do |s|
6 + s.name = 'cw_monero'
7 + s.version = '0.0.2'
8 + s.summary = 'A new flutter plugin project.'
9 + s.description = <<-DESC
10 +A new flutter plugin project.
11 + DESC
12 + s.homepage = 'http://example.com'
13 + s.license = { :file => '../LICENSE' }
14 + s.author = { 'Your Company' => 'email@example.com' }
15 + s.source = { :path => '.' }
16 + s.source_files = 'Classes/**/*'
17 + s.public_header_files = 'Classes/**/*.h, Classes/*.h, External/ios/libs/monero/include/src/**/*.h, External/ios/libs/monero/include/contrib/**/*.h, External/ios/libs/monero/include/External/ios/**/*.h'
18 + s.dependency 'Flutter'
19 + s.platform = :ios, '9.0'
20 + s.swift_version = '4.0'
21 + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS' => 'arm64' }
22 + s.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/#{s.name}/Classes/*.h" }
23 +
24 + s.subspec 'OpenSSL' do |openssl|
25 + openssl.preserve_paths = 'External/ios/libs/OpenSSL/include/openssl/*.h', 'External/ios/libs/OpenSSL/include/LICENSE'
26 + openssl.vendored_libraries = 'External/ios/libs/OpenSSL/lib/libcrypto.a', 'External/ios/libs/OpenSSL/lib/libssl.a'
27 + openssl.libraries = 'ssl', 'crypto'
28 + openssl.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/#{s.name}/External/ios/libs/OpenSSL/include/**" }
29 + end
30 +
31 + s.subspec 'Monero' do |monero|
32 + monero.preserve_paths = 'External/ios/libs/monero/include/src/**/*.h', 'External/ios/libs/monero/include/External/ios/**/*.h', 'External/ios/libs/monero/include/contrib/**/*.h'
33 + monero.vendored_libraries = 'External/ios/libs/monero/libs/lib-ios/*.a'
34 + monero.libraries = 'easylogging', 'epee', 'unbound', 'wallet_merged', 'lmdb', 'randomx'
35 + monero.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/#{s.name}/External/ios/libs/monero/include/src/**" }
36 + end
37 +
38 + s.subspec 'Boost' do |boost|
39 + boost.preserve_paths = 'External/ios/libs/boost/include/**/*.h', 'External/ios/libs/boost/include/**/*.h'
40 + boost.vendored_libraries = 'External/ios/libs/boost/build/libs/universal/*.a'
41 + boost.libraries = 'boost', 'boost_wserialization', 'boost_thread', 'boost_system', 'boost_signals', 'boost_serialization', 'boost_regex', 'boost_random', 'boost_program_options', 'boost_locale', 'boost_graph', 'boost_filesystem', 'boost_date_time', 'boost_chrono'
42 + boost.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/#{s.name}/External/ios/libs/boost/include/**" }
43 + end
44 +
45 + s.subspec 'Sodium' do |sodium|
46 + sodium.preserve_paths = 'External/ios/libs/sodium/include/**/*.h'
47 + sodium.vendored_libraries = 'External/ios/libs/sodium/lib/libsodium.a'
48 + sodium.libraries = 'sodium'
49 + sodium.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/#{s.name}/External/ios/libs/sodium/include/**" }
50 + end
51 +end
\ No newline at end of file
cw_monero/lib/account_list.dart new
+61
@@ -0,0 +1,61 @@
1 +import 'dart:ffi';
2 +import 'package:ffi/ffi.dart';
3 +import 'package:cw_monero/signatures.dart';
4 +import 'package:cw_monero/types.dart';
5 +import 'package:cw_monero/monero_api.dart';
6 +import 'package:cw_monero/structs/account_row.dart';
7 +import 'package:flutter/foundation.dart';
8 +
9 +final accountSizeNative = moneroApi
10 + .lookup<NativeFunction<account_size>>('account_size')
11 + .asFunction<SubaddressSize>();
12 +
13 +final accountRefreshNative = moneroApi
14 + .lookup<NativeFunction<account_refresh>>('account_refresh')
15 + .asFunction<AccountRefresh>();
16 +
17 +final accountGetAllNative = moneroApi
18 + .lookup<NativeFunction<account_get_all>>('account_get_all')
19 + .asFunction<AccountGetAll>();
20 +
21 +final accountAddNewNative = moneroApi
22 + .lookup<NativeFunction<account_add_new>>('account_add_row')
23 + .asFunction<AccountAddNew>();
24 +
25 +final accountSetLabelNative = moneroApi
26 + .lookup<NativeFunction<account_set_label>>('account_set_label_row')
27 + .asFunction<AccountSetLabel>();
28 +
29 +refreshAccounts() => accountRefreshNative();
30 +
31 +List<AccountRow> getAllAccount() {
32 + final size = accountSizeNative();
33 + final accountAddressesPointer = accountGetAllNative();
34 + final accountAddresses = accountAddressesPointer.asTypedList(size);
35 +
36 + return accountAddresses
37 + .map((addr) => Pointer<AccountRow>.fromAddress(addr).ref)
38 + .toList();
39 +}
40 +
41 +addAccountSync({String label}) {
42 + final labelPointer = Utf8.toUtf8(label);
43 + accountAddNewNative(labelPointer);
44 + free(labelPointer);
45 +}
46 +
47 +setLabelForAccountSync({int accountIndex, String label}) {
48 + final labelPointer = Utf8.toUtf8(label);
49 + accountSetLabelNative(accountIndex, labelPointer);
50 + free(labelPointer);
51 +}
52 +
53 +_addAccount(String label) => addAccountSync(label: label);
54 +
55 +_setLabelForAccount(Map args) => setLabelForAccountSync(
56 + label: args['label'], accountIndex: args['accountIndex']);
57 +
58 +Future addAccount({String label}) async => compute(_addAccount, label);
59 +
60 +Future setLabelForAccount({int accountIndex, String label}) async => compute(
61 + _setLabelForAccount, {'accountIndex': accountIndex, 'label': label});
cw_monero/lib/convert_utf8_to_string.dart new
+8
@@ -0,0 +1,8 @@
1 +import 'dart:ffi';
2 +import 'package:ffi/ffi.dart';
3 +
4 +String convertUTF8ToString({Pointer<Utf8> pointer}) {
5 + final str = Utf8.fromUtf8(pointer);
6 + free(pointer);
7 + return str;
8 +}
\ No newline at end of file
cw_monero/lib/exceptions/connection_to_node_exception.dart new
+5
@@ -0,0 +1,5 @@
1 +class ConnectionToNodeException implements Exception {
2 + final String message;
3 +
4 + ConnectionToNodeException({this.message});
5 +}
\ No newline at end of file
cw_monero/lib/exceptions/creation_transaction_exception.dart new
+8
@@ -0,0 +1,8 @@
1 +class CreationTransactionException implements Exception {
2 + final String message;
3 +
4 + CreationTransactionException({this.message});
5 +
6 + @override
7 + String toString() => message;
8 +}
\ No newline at end of file
cw_monero/lib/exceptions/setup_wallet_exception.dart new
+5
@@ -0,0 +1,5 @@
1 +class SetupWalletException implements Exception {
2 + final String message;
3 +
4 + SetupWalletException({this.message});
5 +}
\ No newline at end of file
cw_monero/lib/exceptions/wallet_creation_exception.dart new
+5
@@ -0,0 +1,5 @@
1 +class WalletCreationException implements Exception {
2 + final String message;
3 +
4 + WalletCreationException({this.message});
5 +}
\ No newline at end of file
cw_monero/lib/exceptions/wallet_restore_from_keys_exception.dart new
+5
@@ -0,0 +1,5 @@
1 +class WalletRestoreFromKeysException implements Exception {
2 + final String message;
3 +
4 + WalletRestoreFromKeysException({this.message});
5 +}
\ No newline at end of file
cw_monero/lib/exceptions/wallet_restore_from_seed_exception.dart new
+5
@@ -0,0 +1,5 @@
1 +class WalletRestoreFromSeedException implements Exception {
2 + final String message;
3 +
4 + WalletRestoreFromSeedException({this.message});
5 +}
\ No newline at end of file
cw_monero/lib/monero_api.dart new
+6
@@ -0,0 +1,6 @@
1 +import 'dart:ffi';
2 +import 'dart:io';
3 +
4 +final DynamicLibrary moneroApi = Platform.isAndroid
5 + ? DynamicLibrary.open("libcw_monero.so")
6 + : DynamicLibrary.open("cw_monero.framework/cw_monero");
\ No newline at end of file
cw_monero/lib/signatures.dart new
+108
@@ -0,0 +1,108 @@
1 +import 'dart:ffi';
2 +import 'package:cw_monero/structs/pending_transaction.dart';
3 +import 'package:cw_monero/structs/ut8_box.dart';
4 +import 'package:ffi/ffi.dart';
5 +
6 +typedef create_wallet = Int8 Function(
7 + Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Pointer<Utf8>);
8 +
9 +typedef restore_wallet_from_seed = Int8 Function(
10 + Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>);
11 +
12 +typedef restore_wallet_from_keys = Int8 Function(Pointer<Utf8>, Pointer<Utf8>,
13 + Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>);
14 +
15 +typedef is_wallet_exist = Int8 Function(Pointer<Utf8>);
16 +
17 +typedef load_wallet = Void Function(Pointer<Utf8>, Pointer<Utf8>, Int8);
18 +
19 +typedef get_filename = Pointer<Utf8> Function();
20 +
21 +typedef get_seed = Pointer<Utf8> Function();
22 +
23 +typedef get_address = Pointer<Utf8> Function(Int32, Int32);
24 +
25 +typedef get_full_balanace = Int64 Function(Int32);
26 +
27 +typedef get_unlocked_balanace = Int64 Function(Int32);
28 +
29 +typedef get_current_height = Int64 Function();
30 +
31 +typedef get_node_height = Int64 Function();
32 +
33 +typedef is_connected = Int8 Function();
34 +
35 +typedef setup_node = Int8 Function(
36 + Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int8, Int8, Pointer<Utf8>);
37 +
38 +typedef start_refresh = Void Function();
39 +
40 +typedef connect_to_node = Int8 Function();
41 +
42 +typedef set_refresh_from_block_height = Void Function(Int64);
43 +
44 +typedef set_recovering_from_seed = Void Function(Int8);
45 +
46 +typedef store_c = Void Function(Pointer<Utf8>);
47 +
48 +typedef set_listener = Void Function();
49 +
50 +typedef get_syncing_height = Int64 Function();
51 +
52 +typedef is_needed_to_refresh = Int8 Function();
53 +
54 +typedef is_new_transaction_exist = Int8 Function();
55 +
56 +typedef subaddrress_size = Int32 Function();
57 +
58 +typedef subaddrress_refresh = Void Function(Int32);
59 +
60 +typedef subaddress_get_all = Pointer<Int64> Function();
61 +
62 +typedef subaddress_add_new = Void Function(
63 + Int32 accountIndex, Pointer<Utf8> label);
64 +
65 +typedef subaddress_set_label = Void Function(
66 + Int32 accountIndex, Int32 addressIndex, Pointer<Utf8> label);
67 +
68 +typedef account_size = Int32 Function();
69 +
70 +typedef account_refresh = Void Function();
71 +
72 +typedef account_get_all = Pointer<Int64> Function();
73 +
74 +typedef account_add_new = Void Function(Pointer<Utf8> label);
75 +
76 +typedef account_set_label = Void Function(
77 + Int32 accountIndex, Pointer<Utf8> label);
78 +
79 + typedef transactions_refresh = Void Function();
80 +
81 +typedef transactions_count = Int64 Function();
82 +
83 +typedef transactions_get_all = Pointer<Int64> Function();
84 +
85 +typedef transaction_create = Int8 Function(
86 + Pointer<Utf8> address,
87 + Pointer<Utf8> paymentId,
88 + Pointer<Utf8> amount,
89 + Int8 priorityRaw,
90 + Int32 subaddrAccount,
91 + Pointer<Utf8Box> error,
92 + Pointer<PendingTransactionRaw> pendingTransaction);
93 +
94 +typedef transaction_commit = Int8 Function(Pointer<PendingTransactionRaw>, Pointer<Utf8Box>);
95 +
96 +typedef secret_view_key = Pointer<Utf8> Function();
97 +
98 +typedef public_view_key = Pointer<Utf8> Function();
99 +
100 +typedef secret_spend_key = Pointer<Utf8> Function();
101 +
102 +typedef public_spend_key = Pointer<Utf8> Function();
103 +
104 +typedef close_current_wallet = Void Function();
105 +
106 +typedef on_startup = Void Function();
107 +
108 +typedef rescan_blockchain = Void Function();
cw_monero/lib/structs/account_row.dart new
+11
@@ -0,0 +1,11 @@
1 +import 'dart:ffi';
2 +import 'package:ffi/ffi.dart';
3 +
4 +class AccountRow extends Struct {
5 + @Int64()
6 + int id;
7 + Pointer<Utf8> label;
8 +
9 + String getLabel() => Utf8.fromUtf8(label);
10 + int getId() => id;
11 +}
cw_monero/lib/structs/pending_transaction.dart new
+23
@@ -0,0 +1,23 @@
1 +import 'dart:ffi';
2 +import 'package:ffi/ffi.dart';
3 +
4 +class PendingTransactionRaw extends Struct {
5 + @Int64()
6 + int amount;
7 +
8 + @Int64()
9 + int fee;
10 +
11 + Pointer<Utf8> hash;
12 +
13 + String getHash() => Utf8.fromUtf8(hash);
14 +}
15 +
16 +class PendingTransactionDescription {
17 + final int amount;
18 + final int fee;
19 + final String hash;
20 + final int pointerAddress;
21 +
22 + PendingTransactionDescription({this.amount, this.fee, this.hash, this.pointerAddress});
23 +}
\ No newline at end of file
cw_monero/lib/structs/subaddress_row.dart new
+13
@@ -0,0 +1,13 @@
1 +import 'dart:ffi';
2 +import 'package:ffi/ffi.dart';
3 +
4 +class SubaddressRow extends Struct {
5 + @Int64()
6 + int id;
7 + Pointer<Utf8> address;
8 + Pointer<Utf8> label;
9 +
10 + String getLabel() => Utf8.fromUtf8(label);
11 + String getAddress() => Utf8.fromUtf8(address);
12 + int getId() => id;
13 +}
\ No newline at end of file
cw_monero/lib/structs/transaction_info_row.dart new
+38
@@ -0,0 +1,38 @@
1 +import 'dart:ffi';
2 +import 'package:ffi/ffi.dart';
3 +
4 +class TransactionInfoRow extends Struct {
5 + @Uint64()
6 + int amount;
7 +
8 + @Uint64()
9 + int fee;
10 +
11 + @Uint64()
12 + int blockHeight;
13 +
14 + @Uint64()
15 + int confirmations;
16 +
17 + @Uint32()
18 + int subaddrAccount;
19 +
20 + @Int8()
21 + int direction;
22 +
23 + @Int8()
24 + int isPending;
25 +
26 + Pointer<Utf8> hash;
27 +
28 + Pointer<Utf8> paymentId;
29 +
30 + @Int64()
31 + int datetime;
32 +
33 + int getDatetime() => datetime;
34 + int getAmount() => amount >= 0 ? amount : amount * -1;
35 + bool getIsPending() => isPending != 0;
36 + String getHash() => Utf8.fromUtf8(hash);
37 + String getPaymentId() => Utf8.fromUtf8(paymentId);
38 +}
cw_monero/lib/structs/ut8_box.dart new
+8
@@ -0,0 +1,8 @@
1 +import 'dart:ffi';
2 +import 'package:ffi/ffi.dart';
3 +
4 +class Utf8Box extends Struct {
5 + Pointer<Utf8> value;
6 +
7 + String getValue() => Utf8.fromUtf8(value);
8 +}
cw_monero/lib/subaddress_list.dart new
+72
@@ -0,0 +1,72 @@
1 +import 'dart:ffi';
2 +import 'package:ffi/ffi.dart';
3 +import 'package:flutter/foundation.dart';
4 +import 'package:cw_monero/signatures.dart';
5 +import 'package:cw_monero/types.dart';
6 +import 'package:cw_monero/monero_api.dart';
7 +import 'package:cw_monero/structs/subaddress_row.dart';
8 +
9 +final subaddressSizeNative = moneroApi
10 + .lookup<NativeFunction<subaddrress_size>>('subaddrress_size')
11 + .asFunction<SubaddressSize>();
12 +
13 +final subaddressRefreshNative = moneroApi
14 + .lookup<NativeFunction<subaddrress_refresh>>('subaddress_refresh')
15 + .asFunction<SubaddressRefresh>();
16 +
17 +final subaddrressGetAllNative = moneroApi
18 + .lookup<NativeFunction<subaddress_get_all>>('subaddrress_get_all')
19 + .asFunction<SubaddressGetAll>();
20 +
21 +final subaddrressAddNewNative = moneroApi
22 + .lookup<NativeFunction<subaddress_add_new>>('subaddress_add_row')
23 + .asFunction<SubaddressAddNew>();
24 +
25 +final subaddrressSetLabelNative = moneroApi
26 + .lookup<NativeFunction<subaddress_set_label>>('subaddress_set_label')
27 + .asFunction<SubaddressSetLabel>();
28 +
29 +refreshSubaddresses({int accountIndex}) =>
30 + subaddressRefreshNative(accountIndex);
31 +
32 +List<SubaddressRow> getAllSubaddresses() {
33 + refreshSubaddresses(accountIndex: 0);
34 + final size = subaddressSizeNative();
35 + final subaddressAddressesPointer = subaddrressGetAllNative();
36 + final subaddressAddresses = subaddressAddressesPointer.asTypedList(size);
37 +
38 + return subaddressAddresses
39 + .map((addr) => Pointer<SubaddressRow>.fromAddress(addr).ref)
40 + .toList();
41 +}
42 +
43 +addSubaddressSync({int accountIndex, String label}) {
44 + final labelPointer = Utf8.toUtf8(label);
45 + subaddrressAddNewNative(accountIndex, labelPointer);
46 + free(labelPointer);
47 +}
48 +
49 +setLabelForSubaddressSync({int accountIndex, int addressIndex, String label}) {
50 + final labelPointer = Utf8.toUtf8(label);
51 + subaddrressSetLabelNative(accountIndex, addressIndex, labelPointer);
52 + free(labelPointer);
53 +}
54 +
55 +_addSubaddress(Map args) =>
56 + addSubaddressSync(accountIndex: args['accountIndex'], label: args['label']);
57 +
58 +_setLabelForSubaddress(Map args) => setLabelForSubaddressSync(
59 + accountIndex: args['accountIndex'],
60 + addressIndex: args['addressIndex'],
61 + label: args['label']);
62 +
63 +Future addSubaddress({int accountIndex, String label}) async =>
64 + compute(_addSubaddress, {'accountIndex': accountIndex, 'label': label});
65 +
66 +Future setLabelForSubaddress(
67 + {int accountIndex, int addressIndex, String label}) =>
68 + compute(_setLabelForSubaddress, {
69 + 'accountIndex': accountIndex,
70 + 'addressIndex': addressIndex,
71 + 'label': label
72 + });
\ No newline at end of file
cw_monero/lib/transaction_history.dart new
+122
@@ -0,0 +1,122 @@
1 +import 'dart:ffi';
2 +import 'package:cw_monero/structs/ut8_box.dart';
3 +import 'package:ffi/ffi.dart';
4 +import 'package:flutter/foundation.dart';
5 +import 'package:cw_monero/signatures.dart';
6 +import 'package:cw_monero/types.dart';
7 +import 'package:cw_monero/monero_api.dart';
8 +import 'package:cw_monero/structs/transaction_info_row.dart';
9 +import 'package:cw_monero/structs/pending_transaction.dart';
10 +import 'package:cw_monero/exceptions/creation_transaction_exception.dart';
11 +
12 +final transactionsRefreshNative = moneroApi
13 + .lookup<NativeFunction<transactions_refresh>>('transactions_refresh')
14 + .asFunction<TransactionsRefresh>();
15 +
16 +final transactionsCountNative = moneroApi
17 + .lookup<NativeFunction<transactions_count>>('transactions_count')
18 + .asFunction<TransactionsCount>();
19 +
20 +final transactionsGetAllNative = moneroApi
21 + .lookup<NativeFunction<transactions_get_all>>('transactions_get_all')
22 + .asFunction<TransactionsGetAll>();
23 +
24 +final transactionCreateNative = moneroApi
25 + .lookup<NativeFunction<transaction_create>>('transaction_create')
26 + .asFunction<TransactionCreate>();
27 +
28 +final transactionCommitNative = moneroApi
29 + .lookup<NativeFunction<transaction_commit>>('transaction_commit')
30 + .asFunction<TransactionCommit>();
31 +
32 +refreshTransactions() => transactionsRefreshNative();
33 +
34 +int countOfTransactions() => transactionsCountNative();
35 +
36 +List<TransactionInfoRow> getAllTransations() {
37 + final size = transactionsCountNative();
38 + final transactionsPointer = transactionsGetAllNative();
39 + final transactionsAddresses = transactionsPointer.asTypedList(size);
40 +
41 + return transactionsAddresses
42 + .map((addr) => Pointer<TransactionInfoRow>.fromAddress(addr).ref)
43 + .toList();
44 +}
45 +
46 +PendingTransactionDescription createTransactionSync(
47 + {String address,
48 + String paymentId,
49 + String amount,
50 + int priorityRaw,
51 + int accountIndex = 0}) {
52 + final addressPointer = Utf8.toUtf8(address);
53 + final paymentIdPointer = Utf8.toUtf8(paymentId);
54 + final amountPointer = amount != null ? Utf8.toUtf8(amount) : nullptr;
55 + final errorMessagePointer = allocate<Utf8Box>();
56 + final pendingTransactionRawPointer = allocate<PendingTransactionRaw>();
57 + final created = transactionCreateNative(
58 + addressPointer,
59 + paymentIdPointer,
60 + amountPointer,
61 + priorityRaw,
62 + accountIndex,
63 + errorMessagePointer,
64 + pendingTransactionRawPointer) !=
65 + 0;
66 +
67 + free(addressPointer);
68 + free(paymentIdPointer);
69 +
70 + if (amountPointer != nullptr) {
71 + free(amountPointer);
72 + }
73 +
74 + if (!created) {
75 + final message = errorMessagePointer.ref.getValue();
76 + free(errorMessagePointer);
77 + throw CreationTransactionException(message: message);
78 + }
79 +
80 + return PendingTransactionDescription(
81 + amount: pendingTransactionRawPointer.ref.amount,
82 + fee: pendingTransactionRawPointer.ref.fee,
83 + hash: pendingTransactionRawPointer.ref.getHash(),
84 + pointerAddress: pendingTransactionRawPointer.address);
85 +}
86 +
87 +commitTransactionFromPointerAddress({int address}) => commitTransaction(
88 + transactionPointer: Pointer<PendingTransactionRaw>.fromAddress(address));
89 +
90 +commitTransaction({Pointer<PendingTransactionRaw> transactionPointer}) {
91 + final errorMessagePointer = allocate<Utf8Box>();
92 + final isCommited =
93 + transactionCommitNative(transactionPointer, errorMessagePointer) != 0;
94 +
95 + if (!isCommited) {
96 + final message = errorMessagePointer.ref.getValue();
97 + free(errorMessagePointer);
98 + throw CreationTransactionException(message: message);
99 + }
100 +}
101 +
102 +PendingTransactionDescription _createTransactionSync(Map args) =>
103 + createTransactionSync(
104 + address: args['address'],
105 + paymentId: args['paymentId'],
106 + amount: args['amount'],
107 + priorityRaw: args['priorityRaw'],
108 + accountIndex: args['accountIndex']);
109 +
110 +Future<PendingTransactionDescription> createTransaction(
111 + {String address,
112 + String paymentId,
113 + String amount,
114 + int priorityRaw,
115 + int accountIndex = 0}) =>
116 + compute(_createTransactionSync, {
117 + 'address': address,
118 + 'paymentId': paymentId,
119 + 'amount': amount,
120 + 'priorityRaw': priorityRaw,
121 + 'accountIndex': accountIndex
122 + });
cw_monero/lib/types.dart new
+106
@@ -0,0 +1,106 @@
1 +import 'dart:ffi';
2 +import 'package:cw_monero/structs/pending_transaction.dart';
3 +import 'package:cw_monero/structs/ut8_box.dart';
4 +import 'package:ffi/ffi.dart';
5 +
6 +typedef CreateWallet = int Function(
7 + Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, int, Pointer<Utf8>);
8 +
9 +typedef RestoreWalletFromSeed = int Function(
10 + Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, int, int, Pointer<Utf8>);
11 +
12 +typedef RestoreWalletFromKeys = int Function(Pointer<Utf8>, Pointer<Utf8>,
13 + Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, int, int, Pointer<Utf8>);
14 +
15 +typedef IsWalletExist = int Function(Pointer<Utf8>);
16 +
17 +typedef LoadWallet = void Function(Pointer<Utf8>, Pointer<Utf8>, int);
18 +
19 +typedef GetFilename = Pointer<Utf8> Function();
20 +
21 +typedef GetSeed = Pointer<Utf8> Function();
22 +
23 +typedef GetAddress = Pointer<Utf8> Function(int, int);
24 +
25 +typedef GetFullBalance = int Function(int);
26 +
27 +typedef GetUnlockedBalance = int Function(int);
28 +
29 +typedef GetCurrentHeight = int Function();
30 +
31 +typedef GetNodeHeight = int Function();
32 +
33 +typedef IsConnected = int Function();
34 +
35 +typedef SetupNode = int Function(
36 + Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, int, int, Pointer<Utf8>);
37 +
38 +typedef StartRefresh = void Function();
39 +
40 +typedef ConnectToNode = int Function();
41 +
42 +typedef SetRefreshFromBlockHeight = void Function(int);
43 +
44 +typedef SetRecoveringFromSeed = void Function(int);
45 +
46 +typedef Store = void Function(Pointer<Utf8>);
47 +
48 +typedef SetListener = void Function();
49 +
50 +typedef GetSyncingHeight = int Function();
51 +
52 +typedef IsNeededToRefresh = int Function();
53 +
54 +typedef IsNewTransactionExist = int Function();
55 +
56 +typedef SubaddressSize = int Function();
57 +
58 +typedef SubaddressRefresh = void Function(int);
59 +
60 +typedef SubaddressGetAll = Pointer<Int64> Function();
61 +
62 +typedef SubaddressAddNew = void Function(int accountIndex, Pointer<Utf8> label);
63 +
64 +typedef SubaddressSetLabel = void Function(
65 + int accountIndex, int addressIndex, Pointer<Utf8> label);
66 +
67 +typedef AccountSize = int Function();
68 +
69 +typedef AccountRefresh = void Function();
70 +
71 +typedef AccountGetAll = Pointer<Int64> Function();
72 +
73 +typedef AccountAddNew = void Function(Pointer<Utf8> label);
74 +
75 +typedef AccountSetLabel = void Function(int accountIndex, Pointer<Utf8> label);
76 +
77 +typedef TransactionsRefresh = void Function();
78 +
79 +typedef TransactionsCount = int Function();
80 +
81 +typedef TransactionsGetAll = Pointer<Int64> Function();
82 +
83 +typedef TransactionCreate = int Function(
84 + Pointer<Utf8> address,
85 + Pointer<Utf8> paymentId,
86 + Pointer<Utf8> amount,
87 + int priorityRaw,
88 + int subaddrAccount,
89 + Pointer<Utf8Box> error,
90 + Pointer<PendingTransactionRaw> pendingTransaction);
91 +
92 +typedef TransactionCommit = int Function(Pointer<PendingTransactionRaw>, Pointer<Utf8Box>);
93 +
94 +typedef SecretViewKey = Pointer<Utf8> Function();
95 +
96 +typedef PublicViewKey = Pointer<Utf8> Function();
97 +
98 +typedef SecretSpendKey = Pointer<Utf8> Function();
99 +
100 +typedef PublicSpendKey = Pointer<Utf8> Function();
101 +
102 +typedef CloseCurrentWallet = void Function();
103 +
104 +typedef OnStartup = void Function();
105 +
106 +typedef RescanBlockchainAsync = void Function();
\ No newline at end of file
cw_monero/lib/wallet.dart new
+283
@@ -0,0 +1,283 @@
1 +import 'dart:async';
2 +import 'dart:ffi';
3 +import 'package:ffi/ffi.dart';
4 +import 'package:cw_monero/convert_utf8_to_string.dart';
5 +import 'package:cw_monero/signatures.dart';
6 +import 'package:cw_monero/types.dart';
7 +import 'package:cw_monero/monero_api.dart';
8 +import 'package:cw_monero/exceptions/setup_wallet_exception.dart';
9 +import 'package:flutter/foundation.dart';
10 +import 'package:flutter/services.dart';
11 +
12 +int _boolToInt(bool value) => value ? 1 : 0;
13 +
14 +final moneroAPIChannel = const MethodChannel('cw_monero');
15 +
16 +final getFileNameNative = moneroApi
17 + .lookup<NativeFunction<get_filename>>('get_filename')
18 + .asFunction<GetFilename>();
19 +
20 +final getSeedNative =
21 + moneroApi.lookup<NativeFunction<get_seed>>('seed').asFunction<GetSeed>();
22 +
23 +final getAddressNative = moneroApi
24 + .lookup<NativeFunction<get_address>>('get_address')
25 + .asFunction<GetAddress>();
26 +
27 +final getFullBalanceNative = moneroApi
28 + .lookup<NativeFunction<get_full_balanace>>('get_full_balance')
29 + .asFunction<GetFullBalance>();
30 +
31 +final getUnlockedBalanceNative = moneroApi
32 + .lookup<NativeFunction<get_unlocked_balanace>>('get_unlocked_balance')
33 + .asFunction<GetUnlockedBalance>();
34 +
35 +final getCurrentHeightNative = moneroApi
36 + .lookup<NativeFunction<get_current_height>>('get_current_height')
37 + .asFunction<GetCurrentHeight>();
38 +
39 +final getNodeHeightNative = moneroApi
40 + .lookup<NativeFunction<get_node_height>>('get_node_height')
41 + .asFunction<GetNodeHeight>();
42 +
43 +final isConnectedNative = moneroApi
44 + .lookup<NativeFunction<is_connected>>('is_connected')
45 + .asFunction<IsConnected>();
46 +
47 +final setupNodeNative = moneroApi
48 + .lookup<NativeFunction<setup_node>>('setup_node')
49 + .asFunction<SetupNode>();
50 +
51 +final startRefreshNative = moneroApi
52 + .lookup<NativeFunction<start_refresh>>('start_refresh')
53 + .asFunction<StartRefresh>();
54 +
55 +final connecToNodeNative = moneroApi
56 + .lookup<NativeFunction<connect_to_node>>('connect_to_node')
57 + .asFunction<ConnectToNode>();
58 +
59 +final setRefreshFromBlockHeightNative = moneroApi
60 + .lookup<NativeFunction<set_refresh_from_block_height>>(
61 + 'set_refresh_from_block_height')
62 + .asFunction<SetRefreshFromBlockHeight>();
63 +
64 +final setRecoveringFromSeedNative = moneroApi
65 + .lookup<NativeFunction<set_recovering_from_seed>>(
66 + 'set_recovering_from_seed')
67 + .asFunction<SetRecoveringFromSeed>();
68 +
69 +final storeNative =
70 + moneroApi.lookup<NativeFunction<store_c>>('store').asFunction<Store>();
71 +
72 +final setListenerNative = moneroApi
73 + .lookup<NativeFunction<set_listener>>('set_listener')
74 + .asFunction<SetListener>();
75 +
76 +final getSyncingHeightNative = moneroApi
77 + .lookup<NativeFunction<get_syncing_height>>('get_syncing_height')
78 + .asFunction<GetSyncingHeight>();
79 +
80 +final isNeededToRefreshNative = moneroApi
81 + .lookup<NativeFunction<is_needed_to_refresh>>('is_needed_to_refresh')
82 + .asFunction<IsNeededToRefresh>();
83 +
84 +final isNewTransactionExistNative = moneroApi
85 + .lookup<NativeFunction<is_new_transaction_exist>>(
86 + 'is_new_transaction_exist')
87 + .asFunction<IsNewTransactionExist>();
88 +
89 +final getSecretViewKeyNative = moneroApi
90 + .lookup<NativeFunction<secret_view_key>>('secret_view_key')
91 + .asFunction<SecretViewKey>();
92 +
93 +final getPublicViewKeyNative = moneroApi
94 + .lookup<NativeFunction<public_view_key>>('public_view_key')
95 + .asFunction<PublicViewKey>();
96 +
97 +final getSecretSpendKeyNative = moneroApi
98 + .lookup<NativeFunction<secret_spend_key>>('secret_spend_key')
99 + .asFunction<SecretSpendKey>();
100 +
101 +final getPublicSpendKeyNative = moneroApi
102 + .lookup<NativeFunction<secret_view_key>>('public_spend_key')
103 + .asFunction<PublicSpendKey>();
104 +
105 +final closeCurrentWalletNative = moneroApi
106 + .lookup<NativeFunction<close_current_wallet>>('close_current_wallet')
107 + .asFunction<CloseCurrentWallet>();
108 +
109 +final onStartupNative = moneroApi
110 + .lookup<NativeFunction<on_startup>>('on_startup')
111 + .asFunction<OnStartup>();
112 +
113 +final rescanBlockchainAsyncNative = moneroApi
114 + .lookup<NativeFunction<rescan_blockchain>>('rescan_blockchain')
115 + .asFunction<RescanBlockchainAsync>();
116 +
117 +int getSyncingHeight() => getSyncingHeightNative();
118 +
119 +bool isNeededToRefresh() => isNeededToRefreshNative() != 0;
120 +
121 +bool isNewTransactionExist() => isNewTransactionExistNative() != 0;
122 +
123 +String getFilename() => convertUTF8ToString(pointer: getFileNameNative());
124 +
125 +String getSeed() => convertUTF8ToString(pointer: getSeedNative());
126 +
127 +String getAddress({int accountIndex = 0, int addressIndex = 0}) =>
128 + convertUTF8ToString(pointer: getAddressNative(accountIndex, addressIndex));
129 +
130 +int getFullBalance({int accountIndex = 0}) =>
131 + getFullBalanceNative(accountIndex);
132 +
133 +int getUnlockedBalance({int accountIndex = 0}) =>
134 + getUnlockedBalanceNative(accountIndex);
135 +
136 +int getCurrentHeight() => getCurrentHeightNative();
137 +
138 +int getNodeHeightSync() => getNodeHeightNative();
139 +
140 +bool isConnectedSync() => isConnectedNative() != 0;
141 +
142 +bool setupNodeSync(
143 + {String address,
144 + String login,
145 + String password,
146 + bool useSSL = false,
147 + bool isLightWallet = false}) {
148 + final addressPointer = Utf8.toUtf8(address);
149 + Pointer<Utf8> loginPointer;
150 + Pointer<Utf8> passwordPointer;
151 +
152 + if (login != null) {
153 + loginPointer = Utf8.toUtf8(login);
154 + }
155 +
156 + if (password != null) {
157 + passwordPointer = Utf8.toUtf8(password);
158 + }
159 +
160 + final errorMessagePointer = allocate<Utf8>();
161 + final isSetupNode = setupNodeNative(
162 + addressPointer,
163 + loginPointer,
164 + passwordPointer,
165 + _boolToInt(useSSL),
166 + _boolToInt(isLightWallet),
167 + errorMessagePointer) !=
168 + 0;
169 +
170 + free(addressPointer);
171 + free(loginPointer);
172 + free(passwordPointer);
173 +
174 + if (!isSetupNode) {
175 + throw SetupWalletException(
176 + message: convertUTF8ToString(pointer: errorMessagePointer));
177 + }
178 +
179 + return isSetupNode;
180 +}
181 +
182 +startRefreshSync() => startRefreshNative();
183 +
184 +Future<bool> connectToNode() async => connecToNodeNative() != 0;
185 +
186 +setRefreshFromBlockHeight({int height}) =>
187 + setRefreshFromBlockHeightNative(height);
188 +
189 +setRecoveringFromSeed({bool isRecovery}) =>
190 + setRecoveringFromSeedNative(_boolToInt(isRecovery));
191 +
192 +storeSync() {
193 + final pathPointer = Utf8.toUtf8('');
194 + storeNative(pathPointer);
195 + free(pathPointer);
196 +}
197 +
198 +closeCurrentWallet() => closeCurrentWalletNative();
199 +
200 +String getSecretViewKey() =>
201 + convertUTF8ToString(pointer: getSecretViewKeyNative());
202 +
203 +String getPublicViewKey() =>
204 + convertUTF8ToString(pointer: getPublicViewKeyNative());
205 +
206 +String getSecretSpendKey() =>
207 + convertUTF8ToString(pointer: getSecretSpendKeyNative());
208 +
209 +String getPublicSpendKey() =>
210 + convertUTF8ToString(pointer: getPublicSpendKeyNative());
211 +
212 +Timer _updateSyncInfoTimer;
213 +
214 +int _lastKnownBlockHeight = 0;
215 +
216 +setListeners(Future Function(int) onNewBlock, Future Function() onNeedToRefresh,
217 + Future Function() onNewTransaction) {
218 + if (_updateSyncInfoTimer != null) {
219 + _updateSyncInfoTimer.cancel();
220 + }
221 +
222 + _updateSyncInfoTimer = Timer.periodic(Duration(milliseconds: 200), (_) async {
223 + final syncHeight = getSyncingHeight();
224 + final needToRefresh = isNeededToRefresh();
225 + final newTransactionExist = isNewTransactionExist();
226 +
227 + if (_lastKnownBlockHeight != syncHeight && syncHeight != null) {
228 + _lastKnownBlockHeight = syncHeight;
229 + await onNewBlock(syncHeight);
230 + }
231 +
232 + if (newTransactionExist && onNewTransaction != null) {
233 + await onNewTransaction();
234 + }
235 +
236 + if (needToRefresh && onNeedToRefresh != null) {
237 + await onNeedToRefresh();
238 + }
239 + });
240 + setListenerNative();
241 +}
242 +
243 +closeListeners() {
244 + if (_updateSyncInfoTimer != null) {
245 + _updateSyncInfoTimer.cancel();
246 + }
247 +}
248 +
249 +onStartup() => onStartupNative();
250 +
251 +_storeSync(_) => storeSync();
252 +bool _setupNodeSync(Map args) => setupNodeSync(
253 + address: args['address'],
254 + login: args['login'] ?? '',
255 + password: args['password'] ?? '',
256 + useSSL: args['useSSL'],
257 + isLightWallet: args['isLightWallet']);
258 +bool _isConnected(_) => isConnectedSync();
259 +int _getNodeHeight(_) => getNodeHeightSync();
260 +
261 +startRefresh() => startRefreshSync();
262 +
263 +Future setupNode(
264 + {String address,
265 + String login,
266 + String password,
267 + bool useSSL = false,
268 + bool isLightWallet = false}) =>
269 + compute(_setupNodeSync, {
270 + 'address': address,
271 + 'login': login,
272 + 'password': password,
273 + 'useSSL': useSSL,
274 + 'isLightWallet': isLightWallet
275 + });
276 +
277 +Future store() => compute(_storeSync, 0);
278 +
279 +Future<bool> isConnected() => compute(_isConnected, 0);
280 +
281 +Future<int> getNodeHeight() => compute(_getNodeHeight, 0);
282 +
283 +rescanBlockchainAsync() => rescanBlockchainAsyncNative();
\ No newline at end of file
cw_monero/lib/wallet_manager.dart new
+218
@@ -0,0 +1,218 @@
1 +import 'dart:ffi';
2 +import 'package:ffi/ffi.dart';
3 +import 'package:flutter/foundation.dart';
4 +import 'package:cw_monero/convert_utf8_to_string.dart';
5 +import 'package:cw_monero/signatures.dart';
6 +import 'package:cw_monero/types.dart';
7 +import 'package:cw_monero/monero_api.dart';
8 +import 'package:cw_monero/exceptions/wallet_creation_exception.dart';
9 +import 'package:cw_monero/exceptions/wallet_restore_from_keys_exception.dart';
10 +import 'package:cw_monero/exceptions/wallet_restore_from_seed_exception.dart';
11 +
12 +final createWalletNative = moneroApi
13 + .lookup<NativeFunction<create_wallet>>('create_wallet')
14 + .asFunction<CreateWallet>();
15 +
16 +final restoreWalletFromSeedNative = moneroApi
17 + .lookup<NativeFunction<restore_wallet_from_seed>>(
18 + 'restore_wallet_from_seed')
19 + .asFunction<RestoreWalletFromSeed>();
20 +
21 +final restoreWalletFromKeysNative = moneroApi
22 + .lookup<NativeFunction<restore_wallet_from_keys>>(
23 + 'restore_wallet_from_keys')
24 + .asFunction<RestoreWalletFromKeys>();
25 +
26 +final isWalletExistNative = moneroApi
27 + .lookup<NativeFunction<is_wallet_exist>>('is_wallet_exist')
28 + .asFunction<IsWalletExist>();
29 +
30 +final loadWalletNative = moneroApi
31 + .lookup<NativeFunction<load_wallet>>('load_wallet')
32 + .asFunction<LoadWallet>();
33 +
34 +createWalletSync(
35 + {String path,
36 + String password,
37 + String language = 'English',
38 + int nettype = 0}) {
39 + final pathPointer = Utf8.toUtf8(path);
40 + final passwordPointer = Utf8.toUtf8(password);
41 + final languagePointer = Utf8.toUtf8(language);
42 + final errorMessagePointer = allocate<Utf8>();
43 + final isWalletCreated = createWalletNative(pathPointer, passwordPointer,
44 + languagePointer, nettype, errorMessagePointer) !=
45 + 0;
46 +
47 + free(pathPointer);
48 + free(passwordPointer);
49 + free(languagePointer);
50 +
51 + if (!isWalletCreated) {
52 + throw WalletCreationException(
53 + message: convertUTF8ToString(pointer: errorMessagePointer));
54 + }
55 +}
56 +
57 +bool isWalletExistSync({String path}) {
58 + final pathPointer = Utf8.toUtf8(path);
59 + final isExist = isWalletExistNative(pathPointer) != 0;
60 +
61 + free(pathPointer);
62 +
63 + return isExist;
64 +}
65 +
66 +restoreWalletFromSeedSync(
67 + {String path,
68 + String password,
69 + String seed,
70 + int nettype = 0,
71 + int restoreHeight = 0}) {
72 + final pathPointer = Utf8.toUtf8(path);
73 + final passwordPointer = Utf8.toUtf8(password);
74 + final seedPointer = Utf8.toUtf8(seed);
75 + final errorMessagePointer = allocate<Utf8>();
76 + final isWalletRestored = restoreWalletFromSeedNative(
77 + pathPointer,
78 + passwordPointer,
79 + seedPointer,
80 + nettype,
81 + restoreHeight,
82 + errorMessagePointer) !=
83 + 0;
84 +
85 + free(pathPointer);
86 + free(passwordPointer);
87 + free(seedPointer);
88 +
89 + if (!isWalletRestored) {
90 + throw WalletRestoreFromSeedException(
91 + message: convertUTF8ToString(pointer: errorMessagePointer));
92 + }
93 +}
94 +
95 +restoreWalletFromKeysSync(
96 + {String path,
97 + String password,
98 + String language = 'English',
99 + String address,
100 + String viewKey,
101 + String spendKey,
102 + int nettype = 0,
103 + int restoreHeight = 0}) {
104 + final pathPointer = Utf8.toUtf8(path);
105 + final passwordPointer = Utf8.toUtf8(password);
106 + final languagePointer = Utf8.toUtf8(language);
107 + final addressPointer = Utf8.toUtf8(address);
108 + final viewKeyPointer = Utf8.toUtf8(viewKey);
109 + final spendKeyPointer = Utf8.toUtf8(spendKey);
110 + final errorMessagePointer = allocate<Utf8>();
111 + final isWalletRestored = restoreWalletFromKeysNative(
112 + pathPointer,
113 + passwordPointer,
114 + languagePointer,
115 + addressPointer,
116 + viewKeyPointer,
117 + spendKeyPointer,
118 + nettype,
119 + restoreHeight,
120 + errorMessagePointer) !=
121 + 0;
122 +
123 + free(pathPointer);
124 + free(passwordPointer);
125 + free(languagePointer);
126 + free(addressPointer);
127 + free(viewKeyPointer);
128 + free(spendKeyPointer);
129 +
130 + if (!isWalletRestored) {
131 + throw WalletRestoreFromKeysException(
132 + message: convertUTF8ToString(pointer: errorMessagePointer));
133 + }
134 +}
135 +
136 +loadWallet({String path, String password, int nettype = 0}) {
137 + final pathPointer = Utf8.toUtf8(path);
138 + final passwordPointer = Utf8.toUtf8(password);
139 +
140 + loadWalletNative(pathPointer, passwordPointer, nettype);
141 + free(pathPointer);
142 + free(passwordPointer);
143 +}
144 +
145 +_createWallet(args) =>
146 + createWalletSync(path: args['path'], password: args['password']);
147 +
148 +_restoreFromSeed(args) => restoreWalletFromSeedSync(
149 + path: args['path'],
150 + password: args['password'],
151 + seed: args['seed'],
152 + restoreHeight: args['restoreHeight']);
153 +
154 +_restoreFromKeys(args) => restoreWalletFromKeysSync(
155 + path: args['path'],
156 + password: args['password'],
157 + restoreHeight: args['restoreHeight'],
158 + address: args['address'],
159 + viewKey: args['viewKey'],
160 + spendKey: args['spendKey']);
161 +
162 +_openWallet(Map args) async =>
163 + loadWallet(path: args['path'], password: args['password']);
164 +
165 +bool _isWalletExist(String path) => isWalletExistSync(path: path);
166 +
167 +openWallet({String path, String password, int nettype = 0}) async =>
168 + loadWallet(path: path, password: password);
169 +
170 +Future openWalletAsync(Map args) async => compute(_openWallet, args);
171 +
172 +Future createWallet(
173 + {String path,
174 + String password,
175 + String language = 'English',
176 + int nettype = 0}) async =>
177 + compute(_createWallet, {
178 + 'path': path,
179 + 'password': password,
180 + 'language': language,
181 + 'nettype': nettype
182 + });
183 +
184 +Future restoreFromSeed(
185 + {String path,
186 + String password,
187 + String seed,
188 + int nettype = 0,
189 + int restoreHeight = 0}) async =>
190 + compute(_restoreFromSeed, {
191 + 'path': path,
192 + 'password': password,
193 + 'seed': seed,
194 + 'nettype': nettype,
195 + 'restoreHeight': restoreHeight
196 + });
197 +
198 +Future restoreFromKeys(
199 + {String path,
200 + String password,
201 + String language = 'English',
202 + String address,
203 + String viewKey,
204 + String spendKey,
205 + int nettype = 0,
206 + int restoreHeight = 0}) async =>
207 + compute(_restoreFromKeys, {
208 + 'path': path,
209 + 'password': password,
210 + 'language': language,
211 + 'address': address,
212 + 'viewKey': viewKey,
213 + 'spendKey': spendKey,
214 + 'nettype': nettype,
215 + 'restoreHeight': restoreHeight
216 + });
217 +
218 +Future<bool> isWalletExist({String path}) => compute(_isWalletExist, path);
\ No newline at end of file
cw_monero/pubspec.lock new
+210
@@ -0,0 +1,210 @@
1 +# Generated by pub
2 +# See https://dart.dev/tools/pub/glossary#lockfile
3 +packages:
4 + archive:
5 + dependency: transitive
6 + description:
7 + name: archive
8 + url: "https://pub.dartlang.org"
9 + source: hosted
10 + version: "2.0.11"
11 + args:
12 + dependency: transitive
13 + description:
14 + name: args
15 + url: "https://pub.dartlang.org"
16 + source: hosted
17 + version: "1.5.2"
18 + async:
19 + dependency: transitive
20 + description:
21 + name: async
22 + url: "https://pub.dartlang.org"
23 + source: hosted
24 + version: "2.4.0"
25 + boolean_selector:
26 + dependency: transitive
27 + description:
28 + name: boolean_selector
29 + url: "https://pub.dartlang.org"
30 + source: hosted
31 + version: "1.0.5"
32 + charcode:
33 + dependency: transitive
34 + description:
35 + name: charcode
36 + url: "https://pub.dartlang.org"
37 + source: hosted
38 + version: "1.1.2"
39 + collection:
40 + dependency: transitive
41 + description:
42 + name: collection
43 + url: "https://pub.dartlang.org"
44 + source: hosted
45 + version: "1.14.11"
46 + convert:
47 + dependency: transitive
48 + description:
49 + name: convert
50 + url: "https://pub.dartlang.org"
51 + source: hosted
52 + version: "2.1.1"
53 + crypto:
54 + dependency: transitive
55 + description:
56 + name: crypto
57 + url: "https://pub.dartlang.org"
58 + source: hosted
59 + version: "2.1.3"
60 + ffi:
61 + dependency: "direct main"
62 + description:
63 + name: ffi
64 + url: "https://pub.dartlang.org"
65 + source: hosted
66 + version: "0.1.3"
67 + flutter:
68 + dependency: "direct main"
69 + description: flutter
70 + source: sdk
71 + version: "0.0.0"
72 + flutter_test:
73 + dependency: "direct dev"
74 + description: flutter
75 + source: sdk
76 + version: "0.0.0"
77 + image:
78 + dependency: transitive
79 + description:
80 + name: image
81 + url: "https://pub.dartlang.org"
82 + source: hosted
83 + version: "2.1.4"
84 + matcher:
85 + dependency: transitive
86 + description:
87 + name: matcher
88 + url: "https://pub.dartlang.org"
89 + source: hosted
90 + version: "0.12.6"
91 + meta:
92 + dependency: transitive
93 + description:
94 + name: meta
95 + url: "https://pub.dartlang.org"
96 + source: hosted
97 + version: "1.1.8"
98 + path:
99 + dependency: transitive
100 + description:
101 + name: path
102 + url: "https://pub.dartlang.org"
103 + source: hosted
104 + version: "1.6.4"
105 + path_provider:
106 + dependency: "direct main"
107 + description:
108 + name: path_provider
109 + url: "https://pub.dartlang.org"
110 + source: hosted
111 + version: "1.4.0"
112 + pedantic:
113 + dependency: transitive
114 + description:
115 + name: pedantic
116 + url: "https://pub.dartlang.org"
117 + source: hosted
118 + version: "1.8.0+1"
119 + petitparser:
120 + dependency: transitive
121 + description:
122 + name: petitparser
123 + url: "https://pub.dartlang.org"
124 + source: hosted
125 + version: "2.4.0"
126 + platform:
127 + dependency: transitive
128 + description:
129 + name: platform
130 + url: "https://pub.dartlang.org"
131 + source: hosted
132 + version: "2.2.1"
133 + quiver:
134 + dependency: transitive
135 + description:
136 + name: quiver
137 + url: "https://pub.dartlang.org"
138 + source: hosted
139 + version: "2.0.5"
140 + sky_engine:
141 + dependency: transitive
142 + description: flutter
143 + source: sdk
144 + version: "0.0.99"
145 + source_span:
146 + dependency: transitive
147 + description:
148 + name: source_span
149 + url: "https://pub.dartlang.org"
150 + source: hosted
151 + version: "1.5.5"
152 + stack_trace:
153 + dependency: transitive
154 + description:
155 + name: stack_trace
156 + url: "https://pub.dartlang.org"
157 + source: hosted
158 + version: "1.9.3"
159 + stream_channel:
160 + dependency: transitive
161 + description:
162 + name: stream_channel
163 + url: "https://pub.dartlang.org"
164 + source: hosted
165 + version: "2.0.0"
166 + string_scanner:
167 + dependency: transitive
168 + description:
169 + name: string_scanner
170 + url: "https://pub.dartlang.org"
171 + source: hosted
172 + version: "1.0.5"
173 + term_glyph:
174 + dependency: transitive
175 + description:
176 + name: term_glyph
177 + url: "https://pub.dartlang.org"
178 + source: hosted
179 + version: "1.1.0"
180 + test_api:
181 + dependency: transitive
182 + description:
183 + name: test_api
184 + url: "https://pub.dartlang.org"
185 + source: hosted
186 + version: "0.2.11"
187 + typed_data:
188 + dependency: transitive
189 + description:
190 + name: typed_data
191 + url: "https://pub.dartlang.org"
192 + source: hosted
193 + version: "1.1.6"
194 + vector_math:
195 + dependency: transitive
196 + description:
197 + name: vector_math
198 + url: "https://pub.dartlang.org"
199 + source: hosted
200 + version: "2.0.8"
201 + xml:
202 + dependency: transitive
203 + description:
204 + name: xml
205 + url: "https://pub.dartlang.org"
206 + source: hosted
207 + version: "3.5.0"
208 +sdks:
209 + dart: ">=2.6.0 <3.0.0"
210 + flutter: ">=0.1.4 <2.0.0"
cw_monero/pubspec.yaml new
+62
@@ -0,0 +1,62 @@
1 +name: cw_monero
2 +description: A new flutter plugin project.
3 +version: 0.0.1
4 +author:
5 +homepage:
6 +
7 +environment:
8 + sdk: ">=2.6.0 <3.0.0"
9 +
10 +dependencies:
11 + flutter:
12 + sdk: flutter
13 + ffi: ^0.1.3
14 + path_provider: ^1.4.0
15 +
16 +dev_dependencies:
17 + flutter_test:
18 + sdk: flutter
19 +
20 +# For information on the generic Dart part of this file, see the
21 +# following page: https://dart.dev/tools/pub/pubspec
22 +
23 +# The following section is specific to Flutter.
24 +flutter:
25 + # This section identifies this Flutter project as a plugin project.
26 + # The androidPackage and pluginClass identifiers should not ordinarily
27 + # be modified. They are used by the tooling to maintain consistency when
28 + # adding or updating assets for this project.
29 + plugin:
30 + androidPackage: com.cakewallet.monero
31 + pluginClass: CwMoneroPlugin
32 +
33 + # To add assets to your plugin package, add an assets section, like this:
34 + # assets:
35 + # - images/a_dot_burr.jpeg
36 + # - images/a_dot_ham.jpeg
37 + #
38 + # For details regarding assets in packages, see
39 + # https://flutter.dev/assets-and-images/#from-packages
40 + #
41 + # An image asset can refer to one or more resolution-specific "variants", see
42 + # https://flutter.dev/assets-and-images/#resolution-aware.
43 +
44 + # To add custom fonts to your plugin package, add a fonts section here,
45 + # in this "flutter" section. Each entry in this list should have a
46 + # "family" key with the font family name, and a "fonts" key with a
47 + # list giving the asset and other descriptors for the font. For
48 + # example:
49 + # fonts:
50 + # - family: Schyler
51 + # fonts:
52 + # - asset: fonts/Schyler-Regular.ttf
53 + # - asset: fonts/Schyler-Italic.ttf
54 + # style: italic
55 + # - family: Trajan Pro
56 + # fonts:
57 + # - asset: fonts/TrajanPro.ttf
58 + # - asset: fonts/TrajanPro_Bold.ttf
59 + # weight: 700
60 + #
61 + # For details regarding fonts in packages, see
62 + # https://flutter.dev/custom-fonts/#from-packages
ios/.gitignore new
+32
@@ -0,0 +1,32 @@
1 +*.mode1v3
2 +*.mode2v3
3 +*.moved-aside
4 +*.pbxuser
5 +*.perspectivev3
6 +**/*sync/
7 +.sconsign.dblite
8 +.tags*
9 +**/.vagrant/
10 +**/DerivedData/
11 +Icon?
12 +**/Pods/
13 +**/.symlinks/
14 +profile
15 +xcuserdata
16 +**/.generated/
17 +Flutter/App.framework
18 +Flutter/Flutter.framework
19 +Flutter/Flutter.podspec
20 +Flutter/Generated.xcconfig
21 +Flutter/app.flx
22 +Flutter/app.zip
23 +Flutter/flutter_assets/
24 +Flutter/flutter_export_environment.sh
25 +ServiceDefinitions.json
26 +Runner/GeneratedPluginRegistrant.*
27 +
28 +# Exceptions to above rules.
29 +!default.mode1v3
30 +!default.mode2v3
31 +!default.pbxuser
32 +!default.perspectivev3
ios/Flutter/AppFrameworkInfo.plist new
+26
@@ -0,0 +1,26 @@
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 +<plist version="1.0">
4 +<dict>
5 + <key>CFBundleDevelopmentRegion</key>
6 + <string>$(DEVELOPMENT_LANGUAGE)</string>
7 + <key>CFBundleExecutable</key>
8 + <string>App</string>
9 + <key>CFBundleIdentifier</key>
10 + <string>io.flutter.flutter.app</string>
11 + <key>CFBundleInfoDictionaryVersion</key>
12 + <string>6.0</string>
13 + <key>CFBundleName</key>
14 + <string>App</string>
15 + <key>CFBundlePackageType</key>
16 + <string>FMWK</string>
17 + <key>CFBundleShortVersionString</key>
18 + <string>1.0</string>
19 + <key>CFBundleSignature</key>
20 + <string>????</string>
21 + <key>CFBundleVersion</key>
22 + <string>1.0</string>
23 + <key>MinimumOSVersion</key>
24 + <string>8.0</string>
25 +</dict>
26 +</plist>
ios/Flutter/Debug.xcconfig new
+2
@@ -0,0 +1,2 @@
1 +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 +#include "Generated.xcconfig"
ios/Flutter/Release.xcconfig new
+2
@@ -0,0 +1,2 @@
1 +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 +#include "Generated.xcconfig"
ios/Podfile new
+74
@@ -0,0 +1,74 @@
1 +# Uncomment this line to define a global platform for your project
2 +# platform :ios, '9.0'
3 +
4 +# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 +ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 +
7 +project 'Runner', {
8 + 'Debug' => :debug,
9 + 'Profile' => :release,
10 + 'Release' => :release,
11 +}
12 +
13 +def parse_KV_file(file, separator='=')
14 + file_abs_path = File.expand_path(file)
15 + if !File.exists? file_abs_path
16 + return [];
17 + end
18 + pods_ary = []
19 + skip_line_start_symbols = ["#", "/"]
20 + File.foreach(file_abs_path) { |line|
21 + next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
22 + plugin = line.split(pattern=separator)
23 + if plugin.length == 2
24 + podname = plugin[0].strip()
25 + path = plugin[1].strip()
26 + podpath = File.expand_path("#{path}", file_abs_path)
27 + pods_ary.push({:name => podname, :path => podpath});
28 + else
29 + puts "Invalid plugin specification: #{line}"
30 + end
31 + }
32 + return pods_ary
33 +end
34 +
35 +target 'Runner' do
36 + # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
37 + # referring to absolute paths on developers' machines.
38 + use_frameworks!
39 + system('rm -rf .symlinks')
40 + system('mkdir -p .symlinks/plugins')
41 +
42 + # Flutter Pods
43 + generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
44 + if generated_xcode_build_settings.empty?
45 + puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first."
46 + end
47 + generated_xcode_build_settings.map { |p|
48 + if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
49 + symlink = File.join('.symlinks', 'flutter')
50 + File.symlink(File.dirname(p[:path]), symlink)
51 + pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
52 + end
53 + }
54 +
55 + # Plugin Pods
56 + plugin_pods = parse_KV_file('../.flutter-plugins')
57 + plugin_pods.map { |p|
58 + symlink = File.join('.symlinks', 'plugins', p[:name])
59 + File.symlink(p[:path], symlink)
60 + pod p[:name], :path => File.join(symlink, 'ios')
61 + }
62 +end
63 +
64 +# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
65 +install! 'cocoapods', :disable_input_output_paths => true
66 +
67 +post_install do |installer|
68 + installer.pods_project.targets.each do |target|
69 + target.build_configurations.each do |config|
70 + config.build_settings['SWIFT_VERSION'] = '4.0' # required by simple_permission
71 + config.build_settings['ENABLE_BITCODE'] = 'NO'
72 + end
73 + end
74 +end
ios/Podfile.lock new
+89
@@ -0,0 +1,89 @@
1 +PODS:
2 + - barcode_scan (0.0.1):
3 + - Flutter
4 + - MTBBarcodeScanner
5 + - cw_monero (0.0.2):
6 + - cw_monero/Boost (= 0.0.2)
7 + - cw_monero/Monero (= 0.0.2)
8 + - cw_monero/OpenSSL (= 0.0.2)
9 + - cw_monero/Sodium (= 0.0.2)
10 + - Flutter
11 + - cw_monero/Boost (0.0.2):
12 + - Flutter
13 + - cw_monero/Monero (0.0.2):
14 + - Flutter
15 + - cw_monero/OpenSSL (0.0.2):
16 + - Flutter
17 + - cw_monero/Sodium (0.0.2):
18 + - Flutter
19 + - esys_flutter_share (0.0.1):
20 + - Flutter
21 + - Flutter (1.0.0)
22 + - flutter_secure_storage (3.3.1):
23 + - Flutter
24 + - MTBBarcodeScanner (5.0.11)
25 + - path_provider (0.0.1):
26 + - Flutter
27 + - share (0.5.2):
28 + - Flutter
29 + - shared_preferences (0.0.1):
30 + - Flutter
31 + - url_launcher (0.0.1):
32 + - Flutter
33 + - url_launcher_web (0.0.1):
34 + - Flutter
35 +
36 +DEPENDENCIES:
37 + - barcode_scan (from `.symlinks/plugins/barcode_scan/ios`)
38 + - cw_monero (from `.symlinks/plugins/cw_monero/ios`)
39 + - esys_flutter_share (from `.symlinks/plugins/esys_flutter_share/ios`)
40 + - Flutter (from `.symlinks/flutter/ios-release`)
41 + - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
42 + - path_provider (from `.symlinks/plugins/path_provider/ios`)
43 + - share (from `.symlinks/plugins/share/ios`)
44 + - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
45 + - url_launcher (from `.symlinks/plugins/url_launcher/ios`)
46 + - url_launcher_web (from `.symlinks/plugins/url_launcher_web/ios`)
47 +
48 +SPEC REPOS:
49 + trunk:
50 + - MTBBarcodeScanner
51 +
52 +EXTERNAL SOURCES:
53 + barcode_scan:
54 + :path: ".symlinks/plugins/barcode_scan/ios"
55 + cw_monero:
56 + :path: ".symlinks/plugins/cw_monero/ios"
57 + esys_flutter_share:
58 + :path: ".symlinks/plugins/esys_flutter_share/ios"
59 + Flutter:
60 + :path: ".symlinks/flutter/ios-release"
61 + flutter_secure_storage:
62 + :path: ".symlinks/plugins/flutter_secure_storage/ios"
63 + path_provider:
64 + :path: ".symlinks/plugins/path_provider/ios"
65 + share:
66 + :path: ".symlinks/plugins/share/ios"
67 + shared_preferences:
68 + :path: ".symlinks/plugins/shared_preferences/ios"
69 + url_launcher:
70 + :path: ".symlinks/plugins/url_launcher/ios"
71 + url_launcher_web:
72 + :path: ".symlinks/plugins/url_launcher_web/ios"
73 +
74 +SPEC CHECKSUMS:
75 + barcode_scan: 33f586d02270046fc6559135038b34b5754eaa4f
76 + cw_monero: ca40a57b99f7753ed93d3b50af671a637277eb89
77 + esys_flutter_share: 403498dab005b36ce1f8d7aff377e81f0621b0b4
78 + Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
79 + flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
80 + MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
81 + path_provider: fb74bd0465e96b594bb3b5088ee4a4e7bb1f2a9d
82 + share: bae0a282aab4483288913fc4dc0b935d4b491f2e
83 + shared_preferences: 430726339841afefe5142b9c1f50cb6bd7793e01
84 + url_launcher: a1c0cc845906122c4784c542523d8cacbded5626
85 + url_launcher_web: e5527357f037c87560776e36436bf2b0288b965c
86 +
87 +PODFILE CHECKSUM: f1916a43bb28badbd408be80e8e4b8652a74e93e
88 +
89 +COCOAPODS: 1.8.4
ios/Runner.xcodeproj/project.pbxproj new
+602
@@ -0,0 +1,602 @@
1 +// !$*UTF8*$!
2 +{
3 + archiveVersion = 1;
4 + classes = {
5 + };
6 + objectVersion = 46;
7 + objects = {
8 +
9 +/* Begin PBXBuildFile section */
10 + 02AA3DBD66A19A0A1732294D /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00B973AD352B2957AC387EA9 /* Pods_Runner.framework */; };
11 + 0C0DB1F8237DB1AE00BD32F9 /* A.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C0DB1F7237DB1AE00BD32F9 /* A.swift */; };
12 + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
13 + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
14 + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
15 + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
16 + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
17 + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
18 + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
19 + 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
20 + 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
21 + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
22 + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
23 + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
24 +/* End PBXBuildFile section */
25 +
26 +/* Begin PBXCopyFilesBuildPhase section */
27 + 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
28 + isa = PBXCopyFilesBuildPhase;
29 + buildActionMask = 2147483647;
30 + dstPath = "";
31 + dstSubfolderSpec = 10;
32 + files = (
33 + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
34 + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
35 + );
36 + name = "Embed Frameworks";
37 + runOnlyForDeploymentPostprocessing = 0;
38 + };
39 +/* End PBXCopyFilesBuildPhase section */
40 +
41 +/* Begin PBXFileReference section */
42 + 00B973AD352B2957AC387EA9 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
43 + 0C0DB1F6237DB1AD00BD32F9 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
44 + 0C0DB1F7237DB1AE00BD32F9 /* A.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = A.swift; sourceTree = "<group>"; };
45 + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
46 + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
47 + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
48 + 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
49 + 4B157CEA62824A43D7DD4C38 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
50 + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
51 + 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
52 + 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
53 + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
54 + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
55 + 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
56 + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
57 + 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
58 + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
59 + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
60 + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
61 + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
62 + A64AD09573DE1F9B50A18F2A /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
63 + B39AAE9F098686B29374F51D /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
64 +/* End PBXFileReference section */
65 +
66 +/* Begin PBXFrameworksBuildPhase section */
67 + 97C146EB1CF9000F007C117D /* Frameworks */ = {
68 + isa = PBXFrameworksBuildPhase;
69 + buildActionMask = 2147483647;
70 + files = (
71 + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
72 + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
73 + 02AA3DBD66A19A0A1732294D /* Pods_Runner.framework in Frameworks */,
74 + );
75 + runOnlyForDeploymentPostprocessing = 0;
76 + };
77 +/* End PBXFrameworksBuildPhase section */
78 +
79 +/* Begin PBXGroup section */
80 + 9740EEB11CF90186004384FC /* Flutter */ = {
81 + isa = PBXGroup;
82 + children = (
83 + 3B80C3931E831B6300D905FE /* App.framework */,
84 + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
85 + 9740EEBA1CF902C7004384FC /* Flutter.framework */,
86 + 9740EEB21CF90195004384FC /* Debug.xcconfig */,
87 + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
88 + 9740EEB31CF90195004384FC /* Generated.xcconfig */,
89 + );
90 + name = Flutter;
91 + sourceTree = "<group>";
92 + };
93 + 97C146E51CF9000F007C117D = {
94 + isa = PBXGroup;
95 + children = (
96 + 9740EEB11CF90186004384FC /* Flutter */,
97 + 97C146F01CF9000F007C117D /* Runner */,
98 + 97C146EF1CF9000F007C117D /* Products */,
99 + BB72635863665F0C75A8EBE5 /* Pods */,
100 + D7C5668014A527FFA32576AF /* Frameworks */,
101 + );
102 + sourceTree = "<group>";
103 + };
104 + 97C146EF1CF9000F007C117D /* Products */ = {
105 + isa = PBXGroup;
106 + children = (
107 + 97C146EE1CF9000F007C117D /* Runner.app */,
108 + );
109 + name = Products;
110 + sourceTree = "<group>";
111 + };
112 + 97C146F01CF9000F007C117D /* Runner */ = {
113 + isa = PBXGroup;
114 + children = (
115 + 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
116 + 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
117 + 97C146FA1CF9000F007C117D /* Main.storyboard */,
118 + 97C146FD1CF9000F007C117D /* Assets.xcassets */,
119 + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
120 + 97C147021CF9000F007C117D /* Info.plist */,
121 + 97C146F11CF9000F007C117D /* Supporting Files */,
122 + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
123 + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
124 + 0C0DB1F7237DB1AE00BD32F9 /* A.swift */,
125 + 0C0DB1F6237DB1AD00BD32F9 /* Runner-Bridging-Header.h */,
126 + );
127 + path = Runner;
128 + sourceTree = "<group>";
129 + };
130 + 97C146F11CF9000F007C117D /* Supporting Files */ = {
131 + isa = PBXGroup;
132 + children = (
133 + 97C146F21CF9000F007C117D /* main.m */,
134 + );
135 + name = "Supporting Files";
136 + sourceTree = "<group>";
137 + };
138 + BB72635863665F0C75A8EBE5 /* Pods */ = {
139 + isa = PBXGroup;
140 + children = (
141 + 4B157CEA62824A43D7DD4C38 /* Pods-Runner.debug.xcconfig */,
142 + A64AD09573DE1F9B50A18F2A /* Pods-Runner.release.xcconfig */,
143 + B39AAE9F098686B29374F51D /* Pods-Runner.profile.xcconfig */,
144 + );
145 + path = Pods;
146 + sourceTree = "<group>";
147 + };
148 + D7C5668014A527FFA32576AF /* Frameworks */ = {
149 + isa = PBXGroup;
150 + children = (
151 + 00B973AD352B2957AC387EA9 /* Pods_Runner.framework */,
152 + );
153 + name = Frameworks;
154 + sourceTree = "<group>";
155 + };
156 +/* End PBXGroup section */
157 +
158 +/* Begin PBXNativeTarget section */
159 + 97C146ED1CF9000F007C117D /* Runner */ = {
160 + isa = PBXNativeTarget;
161 + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
162 + buildPhases = (
163 + 95C66705E4338EEA09DF7047 /* [CP] Check Pods Manifest.lock */,
164 + 9740EEB61CF901F6004384FC /* Run Script */,
165 + 97C146EA1CF9000F007C117D /* Sources */,
166 + 97C146EB1CF9000F007C117D /* Frameworks */,
167 + 97C146EC1CF9000F007C117D /* Resources */,
168 + 9705A1C41CF9048500538489 /* Embed Frameworks */,
169 + 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
170 + A51ED02C4D7DF0F1E59D04DE /* [CP] Embed Pods Frameworks */,
171 + );
172 + buildRules = (
173 + );
174 + dependencies = (
175 + );
176 + name = Runner;
177 + productName = Runner;
178 + productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
179 + productType = "com.apple.product-type.application";
180 + };
181 +/* End PBXNativeTarget section */
182 +
183 +/* Begin PBXProject section */
184 + 97C146E61CF9000F007C117D /* Project object */ = {
185 + isa = PBXProject;
186 + attributes = {
187 + LastUpgradeCheck = 1020;
188 + ORGANIZATIONNAME = "The Chromium Authors";
189 + TargetAttributes = {
190 + 97C146ED1CF9000F007C117D = {
191 + CreatedOnToolsVersion = 7.3.1;
192 + DevelopmentTeam = 32J6BB6VUS;
193 + LastSwiftMigration = 1120;
194 + };
195 + };
196 + };
197 + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
198 + compatibilityVersion = "Xcode 3.2";
199 + developmentRegion = en;
200 + hasScannedForEncodings = 0;
201 + knownRegions = (
202 + en,
203 + Base,
204 + );
205 + mainGroup = 97C146E51CF9000F007C117D;
206 + productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
207 + projectDirPath = "";
208 + projectRoot = "";
209 + targets = (
210 + 97C146ED1CF9000F007C117D /* Runner */,
211 + );
212 + };
213 +/* End PBXProject section */
214 +
215 +/* Begin PBXResourcesBuildPhase section */
216 + 97C146EC1CF9000F007C117D /* Resources */ = {
217 + isa = PBXResourcesBuildPhase;
218 + buildActionMask = 2147483647;
219 + files = (
220 + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
221 + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
222 + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
223 + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
224 + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
225 + );
226 + runOnlyForDeploymentPostprocessing = 0;
227 + };
228 +/* End PBXResourcesBuildPhase section */
229 +
230 +/* Begin PBXShellScriptBuildPhase section */
231 + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
232 + isa = PBXShellScriptBuildPhase;
233 + buildActionMask = 2147483647;
234 + files = (
235 + );
236 + inputPaths = (
237 + );
238 + name = "Thin Binary";
239 + outputPaths = (
240 + );
241 + runOnlyForDeploymentPostprocessing = 0;
242 + shellPath = /bin/sh;
243 + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
244 + };
245 + 95C66705E4338EEA09DF7047 /* [CP] Check Pods Manifest.lock */ = {
246 + isa = PBXShellScriptBuildPhase;
247 + buildActionMask = 2147483647;
248 + files = (
249 + );
250 + inputFileListPaths = (
251 + );
252 + inputPaths = (
253 + "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
254 + "${PODS_ROOT}/Manifest.lock",
255 + );
256 + name = "[CP] Check Pods Manifest.lock";
257 + outputFileListPaths = (
258 + );
259 + outputPaths = (
260 + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
261 + );
262 + runOnlyForDeploymentPostprocessing = 0;
263 + shellPath = /bin/sh;
264 + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
265 + showEnvVarsInLog = 0;
266 + };
267 + 9740EEB61CF901F6004384FC /* Run Script */ = {
268 + isa = PBXShellScriptBuildPhase;
269 + buildActionMask = 2147483647;
270 + files = (
271 + );
272 + inputPaths = (
273 + );
274 + name = "Run Script";
275 + outputPaths = (
276 + );
277 + runOnlyForDeploymentPostprocessing = 0;
278 + shellPath = /bin/sh;
279 + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
280 + };
281 + A51ED02C4D7DF0F1E59D04DE /* [CP] Embed Pods Frameworks */ = {
282 + isa = PBXShellScriptBuildPhase;
283 + buildActionMask = 2147483647;
284 + files = (
285 + );
286 + inputPaths = (
287 + );
288 + name = "[CP] Embed Pods Frameworks";
289 + outputPaths = (
290 + );
291 + runOnlyForDeploymentPostprocessing = 0;
292 + shellPath = /bin/sh;
293 + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
294 + showEnvVarsInLog = 0;
295 + };
296 +/* End PBXShellScriptBuildPhase section */
297 +
298 +/* Begin PBXSourcesBuildPhase section */
299 + 97C146EA1CF9000F007C117D /* Sources */ = {
300 + isa = PBXSourcesBuildPhase;
301 + buildActionMask = 2147483647;
302 + files = (
303 + 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
304 + 97C146F31CF9000F007C117D /* main.m in Sources */,
305 + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
306 + 0C0DB1F8237DB1AE00BD32F9 /* A.swift in Sources */,
307 + );
308 + runOnlyForDeploymentPostprocessing = 0;
309 + };
310 +/* End PBXSourcesBuildPhase section */
311 +
312 +/* Begin PBXVariantGroup section */
313 + 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
314 + isa = PBXVariantGroup;
315 + children = (
316 + 97C146FB1CF9000F007C117D /* Base */,
317 + );
318 + name = Main.storyboard;
319 + sourceTree = "<group>";
320 + };
321 + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
322 + isa = PBXVariantGroup;
323 + children = (
324 + 97C147001CF9000F007C117D /* Base */,
325 + );
326 + name = LaunchScreen.storyboard;
327 + sourceTree = "<group>";
328 + };
329 +/* End PBXVariantGroup section */
330 +
331 +/* Begin XCBuildConfiguration section */
332 + 249021D3217E4FDB00AE95B9 /* Profile */ = {
333 + isa = XCBuildConfiguration;
334 + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
335 + buildSettings = {
336 + ALWAYS_SEARCH_USER_PATHS = NO;
337 + CLANG_ANALYZER_NONNULL = YES;
338 + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
339 + CLANG_CXX_LIBRARY = "libc++";
340 + CLANG_ENABLE_MODULES = YES;
341 + CLANG_ENABLE_OBJC_ARC = YES;
342 + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
343 + CLANG_WARN_BOOL_CONVERSION = YES;
344 + CLANG_WARN_COMMA = YES;
345 + CLANG_WARN_CONSTANT_CONVERSION = YES;
346 + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
347 + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
348 + CLANG_WARN_EMPTY_BODY = YES;
349 + CLANG_WARN_ENUM_CONVERSION = YES;
350 + CLANG_WARN_INFINITE_RECURSION = YES;
351 + CLANG_WARN_INT_CONVERSION = YES;
352 + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
353 + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
354 + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
355 + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
356 + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
357 + CLANG_WARN_STRICT_PROTOTYPES = YES;
358 + CLANG_WARN_SUSPICIOUS_MOVE = YES;
359 + CLANG_WARN_UNREACHABLE_CODE = YES;
360 + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
361 + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
362 + COPY_PHASE_STRIP = NO;
363 + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
364 + ENABLE_NS_ASSERTIONS = NO;
365 + ENABLE_STRICT_OBJC_MSGSEND = YES;
366 + GCC_C_LANGUAGE_STANDARD = gnu99;
367 + GCC_NO_COMMON_BLOCKS = YES;
368 + GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
369 + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
370 + GCC_WARN_UNDECLARED_SELECTOR = YES;
371 + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
372 + GCC_WARN_UNUSED_FUNCTION = YES;
373 + GCC_WARN_UNUSED_VARIABLE = YES;
374 + IPHONEOS_DEPLOYMENT_TARGET = 8.0;
375 + MTL_ENABLE_DEBUG_INFO = NO;
376 + SDKROOT = iphoneos;
377 + TARGETED_DEVICE_FAMILY = "1,2";
378 + VALIDATE_PRODUCT = YES;
379 + };
380 + name = Profile;
381 + };
382 + 249021D4217E4FDB00AE95B9 /* Profile */ = {
383 + isa = XCBuildConfiguration;
384 + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
385 + buildSettings = {
386 + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
387 + CLANG_ENABLE_MODULES = YES;
388 + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
389 + DEVELOPMENT_TEAM = 32J6BB6VUS;
390 + ENABLE_BITCODE = NO;
391 + FRAMEWORK_SEARCH_PATHS = (
392 + "$(inherited)",
393 + "$(PROJECT_DIR)/Flutter",
394 + );
395 + INFOPLIST_FILE = Runner/Info.plist;
396 + IPHONEOS_DEPLOYMENT_TARGET = 9.0;
397 + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
398 + LIBRARY_SEARCH_PATHS = (
399 + "$(inherited)",
400 + "$(PROJECT_DIR)/Flutter",
401 + );
402 + PRODUCT_BUNDLE_IDENTIFIER = com.cakewallet.cakewallet;
403 + PRODUCT_NAME = "$(TARGET_NAME)";
404 + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
405 + SWIFT_VERSION = 5.0;
406 + VALID_ARCHS = "arm64 arm64e";
407 + VERSIONING_SYSTEM = "apple-generic";
408 + };
409 + name = Profile;
410 + };
411 + 97C147031CF9000F007C117D /* Debug */ = {
412 + isa = XCBuildConfiguration;
413 + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
414 + buildSettings = {
415 + ALWAYS_SEARCH_USER_PATHS = NO;
416 + CLANG_ANALYZER_NONNULL = YES;
417 + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
418 + CLANG_CXX_LIBRARY = "libc++";
419 + CLANG_ENABLE_MODULES = YES;
420 + CLANG_ENABLE_OBJC_ARC = YES;
421 + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
422 + CLANG_WARN_BOOL_CONVERSION = YES;
423 + CLANG_WARN_COMMA = YES;
424 + CLANG_WARN_CONSTANT_CONVERSION = YES;
425 + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
426 + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
427 + CLANG_WARN_EMPTY_BODY = YES;
428 + CLANG_WARN_ENUM_CONVERSION = YES;
429 + CLANG_WARN_INFINITE_RECURSION = YES;
430 + CLANG_WARN_INT_CONVERSION = YES;
431 + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
432 + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
433 + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
434 + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
435 + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
436 + CLANG_WARN_STRICT_PROTOTYPES = YES;
437 + CLANG_WARN_SUSPICIOUS_MOVE = YES;
438 + CLANG_WARN_UNREACHABLE_CODE = YES;
439 + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
440 + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
441 + COPY_PHASE_STRIP = NO;
442 + DEBUG_INFORMATION_FORMAT = dwarf;
443 + ENABLE_STRICT_OBJC_MSGSEND = YES;
444 + ENABLE_TESTABILITY = YES;
445 + GCC_C_LANGUAGE_STANDARD = gnu99;
446 + GCC_DYNAMIC_NO_PIC = NO;
447 + GCC_NO_COMMON_BLOCKS = YES;
448 + GCC_OPTIMIZATION_LEVEL = 0;
449 + GCC_PREPROCESSOR_DEFINITIONS = (
450 + "DEBUG=1",
451 + "$(inherited)",
452 + );
453 + GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
454 + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
455 + GCC_WARN_UNDECLARED_SELECTOR = YES;
456 + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
457 + GCC_WARN_UNUSED_FUNCTION = YES;
458 + GCC_WARN_UNUSED_VARIABLE = YES;
459 + IPHONEOS_DEPLOYMENT_TARGET = 8.0;
460 + MTL_ENABLE_DEBUG_INFO = YES;
461 + ONLY_ACTIVE_ARCH = YES;
462 + SDKROOT = iphoneos;
463 + TARGETED_DEVICE_FAMILY = "1,2";
464 + };
465 + name = Debug;
466 + };
467 + 97C147041CF9000F007C117D /* Release */ = {
468 + isa = XCBuildConfiguration;
469 + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
470 + buildSettings = {
471 + ALWAYS_SEARCH_USER_PATHS = NO;
472 + CLANG_ANALYZER_NONNULL = YES;
473 + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
474 + CLANG_CXX_LIBRARY = "libc++";
475 + CLANG_ENABLE_MODULES = YES;
476 + CLANG_ENABLE_OBJC_ARC = YES;
477 + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
478 + CLANG_WARN_BOOL_CONVERSION = YES;
479 + CLANG_WARN_COMMA = YES;
480 + CLANG_WARN_CONSTANT_CONVERSION = YES;
481 + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
482 + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
483 + CLANG_WARN_EMPTY_BODY = YES;
484 + CLANG_WARN_ENUM_CONVERSION = YES;
485 + CLANG_WARN_INFINITE_RECURSION = YES;
486 + CLANG_WARN_INT_CONVERSION = YES;
487 + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
488 + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
489 + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
490 + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
491 + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
492 + CLANG_WARN_STRICT_PROTOTYPES = YES;
493 + CLANG_WARN_SUSPICIOUS_MOVE = YES;
494 + CLANG_WARN_UNREACHABLE_CODE = YES;
495 + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
496 + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
497 + COPY_PHASE_STRIP = NO;
498 + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
499 + ENABLE_NS_ASSERTIONS = NO;
500 + ENABLE_STRICT_OBJC_MSGSEND = YES;
501 + GCC_C_LANGUAGE_STANDARD = gnu99;
502 + GCC_NO_COMMON_BLOCKS = YES;
503 + GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
504 + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
505 + GCC_WARN_UNDECLARED_SELECTOR = YES;
506 + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
507 + GCC_WARN_UNUSED_FUNCTION = YES;
508 + GCC_WARN_UNUSED_VARIABLE = YES;
509 + IPHONEOS_DEPLOYMENT_TARGET = 8.0;
510 + MTL_ENABLE_DEBUG_INFO = NO;
511 + SDKROOT = iphoneos;
512 + TARGETED_DEVICE_FAMILY = "1,2";
513 + VALIDATE_PRODUCT = YES;
514 + };
515 + name = Release;
516 + };
517 + 97C147061CF9000F007C117D /* Debug */ = {
518 + isa = XCBuildConfiguration;
519 + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
520 + buildSettings = {
521 + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
522 + CLANG_ENABLE_MODULES = YES;
523 + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
524 + DEVELOPMENT_TEAM = 32J6BB6VUS;
525 + ENABLE_BITCODE = NO;
526 + FRAMEWORK_SEARCH_PATHS = (
527 + "$(inherited)",
528 + "$(PROJECT_DIR)/Flutter",
529 + );
530 + INFOPLIST_FILE = Runner/Info.plist;
531 + IPHONEOS_DEPLOYMENT_TARGET = 9.0;
532 + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
533 + LIBRARY_SEARCH_PATHS = (
534 + "$(inherited)",
535 + "$(PROJECT_DIR)/Flutter",
536 + );
537 + PRODUCT_BUNDLE_IDENTIFIER = com.cakewallet.cakewallet;
538 + PRODUCT_NAME = "$(TARGET_NAME)";
539 + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
540 + SWIFT_OPTIMIZATION_LEVEL = "-Onone";
541 + SWIFT_VERSION = 5.0;
542 + VALID_ARCHS = "arm64 arm64e";
543 + VERSIONING_SYSTEM = "apple-generic";
544 + };
545 + name = Debug;
546 + };
547 + 97C147071CF9000F007C117D /* Release */ = {
548 + isa = XCBuildConfiguration;
549 + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
550 + buildSettings = {
551 + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
552 + CLANG_ENABLE_MODULES = YES;
553 + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
554 + DEVELOPMENT_TEAM = 32J6BB6VUS;
555 + ENABLE_BITCODE = NO;
556 + FRAMEWORK_SEARCH_PATHS = (
557 + "$(inherited)",
558 + "$(PROJECT_DIR)/Flutter",
559 + );
560 + INFOPLIST_FILE = Runner/Info.plist;
561 + IPHONEOS_DEPLOYMENT_TARGET = 9.0;
562 + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
563 + LIBRARY_SEARCH_PATHS = (
564 + "$(inherited)",
565 + "$(PROJECT_DIR)/Flutter",
566 + );
567 + PRODUCT_BUNDLE_IDENTIFIER = com.cakewallet.cakewallet;
568 + PRODUCT_NAME = "$(TARGET_NAME)";
569 + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
570 + SWIFT_VERSION = 5.0;
571 + VALID_ARCHS = "arm64 arm64e";
572 + VERSIONING_SYSTEM = "apple-generic";
573 + };
574 + name = Release;
575 + };
576 +/* End XCBuildConfiguration section */
577 +
578 +/* Begin XCConfigurationList section */
579 + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
580 + isa = XCConfigurationList;
581 + buildConfigurations = (
582 + 97C147031CF9000F007C117D /* Debug */,
583 + 97C147041CF9000F007C117D /* Release */,
584 + 249021D3217E4FDB00AE95B9 /* Profile */,
585 + );
586 + defaultConfigurationIsVisible = 0;
587 + defaultConfigurationName = Release;
588 + };
589 + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
590 + isa = XCConfigurationList;
591 + buildConfigurations = (
592 + 97C147061CF9000F007C117D /* Debug */,
593 + 97C147071CF9000F007C117D /* Release */,
594 + 249021D4217E4FDB00AE95B9 /* Profile */,
595 + );
596 + defaultConfigurationIsVisible = 0;
597 + defaultConfigurationName = Release;
598 + };
599 +/* End XCConfigurationList section */
600 + };
601 + rootObject = 97C146E61CF9000F007C117D /* Project object */;
602 +}
ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new
+7
@@ -0,0 +1,7 @@
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<Workspace
3 + version = "1.0">
4 + <FileRef
5 + location = "group:Runner.xcodeproj">
6 + </FileRef>
7 +</Workspace>
ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new
+87
@@ -0,0 +1,87 @@
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<Scheme
3 + LastUpgradeVersion = "1020"
4 + version = "1.3">
5 + <BuildAction
6 + parallelizeBuildables = "YES"
7 + buildImplicitDependencies = "YES">
8 + <BuildActionEntries>
9 + <BuildActionEntry
10 + buildForTesting = "YES"
11 + buildForRunning = "YES"
12 + buildForProfiling = "YES"
13 + buildForArchiving = "YES"
14 + buildForAnalyzing = "YES">
15 + <BuildableReference
16 + BuildableIdentifier = "primary"
17 + BlueprintIdentifier = "97C146ED1CF9000F007C117D"
18 + BuildableName = "Runner.app"
19 + BlueprintName = "Runner"
20 + ReferencedContainer = "container:Runner.xcodeproj">
21 + </BuildableReference>
22 + </BuildActionEntry>
23 + </BuildActionEntries>
24 + </BuildAction>
25 + <TestAction
26 + buildConfiguration = "Debug"
27 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29 + shouldUseLaunchSchemeArgsEnv = "YES">
30 + <MacroExpansion>
31 + <BuildableReference
32 + BuildableIdentifier = "primary"
33 + BlueprintIdentifier = "97C146ED1CF9000F007C117D"
34 + BuildableName = "Runner.app"
35 + BlueprintName = "Runner"
36 + ReferencedContainer = "container:Runner.xcodeproj">
37 + </BuildableReference>
38 + </MacroExpansion>
39 + <Testables>
40 + </Testables>
41 + </TestAction>
42 + <LaunchAction
43 + buildConfiguration = "Debug"
44 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
45 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
46 + launchStyle = "0"
47 + useCustomWorkingDirectory = "NO"
48 + ignoresPersistentStateOnLaunch = "NO"
49 + debugDocumentVersioning = "YES"
50 + debugServiceExtension = "internal"
51 + allowLocationSimulation = "YES">
52 + <BuildableProductRunnable
53 + runnableDebuggingMode = "0">
54 + <BuildableReference
55 + BuildableIdentifier = "primary"
56 + BlueprintIdentifier = "97C146ED1CF9000F007C117D"
57 + BuildableName = "Runner.app"
58 + BlueprintName = "Runner"
59 + ReferencedContainer = "container:Runner.xcodeproj">
60 + </BuildableReference>
61 + </BuildableProductRunnable>
62 + </LaunchAction>
63 + <ProfileAction
64 + buildConfiguration = "Profile"
65 + shouldUseLaunchSchemeArgsEnv = "YES"
66 + savedToolIdentifier = ""
67 + useCustomWorkingDirectory = "NO"
68 + debugDocumentVersioning = "YES">
69 + <BuildableProductRunnable
70 + runnableDebuggingMode = "0">
71 + <BuildableReference
72 + BuildableIdentifier = "primary"
73 + BlueprintIdentifier = "97C146ED1CF9000F007C117D"
74 + BuildableName = "Runner.app"
75 + BlueprintName = "Runner"
76 + ReferencedContainer = "container:Runner.xcodeproj">
77 + </BuildableReference>
78 + </BuildableProductRunnable>
79 + </ProfileAction>
80 + <AnalyzeAction
81 + buildConfiguration = "Debug">
82 + </AnalyzeAction>
83 + <ArchiveAction
84 + buildConfiguration = "Release"
85 + revealArchiveInOrganizer = "YES">
86 + </ArchiveAction>
87 +</Scheme>
ios/Runner.xcworkspace/contents.xcworkspacedata new
+10
@@ -0,0 +1,10 @@
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<Workspace
3 + version = "1.0">
4 + <FileRef
5 + location = "group:Runner.xcodeproj">
6 + </FileRef>
7 + <FileRef
8 + location = "group:Pods/Pods.xcodeproj">
9 + </FileRef>
10 +</Workspace>
ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new
+8
@@ -0,0 +1,8 @@
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 +<plist version="1.0">
4 +<dict>
5 + <key>IDEDidComputeMac32BitWarning</key>
6 + <true/>
7 +</dict>
8 +</plist>
ios/Runner/A.swift new
+1
@@ -0,0 +1 @@
1 +import Foundation
ios/Runner/AppDelegate.h new
+6
@@ -0,0 +1,6 @@
1 +#import <Flutter/Flutter.h>
2 +#import <UIKit/UIKit.h>
3 +
4 +@interface AppDelegate : FlutterAppDelegate
5 +
6 +@end
ios/Runner/AppDelegate.m new
+25
@@ -0,0 +1,25 @@
1 +#include "AppDelegate.h"
2 +#include "GeneratedPluginRegistrant.h"
3 +
4 +@implementation AppDelegate
5 +
6 +- (BOOL)application:(UIApplication *)application
7 + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
8 + [GeneratedPluginRegistrant registerWithRegistry:self];
9 + // Override point for customization after application launch.
10 + return [super application:application didFinishLaunchingWithOptions:launchOptions];
11 +}
12 +
13 +- (void)applicationDidEnterBackground:(UIApplication *)application
14 +{
15 + UIViewController *blankViewController = [UIViewController new];
16 + blankViewController.view.backgroundColor = [UIColor blackColor];
17 + [self.window.rootViewController presentViewController:blankViewController animated:NO completion:NULL];
18 +}
19 +
20 +- (void)applicationWillEnterForeground:(UIApplication *)application
21 +{
22 + [self.window.rootViewController dismissViewControllerAnimated:NO completion:NO];
23 +}
24 +
25 +@end
ios/Runner/AppDelegate.swift new
+40
@@ -0,0 +1,40 @@
1 +import UIKit
2 +import Flutter
3 +import CWMonero
4 +
5 +class MoneroWalletManagerHandler {
6 +// static let moneroWalletManager = MoneroWalletGateway()
7 +}
8 +
9 +@UIApplicationMain
10 +@objc class AppDelegate: FlutterAppDelegate {
11 + override func application(
12 + _ application: UIApplication,
13 + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
14 + ) -> Bool {
15 + let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
16 + let moneroWalletManagerChannel = FlutterMethodChannel(name: "com.cakewallet.wallet/monero-wallet-manager",
17 + binaryMessenger: controller.binaryMessenger)
18 + moneroWalletManagerChannel.setMethodCallHandler({
19 + (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
20 +
21 + })
22 +
23 + moneroWalletManagerChannel.setMethodCallHandler({
24 + [weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
25 + switch call.method {
26 + case "createWallet":
27 + result(1)
28 + case "isWalletExist":
29 + result(false)
30 + default:
31 + result(FlutterMethodNotImplemented)
32 + }
33 +
34 + result(1);
35 + })
36 +
37 + GeneratedPluginRegistrant.register(with: self)
38 + return super.application(application, didFinishLaunchingWithOptions: launchOptions)
39 + }
40 +}
ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new
+122
@@ -0,0 +1,122 @@
1 +{
2 + "images" : [
3 + {
4 + "size" : "20x20",
5 + "idiom" : "iphone",
6 + "filename" : "Icon-App-20x20@2x.png",
7 + "scale" : "2x"
8 + },
9 + {
10 + "size" : "20x20",
11 + "idiom" : "iphone",
12 + "filename" : "Icon-App-20x20@3x.png",
13 + "scale" : "3x"
14 + },
15 + {
16 + "size" : "29x29",
17 + "idiom" : "iphone",
18 + "filename" : "Icon-App-29x29@1x.png",
19 + "scale" : "1x"
20 + },
21 + {
22 + "size" : "29x29",
23 + "idiom" : "iphone",
24 + "filename" : "Icon-App-29x29@2x.png",
25 + "scale" : "2x"
26 + },
27 + {
28 + "size" : "29x29",
29 + "idiom" : "iphone",
30 + "filename" : "Icon-App-29x29@3x.png",
31 + "scale" : "3x"
32 + },
33 + {
34 + "size" : "40x40",
35 + "idiom" : "iphone",
36 + "filename" : "Icon-App-40x40@2x.png",
37 + "scale" : "2x"
38 + },
39 + {
40 + "size" : "40x40",
41 + "idiom" : "iphone",
42 + "filename" : "Icon-App-40x40@3x.png",
43 + "scale" : "3x"
44 + },
45 + {
46 + "size" : "60x60",
47 + "idiom" : "iphone",
48 + "filename" : "Icon-App-60x60@2x.png",
49 + "scale" : "2x"
50 + },
51 + {
52 + "size" : "60x60",
53 + "idiom" : "iphone",
54 + "filename" : "Icon-App-60x60@3x.png",
55 + "scale" : "3x"
56 + },
57 + {
58 + "size" : "20x20",
59 + "idiom" : "ipad",
60 + "filename" : "Icon-App-20x20@1x.png",
61 + "scale" : "1x"
62 + },
63 + {
64 + "size" : "20x20",
65 + "idiom" : "ipad",
66 + "filename" : "Icon-App-20x20@2x.png",
67 + "scale" : "2x"
68 + },
69 + {
70 + "size" : "29x29",
71 + "idiom" : "ipad",
72 + "filename" : "Icon-App-29x29@1x.png",
73 + "scale" : "1x"
74 + },
75 + {
76 + "size" : "29x29",
77 + "idiom" : "ipad",
78 + "filename" : "Icon-App-29x29@2x.png",
79 + "scale" : "2x"
80 + },
81 + {
82 + "size" : "40x40",
83 + "idiom" : "ipad",
84 + "filename" : "Icon-App-40x40@1x.png",
85 + "scale" : "1x"
86 + },
87 + {
88 + "size" : "40x40",
89 + "idiom" : "ipad",
90 + "filename" : "Icon-App-40x40@2x.png",
91 + "scale" : "2x"
92 + },
93 + {
94 + "size" : "76x76",
95 + "idiom" : "ipad",
96 + "filename" : "Icon-App-76x76@1x.png",
97 + "scale" : "1x"
98 + },
99 + {
100 + "size" : "76x76",
101 + "idiom" : "ipad",
102 + "filename" : "Icon-App-76x76@2x.png",
103 + "scale" : "2x"
104 + },
105 + {
106 + "size" : "83.5x83.5",
107 + "idiom" : "ipad",
108 + "filename" : "Icon-App-83.5x83.5@2x.png",
109 + "scale" : "2x"
110 + },
111 + {
112 + "size" : "1024x1024",
113 + "idiom" : "ios-marketing",
114 + "filename" : "Icon-App-1024x1024@1x.png",
115 + "scale" : "1x"
116 + }
117 + ],
118 + "info" : {
119 + "version" : 1,
120 + "author" : "xcode"
121 + }
122 +}
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ
ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new
+23
@@ -0,0 +1,23 @@
1 +{
2 + "images" : [
3 + {
4 + "idiom" : "universal",
5 + "filename" : "LaunchImage.png",
6 + "scale" : "1x"
7 + },
8 + {
9 + "idiom" : "universal",
10 + "filename" : "LaunchImage@2x.png",
11 + "scale" : "2x"
12 + },
13 + {
14 + "idiom" : "universal",
15 + "filename" : "LaunchImage@3x.png",
16 + "scale" : "3x"
17 + }
18 + ],
19 + "info" : {
20 + "version" : 1,
21 + "author" : "xcode"
22 + }
23 +}
ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ
ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ
ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ
ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new
+5
@@ -0,0 +1,5 @@
1 +# Launch Screen Assets
2 +
3 +You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 +
5 +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
\ No newline at end of file
ios/Runner/Base.lproj/LaunchScreen.storyboard new
+37
@@ -0,0 +1,37 @@
1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
3 + <dependencies>
4 + <deployment identifier="iOS"/>
5 + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
6 + </dependencies>
7 + <scenes>
8 + <!--View Controller-->
9 + <scene sceneID="EHf-IW-A2E">
10 + <objects>
11 + <viewController id="01J-lp-oVM" sceneMemberID="viewController">
12 + <layoutGuides>
13 + <viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
14 + <viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
15 + </layoutGuides>
16 + <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
17 + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
18 + <subviews>
19 + <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
20 + </imageView>
21 + </subviews>
22 + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
23 + <constraints>
24 + <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
25 + <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
26 + </constraints>
27 + </view>
28 + </viewController>
29 + <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
30 + </objects>
31 + <point key="canvasLocation" x="53" y="375"/>
32 + </scene>
33 + </scenes>
34 + <resources>
35 + <image name="LaunchImage" width="168" height="185"/>
36 + </resources>
37 +</document>
ios/Runner/Base.lproj/Main.storyboard new
+26
@@ -0,0 +1,26 @@
1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
3 + <dependencies>
4 + <deployment identifier="iOS"/>
5 + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
6 + </dependencies>
7 + <scenes>
8 + <!--Flutter View Controller-->
9 + <scene sceneID="tne-QT-ifu">
10 + <objects>
11 + <viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
12 + <layoutGuides>
13 + <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
14 + <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
15 + </layoutGuides>
16 + <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
17 + <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
18 + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
19 + <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
20 + </view>
21 + </viewController>
22 + <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
23 + </objects>
24 + </scene>
25 + </scenes>
26 +</document>
ios/Runner/Info.plist new
+45
@@ -0,0 +1,45 @@
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 +<plist version="1.0">
4 +<dict>
5 + <key>CFBundleDevelopmentRegion</key>
6 + <string>$(DEVELOPMENT_LANGUAGE)</string>
7 + <key>CFBundleExecutable</key>
8 + <string>$(EXECUTABLE_NAME)</string>
9 + <key>CFBundleIdentifier</key>
10 + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
11 + <key>CFBundleInfoDictionaryVersion</key>
12 + <string>6.0</string>
13 + <key>CFBundleName</key>
14 + <string>cake_wallet</string>
15 + <key>CFBundlePackageType</key>
16 + <string>APPL</string>
17 + <key>CFBundleShortVersionString</key>
18 + <string>$(FLUTTER_BUILD_NAME)</string>
19 + <key>CFBundleSignature</key>
20 + <string>????</string>
21 + <key>CFBundleVersion</key>
22 + <string>$(FLUTTER_BUILD_NUMBER)</string>
23 + <key>LSRequiresIPhoneOS</key>
24 + <true/>
25 + <key>UILaunchStoryboardName</key>
26 + <string>LaunchScreen</string>
27 + <key>UIMainStoryboardFile</key>
28 + <string>Main</string>
29 + <key>UISupportedInterfaceOrientations</key>
30 + <array>
31 + <string>UIInterfaceOrientationPortrait</string>
32 + <string>UIInterfaceOrientationLandscapeLeft</string>
33 + <string>UIInterfaceOrientationLandscapeRight</string>
34 + </array>
35 + <key>UISupportedInterfaceOrientations~ipad</key>
36 + <array>
37 + <string>UIInterfaceOrientationPortrait</string>
38 + <string>UIInterfaceOrientationPortraitUpsideDown</string>
39 + <string>UIInterfaceOrientationLandscapeLeft</string>
40 + <string>UIInterfaceOrientationLandscapeRight</string>
41 + </array>
42 + <key>UIViewControllerBasedStatusBarAppearance</key>
43 + <false/>
44 +</dict>
45 +</plist>
ios/Runner/Runner-Bridging-Header.h new
+1
@@ -0,0 +1 @@
1 +#import "GeneratedPluginRegistrant.h"
\ No newline at end of file
ios/Runner/main.m new
+9
@@ -0,0 +1,9 @@
1 +#import <Flutter/Flutter.h>
2 +#import <UIKit/UIKit.h>
3 +#import "AppDelegate.h"
4 +
5 +int main(int argc, char* argv[]) {
6 + @autoreleasepool {
7 + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 + }
9 +}
lib/generated/i18n.dart new
+5808
@@ -0,0 +1,5808 @@
1 +import 'dart:async';
2 +
3 +import 'package:flutter/foundation.dart';
4 +import 'package:flutter/material.dart';
5 +
6 +// ignore_for_file: non_constant_identifier_names
7 +// ignore_for_file: camel_case_types
8 +// ignore_for_file: prefer_single_quotes
9 +
10 +// This file is automatically generated. DO NOT EDIT, all your changes would be lost.
11 +class S implements WidgetsLocalizations {
12 + const S();
13 +
14 + static S current;
15 +
16 + static const GeneratedLocalizationsDelegate delegate =
17 + GeneratedLocalizationsDelegate();
18 +
19 + static S of(BuildContext context) => Localizations.of<S>(context, S);
20 +
21 + @override
22 + TextDirection get textDirection => TextDirection.ltr;
23 +
24 + String get account => "Account";
25 + String get accounts => "Accounts";
26 + String get add => "Add";
27 + String get address_book => "Address Book";
28 + String get address_book_menu => "Address book";
29 + String get all => "ALL";
30 + String get amount => "Amount: ";
31 + String get amount_is_estimate => "The receive amount is an estimate";
32 + String get amount_is_guaranteed => "The receive amount is guaranteed";
33 + String get auth_store_ban_timeout => "ban_timeout";
34 + String get auth_store_banned_for => "Banned for ";
35 + String get auth_store_banned_minutes => " minutes";
36 + String get auth_store_incorrect_password => "Wrong PIN";
37 + String get authenticated => "Authenticated";
38 + String get authentication => "Authentication";
39 + String get available_balance => "Available Balance";
40 + String get cancel => "Cancel";
41 + String get change => "Change";
42 + String get change_currency => "Change Currency";
43 + String get change_exchange_provider => "Change Exchange Provider";
44 + String get change_language => "Change language";
45 + String get clear => "Clear";
46 + String get confirm => "Confirm";
47 + String get send_xmr => "Send XMR";
48 + String get confirm_sending => "Confirm sending";
49 + String get contact => "Contact";
50 + String get contact_name => "Contact Name";
51 + String get continue_text => "Continue";
52 + String get copied_to_clipboard => "Copied to Clipboard";
53 + String get copy => "Copy";
54 + String get copy_address => "Copy Address";
55 + String get copy_id => "Copy ID";
56 + String get create_new => "Create new";
57 + String get delete => "Delete";
58 + String get digit_pin => "-digit Pin";
59 + String get edit => "Edit";
60 + String get enter_your_pin => "Enter your PIN";
61 + String get enter_your_pin_again => "Enter your pin again";
62 + String get error => "Error";
63 + String get error_text_account_name => "Account name can only contain letters, numbers\nand must be between 1 and 15 characters long";
64 + String get error_text_address => "Wallet address must correspond to the type\nof cryptocurrency";
65 + String get error_text_amount => "Amount can only contain numbers";
66 + String get error_text_contact_name => "Contact name can't contain ` , ' \" symbols\nand must be between 1 and 32 characters long";
67 + String get error_text_crypto_currency => "The number of fraction digits\nmust be less or equal to 12";
68 + String get error_text_fiat => "Value of amount can't exceed available balance.\nThe number of fraction digits must be less or equal to 2";
69 + String get error_text_keys => "Wallet keys can only contain 64 chars in hex";
70 + String get error_text_node_address => "Please enter a iPv4 address";
71 + String get error_text_node_port => "Node port can only contain numbers between 0 and 65535";
72 + String get error_text_payment_id => "Payment ID can only contain from 16 to 64 chars in hex";
73 + String get error_text_subaddress_name => "Subaddress name can't contain ` , ' \" symbols\nand must be between 1 and 20 characters long";
74 + String get error_text_wallet_name => "Wallet name can only contain letters, numbers\nand must be between 1 and 15 characters long";
75 + String get error_text_xmr => "XMR value can't exceed available balance.\nThe number of fraction digits must be less or equal to 12";
76 + String get estimated => "Estimated";
77 + String get exchange => "Exchange";
78 + String get exchange_result_write_down_ID => "*Please copy or write down your ID shown above.";
79 + String get exchange_result_write_down_trade_id => "Please copy or write down the trade ID to continue.";
80 + String get expired => "Expired";
81 + String get faq => "FAQ";
82 + String get fetching => "Fetching";
83 + String get filters => "Filters";
84 + String get first_wallet_text => "Awesome wallet\nfor Monero";
85 + String get full_balance => "Full Balance";
86 + String get hidden_balance => "Hidden Balance";
87 + String get id => "ID: ";
88 + String get incoming => "Incoming";
89 + String get loading_your_wallet => "Loading your wallet";
90 + String get login => "Login";
91 + String get new_subaddress_create => "Create";
92 + String get new_subaddress_label_name => "Label name";
93 + String get new_subaddress_title => "New subaddress";
94 + String get new_wallet => "New Wallet";
95 + String get node_address => "Node Address";
96 + String get node_new => "New Node";
97 + String get node_port => "Node port";
98 + String get node_reset_settings_title => "Reset settings";
99 + String get nodes => "Nodes";
100 + String get nodes_list_reset_to_default_message => "Are you sure that you want to reset settings to default?";
101 + String get offer_expires_in => "Offer expires in: ";
102 + String get ok => "OK";
103 + String get outgoing => "Outgoing";
104 + String get password => "Password";
105 + String get payment_id => "Payment ID: ";
106 + String get pending => " (pending)";
107 + String get pin_is_incorrect => "PIN is incorrect";
108 + String get please_make_selection => "Please make selection below to\ncreate or recover your wallet.";
109 + String get please_select => "Please select:";
110 + String get please_try_to_connect_to_another_node => "Please try to connect to another node";
111 + String get receive => "Receive";
112 + String get receive_amount => "Amount";
113 + String get received => "Received";
114 + String get reconnect => "Reconnect";
115 + String get reconnect_alert_text => "Are you sure to reconnect?";
116 + String get reconnection => "Reconnection";
117 + String get remove => "Remove";
118 + String get remove_node => "Remove node";
119 + String get remove_node_message => "Are you sure that you want to remove selected node?";
120 + String get rescan => "Rescan";
121 + String get reset => "Reset";
122 + String get restore_address => "Address";
123 + String get restore_description_from_backup => "You can restore the whole Cake Wallet app from\nyour back-up file";
124 + String get restore_description_from_keys => "Restore your wallet from generated\nkeystrokes saved from your private keys";
125 + String get restore_description_from_seed => "Restore your wallet from either the 25 word\nor 13 word combination code";
126 + String get restore_description_from_seed_keys => "Get back your wallet from seed/keys that you've saved to secure place";
127 + String get restore_next => "Next";
128 + String get restore_recover => "Restore";
129 + String get restore_restore_wallet => "Restore Wallet";
130 + String get restore_seed_keys_restore => "Seed/Keys Restore";
131 + String get restore_spend_key_private => "Spend key (private)";
132 + String get restore_title_from_backup => "Restore from a back-up file";
133 + String get restore_title_from_keys => "Restore from keys";
134 + String get restore_title_from_seed => "Restore from seed";
135 + String get restore_title_from_seed_keys => "Restore from seed/keys";
136 + String get restore_view_key_private => "View key (private)";
137 + String get restore_wallet => "Restore wallet";
138 + String get restore_wallet_name => "Wallet name";
139 + String get restore_wallet_restore_description => "Wallet restore description";
140 + String get save => "Save";
141 + String get saved_the_trade_id => "I've saved the trade ID";
142 + String get seed_alert_first_text => "The next page will show\nyou a seed.";
143 + String get seed_alert_menu => " menu.";
144 + String get seed_alert_second_text => "Please write these down just in\ncase you lose or wipe your phone.";
145 + String get seed_alert_settings => "settings";
146 + String get seed_alert_third_text => "You can also see the seed again\nin the ";
147 + String get seed_alert_understand => "I understand";
148 + String get seed_share => "Share seed";
149 + String get seed_title => "Seed";
150 + String get send => "Send";
151 + String get send_creating_transaction => "Creating transaction";
152 + String get send_error_currency => "Currency can only contain numbers";
153 + String get send_error_minimum_value => "Minimum value of amount is 0.01";
154 + String get send_estimated_fee => "Estimated fee:";
155 + String get send_monero_address => "Monero address";
156 + String get send_payment_id => "Payment ID (optional)";
157 + String get send_title => "Send Monero";
158 + String get send_your_wallet => "Your wallet";
159 + String get sending => "Sending";
160 + String get sent => "Sent";
161 + String get settings_all => "ALL";
162 + String get settings_allow_biometrical_authentication => "Allow biometrical authentication";
163 + String get settings_change_language => "Change language";
164 + String get settings_change_pin => "Change PIN";
165 + String get settings_currency => "Currency";
166 + String get settings_current_node => "Current node";
167 + String get settings_dark_mode => "Dark mode";
168 + String get settings_display_balance_as => "Display balance as";
169 + String get settings_display_on_dashboard_list => "Display on dashboard list";
170 + String get settings_fee_priority => "Fee priority";
171 + String get settings_nodes => "Nodes";
172 + String get settings_none => "None";
173 + String get settings_only_trades => "Only trades";
174 + String get settings_only_transactions => "Only transactions";
175 + String get settings_personal => "Personal";
176 + String get settings_save_recipient_address => "Save recipient address";
177 + String get settings_support => "Support";
178 + String get settings_terms_and_conditions => "Terms and conditions";
179 + String get settings_title => "Settings";
180 + String get settings_trades => "Trades";
181 + String get settings_transactions => "Transactions";
182 + String get settings_wallets => "Wallets";
183 + String get setup_pin => "Setup PIN";
184 + String get setup_successful => "Your PIN has been set up successfully!";
185 + String get share_address => "Share address";
186 + String get show_keys => "Show keys";
187 + String get show_seed => "Show seed";
188 + String get spend_key_private => "Spend key (private)";
189 + String get spend_key_public => "Spend key (public)";
190 + String get status => "Status: ";
191 + String get subaddress_title => "Subaddress list";
192 + String get subaddresses => "Subaddresses";
193 + String get sync_status_connected => "CONNECTED";
194 + String get sync_status_connecting => "CONNECTING";
195 + String get sync_status_failed_connect => "FAILED CONNECT TO THE NODE";
196 + String get sync_status_not_connected => "NOT CONNECTED";
197 + String get sync_status_starting_sync => "STARTING SYNC";
198 + String get sync_status_syncronized => "SYNCHRONIZED";
199 + String get sync_status_syncronizing => "SYNCRONIZING";
200 + String get today => "Today";
201 + String get trade_details_created_at => "Created at";
202 + String get trade_details_fetching => "Fetching";
203 + String get trade_details_id => "ID";
204 + String get trade_details_pair => "Pair";
205 + String get trade_details_provider => "Provider";
206 + String get trade_details_state => "State";
207 + String get trade_details_title => "Trade Details";
208 + String get trade_history_title => "Trade history";
209 + String get trade_not_created => "Trade not created.";
210 + String get trade_not_found => "Trade not found.";
211 + String get trade_state_btc_sent => "Btc sent";
212 + String get trade_state_complete => "Complete";
213 + String get trade_state_confirming => "Confirming";
214 + String get trade_state_created => "Created";
215 + String get trade_state_finished => "Finished";
216 + String get trade_state_paid => "Paid";
217 + String get trade_state_paid_unconfirmed => "Paid unconfirmed";
218 + String get trade_state_pending => "Pending";
219 + String get trade_state_timeout => "Timeout";
220 + String get trade_state_to_be_created => "To be created";
221 + String get trade_state_traded => "Traded";
222 + String get trade_state_trading => "Trading";
223 + String get trade_state_underpaid => "Underpaid";
224 + String get trade_state_unpaid => "Unpaid";
225 + String get trades => "Trades";
226 + String get transaction_details_amount => "Amount";
227 + String get transaction_details_date => "Date";
228 + String get transaction_details_height => "Height";
229 + String get transaction_details_recipient_address => "Recipient address";
230 + String get transaction_details_title => "Transaction Details";
231 + String get transaction_details_transaction_id => "Transaction ID";
232 + String get transaction_priority_fast => "Fast";
233 + String get transaction_priority_fastest => "Fastest";
234 + String get transaction_priority_medium => "Medium";
235 + String get transaction_priority_regular => "Regular";
236 + String get transaction_priority_slow => "Slow";
237 + String get transaction_sent => "Transaction sent!";
238 + String get transactions => "Transactions";
239 + String get transactions_by_date => "Transactions by date";
240 + String get use => "Use ";
241 + String get view_key_private => "View key (private)";
242 + String get view_key_public => "View key (public)";
243 + String get wallet_keys => "Wallet keys";
244 + String get wallet_list_create_new_wallet => "Create New Wallet";
245 + String get wallet_list_load_wallet => "Load wallet";
246 + String get wallet_list_restore_wallet => "Restore Wallet";
247 + String get wallet_list_title => "Monero Wallet";
248 + String get wallet_menu => "Menu";
249 + String get wallet_name => "Wallet name";
250 + String get wallet_restoration_store_incorrect_seed_length => "Incorrect seed length";
251 + String get wallet_store_monero_wallet => "Monero Wallet";
252 + String get wallets => "Wallets";
253 + String get welcome => "WELCOME\nTO CAKE WALLET";
254 + String get widgets_address => "Address";
255 + String get widgets_or => "or";
256 + String get widgets_restore_from_blockheight => "Restore from blockheight";
257 + String get widgets_restore_from_date => "Restore from date";
258 + String get widgets_seed => "Seed";
259 + String get xmr_available_balance => "XMR Available Balance";
260 + String get xmr_full_balance => "XMR Full Balance";
261 + String get xmr_hidden => "XMR Hidden";
262 + String get yesterday => "Yesterday";
263 + String get you_will_get => "You will get";
264 + String get you_will_send => "You will send";
265 + String Blocks_remaining(String status) => "${status} Blocks Remaining";
266 + String change_current_node(String node) => "Are you sure to change current node to ${node}?";
267 + String change_language_to(String language) => "Change language to ${language}?";
268 + String commit_transaction_amount_fee(String amount, String fee) => "Commit transaction\nAmount: ${amount}\nFee: ${fee}";
269 + String copied_key_to_clipboard(String key) => "Copied ${key} to Clipboard";
270 + String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "By pressing confirm, you will be sending ${fetchingLabel} ${from} from your wallet called ${walletName} to the address shown above. Or you can send from your external wallet to the above address/QR code.\n\nPlease press confirm to continue or go back to change the amounts.\n\n";
271 + String exchange_result_description(String fetchingLabel, String from) => "Please send ${fetchingLabel} ${from} to the address shown above.\n\n";
272 + String failed_authentication(String state_error) => "Failed authentication. ${state_error}";
273 + String max_value(String value, String currency) => "Max: ${value} ${currency}";
274 + String min_value(String value, String currency) => "Min: ${value} ${currency}";
275 + String powered_by(String title) => "Powered by ${title}";
276 + String router_no_route(String name) => "No route defined for ${name}";
277 + String send_priority(String transactionPriority) => "Currently the fee is set at ${transactionPriority} priority.\nTransaction priority can be adjusted in the settings";
278 + String time(String minutes, String seconds) => "${minutes}m ${seconds}s";
279 + String trade_details_copied(String title) => "${title} copied to Clipboard";
280 + String trade_for_not_created(String title) => "Trade for ${title} is not created.";
281 + String trade_id(String id) => "Trade ID:\n${id}";
282 + String trade_id_not_found(String tradeId, String title) => "Trade ${tradeId} of ${title} not found.";
283 + String trade_is_powered_by(String provider) => "This trade is powered by ${provider}";
284 + String transaction_details_copied(String title) => "${title} copied to Clipboard";
285 + String wallet_list_failed_to_load(String wallet_name, String error) => "Failed to load ${wallet_name} wallet. ${error}";
286 + String wallet_list_failed_to_remove(String wallet_name, String error) => "Failed to remove ${wallet_name} wallet. ${error}";
287 + String wallet_list_loading_wallet(String wallet_name) => "Loading ${wallet_name} wallet";
288 + String wallet_list_removing_wallet(String wallet_name) => "Removing ${wallet_name} wallet";
289 +}
290 +
291 +class $de extends S {
292 + const $de();
293 +
294 + @override
295 + TextDirection get textDirection => TextDirection.ltr;
296 +
297 + @override
298 + String get cancel => "Abbrechen";
299 + @override
300 + String get trade_state_unpaid => "Unbezahlt";
301 + @override
302 + String get authenticated => "Authentifiziert";
303 + @override
304 + String get new_subaddress_create => "Erstellen";
305 + @override
306 + String get restore_view_key_private => "Schlüssel anzeigen(geheim)";
307 + @override
308 + String get transaction_priority_fast => "Schnell";
309 + @override
310 + String get error_text_amount => "Betrag kann nur Zahlen enthalten";
311 + @override
312 + String get hidden_balance => "Verstecktes Gleichgewicht";
313 + @override
314 + String get transaction_sent => "Transaktion gesendet!";
315 + @override
316 + String get password => "Passwort";
317 + @override
318 + String get you_will_get => "Sie erhalten";
319 + @override
320 + String get restore_description_from_seed => "Stellen Sie Ihr Wallet aus den 25 Wörtern wieder her\noder 13-Wort-Kombinationscode";
321 + @override
322 + String get trade_state_underpaid => "Unterbezahlt";
323 + @override
324 + String get welcome => "Willkommen\nzu CAKE WALLET";
325 + @override
326 + String get share_address => "Adresse teilen ";
327 + @override
328 + String get please_try_to_connect_to_another_node => "Bitte versuchen Sie, eine Verbindung zu einem anderen Knoten herzustellen";
329 + @override
330 + String get trade_state_traded => "Handeln";
331 + @override
332 + String get edit => "Bearbeiten";
333 + @override
334 + String get spend_key_public => "Schlüssel ausgeben (Öffentlichkeit)";
335 + @override
336 + String get sync_status_syncronizing => "SYNCHRONISIERUNG";
337 + @override
338 + String get received => "Empfangen";
339 + @override
340 + String get auth_store_banned_minutes => " Protokoll";
341 + @override
342 + String get restore_title_from_seed_keys => "Vom Seed / Schlüssel wiederherstellen";
343 + @override
344 + String get settings_none => "Keiner";
345 + @override
346 + String get wallet_list_create_new_wallet => "Neue Wallet erstellen";
347 + @override
348 + String get seed_alert_third_text => "Sie können den Seed auch wieder sehen\nin dem ";
349 + @override
350 + String get setup_pin => "PIN einrichten";
351 + @override
352 + String get transaction_details_recipient_address => "Empfängeradresse";
353 + @override
354 + String get receive_amount => "Menge";
355 + @override
356 + String get settings_allow_biometrical_authentication => "Biometrische Authentifizierung zulassen";
357 + @override
358 + String get view_key_private => "Schlüssel anzeigen (eheim)";
359 + @override
360 + String get restore_next => "Nächster";
361 + @override
362 + String get trade_state_trading => "Handel";
363 + @override
364 + String get error_text_address => "Die Walletadresse muss dem Typ entsprechen\nder Kryptowährung";
365 + @override
366 + String get send_your_wallet => "Deine Geldbörse";
367 + @override
368 + String get remove_node_message => "Möchten Sie den ausgewählten Knoten wirklich entfernen?";
369 + @override
370 + String get error_text_account_name => "Der Kontoname darf nur Wallet und Zahlen enthalten\nund muss zwischen 1 und 15 Zeichen lang sein";
371 + @override
372 + String get reconnection => "Wiederverbindung";
373 + @override
374 + String get available_balance => "Verfügbares Guthaben";
375 + @override
376 + String get restore_title_from_keys => "Wiederherstellen von Schlüsseln";
377 + @override
378 + String get wallet_keys => "Wallet schlüssel";
379 + @override
380 + String get reconnect => "Erneut verbinden";
381 + @override
382 + String get reconnect_alert_text => "Sind Sie sicher, dass Sie die Verbindung wiederherstellen möchten?";
383 + @override
384 + String get send_error_minimum_value => "Der Mindestbetrag beträgt 0,01";
385 + @override
386 + String get copy_address => "Adresse kopieren";
387 + @override
388 + String get error_text_subaddress_name => "Der Name der Unteradresse darf nicht enthalten sein ` , ' \" symbole\nund muss zwischen 1 und 20 Zeichen lang sein";
389 + @override
390 + String get settings_all => "ALLE";
391 + @override
392 + String get nodes_list_reset_to_default_message => "Möchten Sie die Einstellungen wirklich auf die Standardeinstellungen zurücksetzen?";
393 + @override
394 + String get receive => "Erhalten";
395 + @override
396 + String get amount_is_guaranteed => "Der Empfangsbetrag ist garantiert";
397 + @override
398 + String get auth_store_banned_for => "Gebannt für ";
399 + @override
400 + String get trade_details_pair => "Paar";
401 + @override
402 + String get confirm => "Bestätigen";
403 + String get send_xmr => "Senden XMR";
404 + @override
405 + String get settings_display_balance_as => "Kontostand anzeigen als";
406 + @override
407 + String get trade_details_provider => "Anbieter";
408 + @override
409 + String get you_will_send => "Du wirst senden";
410 + @override
411 + String get create_new => "Erstelle neu";
412 + @override
413 + String get trade_details_fetching => "Holen";
414 + @override
415 + String get seed_alert_menu => " Speisekarte.";
416 + @override
417 + String get confirm_sending => "Bestätigen Sie das Senden";
418 + @override
419 + String get settings_title => "die Einstellungen";
420 + @override
421 + String get address_book_menu => "Adressbuch";
422 + @override
423 + String get wallet_restoration_store_incorrect_seed_length => "Falsche Samenlänge";
424 + @override
425 + String get contact => "Kontakt";
426 + @override
427 + String get auth_store_incorrect_password => "Falsches PIN";
428 + @override
429 + String get transaction_priority_slow => "Schleppend";
430 + @override
431 + String get add => "Hinzufügen";
432 + @override
433 + String get remove_node => "Knoten entfernen";
434 + @override
435 + String get trade_state_paid_unconfirmed => "Unbestätigt bezahlt";
436 + @override
437 + String get please_select => "Bitte auswählen:";
438 + @override
439 + String get restore_title_from_backup => "Aus einer Sicherungsdatei wiederherstellen";
440 + @override
441 + String get full_balance => "Volle Balance";
442 + @override
443 + String get sync_status_not_connected => "NICHT VERBUNDEN";
444 + @override
445 + String get error_text_crypto_currency => "Die Anzahl der Nachkommastellen\nmuss kleiner oder gleich 12 sein.";
446 + @override
447 + String get error_text_contact_name => "Kontaktname darf nicht enthalten sein ` , ' \" Symbole\nund muss zwischen 1 und 32 Zeichen lang sein";
448 + @override
449 + String get restore_seed_keys_restore => "Seed / Schlüssel wiederherstellen";
450 + @override
451 + String get xmr_hidden => "XMR versteckt";
452 + @override
453 + String get exchange => "Austausch";
454 + @override
455 + String get sync_status_failed_connect => "Verbindung zum Knoten fehlgeschlagen";
456 + @override
457 + String get send_estimated_fee => "Geschätzte Gebühr:";
458 + @override
459 + String get outgoing => "Ausgehend";
460 + @override
461 + String get sync_status_connected => "IN VERBINDUNG GEBRACHT";
462 + @override
463 + String get trade_state_pending => "Steht aus";
464 + @override
465 + String get pending => " (steht aus)";
466 + @override
467 + String get setup_successful => "Ihre PIN wurde erfolgreich eingerichtet!";
468 + @override
469 + String get fetching => "holen";
470 + @override
471 + String get settings_nodes => "Knoten";
472 + @override
473 + String get widgets_or => "oder";
474 + @override
475 + String get remove => "Löschen";
476 + @override
477 + String get yesterday => "Gestern";
478 + @override
479 + String get expired => "Abgelaufen";
480 + @override
481 + String get transaction_priority_regular => "Regulär";
482 + @override
483 + String get trade_details_created_at => "Hergestellt in";
484 + @override
485 + String get settings_wallets => "Brieftaschen";
486 + @override
487 + String get settings_only_transactions => "Nur Transaktionen";
488 + @override
489 + String get estimated => "Geschätzt";
490 + @override
491 + String get filters => "Filter";
492 + @override
493 + String get settings_current_node => "Aktueller Knoten";
494 + @override
495 + String get copy_id => "ID kopieren";
496 + @override
497 + String get please_make_selection => "Bitte treffen Sie unten eine Auswahl zu\nErstellen oder Wiederherstellen Ihrer Brieftasche.";
498 + @override
499 + String get loading_your_wallet => "Laden Sie Ihre Brieftasche";
500 + @override
501 + String get subaddresses => "Unteradressen";
502 + @override
503 + String get trade_state_timeout => "Auszeit";
504 + @override
505 + String get nodes => "Knoten";
506 + @override
507 + String get seed_share => "Teilen Sie Seed";
508 + @override
509 + String get widgets_restore_from_blockheight => "Aus Blockhöhe wiederherstellen";
510 + @override
511 + String get new_subaddress_label_name => "Markenname";
512 + @override
513 + String get trade_not_found => "Handel nicht gefunden.";
514 + @override
515 + String get transaction_details_date => "Datum";
516 + @override
517 + String get show_seed => "Seed zeigen";
518 + @override
519 + String get send_error_currency => "Die Währung kann nur Zahlen enthalten";
520 + @override
521 + String get subaddress_title => "Unteradressenliste";
522 + @override
523 + String get wallet_store_monero_wallet => "Monero Wallet";
524 + @override
525 + String get send_creating_transaction => "Transaktion erstellen";
526 + @override
527 + String get trade_state_complete => "Komplett";
528 + @override
529 + String get error_text_xmr => "Der XMR-Wert kann das verfügbare Guthaben nicht überschreiten.\nDie Anzahl der Nachkommastellen muss kleiner oder gleich 12 sein";
530 + @override
531 + String get xmr_available_balance => "XMR verfügbares Guthaben";
532 + @override
533 + String get trade_state_paid => "Bezahlt";
534 + @override
535 + String get node_new => "Neuer Knoten";
536 + @override
537 + String get trade_state_created => "Erstellt";
538 + @override
539 + String get faq => "FAQ";
540 + @override
541 + String get id => "ID: ";
542 + @override
543 + String get saved_the_trade_id => "Ich habe die Geschäfts-ID gespeichert";
544 + @override
545 + String get settings_currency => "Währung";
546 + @override
547 + String get change_language => "Sprache ändern";
548 + @override
549 + String get wallet_name => "Walletname";
550 + @override
551 + String get error_text_payment_id => "Die Zahlungs-ID kann nur 16 bis 64 hexadezimale Zeichen enthalten";
552 + @override
553 + String get seed_alert_second_text => "Bitte schreiben Sie diese nur in\nFalls Sie Ihr Telefon verlieren oder abwischen.";
554 + @override
555 + String get node_reset_settings_title => "Einstellungen zurücksetzen";
556 + @override
557 + String get wallets => "Wallets";
558 + @override
559 + String get enter_your_pin_again => "Geben Sie Ihre PIN erneut ein";
560 + @override
561 + String get transactions => "Transaktionen";
562 + @override
563 + String get amount_is_estimate => "Der empfangene Betrag ist eine Schätzung";
564 + @override
565 + String get error_text_node_address => "Bitte geben Sie eine iPv4-Adresse ein";
566 + @override
567 + String get widgets_restore_from_date => "Vom Datum wiederherstellen";
568 + @override
569 + String get restore_recover => "Genesen";
570 + @override
571 + String get reset => "Zurücksetzen";
572 + @override
573 + String get new_wallet => "Neues Wallet";
574 + @override
575 + String get settings_display_on_dashboard_list => "Anzeige in der Dashboard-Liste";
576 + @override
577 + String get transaction_details_title => "Transaktionsdetails";
578 + @override
579 + String get status => "Status: ";
580 + @override
581 + String get restore_spend_key_private => "Schlüssel ausgeben (geheim)";
582 + @override
583 + String get sync_status_syncronized => "SYNCHRONISIERT";
584 + @override
585 + String get transaction_priority_medium => "Mittel";
586 + @override
587 + String get transaction_details_transaction_id => "Transaktions-ID";
588 + @override
589 + String get save => "speichern";
590 + @override
591 + String get login => "Einloggen";
592 + @override
593 + String get wallet_list_load_wallet => "Wallet einlegen";
594 + @override
595 + String get sending => "Senden";
596 + @override
597 + String get restore_restore_wallet => "Wallet wiederherstellen";
598 + @override
599 + String get restore_description_from_seed_keys => "Holen Sie sich Ihr Wallet von Seed / Schlüsseln zurück, die Sie an einem sicheren Ort aufbewahrt haben";
600 + @override
601 + String get copy => "Kopieren";
602 + @override
603 + String get node_port => "Knotenport";
604 + @override
605 + String get change_currency => "Währung ändern";
606 + @override
607 + String get transaction_details_amount => "Menge";
608 + @override
609 + String get widgets_address => "Adresse";
610 + @override
611 + String get contact_name => "Name des Ansprechpartners";
612 + @override
613 + String get exchange_result_write_down_ID => "*Bitte kopieren oder notieren Sie Ihren oben gezeigten Ausweis.";
614 + @override
615 + String get exchange_result_write_down_trade_id => "Bitte kopieren oder notieren Sie die Handel-ID, um fortzufahren.";
616 + @override
617 + String get new_subaddress_title => "Neue Unteradresse";
618 + @override
619 + String get change => "Veränderung";
620 + @override
621 + String get seed_alert_first_text => "Die nächste Seite wird angezeigt\nDu bist ein Seed.";
622 + @override
623 + String get trade_state_finished => "Fertig";
624 + @override
625 + String get pin_is_incorrect => "PIN ist falsch";
626 + @override
627 + String get trade_not_created => "Handel nicht angelegt.";
628 + @override
629 + String get restore_wallet_name => "Walletname";
630 + @override
631 + String get widgets_seed => "Seed";
632 + @override
633 + String get settings_fee_priority => "Gebührenpriorität";
634 + @override
635 + String get settings_personal => "persönlich";
636 + @override
637 + String get seed_title => "Seed";
638 + @override
639 + String get accounts => "Konten";
640 + @override
641 + String get rescan => "Erneut scannen";
642 + @override
643 + String get seed_alert_understand => "ich verstehe";
644 + @override
645 + String get show_keys => "Schlüssel anzeigen";
646 + @override
647 + String get error_text_fiat => "Der Wert des Betrags darf den verfügbaren Kontostand nicht überschreiten.\nDie Anzahl der Nachkommastellen muss kleiner oder gleich 2 sein";
648 + @override
649 + String get transactions_by_date => "Transaktionen nach Datum";
650 + @override
651 + String get use => "Verwenden ";
652 + @override
653 + String get trade_details_state => "Zustand";
654 + @override
655 + String get spend_key_private => "Schlüssel ausgeben (geheim)";
656 + @override
657 + String get settings_only_trades => "Nur Trades";
658 + @override
659 + String get trade_state_to_be_created => "Geschaffen werden";
660 + @override
661 + String get all => "ALLE";
662 + @override
663 + String get xmr_full_balance => "XMR Volle Balance";
664 + @override
665 + String get incoming => "Eingehend";
666 + @override
667 + String get trade_history_title => "Handelsgeschichte";
668 + @override
669 + String get error_text_wallet_name => "Der Wallet darf nur Buchstaben und Zahlen enthalten\nund muss zwischen 1 und 15 Zeichen lang sein";
670 + @override
671 + String get restore_description_from_keys => "Stellen Sie Ihr Wallet von generiert wieder her\nTastenanschläge, die von Ihren privaten Schlüsseln gespeichert wurden";
672 + @override
673 + String get sent => "Geschickt";
674 + @override
675 + String get view_key_public => "Schlüssel anzeigen (Öffentlichkeit)";
676 + @override
677 + String get trade_details_id => "ID";
678 + @override
679 + String get trade_state_confirming => "Bestätigung";
680 + @override
681 + String get send => "Senden";
682 + @override
683 + String get send_title => "Senden Sie Monero";
684 + @override
685 + String get error_text_keys => "Walletschlüssel können nur 64 hexadezimale Zeichen enthalten";
686 + @override
687 + String get settings_save_recipient_address => "Empfängeradresse speichern";
688 + @override
689 + String get seed_alert_settings => "die Einstellungen";
690 + @override
691 + String get change_exchange_provider => "Wechseln Sie den Exchange-Anbieter";
692 + @override
693 + String get send_payment_id => "Zahlungs ID (wahlweise)";
694 + @override
695 + String get trade_details_title => "Handel Einzelheiten";
696 + @override
697 + String get settings_terms_and_conditions => "Geschäftsbedingungen";
698 + @override
699 + String get auth_store_ban_timeout => "Auszeit verbieten";
700 + @override
701 + String get sync_status_connecting => "ANSCHLUSS";
702 + @override
703 + String get settings_transactions => "Transaktionen";
704 + @override
705 + String get transaction_priority_fastest => "Am schnellsten";
706 + @override
707 + String get error => "Error";
708 + @override
709 + String get delete => "Löschen";
710 + @override
711 + String get sync_status_starting_sync => "STARTEN DER SYNCHRONISIERUNG";
712 + @override
713 + String get copied_to_clipboard => "In die Zwischenablage kopiert";
714 + @override
715 + String get offer_expires_in => "Angebot läuft ab in: ";
716 + @override
717 + String get continue_text => "Fortsetzen";
718 + @override
719 + String get transaction_details_height => "Höhe";
720 + @override
721 + String get wallet_menu => "Brieftaschen-Menü";
722 + @override
723 + String get settings_dark_mode => "Dunkler Modus";
724 + @override
725 + String get payment_id => "Zahlungs ID: ";
726 + @override
727 + String get restore_address => "Adresse";
728 + @override
729 + String get restore_wallet_restore_description => "Beschreibung zur Wiederherstellung der Brieftasche";
730 + @override
731 + String get today => "Heute";
732 + @override
733 + String get settings_support => "Unterstützung";
734 + @override
735 + String get restore_wallet => "Wallet wiederherstellen";
736 + @override
737 + String get ok => "OK";
738 + @override
739 + String get wallet_list_title => "Monero Wallet";
740 + @override
741 + String get authentication => "Authentifizierung";
742 + @override
743 + String get amount => "Menge: ";
744 + @override
745 + String get node_address => "Knotenadresse";
746 + @override
747 + String get settings_change_language => "Sprache ändern";
748 + @override
749 + String get clear => "klar";
750 + @override
751 + String get settings_change_pin => "PIN ändern";
752 + @override
753 + String get trades => "Handel";
754 + @override
755 + String get trade_state_btc_sent => "geschickt";
756 + @override
757 + String get address_book => "Adressbuch";
758 + @override
759 + String get enter_your_pin => "PIN eingeben";
760 + @override
761 + String get wallet_list_restore_wallet => "Wallet wiederherstellen";
762 + @override
763 + String get restore_title_from_seed => "Aus Seed wiederherstellen";
764 + @override
765 + String get restore_description_from_backup => "Sie können die gesamte Cake Wallet-App von wiederherstellen \nIhre Sicherungsdatei";
766 + @override
767 + String get send_monero_address => "Monero-Adresse";
768 + @override
769 + String get error_text_node_port => "Der Knotenport kann nur Nummern zwischen 0 und 65535 enthalten";
770 + @override
771 + String get digit_pin => "-stelliger Pin";
772 + @override
773 + String get first_wallet_text => "tolle Brieftasche\nzum Monero";
774 + @override
775 + String get settings_trades => "Handel";
776 + @override
777 + String get account => "Konto";
778 + @override
779 + String change_language_to(String language) => "Ändern Sie die Sprache in ${language}?";
780 + @override
781 + String change_current_node(String node) => "Möchten Sie den aktuellen Knoten wirklich auf ändern? ${node}?";
782 + @override
783 + String trade_id(String id) => "Handel-ID:\n${id}";
784 + @override
785 + String wallet_list_loading_wallet(String wallet_name) => "Wird geladen ${wallet_name} Wallet";
786 + @override
787 + String router_no_route(String name) => "Keine Route definiert für ${name}";
788 + @override
789 + String trade_id_not_found(String tradeId, String title) => "Handel ${tradeId} von ${title} nicht gefunden.";
790 + @override
791 + String transaction_details_copied(String title) => "${title} in die Zwischenablage kopiert";
792 + @override
793 + String trade_details_copied(String title) => "${title} in die Zwischenablage kopiert";
794 + @override
795 + String powered_by(String title) => "Unterstützt von ${title}";
796 + @override
797 + String send_priority(String transactionPriority) => "Derzeit ist die Gebühr auf festgelegt ${transactionPriority} priorität.\nDie Transaktionspriorität kann in den Einstellungen angepasst werden";
798 + @override
799 + String trade_for_not_created(String title) => "Handel für ${title} wird nicht erstellt.";
800 + @override
801 + String trade_is_powered_by(String provider) => "Dieser Handel wird betrieben von ${provider}";
802 + @override
803 + String time(String minutes, String seconds) => "${minutes}m ${seconds}s";
804 + @override
805 + String max_value(String value, String currency) => "Max: ${value} ${currency}";
806 + @override
807 + String min_value(String value, String currency) => "Mindest: ${value} ${currency}";
808 + @override
809 + String failed_authentication(String state_error) => "Authentifizierung fehlgeschlagen. ${state_error}";
810 + @override
811 + String Blocks_remaining(String status) => "${status} Verbleibende Blöcke";
812 + @override
813 + String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "Durch Drücken von Bestätigen wird gesendet ${fetchingLabel} ${from} von Ihrer Brieftasche aus angerufen ${walletName} an die oben angegebene Adresse. Oder Sie können von Ihrem externen Portemonnaie an die oben angegebene Adresse / QR-Code senden.\n\nBitte bestätigen Sie, um fortzufahren, oder gehen Sie zurück, um die Beträge zu änderns.\n\n";
814 + @override
815 + String exchange_result_description(String fetchingLabel, String from) => "Bitte senden ${fetchingLabel} ${from} an die oben angegebene Adresse.\n\n'";
816 + @override
817 + String commit_transaction_amount_fee(String amount, String fee) => "Transaktion festschreiben\nMenge: ${amount}\nGebühr: ${fee}";
818 + @override
819 + String wallet_list_failed_to_remove(String wallet_name, String error) => "Fehler beim Entfernen ${wallet_name} Wallet. ${error}";
820 + @override
821 + String copied_key_to_clipboard(String key) => "Kopiert ${key} Zur Zwischenablage";
822 + @override
823 + String wallet_list_failed_to_load(String wallet_name, String error) => "Laden fehlgeschlagen ${wallet_name} Wallet. ${error}";
824 + @override
825 + String wallet_list_removing_wallet(String wallet_name) => "Entfernen ${wallet_name} Wallet";
826 +}
827 +
828 +class $hi extends S {
829 + const $hi();
830 +
831 + @override
832 + TextDirection get textDirection => TextDirection.ltr;
833 +
834 + @override
835 + String get cancel => "रद्द करना";
836 + @override
837 + String get trade_state_unpaid => "अवैतनिक";
838 + @override
839 + String get authenticated => "प्रमाणीकृत";
840 + @override
841 + String get new_subaddress_create => "सर्जन करना";
842 + @override
843 + String get restore_view_key_private => "कुंजी देखें (निजी)";
844 + @override
845 + String get transaction_priority_fast => "उपवास";
846 + @override
847 + String get error_text_amount => "राशि में केवल संख्याएँ हो सकती हैं";
848 + @override
849 + String get hidden_balance => "छिपा हुआ संतुलन";
850 + @override
851 + String get transaction_sent => "भेजा गया लेन-देन";
852 + @override
853 + String get password => "पारण शब्द";
854 + @override
855 + String get you_will_get => "आपको मिल जायेगा";
856 + @override
857 + String get restore_description_from_seed => "या तो 25 शब्द से अपने वॉलेट को पुनर्स्थापित करें\nया 13 शब्द संयोजन कोड";
858 + @override
859 + String get trade_state_underpaid => "के तहत भुगतान किया";
860 + @override
861 + String get welcome => "स्वागत हे\nसेवा मेरे CAKE WALLET";
862 + @override
863 + String get share_address => "पता साझा करें";
864 + @override
865 + String get please_try_to_connect_to_another_node => "कृपया दूसरे नोड से कनेक्ट करने का प्रयास करें";
866 + @override
867 + String get trade_state_traded => "ट्रेडेड";
868 + @override
869 + String get edit => "संपादित करें";
870 + @override
871 + String get spend_key_public => "खर्च करना (जनता)";
872 + @override
873 + String get sync_status_syncronizing => "सिंक्रनाइज़ करने";
874 + @override
875 + String get received => "प्राप्त किया";
876 + @override
877 + String get auth_store_banned_minutes => " मिनट";
878 + @override
879 + String get restore_title_from_seed_keys => "बीज / कुंजियों से पुनर्स्थापित करें";
880 + @override
881 + String get settings_none => "कोई नहीं";
882 + @override
883 + String get wallet_list_create_new_wallet => "नया बटुआ बनाएँ";
884 + @override
885 + String get seed_alert_third_text => "आप बीज को फिर से देख सकते हैं\nमें ";
886 + @override
887 + String get setup_pin => "पिन सेट करें";
888 + @override
889 + String get transaction_details_recipient_address => "प्राप्तकर्ता का पता";
890 + @override
891 + String get receive_amount => "रकम";
892 + @override
893 + String get settings_allow_biometrical_authentication => "बायोमेट्रिक प्रमाणीकरण की अनुमति दें";
894 + @override
895 + String get view_key_private => "कुंजी देखें(निजी)";
896 + @override
897 + String get restore_next => "आगामी";
898 + @override
899 + String get trade_state_trading => "व्यापार";
900 + @override
901 + String get error_text_address => "वॉलेट पता प्रकार के अनुरूप होना चाहिए\nक्रिप्टोकरेंसी का";
902 + @override
903 + String get send_your_wallet => "आपका बटुआ";
904 + @override
905 + String get remove_node_message => "क्या आप वाकई चयनित नोड को निकालना चाहते हैं?";
906 + @override
907 + String get error_text_account_name => "खाता नाम में केवल अक्षर, संख्याएं हो सकती हैं\nऔर 1 और 15 वर्णों के बीच लंबा होना चाहिए";
908 + @override
909 + String get reconnection => "पुनर्संयोजन";
910 + @override
911 + String get available_balance => "उपलब्ध शेष राशि";
912 + @override
913 + String get restore_title_from_keys => "कुंजी से पुनर्स्थापित करें";
914 + @override
915 + String get wallet_keys => "बटुआ की";
916 + @override
917 + String get reconnect => "रिकनेक्ट";
918 + @override
919 + String get reconnect_alert_text => "क्या आप पुन: कनेक्ट होना सुनिश्चित करते हैं?";
920 + @override
921 + String get send_error_minimum_value => "राशि का न्यूनतम मूल्य 0.01 है";
922 + @override
923 + String get copy_address => "पता कॉपी करें";
924 + @override
925 + String get error_text_subaddress_name => "सबड्रेस नाम नहीं हो सकता` , ' \" प्रतीकों\nऔर 1 और 20 वर्णों के बीच लंबा होना चाहिए";
926 + @override
927 + String get settings_all => "सब";
928 + @override
929 + String get nodes_list_reset_to_default_message => "क्या आप वाकई सेटिंग को डिफ़ॉल्ट पर रीसेट करना चाहते हैं?";
930 + @override
931 + String get receive => "प्राप्त करना";
932 + @override
933 + String get amount_is_guaranteed => "प्राप्त राशि की गारंटी है";
934 + @override
935 + String get auth_store_banned_for => "के लिए प्रतिबंधित है ";
936 + @override
937 + String get trade_details_pair => "जोड़ा";
938 + @override
939 + String get confirm => "की पुष्टि करें";
940 + String get send_xmr => "संदेश XMR";
941 + @override
942 + String get settings_display_balance_as => "के रूप में संतुलन प्रदर्शित करें";
943 + @override
944 + String get trade_details_provider => "प्रदाता";
945 + @override
946 + String get you_will_send => "तुम भेजोगे";
947 + @override
948 + String get create_new => "नया बनाओ";
949 + @override
950 + String get trade_details_fetching => "ला रहा है";
951 + @override
952 + String get seed_alert_menu => " मेन्यू.";
953 + @override
954 + String get confirm_sending => "भेजने की पुष्टि करें";
955 + @override
956 + String get settings_title => "सेटिंग्स";
957 + @override
958 + String get address_book_menu => "पता पुस्तिका";
959 + @override
960 + String get wallet_restoration_store_incorrect_seed_length => "गलत बीज की लंबाई";
961 + @override
962 + String get contact => "संपर्क करें";
963 + @override
964 + String get auth_store_incorrect_password => "गलत पिन";
965 + @override
966 + String get transaction_priority_slow => "धीरे";
967 + @override
968 + String get add => "जोड़ना";
969 + @override
970 + String get remove_node => "नोड निकालें";
971 + @override
972 + String get trade_state_paid_unconfirmed => "अपुष्ट भुगतान किया";
973 + @override
974 + String get please_select => "कृपया चुने:";
975 + @override
976 + String get restore_title_from_backup => "बैक-अप फ़ाइल से पुनर्स्थापित करें";
977 + @override
978 + String get full_balance => "पूर्ण संतुलन";
979 + @override
980 + String get sync_status_not_connected => "जुड़े नहीं हैं";
981 + @override
982 + String get error_text_crypto_currency => "अंश अंकों की संख्या\n12 से कम या इसके बराबर होना चाहिए";
983 + @override
984 + String get error_text_contact_name => "संपर्क नाम शामिल नहीं हो सकता ` , ' \" प्रतीकों\nऔर 1 और 32 वर्णों के बीच लंबा होना चाहिए";
985 + @override
986 + String get restore_seed_keys_restore => "बीज / कुंजी पुनर्स्थापित करें";
987 + @override
988 + String get xmr_hidden => "XMR छिपा हुआ";
989 + @override
990 + String get exchange => "अदला बदली";
991 + @override
992 + String get sync_status_failed_connect => "फेल हुआ कनेक्ट नोड";
993 + @override
994 + String get send_estimated_fee => "अनुमानित शुल्क:";
995 + @override
996 + String get outgoing => "निवर्तमान";
997 + @override
998 + String get sync_status_connected => "जुड़े हुए";
999 + @override
1000 + String get trade_state_pending => "विचाराधीन";
1001 + @override
1002 + String get pending => " (अपूर्ण)";
1003 + @override
1004 + String get setup_successful => "आपका पिन सफलतापूर्वक सेट हो गया है";
1005 + @override
1006 + String get fetching => "ला रहा है";
1007 + @override
1008 + String get settings_nodes => "नोड्स";
1009 + @override
1010 + String get widgets_or => "या";
1011 + @override
1012 + String get remove => "हटाना";
1013 + @override
1014 + String get yesterday => "बिता कल";
1015 + @override
1016 + String get expired => "समय सीमा समाप्त";
1017 + @override
1018 + String get transaction_priority_regular => "नियमित";
1019 + @override
1020 + String get trade_details_created_at => "पर बनाया गया";
1021 + @override
1022 + String get settings_wallets => "पर्स";
1023 + @override
1024 + String get settings_only_transactions => "केवल लेन-देन";
1025 + @override
1026 + String get estimated => "अनुमानित";
1027 + @override
1028 + String get filters => "फिल्टर";
1029 + @override
1030 + String get settings_current_node => "वर्तमान नोड";
1031 + @override
1032 + String get copy_id => "प्रतिलिपि ID";
1033 + @override
1034 + String get please_make_selection => "कृपया नीचे चयन करें\nअपना बटुआ बनाएं या पुनर्प्राप्त करें.";
1035 + @override
1036 + String get loading_your_wallet => "अपना बटुआ लोड कर रहा है";
1037 + @override
1038 + String get subaddresses => "उप पते";
1039 + @override
1040 + String get trade_state_timeout => "समय समाप्त";
1041 + @override
1042 + String get nodes => "नोड्स";
1043 + @override
1044 + String get seed_share => "बीज साझा करें";
1045 + @override
1046 + String get widgets_restore_from_blockheight => "ब्लॉकचेन से पुनर्स्थापित करें";
1047 + @override
1048 + String get new_subaddress_label_name => "लेबल का नाम";
1049 + @override
1050 + String get trade_not_found => "व्यापार नहीं मिला";
1051 + @override
1052 + String get transaction_details_date => "तारीख";
1053 + @override
1054 + String get show_seed => "बीज दिखाओ";
1055 + @override
1056 + String get send_error_currency => "मुद्रा में केवल संख्याएँ हो सकती हैं";
1057 + @override
1058 + String get subaddress_title => "उपखंड सूची";
1059 + @override
1060 + String get wallet_store_monero_wallet => "मोनरो वॉलेट";
1061 + @override
1062 + String get send_creating_transaction => "लेन-देन बनाना";
1063 + @override
1064 + String get trade_state_complete => "पूर्ण";
1065 + @override
1066 + String get error_text_xmr => "एक्सएमआर मूल्य उपलब्ध शेष राशि से अधिक नहीं हो सकता.\nअंश अंकों की संख्या 12 से कम या इसके बराबर होनी चाहिए";
1067 + @override
1068 + String get xmr_available_balance => "XMR उपलब्ध शेष राशि";
1069 + @override
1070 + String get trade_state_paid => "भुगतान किया है";
1071 + @override
1072 + String get node_new => "नया नोड";
1073 + @override
1074 + String get trade_state_created => "बनाया था";
1075 + @override
1076 + String get faq => "FAQ";
1077 + @override
1078 + String get id => "ID: ";
1079 + @override
1080 + String get saved_the_trade_id => "मैंने व्यापार बचा लिया है ID";
1081 + @override
1082 + String get settings_currency => "मुद्रा";
1083 + @override
1084 + String get change_language => "भाषा बदलो";
1085 + @override
1086 + String get wallet_name => "बटुए का नाम";
1087 + @override
1088 + String get error_text_payment_id => "पेमेंट आईडी केवल हेक्स में 16 से 64 चार्ट तक हो सकती है";
1089 + @override
1090 + String get seed_alert_second_text => "कृपया इन्हें केवल मामले में लिखें\nआप अपना फोन खो देते हैं या मिटा देते हैं.";
1091 + @override
1092 + String get node_reset_settings_title => "सेटिंग्स को दुबारा करें";
1093 + @override
1094 + String get wallets => "पर्स";
1095 + @override
1096 + String get enter_your_pin_again => "फिर से अपना पिन डालें";
1097 + @override
1098 + String get transactions => "लेन-देन";
1099 + @override
1100 + String get amount_is_estimate => "प्राप्त राशि एक अनुमान है";
1101 + @override
1102 + String get error_text_node_address => "कृपया एक IPv4 पता दर्ज करें";
1103 + @override
1104 + String get widgets_restore_from_date => "दिनांक से पुनर्स्थापित करें";
1105 + @override
1106 + String get restore_recover => "वसूली";
1107 + @override
1108 + String get reset => "रीसेट";
1109 + @override
1110 + String get new_wallet => "नया बटुआ";
1111 + @override
1112 + String get settings_display_on_dashboard_list => "डैशबोर्ड सूची पर प्रदर्शित करें";
1113 + @override
1114 + String get transaction_details_title => "लेनदेन का विवरण";
1115 + @override
1116 + String get status => "स्थिति: ";
1117 + @override
1118 + String get restore_spend_key_private => "कुंजी खर्च करें (निजीe)";
1119 + @override
1120 + String get sync_status_syncronized => "सिंक्रनाइज़";
1121 + @override
1122 + String get transaction_priority_medium => "मध्यम";
1123 + @override
1124 + String get transaction_details_transaction_id => "लेनदेन आईडी";
1125 + @override
1126 + String get save => "बचाना";
1127 + @override
1128 + String get login => "लॉग इन करें";
1129 + @override
1130 + String get wallet_list_load_wallet => "वॉलेट लोड करें";
1131 + @override
1132 + String get sending => "भेजना";
1133 + @override
1134 + String get restore_restore_wallet => "वॉलेट को पुनर्स्थापित करें";
1135 + @override
1136 + String get restore_description_from_seed_keys => "अपने बटुए को बीज से वापस लें/वे कुंजियाँ जिन्हें आपने सुरक्षित स्थान पर सहेजा है";
1137 + @override
1138 + String get copy => "प्रतिलिपि";
1139 + @override
1140 + String get node_port => "नोड पोर्ट";
1141 + @override
1142 + String get change_currency => "मुद्रा परिवर्तन करें";
1143 + @override
1144 + String get transaction_details_amount => "रकम";
1145 + @override
1146 + String get widgets_address => "पता";
1147 + @override
1148 + String get contact_name => "संपर्क नाम";
1149 + @override
1150 + String get exchange_result_write_down_ID => "*कृपया ऊपर दिखाए गए अपने ID को कॉपी या लिख लें.";
1151 + @override
1152 + String get exchange_result_write_down_trade_id => "जारी रखने के लिए कृपया ट्रेड ID की प्रतिलिपि बनाएँ या लिखें.";
1153 + @override
1154 + String get new_subaddress_title => "नई उपशादी";
1155 + @override
1156 + String get change => "परिवर्तन";
1157 + @override
1158 + String get seed_alert_first_text => "अगला पेज दिखाएगा\nतुम एक बीज हो.";
1159 + @override
1160 + String get trade_state_finished => "ख़त्म होना";
1161 + @override
1162 + String get pin_is_incorrect => "पिन गलत है";
1163 + @override
1164 + String get trade_not_created => "व्यापार नहीं बनाया गया.";
1165 + @override
1166 + String get restore_wallet_name => "बटुए का नाम";
1167 + @override
1168 + String get widgets_seed => "बीज";
1169 + @override
1170 + String get settings_fee_priority => "शुल्क प्राथमिकता";
1171 + @override
1172 + String get settings_personal => "निजी";
1173 + @override
1174 + String get seed_title => "बीज";
1175 + @override
1176 + String get accounts => "हिसाब किताब";
1177 + @override
1178 + String get rescan => "पुन: स्कैन";
1179 + @override
1180 + String get seed_alert_understand => "मै समझता हुँ";
1181 + @override
1182 + String get show_keys => "चाबी दिखाओ";
1183 + @override
1184 + String get error_text_fiat => "राशि का मूल्य उपलब्ध शेष राशि से अधिक नहीं हो सकता.\nअंश अंकों की संख्या कम या 2 के बराबर होनी चाहिए";
1185 + @override
1186 + String get transactions_by_date => "तारीख से लेन-देन";
1187 + @override
1188 + String get use => "उपयोग ";
1189 + @override
1190 + String get trade_details_state => "राज्य";
1191 + @override
1192 + String get spend_key_private => "खर्च करना (निजी)";
1193 + @override
1194 + String get settings_only_trades => "केवल ट्रेड करता है";
1195 + @override
1196 + String get trade_state_to_be_created => "बनाए जाने के लिए";
1197 + @override
1198 + String get all => "सब";
1199 + @override
1200 + String get xmr_full_balance => "XMR पूर्ण संतुलन";
1201 + @override
1202 + String get incoming => "आने वाली";
1203 + @override
1204 + String get trade_history_title => "व्यापार का इतिहास";
1205 + @override
1206 + String get error_text_wallet_name => "वॉलेट नाम में केवल अक्षर, संख्याएं हो सकती हैं\nऔर 1 और 15 वर्णों के बीच लंबा होना चाहिए";
1207 + @override
1208 + String get restore_description_from_keys => "अपने वॉलेट को जेनरेट से पुनर्स्थापित करें\nआपकी निजी कुंजी से कीस्ट्रोक्स सहेजे गए";
1209 + @override
1210 + String get sent => "भेज दिया";
1211 + @override
1212 + String get view_key_public => "कुंजी देखें (जनता)";
1213 + @override
1214 + String get trade_details_id => "आईडी";
1215 + @override
1216 + String get trade_state_confirming => "पुष्टि";
1217 + @override
1218 + String get send => "संदेश";
1219 + @override
1220 + String get send_title => "संदेश Monero";
1221 + @override
1222 + String get error_text_keys => "वॉलेट कीज़ में हेक्स में केवल 64 वर्ण हो सकते हैं";
1223 + @override
1224 + String get settings_save_recipient_address => "प्राप्तकर्ता का पता सहेजें";
1225 + @override
1226 + String get seed_alert_settings => "सेटिंग्स";
1227 + @override
1228 + String get change_exchange_provider => "एक्सचेंज प्रदाता बदलें";
1229 + @override
1230 + String get send_payment_id => "भुगतान ID (ऐच्छिक)";
1231 + @override
1232 + String get trade_details_title => "व्यापार विवरण";
1233 + @override
1234 + String get settings_terms_and_conditions => "नियम और शर्तें";
1235 + @override
1236 + String get auth_store_ban_timeout => "समय की पाबंदी";
1237 + @override
1238 + String get sync_status_connecting => "कनेक्ट";
1239 + @override
1240 + String get settings_transactions => "लेन-देन";
1241 + @override
1242 + String get transaction_priority_fastest => "सबसे तेजी से";
1243 + @override
1244 + String get error => "त्रुटि";
1245 + @override
1246 + String get delete => "हटाएं";
1247 + @override
1248 + String get sync_status_starting_sync => "सिताज़ा करना";
1249 + @override
1250 + String get copied_to_clipboard => "क्लिपबोर्ड पर नकल";
1251 + @override
1252 + String get offer_expires_in => "में ऑफर समाप्त हो रहा है: ";
1253 + @override
1254 + String get continue_text => "जारी रहना";
1255 + @override
1256 + String get transaction_details_height => "ऊंचाई";
1257 + @override
1258 + String get wallet_menu => "बटुआ मेनू";
1259 + @override
1260 + String get settings_dark_mode => "डार्क मोड";
1261 + @override
1262 + String get payment_id => "भुगतान ID: ";
1263 + @override
1264 + String get restore_address => "पता";
1265 + @override
1266 + String get restore_wallet_restore_description => "बटुआ विवरण पुनर्स्थापित करें";
1267 + @override
1268 + String get today => "आज";
1269 + @override
1270 + String get settings_support => "समर्थन";
1271 + @override
1272 + String get restore_wallet => "वॉलेट को पुनर्स्थापित करें";
1273 + @override
1274 + String get ok => "ठीक है";
1275 + @override
1276 + String get wallet_list_title => "Monero बटुआ";
1277 + @override
1278 + String get authentication => "प्रमाणीकरण";
1279 + @override
1280 + String get amount => "रकम: ";
1281 + @override
1282 + String get node_address => "नोड पता";
1283 + @override
1284 + String get settings_change_language => "भाषा बदलो";
1285 + @override
1286 + String get clear => "स्पष्ट";
1287 + @override
1288 + String get settings_change_pin => "पिन बदलें";
1289 + @override
1290 + String get trades => "ट्रेडों";
1291 + @override
1292 + String get trade_state_btc_sent => "भेज दिया";
1293 + @override
1294 + String get address_book => "पता पुस्तिका";
1295 + @override
1296 + String get enter_your_pin => "अपना पिन दर्ज करो";
1297 + @override
1298 + String get wallet_list_restore_wallet => "वॉलेट को पुनर्स्थापित करें";
1299 + @override
1300 + String get restore_title_from_seed => "बीज से पुनर्स्थापित करें";
1301 + @override
1302 + String get restore_description_from_backup => "आप से पूरे केक वॉलेट एप्लिकेशन को पुनर्स्थापित कर सकते हैं\nआपकी बैक-अप फ़ाइल";
1303 + @override
1304 + String get send_monero_address => "मोनरो पता";
1305 + @override
1306 + String get error_text_node_port => "नोड पोर्ट में केवल 0 और 65535 के बीच संख्याएँ हो सकती हैं";
1307 + @override
1308 + String get digit_pin => "-अंक पिन";
1309 + @override
1310 + String get first_wallet_text => "बहुत बढ़िया बटुआ\nके लिये Monero";
1311 + @override
1312 + String get settings_trades => "ट्रेडों";
1313 + @override
1314 + String get account => "लेखा";
1315 + @override
1316 + String change_language_to(String language) => "को भाषा बदलें ${language}?";
1317 + @override
1318 + String change_current_node(String node) => "क्या आप वर्तमान नोड को बदलना सुनिश्चित करते हैं ${node}?";
1319 + @override
1320 + String trade_id(String id) => "व्यापार ID:\n${id}";
1321 + @override
1322 + String wallet_list_loading_wallet(String wallet_name) => "लोड हो रहा है ${wallet_name} बटुआ";
1323 + @override
1324 + String router_no_route(String name) => "के लिए कोई मार्ग निर्धारित नहीं है ${name}";
1325 + @override
1326 + String trade_id_not_found(String tradeId, String title) => "व्यापार ${tradeId} of ${title} नहीं मिला.";
1327 + @override
1328 + String transaction_details_copied(String title) => "${title} क्लिपबोर्ड पर नकल";
1329 + @override
1330 + String trade_details_copied(String title) => "${title} क्लिपबोर्ड पर नकल";
1331 + @override
1332 + String powered_by(String title) => "द्वारा संचालित ${title}";
1333 + @override
1334 + String send_priority(String transactionPriority) => "वर्तमान में शुल्क निर्धारित है ${transactionPriority} प्राथमिकता.\nलेन-देन की प्राथमिकता को सेटिंग्स में समायोजित किया जा सकता है";
1335 + @override
1336 + String trade_for_not_created(String title) => "के लिए व्यापार ${title} निर्मित नहीं है.";
1337 + @override
1338 + String trade_is_powered_by(String provider) => "यह व्यापार द्वारा संचालित है ${provider}";
1339 + @override
1340 + String time(String minutes, String seconds) => "${minutes}m ${seconds}s";
1341 + @override
1342 + String max_value(String value, String currency) => "मैक्स: ${value} ${currency}";
1343 + @override
1344 + String min_value(String value, String currency) => "मिन: ${value} ${currency}";
1345 + @override
1346 + String failed_authentication(String state_error) => "प्रमाणीकरण विफल. ${state_error}";
1347 + @override
1348 + String Blocks_remaining(String status) => "${status} शेष रहते हैं";
1349 + @override
1350 + String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "पुष्टि दबाकर, आप भेज रहे होंगे ${fetchingLabel} ${from} अपने बटुए से ${walletName} ऊपर दिखाए गए पते पर। या आप अपने बाहरी वॉलेट से उपरोक्त पते / क्यूआर कोड पर भेज सकते हैं।\n\nकृपया जारी रखने या राशि बदलने के लिए वापस जाने के लिए पुष्टि करें दबाएं.\n\n";
1351 + @override
1352 + String exchange_result_description(String fetchingLabel, String from) => "कृपया भेजें ${fetchingLabel} ${from} ऊपर दिखाए गए पते पर\n\n'";
1353 + @override
1354 + String commit_transaction_amount_fee(String amount, String fee) => "लेन-देन करें\nरकम: ${amount}\nशुल्क: ${fee}";
1355 + @override
1356 + String wallet_list_failed_to_remove(String wallet_name, String error) => "निकालने में विफल ${wallet_name} बटुआ. ${error}";
1357 + @override
1358 + String copied_key_to_clipboard(String key) => "की नकल की ${key} क्लिपबोर्ड पर";
1359 + @override
1360 + String wallet_list_failed_to_load(String wallet_name, String error) => "लोड करने में विफल ${wallet_name} बटुआ. ${error}";
1361 + @override
1362 + String wallet_list_removing_wallet(String wallet_name) => "निकाला जा रहा है ${wallet_name} बटुआ";
1363 +}
1364 +
1365 +class $ru extends S {
1366 + const $ru();
1367 +
1368 + @override
1369 + TextDirection get textDirection => TextDirection.ltr;
1370 +
1371 + @override
1372 + String get cancel => "Отменить";
1373 + @override
1374 + String get trade_state_unpaid => "Неоплаченно";
1375 + @override
1376 + String get authenticated => "Аутентифицировано";
1377 + @override
1378 + String get new_subaddress_create => "Создать";
1379 + @override
1380 + String get restore_view_key_private => "View ключ (приватный)";
1381 + @override
1382 + String get transaction_priority_fast => "Быстрый";
1383 + @override
1384 + String get error_text_amount => "Баланс может включать только цифры";
1385 + @override
1386 + String get hidden_balance => "Скрытый баланс";
1387 + @override
1388 + String get transaction_sent => "Tранзакция отправлена!";
1389 + @override
1390 + String get password => "Password";
1391 + @override
1392 + String get you_will_get => "Вы получите";
1393 + @override
1394 + String get restore_description_from_seed => "Вы можете восстановить кошелек используя 25-ти значную код фразу";
1395 + @override
1396 + String get trade_state_underpaid => "Недоплаченно";
1397 + @override
1398 + String get welcome => "Приветствуем в CAKE WALLET";
1399 + @override
1400 + String get share_address => "Поделиться адресом";
1401 + @override
1402 + String get please_try_to_connect_to_another_node => "Пожалуйста, попробуйте подключиться к другой ноде";
1403 + @override
1404 + String get trade_state_traded => "Сделка завершена";
1405 + @override
1406 + String get edit => "Редактировать";
1407 + @override
1408 + String get spend_key_public => "Spend key (публичный)";
1409 + @override
1410 + String get sync_status_syncronizing => "СИНХРОНИЗАЦИЯ";
1411 + @override
1412 + String get received => "Полученные";
1413 + @override
1414 + String get auth_store_banned_minutes => " минут";
1415 + @override
1416 + String get restore_title_from_seed_keys => "Восстановить из код-фразы/ключей";
1417 + @override
1418 + String get settings_none => "Ничего";
1419 + @override
1420 + String get wallet_list_create_new_wallet => "Создать новый кошелек";
1421 + @override
1422 + String get seed_alert_third_text => "Вы так же можете посмотреть Вашу код-фразу\nв";
1423 + @override
1424 + String get setup_pin => "Настроить PIN";
1425 + @override
1426 + String get transaction_details_recipient_address => "Адрес получателя";
1427 + @override
1428 + String get receive_amount => "Баланс";
1429 + @override
1430 + String get settings_allow_biometrical_authentication => "Включить биометрическую аутентификацию";
1431 + @override
1432 + String get view_key_private => "View key (приватный)";
1433 + @override
1434 + String get restore_next => "Продолжить";
1435 + @override
1436 + String get trade_state_trading => "Совершение сделки";
1437 + @override
1438 + String get error_text_address => "Адрес кошелька должен соответствовать типу\nкриптовалюты";
1439 + @override
1440 + String get send_your_wallet => "Ваш кошелек";
1441 + @override
1442 + String get remove_node_message => "Вы уверены, что хотите удалить текущую ноду?";
1443 + @override
1444 + String get error_text_account_name => "Имя аккаунта может включать только буквы, цифры\nи может быть от 1 до 15 символов в длину";
1445 + @override
1446 + String get reconnection => "Переподключение";
1447 + @override
1448 + String get available_balance => "Доступный баланс";
1449 + @override
1450 + String get restore_title_from_keys => "Восстановить с помощью ключей";
1451 + @override
1452 + String get wallet_keys => "Ключи кошелька";
1453 + @override
1454 + String get reconnect => "Переподключиться";
1455 + @override
1456 + String get reconnect_alert_text => "Вы хотите переподключиться?";
1457 + @override
1458 + String get send_error_minimum_value => "Mинимальная сумма 0.01";
1459 + @override
1460 + String get copy_address => "Cкопировать адрес";
1461 + @override
1462 + String get error_text_subaddress_name => "Subaddress имя не может включать ` , ' \" символы\nи может быть от 1 до 32 символов в длину";
1463 + @override
1464 + String get settings_all => "ВСЕ";
1465 + @override
1466 + String get nodes_list_reset_to_default_message => "Вы уверены, что хотите сбросить до настроек по умолчанию?";
1467 + @override
1468 + String get receive => "Получить";
1469 + @override
1470 + String get amount_is_guaranteed => "Сумма получения гарантирована";
1471 + @override
1472 + String get auth_store_banned_for => "Заблокированно на ";
1473 + @override
1474 + String get trade_details_pair => "Пара";
1475 + @override
1476 + String get confirm => "Подтвердить";
1477 + String get send_xmr => "Отправить XMR";
1478 + @override
1479 + String get settings_display_balance_as => "Отображать баланс";
1480 + @override
1481 + String get trade_details_provider => "Провайдер";
1482 + @override
1483 + String get you_will_send => "Вы отправите";
1484 + @override
1485 + String get create_new => "Создать новый";
1486 + @override
1487 + String get trade_details_fetching => "Получение";
1488 + @override
1489 + String get seed_alert_menu => " меню.";
1490 + @override
1491 + String get confirm_sending => "Подтвердить отправку";
1492 + @override
1493 + String get settings_title => "Настройки";
1494 + @override
1495 + String get address_book_menu => "Адресная книга";
1496 + @override
1497 + String get wallet_restoration_store_incorrect_seed_length => "Неверная длина код-фразы";
1498 + @override
1499 + String get contact => "Контакт";
1500 + @override
1501 + String get auth_store_incorrect_password => "Некорректный пин";
1502 + @override
1503 + String get transaction_priority_slow => "Медленный";
1504 + @override
1505 + String get add => "Добавить";
1506 + @override
1507 + String get remove_node => "Удалить ноду";
1508 + @override
1509 + String get trade_state_paid_unconfirmed => "Оплата неподтвержденная";
1510 + @override
1511 + String get please_select => "Пожалуйста, выберите:";
1512 + @override
1513 + String get restore_title_from_backup => "Восстановить из back-up файла";
1514 + @override
1515 + String get full_balance => "Полный баланс";
1516 + @override
1517 + String get sync_status_not_connected => "НЕТ ПОДКЛЮЧЕНИЯ";
1518 + @override
1519 + String get error_text_crypto_currency => "Количество цифр после запятой\nдолжно быть меньше или равно 12";
1520 + @override
1521 + String get error_text_contact_name => "Имя контакта не может включать ` , ' \" символы\n и может быть от 1 до 32 символов в длину";
1522 + @override
1523 + String get restore_seed_keys_restore => "Восстановить с помощью код-фразы/ключей";
1524 + @override
1525 + String get xmr_hidden => "XMR Скрытый";
1526 + @override
1527 + String get exchange => "Обмен";
1528 + @override
1529 + String get sync_status_failed_connect => "ОШИБКА ПОДКЛЮЧЕНИЯ К НОДЕ";
1530 + @override
1531 + String get send_estimated_fee => "Предполагаемый сбор:";
1532 + @override
1533 + String get outgoing => "Исходящие";
1534 + @override
1535 + String get sync_status_connected => "ПОДКЛЮЧЕНО";
1536 + @override
1537 + String get trade_state_pending => "Ожидание";
1538 + @override
1539 + String get pending => " (в ожидании)";
1540 + @override
1541 + String get setup_successful => "PIN был успешно изменен!";
1542 + @override
1543 + String get fetching => "Загрузка";
1544 + @override
1545 + String get settings_nodes => "Ноды";
1546 + @override
1547 + String get widgets_or => "или";
1548 + @override
1549 + String get remove => "Удалить";
1550 + @override
1551 + String get yesterday => "Вчера";
1552 + @override
1553 + String get expired => "Истекает";
1554 + @override
1555 + String get transaction_priority_regular => "Обычный";
1556 + @override
1557 + String get trade_details_created_at => "Создано";
1558 + @override
1559 + String get settings_wallets => "Кошельки";
1560 + @override
1561 + String get settings_only_transactions => "Транзакции";
1562 + @override
1563 + String get estimated => "Примерно ";
1564 + @override
1565 + String get filters => "Фильтры";
1566 + @override
1567 + String get settings_current_node => "Текущая нода";
1568 + @override
1569 + String get copy_id => "Скопировать ID";
1570 + @override
1571 + String get please_make_selection => "Выберите способ создания кошелька: создать новый или восстановить Ваш существующий.";
1572 + @override
1573 + String get loading_your_wallet => "Загрузка кошелька";
1574 + @override
1575 + String get subaddresses => "Subaddresses";
1576 + @override
1577 + String get trade_state_timeout => "Timeout";
1578 + @override
1579 + String get nodes => "Ноды";
1580 + @override
1581 + String get seed_share => "Поделиться код-фразой";
1582 + @override
1583 + String get widgets_restore_from_blockheight => "Восстановить по высоте";
1584 + @override
1585 + String get new_subaddress_label_name => "Имя";
1586 + @override
1587 + String get trade_not_found => "Trade not found.";
1588 + @override
1589 + String get transaction_details_date => "Дата";
1590 + @override
1591 + String get show_seed => "Показать код-фразу";
1592 + @override
1593 + String get send_error_currency => "Валюта может включать только цифры";
1594 + @override
1595 + String get subaddress_title => "Subaddress список";
1596 + @override
1597 + String get wallet_store_monero_wallet => "Monero кошелек";
1598 + @override
1599 + String get send_creating_transaction => "Создать транзакцию";
1600 + @override
1601 + String get trade_state_complete => "Полный";
1602 + @override
1603 + String get error_text_xmr => "XMR баланс не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 12";
1604 + @override
1605 + String get xmr_available_balance => "XMR Доступный баланс";
1606 + @override
1607 + String get trade_state_paid => "Оплачено";
1608 + @override
1609 + String get node_new => "Новая нода";
1610 + @override
1611 + String get trade_state_created => "Создано";
1612 + @override
1613 + String get faq => "FAQ";
1614 + @override
1615 + String get id => "ID: ";
1616 + @override
1617 + String get saved_the_trade_id => "Я сохранил ID сделки";
1618 + @override
1619 + String get settings_currency => "Валюта";
1620 + @override
1621 + String get change_language => "Изменить язык";
1622 + @override
1623 + String get wallet_name => "Имя кошелька";
1624 + @override
1625 + String get error_text_payment_id => "ID транзакции может включать от 16 до 64 символа в hex";
1626 + @override
1627 + String get seed_alert_second_text => "Пожалуйста, запишите на \nслучай, если Вы потеряете или сотрете Ваш телефон.";
1628 + @override
1629 + String get node_reset_settings_title => "Сбросить настройки";
1630 + @override
1631 + String get wallets => "Кошельки";
1632 + @override
1633 + String get enter_your_pin_again => "Введите pin еще раз";
1634 + @override
1635 + String get transactions => "Транзакции";
1636 + @override
1637 + String get amount_is_estimate => "Полученная сумма является приблизительной";
1638 + @override
1639 + String get error_text_node_address => "Пожалуйста, введите iPv4 адрес";
1640 + @override
1641 + String get widgets_restore_from_date => "Восстановить по дате";
1642 + @override
1643 + String get restore_recover => "Восстановить";
1644 + @override
1645 + String get reset => "Сброс";
1646 + @override
1647 + String get new_wallet => "Новый кошелек";
1648 + @override
1649 + String get settings_display_on_dashboard_list => "Показывать в списке транзакций";
1650 + @override
1651 + String get transaction_details_title => "Детали транзакции";
1652 + @override
1653 + String get status => "Статус: ";
1654 + @override
1655 + String get restore_spend_key_private => "Spend ключ (приватный)";
1656 + @override
1657 + String get sync_status_syncronized => "СИНХРОНИЗИРОВАНО";
1658 + @override
1659 + String get transaction_priority_medium => "Средний";
1660 + @override
1661 + String get transaction_details_transaction_id => "ID транзакции";
1662 + @override
1663 + String get save => "Сохранить";
1664 + @override
1665 + String get login => "Login";
1666 + @override
1667 + String get wallet_list_load_wallet => "Загрузка кошелька";
1668 + @override
1669 + String get sending => "Отправка";
1670 + @override
1671 + String get restore_restore_wallet => "Восстановить кошелек";
1672 + @override
1673 + String get restore_description_from_seed_keys => " Вы можете восстановить кошелек из код-фразы/ключей которые Вы сохранили ранее";
1674 + @override
1675 + String get copy => "Скопировать";
1676 + @override
1677 + String get node_port => "Порт ноды";
1678 + @override
1679 + String get change_currency => "Изменить валюту";
1680 + @override
1681 + String get transaction_details_amount => "Сумма";
1682 + @override
1683 + String get widgets_address => "Адрес";
1684 + @override
1685 + String get contact_name => "Имя контакта";
1686 + @override
1687 + String get exchange_result_write_down_ID => "*Пожалуйста, скопируйте или запишите ID, указанный выше.";
1688 + @override
1689 + String get exchange_result_write_down_trade_id => "Пожалуйста, скопируйте или запишите ID сделки.";
1690 + @override
1691 + String get new_subaddress_title => "Новый subaddress";
1692 + @override
1693 + String get change => "Изменить";
1694 + @override
1695 + String get seed_alert_first_text => "Следущая страница содержит\nВашу код-фразу.";
1696 + @override
1697 + String get trade_state_finished => "Окончено";
1698 + @override
1699 + String get pin_is_incorrect => "Некорректный пин";
1700 + @override
1701 + String get trade_not_created => "Сделка не создана.";
1702 + @override
1703 + String get restore_wallet_name => "Имя кошелька";
1704 + @override
1705 + String get widgets_seed => "Код-фраза";
1706 + @override
1707 + String get settings_fee_priority => "Приоритет сбора";
1708 + @override
1709 + String get settings_personal => "Персональные";
1710 + @override
1711 + String get seed_title => "Код-фраза";
1712 + @override
1713 + String get accounts => "Аккаунты";
1714 + @override
1715 + String get rescan => "Пересканировать";
1716 + @override
1717 + String get seed_alert_understand => "Я понимаю";
1718 + @override
1719 + String get show_keys => "Показать ключи";
1720 + @override
1721 + String get error_text_fiat => "Значение суммы не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 2";
1722 + @override
1723 + String get transactions_by_date => "Сортировать по дате";
1724 + @override
1725 + String get use => "Использовать ";
1726 + @override
1727 + String get trade_details_state => "Статус";
1728 + @override
1729 + String get spend_key_private => "Spend key (приватный)";
1730 + @override
1731 + String get settings_only_trades => "Сделки";
1732 + @override
1733 + String get trade_state_to_be_created => "Будет создана";
1734 + @override
1735 + String get all => "ALL";
1736 + @override
1737 + String get xmr_full_balance => "XMR Полный баланс";
1738 + @override
1739 + String get incoming => "Входящие";
1740 + @override
1741 + String get trade_history_title => "История сделок";
1742 + @override
1743 + String get error_text_wallet_name => "Имя кошелька может содержать только буквы, цифры\nи может быть от 1 до 15 символов в длину";
1744 + @override
1745 + String get restore_description_from_keys => "Вы можете восстановить кошелек с помощью приватных ключей";
1746 + @override
1747 + String get sent => "Отправленные";
1748 + @override
1749 + String get view_key_public => "View key (публичный)";
1750 + @override
1751 + String get trade_details_id => "ID";
1752 + @override
1753 + String get trade_state_confirming => "Подтверждение";
1754 + @override
1755 + String get send => "Отправить";
1756 + @override
1757 + String get send_title => "Отправить Monero";
1758 + @override
1759 + String get error_text_keys => "Ключи кошелька могут содержать только 64 символа в hex";
1760 + @override
1761 + String get settings_save_recipient_address => "Сохранять адрес получателя";
1762 + @override
1763 + String get seed_alert_settings => "настройках";
1764 + @override
1765 + String get change_exchange_provider => "Изменить провайдер обмена";
1766 + @override
1767 + String get send_payment_id => "Payment ID (optional)";
1768 + @override
1769 + String get trade_details_title => "Детали сделок";
1770 + @override
1771 + String get settings_terms_and_conditions => "Условия и положения";
1772 + @override
1773 + String get auth_store_ban_timeout => "ban_timeout";
1774 + @override
1775 + String get sync_status_connecting => "ПОДКЛЮЧЕНИЕ";
1776 + @override
1777 + String get settings_transactions => "Транзакции";
1778 + @override
1779 + String get transaction_priority_fastest => "Самый быстрый";
1780 + @override
1781 + String get error => "Ошибка";
1782 + @override
1783 + String get delete => "Удалить";
1784 + @override
1785 + String get sync_status_starting_sync => "НАЧАЛО СИНХРОНИЗАЦИИ";
1786 + @override
1787 + String get copied_to_clipboard => "Скопировано в буфер обмена";
1788 + @override
1789 + String get offer_expires_in => "Предложение истекает через: ";
1790 + @override
1791 + String get continue_text => "Продолжить";
1792 + @override
1793 + String get transaction_details_height => "Высота";
1794 + @override
1795 + String get wallet_menu => "Меню кошелька";
1796 + @override
1797 + String get settings_dark_mode => "Темный режим";
1798 + @override
1799 + String get payment_id => "ID транзакции: ";
1800 + @override
1801 + String get restore_address => "Адрес";
1802 + @override
1803 + String get restore_wallet_restore_description => "Wallet restore description";
1804 + @override
1805 + String get today => "Сегодня";
1806 + @override
1807 + String get settings_support => "Поддержка";
1808 + @override
1809 + String get restore_wallet => "Восстановить";
1810 + @override
1811 + String get ok => "OK";
1812 + @override
1813 + String get wallet_list_title => "Monero кошелек";
1814 + @override
1815 + String get authentication => "Аутентификация";
1816 + @override
1817 + String get amount => "Сумма: ";
1818 + @override
1819 + String get node_address => "Адрес ноды";
1820 + @override
1821 + String get settings_change_language => "Изменить язык";
1822 + @override
1823 + String get clear => "Очистить";
1824 + @override
1825 + String get settings_change_pin => "Изменить PIN";
1826 + @override
1827 + String get trades => "Сделки";
1828 + @override
1829 + String get trade_state_btc_sent => "Btc отправлен";
1830 + @override
1831 + String get address_book => "Адресная книга";
1832 + @override
1833 + String get enter_your_pin => "Введите Ваш PIN";
1834 + @override
1835 + String get wallet_list_restore_wallet => "Восстановить";
1836 + @override
1837 + String get restore_title_from_seed => "Восстановить из код-фразы";
1838 + @override
1839 + String get restore_description_from_backup => "Вы можете восстановить Cake Wallet из\nВашего back-up файла";
1840 + @override
1841 + String get send_monero_address => "Monero адрес";
1842 + @override
1843 + String get error_text_node_port => "Порт ноды может включать только цифры от 0 до 65535";
1844 + @override
1845 + String get digit_pin => "-значный Pin";
1846 + @override
1847 + String get first_wallet_text => "В самом удобном кошельке для Monero";
1848 + @override
1849 + String get settings_trades => "Сделки";
1850 + @override
1851 + String get account => "Аккаунт";
1852 + @override
1853 + String change_language_to(String language) => "Изменить язык на ${language}?";
1854 + @override
1855 + String change_current_node(String node) => "Вы уверены, что хотите изменить текущую ноду на ${node}?";
1856 + @override
1857 + String trade_id(String id) => "ID сделки:\n${id}";
1858 + @override
1859 + String wallet_list_loading_wallet(String wallet_name) => "Загрузка ${wallet_name} кошелька";
1860 + @override
1861 + String router_no_route(String name) => "Экран не найден ${name}";
1862 + @override
1863 + String trade_id_not_found(String tradeId, String title) => "Сделка ${tradeId} ${title} не найдена.";
1864 + @override
1865 + String transaction_details_copied(String title) => "${title} скопировано в буфер обмена";
1866 + @override
1867 + String trade_details_copied(String title) => "${title} скопировано в буфер обмена";
1868 + @override
1869 + String powered_by(String title) => "Используя ${title}";
1870 + @override
1871 + String send_priority(String transactionPriority) => "Сбор установлен в зависимости от приоритета: ${transactionPriority}.\nПриоритет транзакции может быть изменен в настройках";
1872 + @override
1873 + String trade_for_not_created(String title) => "Сделка для ${title} не создана.";
1874 + @override
1875 + String trade_is_powered_by(String provider) => "Сделка выполнена ${provider}";
1876 + @override
1877 + String time(String minutes, String seconds) => "${minutes}мин ${seconds}сек";
1878 + @override
1879 + String max_value(String value, String currency) => "Макс: ${value} ${currency}";
1880 + @override
1881 + String min_value(String value, String currency) => "Мин: ${value} ${currency}";
1882 + @override
1883 + String failed_authentication(String state_error) => "Ошибка аутентификации. ${state_error}";
1884 + @override
1885 + String Blocks_remaining(String status) => "${status} Осталось блоков";
1886 + @override
1887 + String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "Нажимая подтвердить, Вы отправите ${fetchingLabel} ${from} с Вашего кошелька ${walletName} на адрес указанный выше. Или Вы можете отправить со своего внешнего кошелька на вышеуказанный адрес / QR-код.\n\nПожалуйста, нажмите подтвердить для продолжения или вернитесь назад для изменения суммы.\n\n";
1888 + @override
1889 + String exchange_result_description(String fetchingLabel, String from) => "Пожалуйста отправьте ${fetchingLabel} ${from} на адрес, указанный выше.\n\n'";
1890 + @override
1891 + String commit_transaction_amount_fee(String amount, String fee) => "Подтвердить транзакцию \nСумма: ${amount}\nСбор: ${fee}";
1892 + @override
1893 + String wallet_list_failed_to_remove(String wallet_name, String error) => "Ошибка при удалении ${wallet_name} кошелька. ${error}";
1894 + @override
1895 + String copied_key_to_clipboard(String key) => "Скопировано ${key} в буфер обмена";
1896 + @override
1897 + String wallet_list_failed_to_load(String wallet_name, String error) => "Ошибка при загрузке ${wallet_name} кошелька. ${error}";
1898 + @override
1899 + String wallet_list_removing_wallet(String wallet_name) => "Удаление ${wallet_name} кошелька";
1900 +}
1901 +
1902 +class $ko extends S {
1903 + const $ko();
1904 +
1905 + @override
1906 + TextDirection get textDirection => TextDirection.ltr;
1907 +
1908 + @override
1909 + String get cancel => "취소";
1910 + @override
1911 + String get trade_state_unpaid => "미지급";
1912 + @override
1913 + String get authenticated => "인증";
1914 + @override
1915 + String get new_subaddress_create => "몹시 떠들어 대다";
1916 + @override
1917 + String get restore_view_key_private => "키보기 (은밀한)";
1918 + @override
1919 + String get transaction_priority_fast => "빠른";
1920 + @override
1921 + String get error_text_amount => "금액은 숫자 만 포함 할 수 있습니다";
1922 + @override
1923 + String get hidden_balance => "숨겨진 균형";
1924 + @override
1925 + String get transaction_sent => "거래가 전송되었습니다!";
1926 + @override
1927 + String get password => "암호";
1928 + @override
1929 + String get you_will_get => "당신은 얻을 것이다";
1930 + @override
1931 + String get restore_description_from_seed => "25 단어 또는 13 단어 조합 코드에서 지갑을 복원하십시오.";
1932 + @override
1933 + String get trade_state_underpaid => "미지급";
1934 + @override
1935 + String get welcome => "환영\n에 CAKE WALLET";
1936 + @override
1937 + String get share_address => "주소 공유";
1938 + @override
1939 + String get please_try_to_connect_to_another_node => "다른 노드에 연결을 시도하십시오";
1940 + @override
1941 + String get trade_state_traded => "거래";
1942 + @override
1943 + String get edit => "편집하다";
1944 + @override
1945 + String get spend_key_public => "지출 키 (공공의)";
1946 + @override
1947 + String get sync_status_syncronizing => "동기화";
1948 + @override
1949 + String get received => "받았습니다";
1950 + @override
1951 + String get auth_store_banned_minutes => " 의사록";
1952 + @override
1953 + String get restore_title_from_seed_keys => "시드 / 키에서 복원";
1954 + @override
1955 + String get settings_none => "없음";
1956 + @override
1957 + String get wallet_list_create_new_wallet => "새 월렛 만들기";
1958 + @override
1959 + String get seed_alert_third_text => "당신은 또한 씨앗을 다시 볼 수 있습니다\n에서 ";
1960 + @override
1961 + String get setup_pin => "설정 PIN";
1962 + @override
1963 + String get transaction_details_recipient_address => "받는 사람 주소";
1964 + @override
1965 + String get receive_amount => "양";
1966 + @override
1967 + String get settings_allow_biometrical_authentication => "생체 인증 허용";
1968 + @override
1969 + String get view_key_private => "키보기(은밀한)";
1970 + @override
1971 + String get restore_next => "다음 것";
1972 + @override
1973 + String get trade_state_trading => "거래";
1974 + @override
1975 + String get error_text_address => "지갑 주소는 유형과 일치해야합니다\n암호 화폐";
1976 + @override
1977 + String get send_your_wallet => "지갑";
1978 + @override
1979 + String get remove_node_message => "선택한 노드를 제거 하시겠습니까?";
1980 + @override
1981 + String get error_text_account_name => "계정 이름은 문자, 숫자 만 포함 할 수 있습니다\n1 ~ 15 자 사이 여야합니다";
1982 + @override
1983 + String get reconnection => "재 연결";
1984 + @override
1985 + String get available_balance => "사용 가능한 잔액";
1986 + @override
1987 + String get restore_title_from_keys => "키에서 복원";
1988 + @override
1989 + String get wallet_keys => "지갑 키";
1990 + @override
1991 + String get reconnect => "다시 연결";
1992 + @override
1993 + String get reconnect_alert_text => "다시 연결 하시겠습니까?";
1994 + @override
1995 + String get send_error_minimum_value => "금액의 최소값은 0.01입니다";
1996 + @override
1997 + String get copy_address => "주소 복사";
1998 + @override
1999 + String get error_text_subaddress_name => "하위 주소 이름은 포함 할 수 없습니다 ` , ' \" 기호 \n1 ~ 20 자 사이 여야합니다";
2000 + @override
2001 + String get settings_all => "모든";
2002 + @override
2003 + String get nodes_list_reset_to_default_message => "설정을 기본값으로 재설정 하시겠습니까?";
2004 + @override
2005 + String get receive => "받다";
2006 + @override
2007 + String get amount_is_guaranteed => "수신 금액이 보장됩니다";
2008 + @override
2009 + String get auth_store_banned_for => "금지";
2010 + @override
2011 + String get trade_details_pair => "쌍";
2012 + @override
2013 + String get confirm => "확인";
2014 + @override
2015 + String get send_xmr => "보내다 XMR";
2016 + @override
2017 + String get settings_display_balance_as => "잔액 표시";
2018 + @override
2019 + String get trade_details_provider => "공급자";
2020 + @override
2021 + String get you_will_send => "보내드립니다";
2022 + @override
2023 + String get create_new => "새로 만들기";
2024 + @override
2025 + String get trade_details_fetching => "가져 오는 중";
2026 + @override
2027 + String get seed_alert_menu => " 메뉴.";
2028 + @override
2029 + String get confirm_sending => "전송 확인";
2030 + @override
2031 + String get settings_title => "설정";
2032 + @override
2033 + String get address_book_menu => "주소록";
2034 + @override
2035 + String get wallet_restoration_store_incorrect_seed_length => "시드 길이가 잘못되었습니다";
2036 + @override
2037 + String get contact => "접촉";
2038 + @override
2039 + String get auth_store_incorrect_password => "잘못된 PIN";
2040 + @override
2041 + String get transaction_priority_slow => "느린";
2042 + @override
2043 + String get add => "더하다";
2044 + @override
2045 + String get remove_node => "노드 제거";
2046 + @override
2047 + String get trade_state_paid_unconfirmed => "미확인 유료";
2048 + @override
2049 + String get please_select => "선택 해주세요:";
2050 + @override
2051 + String get restore_title_from_backup => "백업 파일에서 복원";
2052 + @override
2053 + String get full_balance => "풀 밸런스";
2054 + @override
2055 + String get sync_status_not_connected => "연결되지 않은";
2056 + @override
2057 + String get error_text_crypto_currency => "소수 자릿수\n12 이하 여야합니다";
2058 + @override
2059 + String get error_text_contact_name => "담당자 이름은 포함 할 수 없습니다 ` , ' \" 기호\n1 자에서 32 자 사이 여야합니다";
2060 + @override
2061 + String get restore_seed_keys_restore => "종자 / 키 복원";
2062 + @override
2063 + String get xmr_hidden => "XMR 숨김";
2064 + @override
2065 + String get exchange => "교환";
2066 + @override
2067 + String get sync_status_failed_connect => "노드에 연결하지 못했습니다";
2068 + @override
2069 + String get send_estimated_fee => "예상 수수료:";
2070 + @override
2071 + String get outgoing => "나가는";
2072 + @override
2073 + String get sync_status_connected => "연결됨";
2074 + @override
2075 + String get trade_state_pending => "대기 중";
2076 + @override
2077 + String get pending => " (보류 중)";
2078 + @override
2079 + String get setup_successful => "PIN이 성공적으로 설정되었습니다!";
2080 + @override
2081 + String get fetching => "가져 오는 중";
2082 + @override
2083 + String get settings_nodes => "노드";
2084 + @override
2085 + String get widgets_or => "또는";
2086 + @override
2087 + String get remove => "없애다";
2088 + @override
2089 + String get yesterday => "어제";
2090 + @override
2091 + String get expired => "만료";
2092 + @override
2093 + String get transaction_priority_regular => "정규병";
2094 + @override
2095 + String get trade_details_created_at => "에 작성";
2096 + @override
2097 + String get settings_wallets => "지갑";
2098 + @override
2099 + String get settings_only_transactions => "거래 만";
2100 + @override
2101 + String get estimated => "예상";
2102 + @override
2103 + String get filters => "필터";
2104 + @override
2105 + String get settings_current_node => "현재 노드";
2106 + @override
2107 + String get copy_id => "부 ID";
2108 + @override
2109 + String get please_make_selection => "아래에서 선택하십시오\n지갑 만들기 또는 복구.";
2110 + @override
2111 + String get loading_your_wallet => "지갑 넣기";
2112 + @override
2113 + String get subaddresses => "하위 주소";
2114 + @override
2115 + String get trade_state_timeout => "타임 아웃";
2116 + @override
2117 + String get nodes => "노드";
2118 + @override
2119 + String get seed_share => "시드 공유";
2120 + @override
2121 + String get widgets_restore_from_blockheight => "블록 높이에서 복원";
2122 + @override
2123 + String get new_subaddress_label_name => "라벨 이름";
2124 + @override
2125 + String get trade_not_found => "거래를 찾을 수 없습니다.";
2126 + @override
2127 + String get transaction_details_date => "날짜";
2128 + @override
2129 + String get show_seed => "종자 표시";
2130 + @override
2131 + String get send_error_currency => "통화는 숫자 만 포함 할 수 있습니다";
2132 + @override
2133 + String get subaddress_title => "하위 주소 목록";
2134 + @override
2135 + String get wallet_store_monero_wallet => "모네로 월렛";
2136 + @override
2137 + String get send_creating_transaction => "거래 생성";
2138 + @override
2139 + String get trade_state_complete => "완전한";
2140 + @override
2141 + String get error_text_xmr => "XMR 값은 사용 가능한 잔액을 초과 할 수 없습니다.\n소수 자릿수는 12 이하 여야합니다";
2142 + @override
2143 + String get xmr_available_balance => "XMR 사용 가능한 잔액";
2144 + @override
2145 + String get trade_state_paid => "유료";
2146 + @override
2147 + String get node_new => "새로운 노드";
2148 + @override
2149 + String get trade_state_created => "만들어진";
2150 + @override
2151 + String get faq => "FAQ";
2152 + @override
2153 + String get id => "ID: ";
2154 + @override
2155 + String get saved_the_trade_id => "거래 ID를 저장했습니다";
2156 + @override
2157 + String get settings_currency => "통화";
2158 + @override
2159 + String get change_language => "언어 변경";
2160 + @override
2161 + String get wallet_name => "지갑 이름";
2162 + @override
2163 + String get error_text_payment_id => "지불 ID는 16 ~ 64 자의 16 진 문자 만 포함 할 수 있습니다";
2164 + @override
2165 + String get seed_alert_second_text => "아래에 적어주세요\n휴대 전화를 분실하거나 닦을 경우.";
2166 + @override
2167 + String get node_reset_settings_title => "설정 초기화";
2168 + @override
2169 + String get wallets => "지갑";
2170 + @override
2171 + String get enter_your_pin_again => "다시 핀을 입력";
2172 + @override
2173 + String get transactions => "업무";
2174 + @override
2175 + String get amount_is_estimate => "수신 금액은 견적입니다";
2176 + @override
2177 + String get error_text_node_address => "iPv4 주소를 입력하십시오";
2178 + @override
2179 + String get widgets_restore_from_date => "날짜에서 복원";
2180 + @override
2181 + String get restore_recover => "다시 덮다";
2182 + @override
2183 + String get reset => "다시 놓기";
2184 + @override
2185 + String get new_wallet => "새 월렛";
2186 + @override
2187 + String get settings_display_on_dashboard_list => "대시 보드 목록에 표시";
2188 + @override
2189 + String get transaction_details_title => "상세 거래 내역";
2190 + @override
2191 + String get status => "지위: ";
2192 + @override
2193 + String get restore_spend_key_private => "지출 키 (은밀한)";
2194 + @override
2195 + String get sync_status_syncronized => "동기화";
2196 + @override
2197 + String get transaction_priority_medium => "매질";
2198 + @override
2199 + String get transaction_details_transaction_id => "트랜잭션 ID";
2200 + @override
2201 + String get save => "구하다";
2202 + @override
2203 + String get login => "로그인";
2204 + @override
2205 + String get wallet_list_load_wallet => "지갑로드";
2206 + @override
2207 + String get sending => "배상";
2208 + @override
2209 + String get restore_restore_wallet => "월렛 복원";
2210 + @override
2211 + String get restore_description_from_seed_keys => "안전한 장소에 저장 한 종자 / 키로 지갑을 되 찾으십시오.";
2212 + @override
2213 + String get copy => "부";
2214 + @override
2215 + String get node_port => "노드 포트";
2216 + @override
2217 + String get change_currency => "통화 변경";
2218 + @override
2219 + String get transaction_details_amount => "양";
2220 + @override
2221 + String get widgets_address => "주소";
2222 + @override
2223 + String get contact_name => "담당자 이름";
2224 + @override
2225 + String get exchange_result_write_down_ID => "*위에 표시된 ID를 복사하거나 적어 두십시오.";
2226 + @override
2227 + String get exchange_result_write_down_trade_id => "계속하려면 거래 ID를 복사하거나 적어 두십시오..";
2228 + @override
2229 + String get new_subaddress_title => "새로운 하위 주소";
2230 + @override
2231 + String get change => "변화";
2232 + @override
2233 + String get seed_alert_first_text => "다음 페이지가 표시됩니다\n당신은 씨앗.";
2234 + @override
2235 + String get trade_state_finished => "끝마친";
2236 + @override
2237 + String get pin_is_incorrect => "PIN이 잘못되었습니다";
2238 + @override
2239 + String get trade_not_created => "거래가 생성되지 않았습니다.";
2240 + @override
2241 + String get restore_wallet_name => "지갑 이름";
2242 + @override
2243 + String get widgets_seed => "씨";
2244 + @override
2245 + String get settings_fee_priority => "수수료 우선";
2246 + @override
2247 + String get settings_personal => "개인적인";
2248 + @override
2249 + String get seed_title => "씨";
2250 + @override
2251 + String get accounts => "계정";
2252 + @override
2253 + String get rescan => "재검색";
2254 + @override
2255 + String get seed_alert_understand => "이해 했어";
2256 + @override
2257 + String get show_keys => "키 표시";
2258 + @override
2259 + String get error_text_fiat => "금액은 사용 가능한 잔액을 초과 할 수 없습니다.\n소수 자릿수는 2보다 작거나 같아야합니다";
2260 + @override
2261 + String get transactions_by_date => "날짜 별 거래";
2262 + @override
2263 + String get use => "용도 ";
2264 + @override
2265 + String get trade_details_state => "상태";
2266 + @override
2267 + String get spend_key_private => "지출 키 (은밀한)";
2268 + @override
2269 + String get settings_only_trades => "거래 만";
2270 + @override
2271 + String get trade_state_to_be_created => "만들려면";
2272 + @override
2273 + String get all => "모든";
2274 + @override
2275 + String get xmr_full_balance => "XMR 풀 밸런스";
2276 + @override
2277 + String get incoming => "들어오는";
2278 + @override
2279 + String get trade_history_title => "무역 역사";
2280 + @override
2281 + String get error_text_wallet_name => "지갑 이름은 문자, 숫자 만 포함 할 수 있습니다\n1 ~ 15 자 사이 여야합니다";
2282 + @override
2283 + String get restore_description_from_keys => "개인 키에서 저장된 생성 된\n키 스트로크에서 월렛 복원";
2284 + @override
2285 + String get sent => "보냄";
2286 + @override
2287 + String get view_key_public => "키보기 (공공의)";
2288 + @override
2289 + String get trade_details_id => "ID";
2290 + @override
2291 + String get trade_state_confirming => "확인 중";
2292 + @override
2293 + String get send => "보내다";
2294 + @override
2295 + String get send_title => "모네로 보내기";
2296 + @override
2297 + String get error_text_keys => "지갑 키는 16 진수로 64 자만 포함 할 수 있습니다";
2298 + @override
2299 + String get settings_save_recipient_address => "수신자 주소 저장";
2300 + @override
2301 + String get seed_alert_settings => "설정";
2302 + @override
2303 + String get change_exchange_provider => "교환 공급자 변경";
2304 + @override
2305 + String get send_payment_id => "지불 ID (optional)";
2306 + @override
2307 + String get trade_details_title => "거래 세부 사항";
2308 + @override
2309 + String get settings_terms_and_conditions => "이용 약관";
2310 + @override
2311 + String get auth_store_ban_timeout => "타임 아웃 금지";
2312 + @override
2313 + String get sync_status_connecting => "연결 중";
2314 + @override
2315 + String get settings_transactions => "업무";
2316 + @override
2317 + String get transaction_priority_fastest => "가장 빠른";
2318 + @override
2319 + String get error => "오류";
2320 + @override
2321 + String get delete => "지우다";
2322 + @override
2323 + String get sync_status_starting_sync => "동기화 시작";
2324 + @override
2325 + String get copied_to_clipboard => "클립 보드에 복사";
2326 + @override
2327 + String get offer_expires_in => "쿠폰 만료일: ";
2328 + @override
2329 + String get continue_text => "잇다";
2330 + @override
2331 + String get transaction_details_height => "신장";
2332 + @override
2333 + String get wallet_menu => "월렛 메뉴";
2334 + @override
2335 + String get settings_dark_mode => "다크 모드";
2336 + @override
2337 + String get payment_id => "지불 ID: ";
2338 + @override
2339 + String get restore_address => "주소";
2340 + @override
2341 + String get restore_wallet_restore_description => "월렛 복원 설명";
2342 + @override
2343 + String get today => "오늘";
2344 + @override
2345 + String get settings_support => "지원하다";
2346 + @override
2347 + String get restore_wallet => "지갑 복원";
2348 + @override
2349 + String get ok => "승인";
2350 + @override
2351 + String get wallet_list_title => "모네로 월렛";
2352 + @override
2353 + String get authentication => "입증";
2354 + @override
2355 + String get amount => "양: ";
2356 + @override
2357 + String get node_address => "노드 주소";
2358 + @override
2359 + String get settings_change_language => "언어 변경";
2360 + @override
2361 + String get clear => "명확한";
2362 + @override
2363 + String get settings_change_pin => "PIN 변경";
2364 + @override
2365 + String get trades => "거래";
2366 + @override
2367 + String get trade_state_btc_sent => "보냄";
2368 + @override
2369 + String get address_book => "주소록";
2370 + @override
2371 + String get enter_your_pin => "PIN을 입력하십시오";
2372 + @override
2373 + String get wallet_list_restore_wallet => "월렛 복원";
2374 + @override
2375 + String get restore_title_from_seed => "종자에서 복원";
2376 + @override
2377 + String get restore_description_from_backup => "백업 파일에서 전체 Cake Wallet 앱을 복원 할 수 있습니다.";
2378 + @override
2379 + String get send_monero_address => "모네로 주소";
2380 + @override
2381 + String get error_text_node_port => "노드 포트는 0에서 65535 사이의 숫자 만 포함 할 수 있습니다";
2382 + @override
2383 + String get digit_pin => "숫자 PIN";
2384 + @override
2385 + String get first_wallet_text => "멋진 지갑\n에 대한 Monero";
2386 + @override
2387 + String get settings_trades => "거래";
2388 + @override
2389 + String get account => "계정";
2390 + @override
2391 + String change_language_to(String language) => "언어를로 변경 ${language}?";
2392 + @override
2393 + String change_current_node(String node) => "현재 노드를 다음으로 변경 하시겠습니까 ${node}?";
2394 + @override
2395 + String trade_id(String id) => "무역 ID:\n${id}";
2396 + @override
2397 + String wallet_list_loading_wallet(String wallet_name) => "로딩 ${wallet_name} 지갑";
2398 + @override
2399 + String router_no_route(String name) => "에 정의 된 경로가 없습니다 ${name}";
2400 + @override
2401 + String trade_id_not_found(String tradeId, String title) => "무역 ${tradeId} 의 ${title} 찾을 수 없습니다.";
2402 + @override
2403 + String transaction_details_copied(String title) => "${title} 클립 보드에 복사";
2404 + @override
2405 + String trade_details_copied(String title) => "${title} 클립 보드에 복사";
2406 + @override
2407 + String powered_by(String title) => "에 의해 구동 ${title}";
2408 + @override
2409 + String send_priority(String transactionPriority) => "현재 수수료는 ${transactionPriority} 우선 순위.\n거래 우선 순위는 설정에서 조정할 수 있습니다";
2410 + @override
2411 + String trade_for_not_created(String title) => "거래 ${title} 생성되지 않습니다.";
2412 + @override
2413 + String trade_is_powered_by(String provider) => "이 거래는 ${provider}";
2414 + @override
2415 + String time(String minutes, String seconds) => "${minutes}m ${seconds}s";
2416 + @override
2417 + String max_value(String value, String currency) => "맥스: ${value} ${currency}";
2418 + @override
2419 + String min_value(String value, String currency) => "최소: ${value} ${currency}";
2420 + @override
2421 + String failed_authentication(String state_error) => "인증 실패. ${state_error}";
2422 + @override
2423 + String Blocks_remaining(String status) => "${status} 남은 블록";
2424 + @override
2425 + String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "확인을 누르면 전송됩니다 ${fetchingLabel} ${from} 지갑에서 ${walletName} 위에 표시된 주소로. 또는 외부 지갑에서 위의 주소 / QR 코드로 보낼 수 있습니다.\n\n확인을 눌러 계속하거나 금액을 변경하려면 돌아가십시오.\n\n";
2426 + @override
2427 + String exchange_result_description(String fetchingLabel, String from) => "보내주세요 ${fetchingLabel} ${from} 위에 표시된 주소로.\n\n'";
2428 + @override
2429 + String commit_transaction_amount_fee(String amount, String fee) => "커밋 거래\n양: ${amount}\n보수: ${fee}";
2430 + @override
2431 + String wallet_list_failed_to_remove(String wallet_name, String error) => "제거하지 못했습니다 ${wallet_name} 지갑. ${error}";
2432 + @override
2433 + String copied_key_to_clipboard(String key) => "복사 ${key} 클립 보드로";
2434 + @override
2435 + String wallet_list_failed_to_load(String wallet_name, String error) => "불러 오지 못했습니다 ${wallet_name} 지갑. ${error}";
2436 + @override
2437 + String wallet_list_removing_wallet(String wallet_name) => "풀이 ${wallet_name} 지갑";
2438 +}
2439 +
2440 +class $pt extends S {
2441 + const $pt();
2442 +
2443 + @override
2444 + TextDirection get textDirection => TextDirection.ltr;
2445 +
2446 + @override
2447 + String get cancel => "Cancelar";
2448 + @override
2449 + String get trade_state_unpaid => "Não remunerado";
2450 + @override
2451 + String get authenticated => "Autenticado";
2452 + @override
2453 + String get new_subaddress_create => "Crio";
2454 + @override
2455 + String get restore_view_key_private => "Tecla Ver (privado)";
2456 + @override
2457 + String get transaction_priority_fast => "Rápido";
2458 + @override
2459 + String get error_text_amount => "O valor pode conter apenas números";
2460 + @override
2461 + String get hidden_balance => "Saldo Oculto";
2462 + @override
2463 + String get transaction_sent => "Transação enviada!";
2464 + @override
2465 + String get password => "Senha";
2466 + @override
2467 + String get you_will_get => "Você vai ter";
2468 + @override
2469 + String get restore_description_from_seed => "Restaure sua carteira a partir das 25 palavras\noou código de combinação de 13 palavras";
2470 + @override
2471 + String get trade_state_underpaid => "Mal pago";
2472 + @override
2473 + String get welcome => "BEM-VINDO\nAO CAKE WALLET";
2474 + @override
2475 + String get share_address => "Compartilhar endereço";
2476 + @override
2477 + String get please_try_to_connect_to_another_node => "Por favor, tente conectar-se a outro nó";
2478 + @override
2479 + String get trade_state_traded => "Negociados";
2480 + @override
2481 + String get edit => "Editar";
2482 + @override
2483 + String get spend_key_public => "Chave de gastos (público)";
2484 + @override
2485 + String get sync_status_syncronizing => "SINCRONIZANDO";
2486 + @override
2487 + String get received => "Recebido";
2488 + @override
2489 + String get auth_store_banned_minutes => " minutes";
2490 + @override
2491 + String get restore_title_from_seed_keys => "Restaurar a partir de sementes / chaves";
2492 + @override
2493 + String get settings_none => "Nenhum";
2494 + @override
2495 + String get wallet_list_create_new_wallet => "Criar nova carteira";
2496 + @override
2497 + String get seed_alert_third_text => "Você também pode ver a semente novamente\nno ";
2498 + @override
2499 + String get setup_pin => "PIN de configuração";
2500 + @override
2501 + String get transaction_details_recipient_address => "Endereço do destinatário";
2502 + @override
2503 + String get receive_amount => "Montante";
2504 + @override
2505 + String get settings_allow_biometrical_authentication => "Permitir autenticação biométrica";
2506 + @override
2507 + String get view_key_private => "Tecla Ver (privado)";
2508 + @override
2509 + String get restore_next => "Próximo";
2510 + @override
2511 + String get trade_state_trading => "Negociação";
2512 + @override
2513 + String get error_text_address => "O endereço da carteira deve corresponder ao tipo\nde criptomoeda";
2514 + @override
2515 + String get send_your_wallet => "Enviar Monero";
2516 + @override
2517 + String get remove_node_message => "Tem certeza de que deseja remover o nó selecionado?";
2518 + @override
2519 + String get error_text_account_name => "O nome da conta pode conter apenas letras, números\ne deve ter entre 1 e 15 caracteres";
2520 + @override
2521 + String get reconnection => "Reconexão";
2522 + @override
2523 + String get available_balance => "Saldo disponível";
2524 + @override
2525 + String get restore_title_from_keys => "Restaurar a partir de chaves";
2526 + @override
2527 + String get wallet_keys => "Chaves da carteira";
2528 + @override
2529 + String get reconnect => "Reconectar";
2530 + @override
2531 + String get reconnect_alert_text => "Você tem certeza de reconectar?";
2532 + @override
2533 + String get send_error_minimum_value => "O valor mínimo da quantia é 0,01";
2534 + @override
2535 + String get copy_address => "Copiar endereço";
2536 + @override
2537 + String get error_text_subaddress_name => "O nome do sub-endereço não pode conter ` , ' \" símbolos\ne deve ter entre 1 e 20 caracteres";
2538 + @override
2539 + String get settings_all => "TODOS";
2540 + @override
2541 + String get nodes_list_reset_to_default_message => "Tem certeza de que deseja redefinir as configurações para o padrão?";
2542 + @override
2543 + String get receive => "Receber";
2544 + @override
2545 + String get amount_is_guaranteed => "O valor do recebimento é garantido";
2546 + @override
2547 + String get auth_store_banned_for => "Banido por";
2548 + @override
2549 + String get trade_details_pair => "Par";
2550 + @override
2551 + String get confirm => "Confirme";
2552 + @override
2553 + String get send_xmr => "Mandar XMR";
2554 + @override
2555 + String get settings_display_balance_as => "Exibir saldo como";
2556 + @override
2557 + String get trade_details_provider => "Fornecedor";
2558 + @override
2559 + String get you_will_send => "Você enviará";
2560 + @override
2561 + String get create_new => "Crie um novo";
2562 + @override
2563 + String get trade_details_fetching => "Buscando";
2564 + @override
2565 + String get seed_alert_menu => "cardápio.";
2566 + @override
2567 + String get confirm_sending => "Confirme o envio";
2568 + @override
2569 + String get settings_title => "Configurações";
2570 + @override
2571 + String get address_book_menu => "Livro de endereços";
2572 + @override
2573 + String get wallet_restoration_store_incorrect_seed_length => "Comprimento de semente incorreto";
2574 + @override
2575 + String get contact => "Contato";
2576 + @override
2577 + String get auth_store_incorrect_password => "PIN incorreto";
2578 + @override
2579 + String get transaction_priority_slow => "Lento";
2580 + @override
2581 + String get add => "Adicionar";
2582 + @override
2583 + String get remove_node => "Remover nó";
2584 + @override
2585 + String get trade_state_paid_unconfirmed => "Pago não confirmado";
2586 + @override
2587 + String get please_select => "Por favor selecione:";
2588 + @override
2589 + String get restore_title_from_backup => "Restaurar a partir de um arquivo de backup";
2590 + @override
2591 + String get full_balance => "Saldo total";
2592 + @override
2593 + String get sync_status_not_connected => "NÃO CONECTADO";
2594 + @override
2595 + String get error_text_crypto_currency => "O número de dígitos da fração\ndeve ser menor ou igual a 12";
2596 + @override
2597 + String get error_text_contact_name => "O nome do contato não pode conter ` , ' \" símbolos\ne deve ter entre 1 e 32 caracteres";
2598 + @override
2599 + String get restore_seed_keys_restore => "Restauração de sementes / chaves";
2600 + @override
2601 + String get xmr_hidden => "XMR Oculto";
2602 + @override
2603 + String get exchange => "Troca";
2604 + @override
2605 + String get sync_status_failed_connect => "Falha na conexão com o nó";
2606 + @override
2607 + String get send_estimated_fee => "Taxa estimada:";
2608 + @override
2609 + String get outgoing => "Extrovertido";
2610 + @override
2611 + String get sync_status_connected => "CONECTADO";
2612 + @override
2613 + String get trade_state_pending => "Pendente";
2614 + @override
2615 + String get pending => " (pendente)";
2616 + @override
2617 + String get setup_successful => "Seu PIN foi configurado com sucesso!";
2618 + @override
2619 + String get fetching => "Buscando";
2620 + @override
2621 + String get settings_nodes => "Nós";
2622 + @override
2623 + String get widgets_or => "ou";
2624 + @override
2625 + String get remove => "Remover";
2626 + @override
2627 + String get yesterday => "Ontem";
2628 + @override
2629 + String get expired => "Expirado";
2630 + @override
2631 + String get transaction_priority_regular => "Regular";
2632 + @override
2633 + String get trade_details_created_at => "Criado em";
2634 + @override
2635 + String get settings_wallets => "Carteiras";
2636 + @override
2637 + String get settings_only_transactions => "Somente transações";
2638 + @override
2639 + String get estimated => "Estimado";
2640 + @override
2641 + String get filters => "Filtros";
2642 + @override
2643 + String get settings_current_node => "Nó atual";
2644 + @override
2645 + String get copy_id => "Cópia de ID";
2646 + @override
2647 + String get please_make_selection => "Faça a seleção abaixo para\ncrie ou recupere sua carteira.";
2648 + @override
2649 + String get loading_your_wallet => "Carregando sua carteira";
2650 + @override
2651 + String get subaddresses => "Sub-endereços";
2652 + @override
2653 + String get trade_state_timeout => "Tempo esgotado";
2654 + @override
2655 + String get nodes => "Nós";
2656 + @override
2657 + String get seed_share => "Compartilhar sementes";
2658 + @override
2659 + String get widgets_restore_from_blockheight => "Restaurar da altura do bloco";
2660 + @override
2661 + String get new_subaddress_label_name => "Nome do rótulo";
2662 + @override
2663 + String get trade_not_found => "Comércio não encontrado.";
2664 + @override
2665 + String get transaction_details_date => "Encontro";
2666 + @override
2667 + String get show_seed => "Mostrar semente";
2668 + @override
2669 + String get send_error_currency => "A moeda pode conter apenas números";
2670 + @override
2671 + String get subaddress_title => "Lista de sub-endereços";
2672 + @override
2673 + String get wallet_store_monero_wallet => "Carteira Monero";
2674 + @override
2675 + String get send_creating_transaction => "Criando transação";
2676 + @override
2677 + String get trade_state_complete => "Completo";
2678 + @override
2679 + String get error_text_xmr => "O valor XMR não pode exceder o saldo disponível.\nTO número de dígitos da fração deve ser menor ou igual a 12";
2680 + @override
2681 + String get xmr_available_balance => "Saldo disponível do XMR";
2682 + @override
2683 + String get trade_state_paid => "Pago";
2684 + @override
2685 + String get node_new => "Novo nó";
2686 + @override
2687 + String get trade_state_created => "Criado";
2688 + @override
2689 + String get faq => "FAQ";
2690 + @override
2691 + String get id => "ID: ";
2692 + @override
2693 + String get saved_the_trade_id => "Salvei o ID comercial";
2694 + @override
2695 + String get settings_currency => "Moeda";
2696 + @override
2697 + String get change_language => "Mudar idioma";
2698 + @override
2699 + String get wallet_name => "Nome da carteira";
2700 + @override
2701 + String get error_text_payment_id => "O código de pagamento pode conter apenas de 16 a 64 caracteres em hexadecimal";
2702 + @override
2703 + String get seed_alert_second_text => "Por favor, escreva-as apenas em\ncaso você perca ou limpe seu telefone.";
2704 + @override
2705 + String get node_reset_settings_title => "Redefinir configurações";
2706 + @override
2707 + String get wallets => "Carteiras";
2708 + @override
2709 + String get enter_your_pin_again => "Insira seu pin novamente";
2710 + @override
2711 + String get transactions => "Transações";
2712 + @override
2713 + String get amount_is_estimate => "O valor recebido é uma estimativa";
2714 + @override
2715 + String get error_text_node_address => "Digite um endereço iPv4";
2716 + @override
2717 + String get widgets_restore_from_date => "Restaurar a partir da data";
2718 + @override
2719 + String get restore_recover => "Recuperar";
2720 + @override
2721 + String get reset => "Restabelecer";
2722 + @override
2723 + String get new_wallet => "Nova carteira";
2724 + @override
2725 + String get settings_display_on_dashboard_list => "Exibir na lista do painel";
2726 + @override
2727 + String get transaction_details_title => "Detalhes da transação";
2728 + @override
2729 + String get status => "Status: ";
2730 + @override
2731 + String get restore_spend_key_private => "Chave de gastos (privado)";
2732 + @override
2733 + String get sync_status_syncronized => "SINCRONIZADO";
2734 + @override
2735 + String get transaction_priority_medium => "Médio";
2736 + @override
2737 + String get transaction_details_transaction_id => "ID da transação";
2738 + @override
2739 + String get save => "Salve";
2740 + @override
2741 + String get login => "Entrar";
2742 + @override
2743 + String get wallet_list_load_wallet => "Carregar carteira";
2744 + @override
2745 + String get sending => "Enviando";
2746 + @override
2747 + String get restore_restore_wallet => "Restaurar carteira";
2748 + @override
2749 + String get restore_description_from_seed_keys => "Volte sua carteira a partir de sementes / chaves que você salvou em um local seguro";
2750 + @override
2751 + String get copy => "Cópia de";
2752 + @override
2753 + String get node_port => "Porta do nó";
2754 + @override
2755 + String get change_currency => "Alteração de moeda";
2756 + @override
2757 + String get transaction_details_amount => "Montante";
2758 + @override
2759 + String get widgets_address => "Endereço";
2760 + @override
2761 + String get contact_name => "Nome de contato";
2762 + @override
2763 + String get exchange_result_write_down_ID => "*Copie ou anote seu ID mostrado acima.";
2764 + @override
2765 + String get exchange_result_write_down_trade_id => "Copie ou anote o ID comercial para continuar.";
2766 + @override
2767 + String get new_subaddress_title => "Novo sub-endereço";
2768 + @override
2769 + String get change => "Mudança";
2770 + @override
2771 + String get seed_alert_first_text => "A próxima página mostrará\nvocê é uma semente.";
2772 + @override
2773 + String get trade_state_finished => "Acabado";
2774 + @override
2775 + String get pin_is_incorrect => "PIN incorreto";
2776 + @override
2777 + String get trade_not_created => "Comércio não criado.";
2778 + @override
2779 + String get restore_wallet_name => "Nome da carteira";
2780 + @override
2781 + String get widgets_seed => "Semente";
2782 + @override
2783 + String get settings_fee_priority => "Prioridade da taxa";
2784 + @override
2785 + String get settings_personal => "Pessoal";
2786 + @override
2787 + String get seed_title => "Semente";
2788 + @override
2789 + String get accounts => "Contas";
2790 + @override
2791 + String get rescan => "Verificar novamente";
2792 + @override
2793 + String get seed_alert_understand => "Compreendo";
2794 + @override
2795 + String get show_keys => "Mostrar chaves";
2796 + @override
2797 + String get error_text_fiat => "O valor do valor não pode exceder o saldo disponível.\nO número de dígitos da fração deve ser menor ou igual a 2";
2798 + @override
2799 + String get transactions_by_date => "Transações por data";
2800 + @override
2801 + String get use => "Usar ";
2802 + @override
2803 + String get trade_details_state => "Estado";
2804 + @override
2805 + String get spend_key_private => "Chave de gastos (privado)";
2806 + @override
2807 + String get settings_only_trades => "Somente negociações";
2808 + @override
2809 + String get trade_state_to_be_created => "Para ser criado";
2810 + @override
2811 + String get all => "TODOS";
2812 + @override
2813 + String get xmr_full_balance => "Saldo total do XMR";
2814 + @override
2815 + String get incoming => "Entrada";
2816 + @override
2817 + String get trade_history_title => "Histórico comercial";
2818 + @override
2819 + String get error_text_wallet_name => "O nome da carteira só pode conter letras, números\ne deve ter entre 1 e 15 caracteres";
2820 + @override
2821 + String get restore_description_from_keys => "Restaure sua carteira da geração\npressionamentos de tecla salvos em suas chaves privadas";
2822 + @override
2823 + String get sent => "Enviei";
2824 + @override
2825 + String get view_key_public => "Tecla Ver (público)";
2826 + @override
2827 + String get trade_details_id => "ID";
2828 + @override
2829 + String get trade_state_confirming => "Confirmando";
2830 + @override
2831 + String get send => "Mandar";
2832 + @override
2833 + String get send_title => "Enviar Monero";
2834 + @override
2835 + String get error_text_keys => "As chaves da carteira podem conter apenas 64 caracteres em hexadecimal";
2836 + @override
2837 + String get settings_save_recipient_address => "Salvar endereço do destinatário";
2838 + @override
2839 + String get seed_alert_settings => "configurações";
2840 + @override
2841 + String get change_exchange_provider => "Alterar provedor de câmbio";
2842 + @override
2843 + String get send_payment_id => "ID de pagamento (opcional)";
2844 + @override
2845 + String get trade_details_title => "Detalhes do comércio";
2846 + @override
2847 + String get settings_terms_and_conditions => "Termos e Condições";
2848 + @override
2849 + String get auth_store_ban_timeout => "proibir timeout";
2850 + @override
2851 + String get sync_status_connecting => "CONECTANDO";
2852 + @override
2853 + String get settings_transactions => "Transações";
2854 + @override
2855 + String get transaction_priority_fastest => "O mais rápido";
2856 + @override
2857 + String get error => "Erro";
2858 + @override
2859 + String get delete => "Excluir";
2860 + @override
2861 + String get sync_status_starting_sync => "INÍCIO DE SINCRONIZAÇÃO";
2862 + @override
2863 + String get copied_to_clipboard => "Copiado para a área de transferência";
2864 + @override
2865 + String get offer_expires_in => "A oferta expira em: ";
2866 + @override
2867 + String get continue_text => "Continuar";
2868 + @override
2869 + String get transaction_details_height => "Altura";
2870 + @override
2871 + String get wallet_menu => "Menu da Carteira";
2872 + @override
2873 + String get settings_dark_mode => "Modo escuro";
2874 + @override
2875 + String get payment_id => "ID de pagamento: ";
2876 + @override
2877 + String get restore_address => "Endereço";
2878 + @override
2879 + String get restore_wallet_restore_description => "Restauração de carteira";
2880 + @override
2881 + String get today => "Hoje";
2882 + @override
2883 + String get settings_support => "Suporte";
2884 + @override
2885 + String get restore_wallet => "Restaurar carteira";
2886 + @override
2887 + String get ok => "Está bem";
2888 + @override
2889 + String get wallet_list_title => "Monero Carteira";
2890 + @override
2891 + String get authentication => "Autenticação";
2892 + @override
2893 + String get amount => "Montante: ";
2894 + @override
2895 + String get node_address => "Endereço do nó";
2896 + @override
2897 + String get settings_change_language => "Mudar idioma";
2898 + @override
2899 + String get clear => "Claro";
2900 + @override
2901 + String get settings_change_pin => "Alterar PIN";
2902 + @override
2903 + String get trades => "Comércios";
2904 + @override
2905 + String get trade_state_btc_sent => "Enviei";
2906 + @override
2907 + String get address_book => "Livro de endereços";
2908 + @override
2909 + String get enter_your_pin => "Insira seu PIN";
2910 + @override
2911 + String get wallet_list_restore_wallet => "Restaurar carteira";
2912 + @override
2913 + String get restore_title_from_seed => "Restaurar a partir da semente";
2914 + @override
2915 + String get restore_description_from_backup => "Você pode restaurar todo o aplicativo Cake Wallet em\nseu arquivo de backup";
2916 + @override
2917 + String get send_monero_address => "Endereço Monero";
2918 + @override
2919 + String get error_text_node_port => "A porta do nó pode conter apenas números entre 0 e 65535";
2920 + @override
2921 + String get digit_pin => "de dois dígitos";
2922 + @override
2923 + String get first_wallet_text => "Carteira impressionante\npara Monero";
2924 + @override
2925 + String get settings_trades => "Comércios";
2926 + @override
2927 + String get account => "Conta";
2928 + @override
2929 + String change_language_to(String language) => "Alterar idioma para ${language}?";
2930 + @override
2931 + String change_current_node(String node) => "Você tem certeza de alterar o nó atual para ${node}?";
2932 + @override
2933 + String trade_id(String id) => "ID comercial:\n${id}";
2934 + @override
2935 + String wallet_list_loading_wallet(String wallet_name) => "Carregando ${wallet_name} carteira";
2936 + @override
2937 + String router_no_route(String name) => "Nenhuma rota definida para ${name}";
2938 + @override
2939 + String trade_id_not_found(String tradeId, String title) => "Comércio${tradeId} of ${title} não encontrado.";
2940 + @override
2941 + String transaction_details_copied(String title) => "${title} Copiado para a área de transferência";
2942 + @override
2943 + String trade_details_copied(String title) => "${title} Copiado para a área de transferência";
2944 + @override
2945 + String powered_by(String title) => "Distribuído por ${title}";
2946 + @override
2947 + String send_priority(String transactionPriority) => "Atualmente, a taxa está definida em ${transactionPriority} prioridade.\nA prioridade da transação pode ser ajustada nas configurações";
2948 + @override
2949 + String trade_for_not_created(String title) => "Comércio por ${title} não é criado.";
2950 + @override
2951 + String trade_is_powered_by(String provider) => "Este comércio é alimentado por ${provider}";
2952 + @override
2953 + String time(String minutes, String seconds) => "${minutes}m ${seconds}s";
2954 + @override
2955 + String max_value(String value, String currency) => "Máx: ${value} ${currency}";
2956 + @override
2957 + String min_value(String value, String currency) => "Mín: ${value} ${currency}";
2958 + @override
2959 + String failed_authentication(String state_error) => "Falha na autenticação. ${state_error}";
2960 + @override
2961 + String Blocks_remaining(String status) => "${status} Blocos restantes";
2962 + @override
2963 + String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "Ao pressionar confirmar, você estará enviando ${fetchingLabel} ${from} da sua carteira ${walletName} para o endereço mostrado acima. Ou você pode enviar da sua carteira externa para o endereço / código QR acima.\n\nPressione confirmar para continuar ou voltar para alterar os valores.\n\n";
2964 + @override
2965 + String exchange_result_description(String fetchingLabel, String from) => "Por favor envie ${fetchingLabel} ${from} para o endereço mostrado acima.\n\n'";
2966 + @override
2967 + String commit_transaction_amount_fee(String amount, String fee) => "Confirmar transação\nMontante: ${amount}\nTaxa: ${fee}";
2968 + @override
2969 + String wallet_list_failed_to_remove(String wallet_name, String error) => "Falha ao remover ${wallet_name} carteira. ${error}";
2970 + @override
2971 + String copied_key_to_clipboard(String key) => "Copiado ${key} para a área de transferência";
2972 + @override
2973 + String wallet_list_failed_to_load(String wallet_name, String error) => "Falha ao carregar ${wallet_name} carteira. ${error}";
2974 + @override
2975 + String wallet_list_removing_wallet(String wallet_name) => "Removendo ${wallet_name} carteira";
2976 +}
2977 +
2978 +class $ja extends S {
2979 + const $ja();
2980 +
2981 + @override
2982 + TextDirection get textDirection => TextDirection.ltr;
2983 +
2984 + @override
2985 + String get cancel => "キャンセル";
2986 + @override
2987 + String get trade_state_unpaid => "未払い";
2988 + @override
2989 + String get authenticated => "認証済み";
2990 + @override
2991 + String get new_subaddress_create => "作成する";
2992 + @override
2993 + String get restore_view_key_private => "ビューキー (プライベート)";
2994 + @override
2995 + String get transaction_priority_fast => "速い";
2996 + @override
2997 + String get error_text_amount => "金額には数字のみを含めることができます";
2998 + @override
2999 + String get hidden_balance => "隠れたバランス";
3000 + @override
3001 + String get transaction_sent => "トランザクションが送信されました!";
3002 + @override
3003 + String get password => "パスワード";
3004 + @override
3005 + String get you_will_get => "あなたが取得します";
3006 + @override
3007 + String get restore_description_from_seed => "25ワードからウォレットを復元します\nまたは13ワードの組み合わせコード";
3008 + @override
3009 + String get trade_state_underpaid => "支払不足";
3010 + @override
3011 + String get welcome => "ようこそ\nに CAKE WALLET";
3012 + @override
3013 + String get share_address => "住所を共有する";
3014 + @override
3015 + String get please_try_to_connect_to_another_node => "別のノードに接続してみてください";
3016 + @override
3017 + String get trade_state_traded => "取引済み";
3018 + @override
3019 + String get edit => "編集";
3020 + @override
3021 + String get spend_key_public => "キーを使う (パブリック)";
3022 + @override
3023 + String get sync_status_syncronizing => "同期";
3024 + @override
3025 + String get received => "受け取った";
3026 + @override
3027 + String get auth_store_banned_minutes => " 数分";
3028 + @override
3029 + String get restore_title_from_seed_keys => "シード/キーから復元";
3030 + @override
3031 + String get settings_none => "なし";
3032 + @override
3033 + String get wallet_list_create_new_wallet => "新しいウォレットを作成";
3034 + @override
3035 + String get seed_alert_third_text => "また、種子を見ることができます\nの中に ";
3036 + @override
3037 + String get setup_pin => "PINのセットアップ";
3038 + @override
3039 + String get transaction_details_recipient_address => "受取人の住所";
3040 + @override
3041 + String get receive_amount => "量";
3042 + @override
3043 + String get settings_allow_biometrical_authentication => "生体認証を許可する";
3044 + @override
3045 + String get view_key_private => "ビューキー (プライベート)";
3046 + @override
3047 + String get restore_next => "次";
3048 + @override
3049 + String get trade_state_trading => "トレーディング";
3050 + @override
3051 + String get error_text_address => "ウォレットアドレスは、\n暗号通貨";
3052 + @override
3053 + String get send_your_wallet => "あなたの財布";
3054 + @override
3055 + String get remove_node_message => "選択したノードを削除してもよろしいですか?";
3056 + @override
3057 + String get error_text_account_name => "アカウント名には文字のみを含めることができます \n1〜15文字である必要があります";
3058 + @override
3059 + String get reconnection => "再接続";
3060 + @override
3061 + String get available_balance => "利用可能残高";
3062 + @override
3063 + String get restore_title_from_keys => "キーから復元する";
3064 + @override
3065 + String get wallet_keys => "ウォレットキー";
3066 + @override
3067 + String get reconnect => "再接続";
3068 + @override
3069 + String get reconnect_alert_text => "再接続しますか?";
3070 + @override
3071 + String get send_error_minimum_value => "金額の最小値は0.01です";
3072 + @override
3073 + String get copy_address => "住所をコピー";
3074 + @override
3075 + String get error_text_subaddress_name => "サブアドレス名に含めることはできません` , ' \" シンボル\n1〜20文字の長さである必要があります";
3076 + @override
3077 + String get settings_all => "すべて";
3078 + @override
3079 + String get nodes_list_reset_to_default_message => "設定をデフォルトにリセットしてもよろしいですか?";
3080 + @override
3081 + String get receive => "受け取る";
3082 + @override
3083 + String get amount_is_guaranteed => "受信金額は保証されています";
3084 + @override
3085 + String get auth_store_banned_for => "禁止されています ";
3086 + @override
3087 + String get trade_details_pair => "ペア";
3088 + @override
3089 + String get confirm => "確認する";
3090 + @override
3091 + String get send_xmr => "送る XMR";
3092 + @override
3093 + String get settings_display_balance_as => "残高を表示";
3094 + @override
3095 + String get trade_details_provider => "プロバイダー";
3096 + @override
3097 + String get you_will_send => "送ります";
3098 + @override
3099 + String get create_new => "新しく作る";
3100 + @override
3101 + String get trade_details_fetching => "フェッチング";
3102 + @override
3103 + String get seed_alert_menu => " メニュー.";
3104 + @override
3105 + String get confirm_sending => "送信を確認";
3106 + @override
3107 + String get settings_title => "設定";
3108 + @override
3109 + String get address_book_menu => "住所録";
3110 + @override
3111 + String get wallet_restoration_store_incorrect_seed_length => "誤ったシード長s";
3112 + @override
3113 + String get contact => "接触";
3114 + @override
3115 + String get auth_store_incorrect_password => "間違ったPIN";
3116 + @override
3117 + String get transaction_priority_slow => "スロー";
3118 + @override
3119 + String get add => "加える";
3120 + @override
3121 + String get remove_node => "ノードを削除";
3122 + @override
3123 + String get trade_state_paid_unconfirmed => "未確認の支払い";
3124 + @override
3125 + String get please_select => "選んでください:";
3126 + @override
3127 + String get restore_title_from_backup => "バックアップファイルから復元する";
3128 + @override
3129 + String get full_balance => "フルバランス";
3130 + @override
3131 + String get sync_status_not_connected => "接続されていません";
3132 + @override
3133 + String get error_text_crypto_currency => "小数桁数\n12以下でなければなりません";
3134 + @override
3135 + String get error_text_contact_name => "連絡先名に含めることはできません ` , ' \" シンボル\n長さは1〜32文字でなければなりません";
3136 + @override
3137 + String get restore_seed_keys_restore => "シード/キーの復元";
3138 + @override
3139 + String get xmr_hidden => "XMR非表示";
3140 + @override
3141 + String get exchange => "交換する";
3142 + @override
3143 + String get sync_status_failed_connect => "ノードへの接続に失敗しました";
3144 + @override
3145 + String get send_estimated_fee => "見積手数料:";
3146 + @override
3147 + String get outgoing => "発信";
3148 + @override
3149 + String get sync_status_connected => "接続済み";
3150 + @override
3151 + String get trade_state_pending => "保留中";
3152 + @override
3153 + String get pending => " (保留中)";
3154 + @override
3155 + String get setup_successful => "PINは正常に設定されました!";
3156 + @override
3157 + String get fetching => "フェッチング";
3158 + @override
3159 + String get settings_nodes => "ノード";
3160 + @override
3161 + String get widgets_or => "または";
3162 + @override
3163 + String get remove => "削除する";
3164 + @override
3165 + String get yesterday => "昨日";
3166 + @override
3167 + String get expired => "期限切れ";
3168 + @override
3169 + String get transaction_priority_regular => "レギュラー";
3170 + @override
3171 + String get trade_details_created_at => "で作成";
3172 + @override
3173 + String get settings_wallets => "財布";
3174 + @override
3175 + String get settings_only_transactions => "トランザクションのみ";
3176 + @override
3177 + String get estimated => "推定";
3178 + @override
3179 + String get filters => "フィルター";
3180 + @override
3181 + String get settings_current_node => "現在のノード";
3182 + @override
3183 + String get copy_id => "IDをコピー";
3184 + @override
3185 + String get please_make_selection => "以下を選択してください\nウォレットを作成または回復する.";
3186 + @override
3187 + String get loading_your_wallet => "ウォレットをロードしています";
3188 + @override
3189 + String get subaddresses => "サブアドレス";
3190 + @override
3191 + String get trade_state_timeout => "タイムアウト";
3192 + @override
3193 + String get nodes => "ノード";
3194 + @override
3195 + String get seed_share => "シードを共有する";
3196 + @override
3197 + String get widgets_restore_from_blockheight => "ブロックの高さから復元";
3198 + @override
3199 + String get new_subaddress_label_name => "ラベル名";
3200 + @override
3201 + String get trade_not_found => "取引が見つかりません";
3202 + @override
3203 + String get transaction_details_date => "日付";
3204 + @override
3205 + String get show_seed => "シードを表示";
3206 + @override
3207 + String get send_error_currency => "通貨には数字のみを含めることができます";
3208 + @override
3209 + String get subaddress_title => "サブアドレス一覧";
3210 + @override
3211 + String get wallet_store_monero_wallet => "Monero 財布";
3212 + @override
3213 + String get send_creating_transaction => "トランザクションを作成する";
3214 + @override
3215 + String get trade_state_complete => "コンプリート";
3216 + @override
3217 + String get error_text_xmr => "XMR値は利用可能な残高を超えることはできません.\n小数桁数は12以下でなければなりません";
3218 + @override
3219 + String get xmr_available_balance => "XMR利用可能残高";
3220 + @override
3221 + String get trade_state_paid => "有料";
3222 + @override
3223 + String get node_new => "新しいノード";
3224 + @override
3225 + String get trade_state_created => "作成した";
3226 + @override
3227 + String get faq => "FAQ";
3228 + @override
3229 + String get id => "ID: ";
3230 + @override
3231 + String get saved_the_trade_id => "取引IDを保存しました";
3232 + @override
3233 + String get settings_currency => "通貨";
3234 + @override
3235 + String get change_language => "言語を変えてください";
3236 + @override
3237 + String get wallet_name => "ウォレット名";
3238 + @override
3239 + String get error_text_payment_id => "支払いIDには、16進数で16〜64文字しか含めることができません";
3240 + @override
3241 + String get seed_alert_second_text => "これらを書き留めてください \n電話を紛失した場合や拭いた場合.";
3242 + @override
3243 + String get node_reset_settings_title => "設定をリセット";
3244 + @override
3245 + String get wallets => "財布";
3246 + @override
3247 + String get enter_your_pin_again => "ピンをもう一度入力してください";
3248 + @override
3249 + String get transactions => "取引";
3250 + @override
3251 + String get amount_is_estimate => "受け取り金額は見積もりです";
3252 + @override
3253 + String get error_text_node_address => "iPv4アドレスを入力してください";
3254 + @override
3255 + String get widgets_restore_from_date => "日付から復元";
3256 + @override
3257 + String get restore_recover => "回復します";
3258 + @override
3259 + String get reset => "リセットする";
3260 + @override
3261 + String get new_wallet => "新しいウォレット";
3262 + @override
3263 + String get settings_display_on_dashboard_list => "ダッシュボードリストに表示";
3264 + @override
3265 + String get transaction_details_title => "取引の詳細";
3266 + @override
3267 + String get status => "状態: ";
3268 + @override
3269 + String get restore_spend_key_private => "キーを使う (プライベート)";
3270 + @override
3271 + String get sync_status_syncronized => "同期された";
3272 + @override
3273 + String get transaction_priority_medium => "中";
3274 + @override
3275 + String get transaction_details_transaction_id => "トランザクションID";
3276 + @override
3277 + String get save => "セーブ";
3278 + @override
3279 + String get login => "ログイン";
3280 + @override
3281 + String get wallet_list_load_wallet => "ウォレットをロード";
3282 + @override
3283 + String get sending => "送信";
3284 + @override
3285 + String get restore_restore_wallet => "ウォレットを復元";
3286 + @override
3287 + String get restore_description_from_seed_keys => "安全な場所に保存したシード/キーから財布を取り戻す";
3288 + @override
3289 + String get copy => "コピー";
3290 + @override
3291 + String get node_port => "ノードポート";
3292 + @override
3293 + String get change_currency => "通貨を変更する";
3294 + @override
3295 + String get transaction_details_amount => "量";
3296 + @override
3297 + String get widgets_address => "住所";
3298 + @override
3299 + String get contact_name => "連絡先";
3300 + @override
3301 + String get exchange_result_write_down_ID => "*上記のIDをコピーまたは書き留めてください.";
3302 + @override
3303 + String get exchange_result_write_down_trade_id => "続行するには、取引IDをコピーまたは書き留めてください.";
3304 + @override
3305 + String get new_subaddress_title => "新しいサブアドレス";
3306 + @override
3307 + String get change => "変化する";
3308 + @override
3309 + String get seed_alert_first_text => "次のページが表示されます\nあなたは種.";
3310 + @override
3311 + String get trade_state_finished => "完成した";
3312 + @override
3313 + String get pin_is_incorrect => "PINが間違っています";
3314 + @override
3315 + String get trade_not_created => "作成されていない取引";
3316 + @override
3317 + String get restore_wallet_name => "ウォレット名";
3318 + @override
3319 + String get widgets_seed => "シード";
3320 + @override
3321 + String get settings_fee_priority => "料金優先";
3322 + @override
3323 + String get settings_personal => "パーソナル";
3324 + @override
3325 + String get seed_title => "シード";
3326 + @override
3327 + String get accounts => "アカウント";
3328 + @override
3329 + String get rescan => "再スキャン";
3330 + @override
3331 + String get seed_alert_understand => "わかります";
3332 + @override
3333 + String get show_keys => "キーを表示";
3334 + @override
3335 + String get error_text_fiat => "金額は利用可能な残高を超えることはできません.\n小数桁の数は2以下でなければなりません";
3336 + @override
3337 + String get transactions_by_date => "日付ごとの取引";
3338 + @override
3339 + String get use => "つかいます ";
3340 + @override
3341 + String get trade_details_state => "状態";
3342 + @override
3343 + String get spend_key_private => "キーを使う (プライベート)";
3344 + @override
3345 + String get settings_only_trades => "取引のみ";
3346 + @override
3347 + String get trade_state_to_be_created => "作成される";
3348 + @override
3349 + String get all => "すべて";
3350 + @override
3351 + String get xmr_full_balance => "XMRフルバランス";
3352 + @override
3353 + String get incoming => "着信";
3354 + @override
3355 + String get trade_history_title => "取引履歴";
3356 + @override
3357 + String get error_text_wallet_name => "ウォレット名には文字のみを含めることができます\n1〜15文字である必要があります";
3358 + @override
3359 + String get restore_description_from_keys => "生成されたウォレットを復元します\n秘密鍵から保存されたキーストローク";
3360 + @override
3361 + String get sent => "送信済み";
3362 + @override
3363 + String get view_key_public => "ビューキー (パブリック)";
3364 + @override
3365 + String get trade_details_id => "ID";
3366 + @override
3367 + String get trade_state_confirming => "確認中";
3368 + @override
3369 + String get send => "送る";
3370 + @override
3371 + String get send_title => "Moneroを送信";
3372 + @override
3373 + String get error_text_keys => "ウォレットキーには、16進数で64文字しか含めることができません";
3374 + @override
3375 + String get settings_save_recipient_address => "受信者のアドレスを保存";
3376 + @override
3377 + String get seed_alert_settings => "設定";
3378 + @override
3379 + String get change_exchange_provider => "Exchangeプロバイダーの変更";
3380 + @override
3381 + String get send_payment_id => "支払いID (オプショナル)";
3382 + @override
3383 + String get trade_details_title => "取引の詳細";
3384 + @override
3385 + String get settings_terms_and_conditions => "規約と条件";
3386 + @override
3387 + String get auth_store_ban_timeout => "禁止タイムアウト";
3388 + @override
3389 + String get sync_status_connecting => "接続中";
3390 + @override
3391 + String get settings_transactions => "取引";
3392 + @override
3393 + String get transaction_priority_fastest => "最速";
3394 + @override
3395 + String get error => "エラー";
3396 + @override
3397 + String get delete => "削除する";
3398 + @override
3399 + String get sync_status_starting_sync => "同期の開始";
3400 + @override
3401 + String get copied_to_clipboard => "クリップボードにコピーしました";
3402 + @override
3403 + String get offer_expires_in => "で有効期限が切れます: ";
3404 + @override
3405 + String get continue_text => "持続する";
3406 + @override
3407 + String get transaction_details_height => "高さ";
3408 + @override
3409 + String get wallet_menu => "ウォレットメニュー";
3410 + @override
3411 + String get settings_dark_mode => "ダークモード";
3412 + @override
3413 + String get payment_id => "支払いID: ";
3414 + @override
3415 + String get restore_address => "住所";
3416 + @override
3417 + String get restore_wallet_restore_description => "ウォレットの復元";
3418 + @override
3419 + String get today => "今日";
3420 + @override
3421 + String get settings_support => "サポート";
3422 + @override
3423 + String get restore_wallet => "ウォレットを復元する";
3424 + @override
3425 + String get ok => "OK";
3426 + @override
3427 + String get wallet_list_title => "Monero 財布";
3428 + @override
3429 + String get authentication => "認証";
3430 + @override
3431 + String get amount => "量: ";
3432 + @override
3433 + String get node_address => "ノードアドレス";
3434 + @override
3435 + String get settings_change_language => "言語を変えてください";
3436 + @override
3437 + String get clear => "クリア";
3438 + @override
3439 + String get settings_change_pin => "PINを変更";
3440 + @override
3441 + String get trades => "取引";
3442 + @override
3443 + String get trade_state_btc_sent => "送った";
3444 + @override
3445 + String get address_book => "住所録";
3446 + @override
3447 + String get enter_your_pin => "PINを入力してください";
3448 + @override
3449 + String get wallet_list_restore_wallet => "ウォレットを復元";
3450 + @override
3451 + String get restore_title_from_seed => "シードから復元";
3452 + @override
3453 + String get restore_description_from_backup => "Cake Walletアプリ全体を復元できます\nバックアップファイル";
3454 + @override
3455 + String get send_monero_address => "Monero 住所";
3456 + @override
3457 + String get error_text_node_port => "ノードポートには、0〜65535の数字のみを含めることができます";
3458 + @override
3459 + String get digit_pin => "桁ピン";
3460 + @override
3461 + String get first_wallet_text => "素晴らしい財布\nために Monero";
3462 + @override
3463 + String get settings_trades => "取引";
3464 + @override
3465 + String get account => "アカウント";
3466 + @override
3467 + String change_language_to(String language) => "言語を変更 ${language}?";
3468 + @override
3469 + String change_current_node(String node) => "現在のノードを変更してよろしいですか ${node}?";
3470 + @override
3471 + String trade_id(String id) => "取引ID:\n${id}";
3472 + @override
3473 + String wallet_list_loading_wallet(String wallet_name) => "読み込み中 ${wallet_name} 財布";
3474 + @override
3475 + String router_no_route(String name) => "ルートが定義されていません ${name}";
3476 + @override
3477 + String trade_id_not_found(String tradeId, String title) => "トレード ${tradeId} of ${title} 見つかりません";
3478 + @override
3479 + String transaction_details_copied(String title) => "${title} クリップボードにコピーしました";
3480 + @override
3481 + String trade_details_copied(String title) => "${title} クリップボードにコピーしました";
3482 + @override
3483 + String powered_by(String title) => "搭載 ${title}";
3484 + @override
3485 + String send_priority(String transactionPriority) => "現在、料金は ${transactionPriority} 優先度.\nトランザクションの優先度は設定で調整できます";
3486 + @override
3487 + String trade_for_not_created(String title) => "取引 ${title} 作成されません";
3488 + @override
3489 + String trade_is_powered_by(String provider) => "この取引は ${provider}";
3490 + @override
3491 + String time(String minutes, String seconds) => "${minutes}m ${seconds}s";
3492 + @override
3493 + String max_value(String value, String currency) => "マックス: ${value} ${currency}";
3494 + @override
3495 + String min_value(String value, String currency) => "分: ${value} ${currency}";
3496 + @override
3497 + String failed_authentication(String state_error) => "認証失敗. ${state_error}";
3498 + @override
3499 + String Blocks_remaining(String status) => "${status} 残りのブロック";
3500 + @override
3501 + String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "確認を押すと、送信されます ${fetchingLabel} ${from} と呼ばれるあなたの財布から ${walletName} 上記のアドレスへ. または、外部ウォレットから上記のアドレス/ QRコードに送信できます.\n\n確認を押して続行するか、戻って金額を変更してください.\n\n";
3502 + @override
3503 + String exchange_result_description(String fetchingLabel, String from) => "送信してください ${fetchingLabel} ${from} 上記のアドレスへ.\n\n'";
3504 + @override
3505 + String commit_transaction_amount_fee(String amount, String fee) => "トランザクションをコミット\n量: ${amount}\n費用: ${fee}";
3506 + @override
3507 + String wallet_list_failed_to_remove(String wallet_name, String error) => "削除できませんでした ${wallet_name} 財布. ${error}";
3508 + @override
3509 + String copied_key_to_clipboard(String key) => "コピー済み ${key} クリップボードへ";
3510 + @override
3511 + String wallet_list_failed_to_load(String wallet_name, String error) => "読み込みに失敗しました ${wallet_name} 財布. ${error}";
3512 + @override
3513 + String wallet_list_removing_wallet(String wallet_name) => "取りはずし ${wallet_name} 財布";
3514 +}
3515 +
3516 +class $en extends S {
3517 + const $en();
3518 +}
3519 +
3520 +class $pl extends S {
3521 + const $pl();
3522 +
3523 + @override
3524 + TextDirection get textDirection => TextDirection.ltr;
3525 +
3526 + @override
3527 + String get cancel => "Anulować";
3528 + @override
3529 + String get trade_state_unpaid => "Nie zapłacony";
3530 + @override
3531 + String get authenticated => "Zalegalizowany";
3532 + @override
3533 + String get new_subaddress_create => "Stwórz";
3534 + @override
3535 + String get restore_view_key_private => "Wyświetl klucz (prywatny)";
3536 + @override
3537 + String get transaction_priority_fast => "Szybki";
3538 + @override
3539 + String get error_text_amount => "Kwota może zawierać tylko liczby";
3540 + @override
3541 + String get hidden_balance => "Ukryta równowaga";
3542 + @override
3543 + String get transaction_sent => "Transakcja wysłana!";
3544 + @override
3545 + String get password => "Hasło";
3546 + @override
3547 + String get you_will_get => "Dostaniesz";
3548 + @override
3549 + String get restore_description_from_seed => "Przywróć swój portfel z 25 słów\nlub 13-słowny kod kombinacji";
3550 + @override
3551 + String get trade_state_underpaid => "Niedopłacone";
3552 + @override
3553 + String get welcome => "WITAMY\nW CAKE WALLET";
3554 + @override
3555 + String get share_address => "Udostępnij adres";
3556 + @override
3557 + String get please_try_to_connect_to_another_node => "Spróbuj połączyć się z innym węzłem";
3558 + @override
3559 + String get trade_state_traded => "Handlowane";
3560 + @override
3561 + String get edit => "Edytować";
3562 + @override
3563 + String get spend_key_public => "Wydaj klucz (publiczny)";
3564 + @override
3565 + String get sync_status_syncronizing => "SYNCHRONIZACJA";
3566 + @override
3567 + String get received => "Odebrane";
3568 + @override
3569 + String get auth_store_banned_minutes => " minuty";
3570 + @override
3571 + String get restore_title_from_seed_keys => "Przywróć z nasion / kluczy";
3572 + @override
3573 + String get settings_none => "Żaden";
3574 + @override
3575 + String get wallet_list_create_new_wallet => "Utwórz nowy portfel";
3576 + @override
3577 + String get seed_alert_third_text => "Możesz także ponownie zobaczyć ziarno\nw ";
3578 + @override
3579 + String get setup_pin => "Ustaw PIN";
3580 + @override
3581 + String get transaction_details_recipient_address => "Adres odbiorcy";
3582 + @override
3583 + String get receive_amount => "Ilość";
3584 + @override
3585 + String get settings_allow_biometrical_authentication => "Zezwalaj na uwierzytelnianie biometryczne";
3586 + @override
3587 + String get view_key_private => "Wyświetl klucz (prywatny)";
3588 + @override
3589 + String get restore_next => "Kolejny";
3590 + @override
3591 + String get trade_state_trading => "Handlowy";
3592 + @override
3593 + String get error_text_address => "Wallet address must correspond to the type\nof cryptocurrency";
3594 + @override
3595 + String get send_your_wallet => "Twój portfel";
3596 + @override
3597 + String get remove_node_message => "Czy na pewno chcesz usunąć wybrany węzeł?";
3598 + @override
3599 + String get error_text_account_name => "Nazwa konta może zawierać tylko litery, cyfry\ni musi mieć od 1 do 15 znaków";
3600 + @override
3601 + String get reconnection => "Ponowne połączenie";
3602 + @override
3603 + String get available_balance => "Dostępne saldo";
3604 + @override
3605 + String get restore_title_from_keys => "Przywróć z kluczy";
3606 + @override
3607 + String get wallet_keys => "Klucze portfela";
3608 + @override
3609 + String get reconnect => "Na nowo połączyć";
3610 + @override
3611 + String get reconnect_alert_text => "Czy na pewno ponownie się połączysz?";
3612 + @override
3613 + String get send_error_minimum_value => "Minimalna wartość kwoty to 0,01";
3614 + @override
3615 + String get copy_address => "Skopiuj adress";
3616 + @override
3617 + String get error_text_subaddress_name => "Nazwa podadresu nie może zawierać ` , ' \" symbolika\ni musi mieć od 1 do 20 znaków";
3618 + @override
3619 + String get settings_all => "Cały";
3620 + @override
3621 + String get nodes_list_reset_to_default_message => "Czy na pewno chcesz przywrócić ustawienia domyślne?";
3622 + @override
3623 + String get receive => "Otrzymać";
3624 + @override
3625 + String get amount_is_guaranteed => "Otrzymana kwota jest gwarantowana";
3626 + @override
3627 + String get auth_store_banned_for => "Bzbanowany za ";
3628 + @override
3629 + String get trade_details_pair => "Para";
3630 + @override
3631 + String get confirm => "Potwierdzać";
3632 + @override
3633 + String get send_xmr => "Wysłać XMR";
3634 + @override
3635 + String get settings_display_balance_as => "Wyświetl saldo jako";
3636 + @override
3637 + String get trade_details_provider => "Dostawca";
3638 + @override
3639 + String get you_will_send => "Wyślesz";
3640 + @override
3641 + String get create_new => "Tworzyć nowe";
3642 + @override
3643 + String get trade_details_fetching => "Ujmujący";
3644 + @override
3645 + String get seed_alert_menu => " menu.";
3646 + @override
3647 + String get confirm_sending => "Potwierdź wysłanie";
3648 + @override
3649 + String get settings_title => "Ustawienia";
3650 + @override
3651 + String get address_book_menu => "Książka adresowa";
3652 + @override
3653 + String get wallet_restoration_store_incorrect_seed_length => "Nieprawidłowa długość nasion";
3654 + @override
3655 + String get contact => "Kontakt";
3656 + @override
3657 + String get auth_store_incorrect_password => "Niepoprawny PIN";
3658 + @override
3659 + String get transaction_priority_slow => "Powolny";
3660 + @override
3661 + String get add => "Dodaj";
3662 + @override
3663 + String get remove_node => "Usuń węzeł";
3664 + @override
3665 + String get trade_state_paid_unconfirmed => "Płatne niepotwierdzone";
3666 + @override
3667 + String get please_select => "Proszę wybrać:";
3668 + @override
3669 + String get restore_title_from_backup => "Przywróć z pliku kopii zapasowej";
3670 + @override
3671 + String get full_balance => "Pełna równowaga";
3672 + @override
3673 + String get sync_status_not_connected => "NIE POŁĄCZONY";
3674 + @override
3675 + String get error_text_crypto_currency => "Liczba cyfr ułamkowych\nmusi być mniejsza lub równa 12";
3676 + @override
3677 + String get error_text_contact_name => "Nazwa kontaktu nie może zawierać` , ' \" symbolika\ni musi mieć od 1 do 32 znaków ";
3678 + @override
3679 + String get restore_seed_keys_restore => "Przywracanie nasion / kluczy";
3680 + @override
3681 + String get xmr_hidden => "XMR Ukryty";
3682 + @override
3683 + String get exchange => "Wymieniać się";
3684 + @override
3685 + String get sync_status_failed_connect => "NIE MOŻNA PODŁĄCZYĆ DO WĘZŁA";
3686 + @override
3687 + String get send_estimated_fee => "Szacowana opłata:";
3688 + @override
3689 + String get outgoing => "Towarzyski";
3690 + @override
3691 + String get sync_status_connected => "POŁĄCZONY";
3692 + @override
3693 + String get trade_state_pending => "W oczekiwaniu";
3694 + @override
3695 + String get pending => " (w oczekiwaniu)";
3696 + @override
3697 + String get setup_successful => "Twój kod PIN został pomyślnie skonfigurowany!";
3698 + @override
3699 + String get fetching => "Ujmujący";
3700 + @override
3701 + String get settings_nodes => "Węzły";
3702 + @override
3703 + String get widgets_or => "lub";
3704 + @override
3705 + String get remove => "Usunąć";
3706 + @override
3707 + String get yesterday => "Wczoraj";
3708 + @override
3709 + String get expired => "Przedawniony";
3710 + @override
3711 + String get transaction_priority_regular => "Regularny";
3712 + @override
3713 + String get trade_details_created_at => "Utworzono w";
3714 + @override
3715 + String get settings_wallets => "Portfele";
3716 + @override
3717 + String get settings_only_transactions => "Tylko transakcje";
3718 + @override
3719 + String get estimated => "Oszacowano";
3720 + @override
3721 + String get filters => "Filtry";
3722 + @override
3723 + String get settings_current_node => "Bieżący węzeł";
3724 + @override
3725 + String get copy_id => "ID kopii";
3726 + @override
3727 + String get please_make_selection => "Wybierz poniżej, aby\ncutwórz lub odzyskaj swój portfel.";
3728 + @override
3729 + String get loading_your_wallet => "Ładowanie portfela";
3730 + @override
3731 + String get subaddresses => "Podadresy";
3732 + @override
3733 + String get trade_state_timeout => "Koniec czasu";
3734 + @override
3735 + String get nodes => "Węzły";
3736 + @override
3737 + String get seed_share => "Udostępnij ziarno";
3738 + @override
3739 + String get widgets_restore_from_blockheight => "Przywróć z wysokości bloku";
3740 + @override
3741 + String get new_subaddress_label_name => "Nazwa etykiety";
3742 + @override
3743 + String get trade_not_found => "Nie znaleziono handlu.";
3744 + @override
3745 + String get transaction_details_date => "Data";
3746 + @override
3747 + String get show_seed => "Pokaż nasiona";
3748 + @override
3749 + String get send_error_currency => "Waluta może zawierać tylko cyfry";
3750 + @override
3751 + String get subaddress_title => "Lista podadresów";
3752 + @override
3753 + String get wallet_store_monero_wallet => "Portfel Monero";
3754 + @override
3755 + String get send_creating_transaction => "Tworzenie transakcji";
3756 + @override
3757 + String get trade_state_complete => "Kompletny";
3758 + @override
3759 + String get error_text_xmr => "Wartość XMR nie może przekraczać dostępnego salda.\nLiczba cyfr ułamkowych musi być mniejsza lub równa 12";
3760 + @override
3761 + String get xmr_available_balance => "XMR Dostępne saldo";
3762 + @override
3763 + String get trade_state_paid => "Płatny";
3764 + @override
3765 + String get node_new => "Nowy węzeł";
3766 + @override
3767 + String get trade_state_created => "Stworzony";
3768 + @override
3769 + String get faq => "FAQ";
3770 + @override
3771 + String get id => "ID: ";
3772 + @override
3773 + String get saved_the_trade_id => "Zapisałem ID";
3774 + @override
3775 + String get settings_currency => "Waluta";
3776 + @override
3777 + String get change_language => "Zmień język";
3778 + @override
3779 + String get wallet_name => "Nazwa portfela";
3780 + @override
3781 + String get error_text_payment_id => "ID może zawierać od 16 do 64 znaków w formacie szesnastkowym";
3782 + @override
3783 + String get seed_alert_second_text => "Zapisz je na wszelki wypadek\nzgubisz lub wyczyścisz telefon.";
3784 + @override
3785 + String get node_reset_settings_title => "Resetowanie ustawień";
3786 + @override
3787 + String get wallets => "Portfele";
3788 + @override
3789 + String get enter_your_pin_again => "Wprowadź ponownie swój kod PIN";
3790 + @override
3791 + String get transactions => "Transakcje";
3792 + @override
3793 + String get amount_is_estimate => "Otrzymana kwota jest wartością szacunkową";
3794 + @override
3795 + String get error_text_node_address => "Wpisz adres iPv4";
3796 + @override
3797 + String get widgets_restore_from_date => "Przywróć od daty";
3798 + @override
3799 + String get restore_recover => "Wyzdrowieć";
3800 + @override
3801 + String get reset => "Nastawić";
3802 + @override
3803 + String get new_wallet => "Nowy portfel";
3804 + @override
3805 + String get settings_display_on_dashboard_list => "Wyświetl na liście kokpitu";
3806 + @override
3807 + String get transaction_details_title => "Szczegóły transakcji";
3808 + @override
3809 + String get status => "Status: ";
3810 + @override
3811 + String get restore_spend_key_private => "Wydaj klucz (prywatny)";
3812 + @override
3813 + String get sync_status_syncronized => "SYNCHRONIZOWANY";
3814 + @override
3815 + String get transaction_priority_medium => "Średni";
3816 + @override
3817 + String get transaction_details_transaction_id => "Transakcja ID";
3818 + @override
3819 + String get save => "Zapisać";
3820 + @override
3821 + String get login => "Zaloguj Się";
3822 + @override
3823 + String get wallet_list_load_wallet => "Załaduj portfel";
3824 + @override
3825 + String get sending => "Wysyłanie";
3826 + @override
3827 + String get restore_restore_wallet => "Przywróć portfel";
3828 + @override
3829 + String get restore_description_from_seed_keys => "Odzyskaj swój portfel z nasion / kluczy, które zapisałeś w bezpiecznym miejscu";
3830 + @override
3831 + String get copy => "Kopiuj";
3832 + @override
3833 + String get node_port => "Port węzła";
3834 + @override
3835 + String get change_currency => "Change Currency";
3836 + @override
3837 + String get transaction_details_amount => "Ilość";
3838 + @override
3839 + String get widgets_address => "Adres";
3840 + @override
3841 + String get contact_name => "Nazwa Kontaktu";
3842 + @override
3843 + String get exchange_result_write_down_ID => "*Skopiuj lub zanotuj swój identyfikator pokazany powyżej.";
3844 + @override
3845 + String get exchange_result_write_down_trade_id => "Skopiuj lub zanotuj identyfikator transakcji, aby kontynuować.";
3846 + @override
3847 + String get new_subaddress_title => "Nowy podadres";
3848 + @override
3849 + String get change => "Zmiana";
3850 + @override
3851 + String get seed_alert_first_text => "Pojawi się następna strona\nziarno.";
3852 + @override
3853 + String get trade_state_finished => "Skończone";
3854 + @override
3855 + String get pin_is_incorrect => "PPIN jest niepoprawny";
3856 + @override
3857 + String get trade_not_created => "Handel nie utworzony.";
3858 + @override
3859 + String get restore_wallet_name => "Nazwa portfela";
3860 + @override
3861 + String get widgets_seed => "Ziarno";
3862 + @override
3863 + String get settings_fee_priority => "Priorytet opłaty";
3864 + @override
3865 + String get settings_personal => "Osobisty";
3866 + @override
3867 + String get seed_title => "Ziarno";
3868 + @override
3869 + String get accounts => "Konta";
3870 + @override
3871 + String get rescan => "Skanuj ponownie";
3872 + @override
3873 + String get seed_alert_understand => "rozumiem";
3874 + @override
3875 + String get show_keys => "Pokaż klucze";
3876 + @override
3877 + String get error_text_fiat => "Wartość kwoty nie może przekroczyć dostępnego salda.\nLiczba cyfr ułamkowych musi być mniejsza lub równa 2";
3878 + @override
3879 + String get transactions_by_date => "Transakcje według daty";
3880 + @override
3881 + String get use => "Posługiwać się ";
3882 + @override
3883 + String get trade_details_state => "Stan";
3884 + @override
3885 + String get spend_key_private => "Wydaj klucz (prywatny)";
3886 + @override
3887 + String get settings_only_trades => "Tylko transakcje";
3888 + @override
3889 + String get trade_state_to_be_created => "Zostać stworzonym";
3890 + @override
3891 + String get all => "WSZYSTKO";
3892 + @override
3893 + String get xmr_full_balance => "XMR Pełna równowaga";
3894 + @override
3895 + String get incoming => "Przychodzące";
3896 + @override
3897 + String get trade_history_title => "Historia handlu";
3898 + @override
3899 + String get error_text_wallet_name => "Nazwa portfela może zawierać tylko litery i cyfry\ni musi mieć od 1 do 15 znaków";
3900 + @override
3901 + String get restore_description_from_keys => "Przywróć swój portfel z wygenerowanego\nnaciśnięcia klawiszy zapisane z kluczy prywatnych";
3902 + @override
3903 + String get sent => "Wysłano";
3904 + @override
3905 + String get view_key_public => "Wyświetl klucz (publiczny)";
3906 + @override
3907 + String get trade_details_id => "ID";
3908 + @override
3909 + String get trade_state_confirming => "Potwierdzam";
3910 + @override
3911 + String get send => "Wysłać";
3912 + @override
3913 + String get send_title => "Wyślij Monero";
3914 + @override
3915 + String get error_text_keys => "Klucze portfela mogą zawierać tylko 64 znaki w systemie szesnastkowym";
3916 + @override
3917 + String get settings_save_recipient_address => "Zapisz adres odbiorcy";
3918 + @override
3919 + String get seed_alert_settings => "ustawienia";
3920 + @override
3921 + String get change_exchange_provider => "Zmień dostawcę programu Exchange";
3922 + @override
3923 + String get send_payment_id => "Identyfikator płatności (opcjonalny)";
3924 + @override
3925 + String get trade_details_title => "Szczegóły handlu";
3926 + @override
3927 + String get settings_terms_and_conditions => "Zasady i warunki";
3928 + @override
3929 + String get auth_store_ban_timeout => "przekroczenie limitu czasu";
3930 + @override
3931 + String get sync_status_connecting => "ZŁĄCZONY";
3932 + @override
3933 + String get settings_transactions => "Transakcje";
3934 + @override
3935 + String get transaction_priority_fastest => "Najszybszy";
3936 + @override
3937 + String get error => "Błąd";
3938 + @override
3939 + String get delete => "Kasować";
3940 + @override
3941 + String get sync_status_starting_sync => "ROZPOCZĘCIE SYNCHRONIZACJI";
3942 + @override
3943 + String get copied_to_clipboard => "Skopiowane do schowka";
3944 + @override
3945 + String get offer_expires_in => "Oferta wygasa za ";
3946 + @override
3947 + String get continue_text => "Dalej";
3948 + @override
3949 + String get transaction_details_height => "Wysokość";
3950 + @override
3951 + String get wallet_menu => "Menu portfela";
3952 + @override
3953 + String get settings_dark_mode => "Tryb ciemny";
3954 + @override
3955 + String get payment_id => "Płatności ID: ";
3956 + @override
3957 + String get restore_address => "Adres";
3958 + @override
3959 + String get restore_wallet_restore_description => "Opis przywracania portfela";
3960 + @override
3961 + String get today => "Dzisiaj";
3962 + @override
3963 + String get settings_support => "Wsparcie";
3964 + @override
3965 + String get restore_wallet => "Przywróć portfel";
3966 + @override
3967 + String get ok => "Dobrze";
3968 + @override
3969 + String get wallet_list_title => "Portfel Monero";
3970 + @override
3971 + String get authentication => "Poświadczenie";
3972 + @override
3973 + String get amount => "Ilość: ";
3974 + @override
3975 + String get node_address => "Adres węzła";
3976 + @override
3977 + String get settings_change_language => "Zmień język";
3978 + @override
3979 + String get clear => "Jasny";
3980 + @override
3981 + String get settings_change_pin => "Zmień PIN";
3982 + @override
3983 + String get trades => "Transakcje";
3984 + @override
3985 + String get trade_state_btc_sent => "Wysłane";
3986 + @override
3987 + String get address_book => "Książka adresowa";
3988 + @override
3989 + String get enter_your_pin => "Wpisz Twój kod PIN";
3990 + @override
3991 + String get wallet_list_restore_wallet => "Przywróć portfel";
3992 + @override
3993 + String get restore_title_from_seed => "Przywróć z nasion";
3994 + @override
3995 + String get restore_description_from_backup => "Możesz przywrócić całą aplikację Cake Wallet z\nplik kopii zapasowej";
3996 + @override
3997 + String get send_monero_address => "Adres Monero";
3998 + @override
3999 + String get error_text_node_port => "Port węzła może zawierać tylko liczby od 0 do 65535";
4000 + @override
4001 + String get digit_pin => "- znak PIN";
4002 + @override
4003 + String get first_wallet_text => "Niesamowity portfel\nfdla Monero";
4004 + @override
4005 + String get settings_trades => "Transakcje";
4006 + @override
4007 + String get account => "Konto";
4008 + @override
4009 + String change_language_to(String language) => "Zmień język na ${language}?";
4010 + @override
4011 + String change_current_node(String node) => "Czy na pewno chcesz przywrócić ustawienia domyślne? ${node}?";
4012 + @override
4013 + String trade_id(String id) => "Identyfikator handlu:\n${id}";
4014 + @override
4015 + String wallet_list_loading_wallet(String wallet_name) => "Ładuję ${wallet_name} portfel";
4016 + @override
4017 + String router_no_route(String name) => "Brak zdefiniowanej trasy dla ${name}";
4018 + @override
4019 + String trade_id_not_found(String tradeId, String title) => "Handel ${tradeId} of ${title} nie znaleziono.";
4020 + @override
4021 + String transaction_details_copied(String title) => "${title} skopiowane do schowka";
4022 + @override
4023 + String trade_details_copied(String title) => "${title} skopiowane do schowka";
4024 + @override
4025 + String powered_by(String title) => "Zasilany przez ${title}";
4026 + @override
4027 + String send_priority(String transactionPriority) => "Obecnie opłata ustalona jest na ${transactionPriority} priorytet.\nPriorytet transakcji można zmienić w ustawieniach";
4028 + @override
4029 + String trade_for_not_created(String title) => "Zamienić się za ${title} nie jest tworzony.";
4030 + @override
4031 + String trade_is_powered_by(String provider) => "Ten handel jest zasilany przez ${provider}";
4032 + @override
4033 + String time(String minutes, String seconds) => "${minutes}m ${seconds}s";
4034 + @override
4035 + String max_value(String value, String currency) => "Max: ${value} ${currency}";
4036 + @override
4037 + String min_value(String value, String currency) => "Min: ${value} ${currency}";
4038 + @override
4039 + String failed_authentication(String state_error) => "Nieudane uwierzytelnienie. ${state_error}";
4040 + @override
4041 + String Blocks_remaining(String status) => "${status} Bloki pozostałe";
4042 + @override
4043 + String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "Naciskając Potwierdź, wyślesz ${fetchingLabel} ${from} z twojego portfela ${walletName} z twojego portfela. Lub możesz wysłać z zewnętrznego portfela na powyższy adres / kod QR.\n\nNaciśnij Potwierdź, aby kontynuować lub wróć, aby zmienić kwoty.\n\n";
4044 + @override
4045 + String exchange_result_description(String fetchingLabel, String from) => "Proszę wyślij ${fetchingLabel} ${from} na adres podany powyżej.\n\n'";
4046 + @override
4047 + String commit_transaction_amount_fee(String amount, String fee) => "Zatwierdź transakcję\nIlość: ${amount}\nOpłata: ${fee}";
4048 + @override
4049 + String wallet_list_failed_to_remove(String wallet_name, String error) => "Nie udało się usunąć ${wallet_name} portfel. ${error}";
4050 + @override
4051 + String copied_key_to_clipboard(String key) => "Skopiowane ${key} do schowka";
4052 + @override
4053 + String wallet_list_failed_to_load(String wallet_name, String error) => "Nie udało się załadować ${wallet_name} portfel. ${error}";
4054 + @override
4055 + String wallet_list_removing_wallet(String wallet_name) => "Usuwanie ${wallet_name} portfel";
4056 +}
4057 +
4058 +class $es extends S {
4059 + const $es();
4060 +
4061 + @override
4062 + TextDirection get textDirection => TextDirection.ltr;
4063 +
4064 + @override
4065 + String get cancel => "Cancelar";
4066 + @override
4067 + String get trade_state_unpaid => "No pagado";
4068 + @override
4069 + String get authenticated => "Autenticados";
4070 + @override
4071 + String get new_subaddress_create => "Crear";
4072 + @override
4073 + String get restore_view_key_private => "View clave (privado)";
4074 + @override
4075 + String get transaction_priority_fast => "Rápido";
4076 + @override
4077 + String get error_text_amount => "La cantidad solo puede contener números";
4078 + @override
4079 + String get hidden_balance => "Balance oculto";
4080 + @override
4081 + String get transaction_sent => "Transacción enviada!";
4082 + @override
4083 + String get password => "Contraseña";
4084 + @override
4085 + String get you_will_get => "Conseguirás";
4086 + @override
4087 + String get restore_description_from_seed => "Restaure su billetera desde el código de combinación de 25 palabras \ni de 13 palabras";
4088 + @override
4089 + String get trade_state_underpaid => "Poco pagado";
4090 + @override
4091 + String get welcome => "Bienvenido\n CAKE WALLET";
4092 + @override
4093 + String get share_address => "Compartir dirección";
4094 + @override
4095 + String get please_try_to_connect_to_another_node => "Intenta conectarte a otro nodo";
4096 + @override
4097 + String get trade_state_traded => "Negociado";
4098 + @override
4099 + String get edit => "Editar";
4100 + @override
4101 + String get spend_key_public => "Spend clave (público)";
4102 + @override
4103 + String get sync_status_syncronizing => "SINCRONIZANDO";
4104 + @override
4105 + String get received => "Recibido";
4106 + @override
4107 + String get auth_store_banned_minutes => " minutos";
4108 + @override
4109 + String get restore_title_from_seed_keys => "Restaurar desde semilla/claves";
4110 + @override
4111 + String get settings_none => "Ninguno";
4112 + @override
4113 + String get wallet_list_create_new_wallet => "Crear nueva billetera";
4114 + @override
4115 + String get seed_alert_third_text => "También puede ver la semilla nuevamente \nen el ";
4116 + @override
4117 + String get setup_pin => "PIN de configuración";
4118 + @override
4119 + String get transaction_details_recipient_address => "Dirección del receptor";
4120 + @override
4121 + String get receive_amount => "Cantidad";
4122 + @override
4123 + String get settings_allow_biometrical_authentication => "Permitir autenticación biométrica";
4124 + @override
4125 + String get view_key_private => "View clave (privado)";
4126 + @override
4127 + String get restore_next => "Próximo";
4128 + @override
4129 + String get trade_state_trading => "Comercio";
4130 + @override
4131 + String get error_text_address => "La dirección de la billetera debe corresponder al tipo \nde criptomoneda";
4132 + @override
4133 + String get send_your_wallet => "Tu billetera";
4134 + @override
4135 + String get remove_node_message => "¿Está seguro de que desea eliminar el nodo seleccionado?";
4136 + @override
4137 + String get error_text_account_name => "El nombre de la cuenta solo puede contener letras, números \ny debe tener entre 1 y 15 caracteres de longitud";
4138 + @override
4139 + String get reconnection => "Reconexión";
4140 + @override
4141 + String get available_balance => "Balance disponible";
4142 + @override
4143 + String get restore_title_from_keys => "De las claves";
4144 + @override
4145 + String get wallet_keys => "Billetera clave";
4146 + @override
4147 + String get reconnect => "Volver a conectar";
4148 + @override
4149 + String get reconnect_alert_text => "¿Estás seguro de reconectar?";
4150 + @override
4151 + String get send_error_minimum_value => "El valor mínimo de la cantidad es 0.01";
4152 + @override
4153 + String get copy_address => "Copiar dirección ";
4154 + @override
4155 + String get error_text_subaddress_name => "El nombre de la subdirección no puede contener símbolos `, '\" \ny debe tener entre 1 y 20 caracteres de longitud";
4156 + @override
4157 + String get settings_all => "TODOS";
4158 + @override
4159 + String get nodes_list_reset_to_default_message => "¿Está seguro de que desea restablecer la configuración predeterminada?";
4160 + @override
4161 + String get receive => "Recibir";
4162 + @override
4163 + String get amount_is_guaranteed => "El monto recibido está garantizado";
4164 + @override
4165 + String get auth_store_banned_for => "Prohibido para ";
4166 + @override
4167 + String get trade_details_pair => "Par";
4168 + @override
4169 + String get confirm => "Confirmar";
4170 + @override
4171 + String get send_xmr => "Enviar XMR";
4172 + @override
4173 + String get settings_display_balance_as => "Mostrar saldo como";
4174 + @override
4175 + String get trade_details_provider => "Proveedor";
4176 + @override
4177 + String get you_will_send => "Enviarás";
4178 + @override
4179 + String get create_new => "Crear nuevo";
4180 + @override
4181 + String get trade_details_fetching => "Cargando";
4182 + @override
4183 + String get seed_alert_menu => " menú .";
4184 + @override
4185 + String get confirm_sending => "Confirmar envío";
4186 + @override
4187 + String get settings_title => "Configuraciones";
4188 + @override
4189 + String get address_book_menu => "Libreta de direcciones";
4190 + @override
4191 + String get wallet_restoration_store_incorrect_seed_length => "Longitud de semilla incorrecta";
4192 + @override
4193 + String get contact => "Contacto";
4194 + @override
4195 + String get auth_store_incorrect_password => "Contraseña PIN";
4196 + @override
4197 + String get transaction_priority_slow => "Lento";
4198 + @override
4199 + String get add => "Añadir";
4200 + @override
4201 + String get remove_node => "Eliminar nodo";
4202 + @override
4203 + String get trade_state_paid_unconfirmed => "Pagado sin confirmar";
4204 + @override
4205 + String get please_select => "Por favor seleccione:";
4206 + @override
4207 + String get restore_title_from_backup => "Restaurar desde un archivo de respaldo";
4208 + @override
4209 + String get full_balance => "Balance completo";
4210 + @override
4211 + String get sync_status_not_connected => "NO CONECTADO";
4212 + @override
4213 + String get error_text_crypto_currency => "El número de dígitos fraccionarios \ndebe ser menor o igual a 12";
4214 + @override
4215 + String get error_text_contact_name => "El nombre del contacto no puede contener símbolos `, '\" \ny debe tener entre 1 y 32 caracteres de longitud";
4216 + @override
4217 + String get restore_seed_keys_restore => "Restauración de semillas / llaves";
4218 + @override
4219 + String get xmr_hidden => "XMR Oculto";
4220 + @override
4221 + String get exchange => "Intercambiar";
4222 + @override
4223 + String get sync_status_failed_connect => "CONEXIÓN FALLIDA AL NODO";
4224 + @override
4225 + String get send_estimated_fee => "Tarifa estimada:";
4226 + @override
4227 + String get outgoing => "Saliente";
4228 + @override
4229 + String get sync_status_connected => "CONECTADO";
4230 + @override
4231 + String get trade_state_pending => "Pendiente";
4232 + @override
4233 + String get pending => " (pendiente)";
4234 + @override
4235 + String get setup_successful => "Su PIN se ha configurado correctamente!";
4236 + @override
4237 + String get fetching => "Cargando";
4238 + @override
4239 + String get settings_nodes => "Nodos";
4240 + @override
4241 + String get widgets_or => "o";
4242 + @override
4243 + String get remove => "Retirar";
4244 + @override
4245 + String get yesterday => "Ayer";
4246 + @override
4247 + String get expired => "Muerto";
4248 + @override
4249 + String get transaction_priority_regular => "Regular";
4250 + @override
4251 + String get trade_details_created_at => "Creado en";
4252 + @override
4253 + String get settings_wallets => "Carteras";
4254 + @override
4255 + String get settings_only_transactions => "Solo transacciones";
4256 + @override
4257 + String get estimated => "Estimado";
4258 + @override
4259 + String get filters => "Filtros";
4260 + @override
4261 + String get settings_current_node => "Nodo actual";
4262 + @override
4263 + String get copy_id => "Copiar ID";
4264 + @override
4265 + String get please_make_selection => "Seleccione a continuación para\ncrear o recuperar su billetera.";
4266 + @override
4267 + String get loading_your_wallet => "Cargando tu billetera";
4268 + @override
4269 + String get subaddresses => "Subdirecciones";
4270 + @override
4271 + String get trade_state_timeout => "Se acabó el tiempo";
4272 + @override
4273 + String get nodes => "Nodos";
4274 + @override
4275 + String get seed_share => "Compartir semillas";
4276 + @override
4277 + String get widgets_restore_from_blockheight => "Restaurar desde blockheight";
4278 + @override
4279 + String get new_subaddress_label_name => "Nombre de etiqueta";
4280 + @override
4281 + String get trade_not_found => "Comercio no encontrado.";
4282 + @override
4283 + String get transaction_details_date => "Fecha";
4284 + @override
4285 + String get show_seed => "Mostrar semilla";
4286 + @override
4287 + String get send_error_currency => "La moneda solo puede contener números";
4288 + @override
4289 + String get subaddress_title => "Lista de subdirecciones";
4290 + @override
4291 + String get wallet_store_monero_wallet => "Monedero Monero";
4292 + @override
4293 + String get send_creating_transaction => "Creando transacción";
4294 + @override
4295 + String get trade_state_complete => "Completar";
4296 + @override
4297 + String get error_text_xmr => "El valor XMR no puede exceder el saldo disponible.\nTEl número de dígitos de fracción debe ser menor o igual a 12";
4298 + @override
4299 + String get xmr_available_balance => "XMR Available Balance";
4300 + @override
4301 + String get trade_state_paid => "Pagado";
4302 + @override
4303 + String get node_new => "Nuevo nodo";
4304 + @override
4305 + String get trade_state_created => "Creado";
4306 + @override
4307 + String get faq => "FAQ";
4308 + @override
4309 + String get id => "ID: ";
4310 + @override
4311 + String get saved_the_trade_id => "He salvado comercial ID";
4312 + @override
4313 + String get settings_currency => "Moneda";
4314 + @override
4315 + String get change_language => "Cambiar idioma";
4316 + @override
4317 + String get wallet_name => "Nombre de la billetera";
4318 + @override
4319 + String get error_text_payment_id => "La ID de pago solo puede contener de 16 a 64 caracteres en hexadecimal";
4320 + @override
4321 + String get seed_alert_second_text => "Anótelos solo en caso de que pierda\no limpie su teléfono.";
4322 + @override
4323 + String get node_reset_settings_title => "Reiniciar ajustes";
4324 + @override
4325 + String get wallets => "Carteras";
4326 + @override
4327 + String get enter_your_pin_again => "Ingrese su PIN nuevamente";
4328 + @override
4329 + String get transactions => "Actas";
4330 + @override
4331 + String get amount_is_estimate => "El monto recibido es un estimado";
4332 + @override
4333 + String get error_text_node_address => "Por favor, introduzca una dirección iPv4";
4334 + @override
4335 + String get widgets_restore_from_date => "Restaurar desde fecha";
4336 + @override
4337 + String get restore_recover => "Recuperar";
4338 + @override
4339 + String get reset => "Reiniciar";
4340 + @override
4341 + String get new_wallet => "Nueva billetera";
4342 + @override
4343 + String get settings_display_on_dashboard_list => "Mostrar en la lista del tablero";
4344 + @override
4345 + String get transaction_details_title => "Detalles de la transacción";
4346 + @override
4347 + String get status => "Estado: ";
4348 + @override
4349 + String get restore_spend_key_private => "Spend clave (privado)";
4350 + @override
4351 + String get sync_status_syncronized => "SINCRONIZADO";
4352 + @override
4353 + String get transaction_priority_medium => "Medio";
4354 + @override
4355 + String get transaction_details_transaction_id => "ID de transacción";
4356 + @override
4357 + String get save => "Salvar";
4358 + @override
4359 + String get login => "Iniciar sesión";
4360 + @override
4361 + String get wallet_list_load_wallet => "Billetera de carga";
4362 + @override
4363 + String get sending => "Enviando";
4364 + @override
4365 + String get restore_restore_wallet => "Recuperar Cartera";
4366 + @override
4367 + String get restore_description_from_seed_keys => "Recupere su billetera de las semillas/claves que ha guardado en un lugar seguro";
4368 + @override
4369 + String get copy => "Dupdo";
4370 + @override
4371 + String get node_port => "Puerto de nodo";
4372 + @override
4373 + String get change_currency => "Cambiar moneda";
4374 + @override
4375 + String get transaction_details_amount => "Cantidad";
4376 + @override
4377 + String get widgets_address => "Dirección";
4378 + @override
4379 + String get contact_name => "Nombre de contacto";
4380 + @override
4381 + String get exchange_result_write_down_ID => "*Copie o escriba su identificación que se muestra arriba.";
4382 + @override
4383 + String get exchange_result_write_down_trade_id => "Por favor, copia o escribe el ID.";
4384 + @override
4385 + String get new_subaddress_title => "Nueva subdirección";
4386 + @override
4387 + String get change => "Cambio";
4388 + @override
4389 + String get seed_alert_first_text => "La siguiente página te mostrará \nuna semilla.";
4390 + @override
4391 + String get trade_state_finished => "Terminado";
4392 + @override
4393 + String get pin_is_incorrect => "PIN es incorrecto";
4394 + @override
4395 + String get trade_not_created => "Comercio no se crea.";
4396 + @override
4397 + String get restore_wallet_name => "Nombre de la billetera";
4398 + @override
4399 + String get widgets_seed => "Semilla";
4400 + @override
4401 + String get settings_fee_priority => "Prioridad de tasa";
4402 + @override
4403 + String get settings_personal => "Personal";
4404 + @override
4405 + String get seed_title => "Semilla";
4406 + @override
4407 + String get accounts => "Cuentas";
4408 + @override
4409 + String get rescan => "Reescanear";
4410 + @override
4411 + String get seed_alert_understand => "Entiendo";
4412 + @override
4413 + String get show_keys => "Mostrar llaves";
4414 + @override
4415 + String get error_text_fiat => "El valor de la cantidad no puede exceder el saldo disponible.\nEl número de dígitos de fracción debe ser menor o igual a 2";
4416 + @override
4417 + String get transactions_by_date => "Transacciones por fecha";
4418 + @override
4419 + String get use => "Utilizar ";
4420 + @override
4421 + String get trade_details_state => "Estado";
4422 + @override
4423 + String get spend_key_private => "Spend clave (privado)";
4424 + @override
4425 + String get settings_only_trades => "Solo comercia";
4426 + @override
4427 + String get trade_state_to_be_created => "Ser creado";
4428 + @override
4429 + String get all => "TODOS";
4430 + @override
4431 + String get xmr_full_balance => "XMR Saldo disponible";
4432 + @override
4433 + String get incoming => "Entrante";
4434 + @override
4435 + String get trade_history_title => "Historia del comercio";
4436 + @override
4437 + String get error_text_wallet_name => "El nombre de la billetera solo puede contener letras, números \ny debe tener entre 1 y 15 caracteres de longitud";
4438 + @override
4439 + String get restore_description_from_keys => "Restaure su billetera de las pulsaciones de teclas generadas\nguardadas de sus claves privadas";
4440 + @override
4441 + String get sent => "Expedido";
4442 + @override
4443 + String get view_key_public => "View clave (público)";
4444 + @override
4445 + String get trade_details_id => "ID";
4446 + @override
4447 + String get trade_state_confirming => "Confirmando";
4448 + @override
4449 + String get send => "Enviar";
4450 + @override
4451 + String get send_title => "Enviar Monero";
4452 + @override
4453 + String get error_text_keys => "Las llaves de billetera solo pueden contener 64 caracteres en hexadecimal";
4454 + @override
4455 + String get settings_save_recipient_address => "Guardar dirección del destinatario";
4456 + @override
4457 + String get seed_alert_settings => "de configuración";
4458 + @override
4459 + String get change_exchange_provider => "Cambiar proveedor de intercambio";
4460 + @override
4461 + String get send_payment_id => "ID de pago (opcional)";
4462 + @override
4463 + String get trade_details_title => "Detalles comerciales";
4464 + @override
4465 + String get settings_terms_and_conditions => "Términos y Condiciones";
4466 + @override
4467 + String get auth_store_ban_timeout => "prohibición de tiempo de espera";
4468 + @override
4469 + String get sync_status_connecting => "CONECTANDO";
4470 + @override
4471 + String get settings_transactions => "Transacciones";
4472 + @override
4473 + String get transaction_priority_fastest => "Lo más rápido";
4474 + @override
4475 + String get error => "Error";
4476 + @override
4477 + String get delete => "Borrar";
4478 + @override
4479 + String get sync_status_starting_sync => "EMPEZANDO A SINCRONIZAR";
4480 + @override
4481 + String get copied_to_clipboard => "Copiado al portapapeles";
4482 + @override
4483 + String get offer_expires_in => "Oferta expira en: ";
4484 + @override
4485 + String get continue_text => "Continuar";
4486 + @override
4487 + String get transaction_details_height => "Altura";
4488 + @override
4489 + String get wallet_menu => "Menú de billetera";
4490 + @override
4491 + String get settings_dark_mode => "Modo oscuro";
4492 + @override
4493 + String get payment_id => "ID de pago: ";
4494 + @override
4495 + String get restore_address => "Dirección";
4496 + @override
4497 + String get restore_wallet_restore_description => "Restaurar billetera";
4498 + @override
4499 + String get today => "Hoy";
4500 + @override
4501 + String get settings_support => "Apoyo";
4502 + @override
4503 + String get restore_wallet => "Restaurar billetera";
4504 + @override
4505 + String get ok => "OK";
4506 + @override
4507 + String get wallet_list_title => "Monedero Monero";
4508 + @override
4509 + String get authentication => "Autenticación";
4510 + @override
4511 + String get amount => "Cantidad: ";
4512 + @override
4513 + String get node_address => "Dirección de nodo";
4514 + @override
4515 + String get settings_change_language => "Cambiar idioma";
4516 + @override
4517 + String get clear => "Claro";
4518 + @override
4519 + String get settings_change_pin => "Cambiar PIN";
4520 + @override
4521 + String get trades => "Cambios";
4522 + @override
4523 + String get trade_state_btc_sent => "Btc expedido";
4524 + @override
4525 + String get address_book => "Libreta de direcciones";
4526 + @override
4527 + String get enter_your_pin => "Introduce tu PIN";
4528 + @override
4529 + String get wallet_list_restore_wallet => "Restaurar billetera";
4530 + @override
4531 + String get restore_title_from_seed => "De la semilla";
4532 + @override
4533 + String get restore_description_from_backup => "Puede restaurar toda la aplicación Cake Wallet desde \nysu archivo de respaldo";
4534 + @override
4535 + String get send_monero_address => "Dirección de Monero";
4536 + @override
4537 + String get error_text_node_port => "El puerto de nodo solo puede contener números entre 0 y 65535";
4538 + @override
4539 + String get digit_pin => "-dígito Pin";
4540 + @override
4541 + String get first_wallet_text => "Impresionante billetera\npara Monero";
4542 + @override
4543 + String get settings_trades => "Comercia";
4544 + @override
4545 + String get account => "Cuenta";
4546 + @override
4547 + String change_language_to(String language) => "Cambiar el idioma a ${language}?";
4548 + @override
4549 + String change_current_node(String node) => "¿Está seguro de cambiar el nodo actual a ${node}?";
4550 + @override
4551 + String trade_id(String id) => "Comercial ID:\n${id}";
4552 + @override
4553 + String wallet_list_loading_wallet(String wallet_name) => "Billetera ${wallet_name} de carga";
4554 + @override
4555 + String router_no_route(String name) => "No hay ruta definida para ${name}";
4556 + @override
4557 + String trade_id_not_found(String tradeId, String title) => "Comercio ${tradeId} de ${title} no encontrado.";
4558 + @override
4559 + String transaction_details_copied(String title) => "${title} Copiado al portapapeles";
4560 + @override
4561 + String trade_details_copied(String title) => "${title} Copiado al portapapeles";
4562 + @override
4563 + String powered_by(String title) => "Energizado por ${title}";
4564 + @override
4565 + String send_priority(String transactionPriority) => "Actualmente la tarifa se establece en ${transactionPriority} prioridad.\nLa prioridad de la transacción se puede ajustar en la configuración";
4566 + @override
4567 + String trade_for_not_created(String title) => "Comercio por ${title} no se crea.";
4568 + @override
4569 + String trade_is_powered_by(String provider) => "Este comercio es impulsado por ${provider}";
4570 + @override
4571 + String time(String minutes, String seconds) => "${minutes}m ${seconds}s";
4572 + @override
4573 + String max_value(String value, String currency) => "Max: ${value} ${currency}";
4574 + @override
4575 + String min_value(String value, String currency) => "Min: ${value} ${currency}";
4576 + @override
4577 + String failed_authentication(String state_error) => "Autenticación fallida. ${state_error}";
4578 + @override
4579 + String Blocks_remaining(String status) => "${status} Bloques restantes";
4580 + @override
4581 + String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "Al presionar confirmar, enviará ${fetchingLabel} ${from} desde su billetera llamada ${walletName} a la dirección que se muestra arriba. O puede enviar desde su billetera externa a la dirección / código QR anterior.\n\nPresione confirmar para continuar o regrese para cambiar los montos.\n\n";
4582 + @override
4583 + String exchange_result_description(String fetchingLabel, String from) => "Envíe ${fetchingLabel} ${from} a la dirección que se muestra arriba.\n\n'";
4584 + @override
4585 + String commit_transaction_amount_fee(String amount, String fee) => "Confirmar transacción\nCantidad: ${amount}\nCuota: ${fee}";
4586 + @override
4587 + String wallet_list_failed_to_remove(String wallet_name, String error) => "Error al elimina ${wallet_name} billetera. ${error}";
4588 + @override
4589 + String copied_key_to_clipboard(String key) => "Copiado ${key} al portapapeles";
4590 + @override
4591 + String wallet_list_failed_to_load(String wallet_name, String error) => "No se pudo cargar ${wallet_name} la billetera. ${error}";
4592 + @override
4593 + String wallet_list_removing_wallet(String wallet_name) => "Retirar ${wallet_name} billetera";
4594 +}
4595 +
4596 +class $nl extends S {
4597 + const $nl();
4598 +
4599 + @override
4600 + TextDirection get textDirection => TextDirection.ltr;
4601 +
4602 + @override
4603 + String get cancel => "Annuleer";
4604 + @override
4605 + String get trade_state_unpaid => "Onbetaald";
4606 + @override
4607 + String get authenticated => "Authenticated";
4608 + @override
4609 + String get new_subaddress_create => "Creëren";
4610 + @override
4611 + String get restore_view_key_private => "Bekijk sleutel (privaat)";
4612 + @override
4613 + String get transaction_priority_fast => "Snel";
4614 + @override
4615 + String get error_text_amount => "Bedrag kan alleen cijfers bevatten";
4616 + @override
4617 + String get hidden_balance => "Verborgen balans";
4618 + @override
4619 + String get transaction_sent => "Transactie verzonden!";
4620 + @override
4621 + String get password => "Wachtwoord";
4622 + @override
4623 + String get you_will_get => "Je zult krijgen";
4624 + @override
4625 + String get restore_description_from_seed => "Herstel uw portemonnee van het 25 woord\nof 13 woord combinatiecode";
4626 + @override
4627 + String get trade_state_underpaid => "Slecht betaald";
4628 + @override
4629 + String get welcome => "WELKOM\nBIJ CAKE WALLET";
4630 + @override
4631 + String get share_address => "Deel adres";
4632 + @override
4633 + String get please_try_to_connect_to_another_node => "Probeer verbinding te maken met een ander knooppunt";
4634 + @override
4635 + String get trade_state_traded => "Traded";
4636 + @override
4637 + String get edit => "Bewerk";
4638 + @override
4639 + String get spend_key_public => "Sleutel uitgeven (openbaar)";
4640 + @override
4641 + String get sync_status_syncronizing => "SYNCHRONISEREN";
4642 + @override
4643 + String get received => "Ontvangen";
4644 + @override
4645 + String get auth_store_banned_minutes => " notulen";
4646 + @override
4647 + String get restore_title_from_seed_keys => "Herstel van zaad / sleutels";
4648 + @override
4649 + String get settings_none => "Geen";
4650 + @override
4651 + String get wallet_list_create_new_wallet => "Maak een nieuwe portemonnee";
4652 + @override
4653 + String get seed_alert_third_text => "Je kunt het zaad ook weer zien\nin de ";
4654 + @override
4655 + String get setup_pin => "PIN instellen";
4656 + @override
4657 + String get transaction_details_recipient_address => "Adres van de ontvanger";
4658 + @override
4659 + String get receive_amount => "Bedrag";
4660 + @override
4661 + String get settings_allow_biometrical_authentication => "Biometrische authenticatie toestaan";
4662 + @override
4663 + String get view_key_private => "Bekijk sleutel (privaat)";
4664 + @override
4665 + String get restore_next => "Volgende";
4666 + @override
4667 + String get trade_state_trading => "Handel";
4668 + @override
4669 + String get error_text_address => "Portemonnee-adres moet overeenkomen met het type\nvan cryptocurrency";
4670 + @override
4671 + String get send_your_wallet => "Uw portemonnee";
4672 + @override
4673 + String get remove_node_message => "Weet u zeker dat u het geselecteerde knooppunt wilt verwijderen?";
4674 + @override
4675 + String get error_text_account_name => "Accountnaam mag alleen letters, cijfers bevatten\nen moet tussen de 1 en 15 tekens lang zijn";
4676 + @override
4677 + String get reconnection => "Reconnection";
4678 + @override
4679 + String get available_balance => "Beschikbaar saldo";
4680 + @override
4681 + String get restore_title_from_keys => "Herstel van sleutels";
4682 + @override
4683 + String get wallet_keys => "Portemonnee sleutels";
4684 + @override
4685 + String get reconnect => "Sluit";
4686 + @override
4687 + String get reconnect_alert_text => "Weet u zeker dat u opnieuw verbinding wilt maken?";
4688 + @override
4689 + String get send_error_minimum_value => "Minimale waarde van bedrag is 0,01";
4690 + @override
4691 + String get copy_address => "Adres kopiëren";
4692 + @override
4693 + String get error_text_subaddress_name => "Naam subadres mag niet bevatten ` , ' \" symbolen\nen moet tussen de 1 en 20 tekens lang zijn";
4694 + @override
4695 + String get settings_all => "ALLE";
4696 + @override
4697 + String get nodes_list_reset_to_default_message => "Weet u zeker dat u de standaardinstellingen wilt herstellen?";
4698 + @override
4699 + String get receive => "Krijgen";
4700 + @override
4701 + String get amount_is_guaranteed => "Het ontvangen bedrag is gegarandeerd";
4702 + @override
4703 + String get auth_store_banned_for => "Verboden voor ";
4704 + @override
4705 + String get trade_details_pair => "Paar";
4706 + @override
4707 + String get confirm => "Bevestigen";
4708 + @override
4709 + String get send_xmr => "Sturen XMR";
4710 + @override
4711 + String get settings_display_balance_as => "Toon saldo als";
4712 + @override
4713 + String get trade_details_provider => "Leverancier";
4714 + @override
4715 + String get you_will_send => "Je zal versturen";
4716 + @override
4717 + String get create_new => "Maak nieuw";
4718 + @override
4719 + String get trade_details_fetching => "Ophalen";
4720 + @override
4721 + String get seed_alert_menu => " menu.";
4722 + @override
4723 + String get confirm_sending => "Bevestig verzending";
4724 + @override
4725 + String get settings_title => "Instellingen";
4726 + @override
4727 + String get address_book_menu => "Adresboek";
4728 + @override
4729 + String get wallet_restoration_store_incorrect_seed_length => "Onjuiste zaadlengte";
4730 + @override
4731 + String get contact => "Contact";
4732 + @override
4733 + String get auth_store_incorrect_password => "Incorrect PIN";
4734 + @override
4735 + String get transaction_priority_slow => "Langzaam";
4736 + @override
4737 + String get add => "Toevoegen";
4738 + @override
4739 + String get remove_node => "Knoop verwijderen";
4740 + @override
4741 + String get trade_state_paid_unconfirmed => "Niet bevestigd";
4742 + @override
4743 + String get please_select => "Selecteer alstublieft:";
4744 + @override
4745 + String get restore_title_from_backup => "Herstellen vanuit een back-upbestand";
4746 + @override
4747 + String get full_balance => "Volledig saldo";
4748 + @override
4749 + String get sync_status_not_connected => "NIET VERBONDEN";
4750 + @override
4751 + String get error_text_crypto_currency => "Het aantal breukcijfers\nmoet kleiner zijn dan of gelijk zijn aan 12";
4752 + @override
4753 + String get error_text_contact_name => "Naam contactpersoon kan niet bevatten ` , ' \" symbolen\nen moet tussen de 1 en 32 tekens lang zijn";
4754 + @override
4755 + String get restore_seed_keys_restore => "Zaad / sleutels herstellen";
4756 + @override
4757 + String get xmr_hidden => "XMR Verborgen";
4758 + @override
4759 + String get exchange => "Uitwisseling";
4760 + @override
4761 + String get sync_status_failed_connect => "MISLUKT VERBINDING MET DE NODE";
4762 + @override
4763 + String get send_estimated_fee => "Geschatte vergoeding:";
4764 + @override
4765 + String get outgoing => "Uitgaande";
4766 + @override
4767 + String get sync_status_connected => "VERBONDEN";
4768 + @override
4769 + String get trade_state_pending => "In afwachting";
4770 + @override
4771 + String get pending => " (in afwachting)";
4772 + @override
4773 + String get setup_successful => "Uw PIN is succesvol ingesteld!";
4774 + @override
4775 + String get fetching => "Ophalen";
4776 + @override
4777 + String get settings_nodes => "knooppunten";
4778 + @override
4779 + String get widgets_or => "of";
4780 + @override
4781 + String get remove => "Verwijderen";
4782 + @override
4783 + String get yesterday => "Gisteren";
4784 + @override
4785 + String get expired => "Verlopen";
4786 + @override
4787 + String get transaction_priority_regular => "Regelmatig";
4788 + @override
4789 + String get trade_details_created_at => "Gemaakt bij";
4790 + @override
4791 + String get settings_wallets => "Portemonnee";
4792 + @override
4793 + String get settings_only_transactions => "Alleen transacties";
4794 + @override
4795 + String get estimated => "Geschatte";
4796 + @override
4797 + String get filters => "Filters";
4798 + @override
4799 + String get settings_current_node => "Huidige knooppunt";
4800 + @override
4801 + String get copy_id => "ID kopiëren";
4802 + @override
4803 + String get please_make_selection => "Maak hieronder uw keuze tot\nmaak of herstel je portemonnee.";
4804 + @override
4805 + String get loading_your_wallet => "Uw portemonnee laden";
4806 + @override
4807 + String get subaddresses => "Subadressen";
4808 + @override
4809 + String get trade_state_timeout => "Time-out";
4810 + @override
4811 + String get nodes => "Knooppunten";
4812 + @override
4813 + String get seed_share => "Deel zaad";
4814 + @override
4815 + String get widgets_restore_from_blockheight => "Herstel vanaf blockheight";
4816 + @override
4817 + String get new_subaddress_label_name => "Label naam";
4818 + @override
4819 + String get trade_not_found => "Handel niet gevonden.";
4820 + @override
4821 + String get transaction_details_date => "Datum";
4822 + @override
4823 + String get show_seed => "Toon zaad";
4824 + @override
4825 + String get send_error_currency => "Valuta kan alleen cijfers bevatten";
4826 + @override
4827 + String get subaddress_title => "Subadreslijst";
4828 + @override
4829 + String get wallet_store_monero_wallet => "Monero portemonnee";
4830 + @override
4831 + String get send_creating_transaction => "Transactie maken";
4832 + @override
4833 + String get trade_state_complete => "Compleet";
4834 + @override
4835 + String get error_text_xmr => "XMR-waarde kan het beschikbare saldo niet overschrijden.\nHet aantal breukcijfers moet kleiner zijn dan of gelijk zijn aan 12";
4836 + @override
4837 + String get xmr_available_balance => "XMR Beschikbaar saldo";
4838 + @override
4839 + String get trade_state_paid => "Betaald";
4840 + @override
4841 + String get node_new => "Nieuw knooppunt";
4842 + @override
4843 + String get trade_state_created => "Gemaakt";
4844 + @override
4845 + String get faq => "FAQ";
4846 + @override
4847 + String get id => "ID: ";
4848 + @override
4849 + String get saved_the_trade_id => "Ik heb de ruil-ID opgeslagen";
4850 + @override
4851 + String get settings_currency => "Valuta";
4852 + @override
4853 + String get change_language => "Verander de taal";
4854 + @override
4855 + String get wallet_name => "Portemonnee naam";
4856 + @override
4857 + String get error_text_payment_id => "Betalings-ID kan alleen 16 tot 64 tekens bevatten in hexadecimale volgorde";
4858 + @override
4859 + String get seed_alert_second_text => "Noteer deze voor het geval dat\nje verliest of veegt je telefoon.";
4860 + @override
4861 + String get node_reset_settings_title => "Reset instellingen";
4862 + @override
4863 + String get wallets => "Portefeuilles";
4864 + @override
4865 + String get enter_your_pin_again => "Voer uw PIN opnieuw in";
4866 + @override
4867 + String get transactions => "Transacties";
4868 + @override
4869 + String get amount_is_estimate => "Het ontvangen bedrag is een schatting";
4870 + @override
4871 + String get error_text_node_address => "Voer een iPv4-adres in";
4872 + @override
4873 + String get widgets_restore_from_date => "Herstel vanaf datum";
4874 + @override
4875 + String get restore_recover => "Herstellen";
4876 + @override
4877 + String get reset => "Reset";
4878 + @override
4879 + String get new_wallet => "Nieuwe portemonnee";
4880 + @override
4881 + String get settings_display_on_dashboard_list => "Weergeven op dashboardlijst";
4882 + @override
4883 + String get transaction_details_title => "Transactie details";
4884 + @override
4885 + String get status => "Staat: ";
4886 + @override
4887 + String get restore_spend_key_private => "Sleutel uitgeven (privaat)";
4888 + @override
4889 + String get sync_status_syncronized => "SYNCHRONIZED";
4890 + @override
4891 + String get transaction_priority_medium => "Medium";
4892 + @override
4893 + String get transaction_details_transaction_id => "Transactie ID";
4894 + @override
4895 + String get save => "Opslaan";
4896 + @override
4897 + String get login => "Log in";
4898 + @override
4899 + String get wallet_list_load_wallet => "Portemonnee laden";
4900 + @override
4901 + String get sending => "Bezig met verzenden";
4902 + @override
4903 + String get restore_restore_wallet => "Portemonnee herstellen";
4904 + @override
4905 + String get restore_description_from_seed_keys => "Ontvang uw portemonnee terug uit seed / keys die u hebt opgeslagen op een veilige plaats";
4906 + @override
4907 + String get copy => "Kopiëren";
4908 + @override
4909 + String get node_port => "Knooppunt poort";
4910 + @override
4911 + String get change_currency => "Verander valuta";
4912 + @override
4913 + String get transaction_details_amount => "Bedrag";
4914 + @override
4915 + String get widgets_address => "Adres";
4916 + @override
4917 + String get contact_name => "Contactnaam";
4918 + @override
4919 + String get exchange_result_write_down_ID => "*Kopieer of noteer uw hierboven getoonde ID.";
4920 + @override
4921 + String get exchange_result_write_down_trade_id => "Kopieer of noteer de handels-ID om door te gaan.";
4922 + @override
4923 + String get new_subaddress_title => "Nieuw subadres";
4924 + @override
4925 + String get change => "Verandering";
4926 + @override
4927 + String get seed_alert_first_text => "De volgende pagina wordt getoond\njij een zaadje.";
4928 + @override
4929 + String get trade_state_finished => "Afgewerkt";
4930 + @override
4931 + String get pin_is_incorrect => "PIN is onjuist";
4932 + @override
4933 + String get trade_not_created => "Handel niet gecreëerd.";
4934 + @override
4935 + String get restore_wallet_name => "Portemonnee naam";
4936 + @override
4937 + String get widgets_seed => "Zaad";
4938 + @override
4939 + String get settings_fee_priority => "Tariefprioriteit";
4940 + @override
4941 + String get settings_personal => "Persoonlijk";
4942 + @override
4943 + String get seed_title => "Zaad";
4944 + @override
4945 + String get accounts => "Accounts";
4946 + @override
4947 + String get rescan => "Opnieuw scannen";
4948 + @override
4949 + String get seed_alert_understand => "Ik begrijp het";
4950 + @override
4951 + String get show_keys => "Toon sleutels";
4952 + @override
4953 + String get error_text_fiat => "Waarde van bedrag kan het beschikbare saldo niet overschrijden.\nHet aantal breukcijfers moet kleiner zijn dan of gelijk zijn aan 2";
4954 + @override
4955 + String get transactions_by_date => "Transacties op datum";
4956 + @override
4957 + String get use => "Gebruik ";
4958 + @override
4959 + String get trade_details_state => "Staat";
4960 + @override
4961 + String get spend_key_private => "Sleutel uitgeven (privaat)";
4962 + @override
4963 + String get settings_only_trades => "Alleen handel";
4964 + @override
4965 + String get trade_state_to_be_created => "Om gecreëerd te worden";
4966 + @override
4967 + String get all => "ALLE";
4968 + @override
4969 + String get xmr_full_balance => "XMR Volledig saldo";
4970 + @override
4971 + String get incoming => "inkomend";
4972 + @override
4973 + String get trade_history_title => "Handelsgeschiedenis";
4974 + @override
4975 + String get error_text_wallet_name => "Naam portemonnee kan alleen letters, cijfers bevatten\nen moet tussen de 1 en 15 tekens lang zijn";
4976 + @override
4977 + String get restore_description_from_keys => "Herstel uw portemonnee van gegenereerd\ntoetsaanslagen opgeslagen van uw privésleutels";
4978 + @override
4979 + String get sent => "Verzonden";
4980 + @override
4981 + String get view_key_public => "Bekijk sleutel (openbaar)";
4982 + @override
4983 + String get trade_details_id => "ID";
4984 + @override
4985 + String get trade_state_confirming => "Bevestiging";
4986 + @override
4987 + String get send => "Sturen";
4988 + @override
4989 + String get send_title => "Stuur Monero";
4990 + @override
4991 + String get error_text_keys => "Portefeuillesleutels kunnen maximaal 64 tekens bevatten in hexadecimale volgorde";
4992 + @override
4993 + String get settings_save_recipient_address => "Adres ontvanger opslaan";
4994 + @override
4995 + String get seed_alert_settings => "instellingen";
4996 + @override
4997 + String get change_exchange_provider => "Wijzig Exchange Provider";
4998 + @override
4999 + String get send_payment_id => "Betaling ID (facultatief)";

This file is too large to show in full.

lib/main.dart new
+215
@@ -0,0 +1,215 @@
1 +import 'package:flutter_localizations/flutter_localizations.dart';
2 +import 'package:path_provider/path_provider.dart';
3 +import 'package:shared_preferences/shared_preferences.dart';
4 +import 'package:flutter_secure_storage/flutter_secure_storage.dart';
5 +import 'package:provider/provider.dart';
6 +import 'package:flutter/material.dart';
7 +import 'package:flutter/services.dart';
8 +import 'package:hive/hive.dart';
9 +import 'package:cw_monero/wallet.dart' as moneroWallet;
10 +import 'package:cake_wallet/router.dart';
11 +import 'theme_changer.dart';
12 +import 'themes.dart';
13 +import 'package:cake_wallet/src/domain/common/get_encryption_key.dart';
14 +import 'package:cake_wallet/src/domain/common/contact.dart';
15 +import 'package:cake_wallet/src/domain/common/node.dart';
16 +import 'package:cake_wallet/src/domain/common/wallet_info.dart';
17 +import 'package:cake_wallet/src/domain/exchange/trade.dart';
18 +import 'package:cake_wallet/src/domain/monero/transaction_description.dart';
19 +import 'package:cake_wallet/src/reactions/set_reactions.dart';
20 +import 'package:cake_wallet/src/stores/login/login_store.dart';
21 +import 'package:cake_wallet/src/stores/balance/balance_store.dart';
22 +import 'package:cake_wallet/src/stores/sync/sync_store.dart';
23 +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
24 +import 'package:cake_wallet/src/screens/root/root.dart';
25 +import 'package:cake_wallet/src/stores/authentication/authentication_store.dart';
26 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
27 +import 'package:cake_wallet/src/stores/price/price_store.dart';
28 +import 'package:cake_wallet/src/domain/services/user_service.dart';
29 +import 'package:cake_wallet/src/domain/services/wallet_list_service.dart';
30 +import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
31 +import 'package:cake_wallet/src/domain/common/default_settings_migration.dart';
32 +import 'package:cake_wallet/src/domain/common/fiat_currency.dart';
33 +import 'package:cake_wallet/src/domain/common/transaction_priority.dart';
34 +import 'package:cake_wallet/src/domain/common/wallet_type.dart';
35 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
36 +import 'package:cake_wallet/generated/i18n.dart';
37 +import 'package:cake_wallet/src/domain/common/language.dart';
38 +
39 +void main() async {
40 + WidgetsFlutterBinding.ensureInitialized();
41 +
42 + var appDir = await getApplicationDocumentsDirectory();
43 + Hive.init(appDir.path);
44 + Hive.registerAdapter(ContactAdapter(), 0);
45 + Hive.registerAdapter(NodeAdapter(), 1);
46 + Hive.registerAdapter(TransactionDescriptionAdapter(), 2);
47 + Hive.registerAdapter(TradeAdapter(), 3);
48 + Hive.registerAdapter(WalletInfoAdapter(), 4);
49 + Hive.registerAdapter(WalletTypeAdapter(), 5);
50 +
51 + final secureStorage = FlutterSecureStorage();
52 + final transactionDescriptionsBoxKey = await getEncryptionKey(
53 + secureStorage: secureStorage, forKey: 'transactionDescriptionsBoxKey'); // FIXME: Unnamed constant
54 + final tradesBoxKey = await getEncryptionKey(
55 + secureStorage: secureStorage, forKey: 'tradesBoxKey'); // FIXME: Unnamed constant
56 +
57 + var contacts = await Hive.openBox<Contact>(Contact.boxName);
58 + var nodes = await Hive.openBox<Node>(Node.boxName);
59 + var transactionDescriptions = await Hive.openBox<TransactionDescription>(
60 + TransactionDescription.boxName,
61 + encryptionKey: transactionDescriptionsBoxKey);
62 + var trades =
63 + await Hive.openBox<Trade>(Trade.boxName, encryptionKey: tradesBoxKey);
64 + var walletInfoSource = await Hive.openBox<WalletInfo>(WalletInfo.boxName);
65 +
66 + final sharedPreferences = await SharedPreferences.getInstance();
67 + final walletService = WalletService();
68 + final walletListService = WalletListService(
69 + secureStorage: secureStorage,
70 + walletInfoSource: walletInfoSource,
71 + walletService: walletService,
72 + sharedPreferences: sharedPreferences);
73 + final userService = UserService(
74 + sharedPreferences: sharedPreferences, secureStorage: secureStorage);
75 + final authenticationStore = AuthenticationStore(userService: userService);
76 +
77 + await initialSetup(
78 + sharedPreferences: sharedPreferences,
79 + walletListService: walletListService,
80 + nodes: nodes,
81 + authStore: authenticationStore);
82 +
83 + final settingsStore = await SettingsStoreBase.load(
84 + nodes: nodes,
85 + sharedPreferences: sharedPreferences,
86 + initialFiatCurrency: FiatCurrency.usd,
87 + initialTransactionPriority: TransactionPriority.slow,
88 + initialBalanceDisplayMode: BalanceDisplayMode.availableBalance);
89 + final priceStore = PriceStore();
90 + final walletStore =
91 + WalletStore(walletService: walletService, settingsStore: settingsStore);
92 + final syncStore = SyncStore(walletService: walletService);
93 + final balanceStore = BalanceStore(
94 + walletService: walletService,
95 + settingsStore: settingsStore,
96 + priceStore: priceStore);
97 + final loginStore = LoginStore(
98 + sharedPreferences: sharedPreferences, walletsService: walletListService);
99 +
100 + setReactions(
101 + settingsStore: settingsStore,
102 + priceStore: priceStore,
103 + syncStore: syncStore,
104 + walletStore: walletStore,
105 + walletService: walletService,
106 + authenticationStore: authenticationStore,
107 + loginStore: loginStore);
108 +
109 + runApp(MultiProvider(providers: [
110 + Provider(create: (_) => sharedPreferences),
111 + Provider(create: (_) => walletService),
112 + Provider(create: (_) => walletListService),
113 + Provider(create: (_) => userService),
114 + Provider(create: (_) => settingsStore),
115 + Provider(create: (_) => priceStore),
116 + Provider(create: (_) => walletStore),
117 + Provider(create: (_) => syncStore),
118 + Provider(create: (_) => balanceStore),
119 + Provider(create: (_) => authenticationStore),
120 + Provider(create: (_) => contacts),
121 + Provider(create: (_) => nodes),
122 + Provider(create: (_) => transactionDescriptions),
123 + Provider(create: (_) => trades)
124 + ], child: CakeWalletApp()));
125 +}
126 +
127 +initialSetup(
128 + {WalletListService walletListService,
129 + SharedPreferences sharedPreferences,
130 + Box<Node> nodes,
131 + AuthenticationStore authStore,
132 + int initialMigrationVersion = 1,
133 + WalletType initialWalletType = WalletType.monero}) async {
134 + await walletListService.changeWalletManger(walletType: initialWalletType);
135 + await defaultSettingsMigration(
136 + version: initialMigrationVersion,
137 + sharedPreferences: sharedPreferences,
138 + nodes: nodes);
139 + await authStore.started();
140 + moneroWallet.onStartup();
141 +}
142 +
143 +class CakeWalletApp extends StatelessWidget {
144 + CakeWalletApp() {
145 + SystemChrome.setPreferredOrientations(
146 + [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
147 + }
148 +
149 + @override
150 + Widget build(BuildContext context) {
151 + final settingsStore = Provider.of<SettingsStore>(context);
152 +
153 + return ChangeNotifierProvider<ThemeChanger>(
154 + create: (_) => ThemeChanger(
155 + settingsStore.isDarkTheme ? Themes.darkTheme : Themes.lightTheme),
156 + child: ChangeNotifierProvider<Language>(
157 + create: (_) => Language(settingsStore.languageCode),
158 + child: MaterialAppWithTheme()));
159 + }
160 +}
161 +
162 +class MaterialAppWithTheme extends StatelessWidget {
163 + @override
164 + Widget build(BuildContext context) {
165 + final sharedPreferences = Provider.of<SharedPreferences>(context);
166 + final walletService = Provider.of<WalletService>(context);
167 + final walletListService = Provider.of<WalletListService>(context);
168 + final userService = Provider.of<UserService>(context);
169 + final settingsStore = Provider.of<SettingsStore>(context);
170 + final priceStore = Provider.of<PriceStore>(context);
171 + final walletStore = Provider.of<WalletStore>(context);
172 + final syncStore = Provider.of<SyncStore>(context);
173 + final balanceStore = Provider.of<BalanceStore>(context);
174 + final theme = Provider.of<ThemeChanger>(context);
175 + final statusBarColor =
176 + settingsStore.isDarkTheme ? Colors.black : Colors.white;
177 + final currentLanguage = Provider.of<Language>(context);
178 + final contacts = Provider.of<Box<Contact>>(context);
179 + final nodes = Provider.of<Box<Node>>(context);
180 + final trades = Provider.of<Box<Trade>>(context);
181 + final transactionDescriptions =
182 + Provider.of<Box<TransactionDescription>>(context);
183 +
184 + SystemChrome.setSystemUIOverlayStyle(
185 + SystemUiOverlayStyle(statusBarColor: statusBarColor));
186 +
187 + return MaterialApp(
188 + debugShowCheckedModeBanner: false,
189 + theme: theme.getTheme(),
190 + localizationsDelegates: [
191 + S.delegate,
192 + GlobalCupertinoLocalizations.delegate,
193 + GlobalMaterialLocalizations.delegate,
194 + GlobalWidgetsLocalizations.delegate,
195 + ],
196 + supportedLocales: S.delegate.supportedLocales,
197 + locale: Locale(currentLanguage.getCurrentLanguage()),
198 + onGenerateRoute: (settings) => Router.generateRoute(
199 + sharedPreferences: sharedPreferences,
200 + walletListService: walletListService,
201 + walletService: walletService,
202 + userService: userService,
203 + settings: settings,
204 + priceStore: priceStore,
205 + walletStore: walletStore,
206 + syncStore: syncStore,
207 + balanceStore: balanceStore,
208 + settingsStore: settingsStore,
209 + contacts: contacts,
210 + nodes: nodes,
211 + trades: trades,
212 + transactionDescriptions: transactionDescriptions),
213 + home: Root());
214 + }
215 +}
lib/palette.dart new
+72
@@ -0,0 +1,72 @@
1 +import 'package:flutter/material.dart';
2 +
3 +class Palette {
4 + static const Color lightBlue = Color.fromRGBO(126, 147, 177, 1.0);
5 + static const Color lightBlueWithOpacity = Color.fromRGBO(126, 147, 177, 0.4);
6 + static const Color lightGrey = Color.fromRGBO(224, 233, 246, 1.0);
7 + static const Color purple = Color.fromRGBO(243, 229, 245, 1.0);
8 + static const Color deepPink = Color.fromRGBO(225, 190, 231, 1.0);
9 + static const Color indigo = Color.fromRGBO(232, 234, 246, 1.0);
10 + static const Color deepIndigo = Color.fromRGBO(197, 202, 233, 1.0);
11 + static const Color creamyGrey = Color.fromRGBO(245, 246, 249, 1.0);
12 + static const Color deepPurple = Color.fromRGBO(124, 83, 240, 1.0);
13 + static const Color wildDarkBlue = Color.fromRGBO(155, 172, 197, 1.0);
14 + static const Color wildDarkBlueWithOpacity = Color.fromRGBO(155, 172, 197, 0.1);
15 + static const Color lightGreen = Color.fromRGBO(52, 186, 204, 1.0);
16 + static const Color darkPurple = Color.fromRGBO(124, 83, 240, 1.0);
17 + static const Color brightBlue = Color.fromRGBO(151, 226, 255, 0.6);
18 + static const Color cloudySky = Color.fromRGBO(121, 201, 233, 0.8);
19 + static const Color darkGrey = Color.fromRGBO(136, 155, 183, 0.21);
20 + static const Color shadowGrey = Color.fromRGBO(132, 141, 198, 0.14);
21 + static const Color shadowGreyWithOpacity = Color.fromRGBO(132, 141, 198, 0.05);
22 + static const Color blueGrey = Color.fromRGBO(103, 107, 141, 1.0);
23 + static const Color lightGrey2 = Color.fromRGBO(249, 249, 249, 1.0);
24 + static const Color violet = Color.fromRGBO(138, 80, 255, 1.0);
25 + static const Color lightViolet = Color.fromRGBO(131, 87, 255, 1);
26 + static const Color cakeGreen = Color.fromRGBO(41, 187, 244, 1.0);
27 + static const Color cakeGreenWithOpacity = Color.fromRGBO(41, 187, 244, 0.2);
28 + static const Color switchBackground = Color.fromRGBO(228, 231, 240, 1.0);
29 + static const Color switchBorder = Color.fromRGBO(211, 222, 238, 1.0);
30 + static const Color green = Color.fromRGBO(39, 206, 80, 1.0);
31 + static const Color red = Color.fromRGBO(255, 51, 51, 1.0);
32 + static const Color nightBlue = Color.fromRGBO(34, 40, 75, 1.0);
33 + static const Color lavender = Color.fromRGBO(249, 250, 253, 1);
34 + static const Color lightLavender = Color.fromRGBO(242, 244, 247, 1);
35 + static const Color cadetBlue = Color.fromRGBO(191, 201, 215, 1);
36 + static const Color manatee = Color.fromRGBO(138, 153, 175, 1);
37 + static const Color separator = Color.fromRGBO(240, 241, 244, 1);
38 + static const Color containerLavender = Color.fromRGBO(226, 235, 238, 0.4);
39 + static const Color purpleBlue = Color.fromRGBO(84, 92, 139, 1);
40 + static const Color floatingActionButton = Color.fromRGBO(213, 56, 99, 1);
41 + static const Color failure = Color.fromRGBO(226, 35, 35, 1);
42 + static const Color powered = Color.fromRGBO(191, 201, 215, 1);
43 + static const Color buttonShadow = Color.fromRGBO(23, 46, 77, 0.129207);
44 +}
45 +
46 +class PaletteDark {
47 + static const Color darkThemeTitle = Color.fromRGBO(132, 154, 186, 1.0);
48 + static const Color darkThemeTitleViolet = Color.fromRGBO(121, 92, 190, 1.0);
49 + static const Color darkThemeGrey = Color.fromRGBO(100, 115, 137, 1.0);
50 + static const Color darkThemeGreyWithOpacity = Color.fromRGBO(100, 115, 137, 0.5);
51 + static const Color darkThemeMidGrey = Color.fromRGBO(20, 26, 38, 1.0);
52 + static const Color darkThemePurpleButton = Color.fromRGBO(182, 143, 255, 0.1);
53 + static const Color darkThemePurpleButtonBorder = Color.fromRGBO(161, 120, 255, 0.7);
54 + static const Color darkThemeBackground = Color.fromRGBO(39, 41, 50, 1.0);
55 + static const Color darkThemeBackgroundDark = Color.fromRGBO(9, 12, 18, 1.0);
56 + static const Color darkThemeDarkGrey = Color.fromRGBO(218, 228, 243, 0.06);
57 + static const Color darkGrey = Color.fromRGBO(218, 228, 243, 0.4);
58 + static const Color darkThemeBlackWithOpacity = Color.fromRGBO(0, 0, 0, 0.2);
59 + static const Color darkThemeBlack = Color.fromRGBO(7, 10, 14, 1.0);
60 + static const Color darkThemeAppBarBlack = Color.fromRGBO(4, 5, 7, 1.0);
61 + static const Color darkThemeViolet = Color.fromRGBO(131, 87, 255, 0.2);
62 + static const Color darkThemeIndigoButton = Color.fromRGBO(216, 223, 246, 0.1);
63 + static const Color darkThemeIndigoButtonBorder = Color.fromRGBO(196, 206, 237, 0.4);
64 + static const Color darkThemeBlueButton = Color.fromRGBO(151, 226, 255, 0.1);
65 + static const Color darkThemeBlueButtonBorder = Color.fromRGBO(62, 190, 240, 0.6);
66 + static const Color darkThemeCloseButton = Color.fromRGBO(34, 40, 74, 1.0);
67 + static const Color darkThemePinButton = Color.fromRGBO(136, 155, 183, 0.1);
68 + static const Color darkThemePinDigitButton = Color.fromRGBO(100, 115, 137, 0.34);
69 + static const Color switchBackground = Color.fromRGBO(100, 115, 137, 0.4);
70 + static const Color wildDarkBlueWithOpacity = Color.fromRGBO(155, 172, 197, 0.4);
71 + static const Color wildDarkBlue = Color.fromRGBO(155, 172, 197, 0.8);
72 +}
\ No newline at end of file
lib/router.dart new
+477
@@ -0,0 +1,477 @@
1 +import 'package:flutter/cupertino.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:flutter_secure_storage/flutter_secure_storage.dart';
4 +import 'package:shared_preferences/shared_preferences.dart';
5 +import 'package:provider/provider.dart';
6 +import 'package:hive/hive.dart';
7 +import 'package:cake_wallet/routes.dart';
8 +import 'package:cake_wallet/generated/i18n.dart';
9 +
10 +// MARK: Import domains
11 +
12 +import 'package:cake_wallet/src/domain/common/contact.dart';
13 +import 'package:cake_wallet/src/domain/services/user_service.dart';
14 +import 'package:cake_wallet/src/domain/services/wallet_list_service.dart';
15 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
16 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
17 +import 'package:cake_wallet/src/domain/exchange/changenow/changenow_exchange_provider.dart';
18 +import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart';
19 +import 'package:cake_wallet/src/domain/common/node.dart';
20 +import 'package:cake_wallet/src/domain/monero/transaction_description.dart';
21 +import 'package:cake_wallet/src/domain/exchange/trade.dart';
22 +
23 +// MARK: Import stores
24 +
25 +import 'package:cake_wallet/src/stores/authentication/authentication_store.dart';
26 +import 'package:cake_wallet/src/stores/node_list/node_list_store.dart';
27 +import 'package:cake_wallet/src/stores/auth/auth_store.dart';
28 +import 'package:cake_wallet/src/stores/balance/balance_store.dart';
29 +import 'package:cake_wallet/src/stores/send/send_store.dart';
30 +import 'package:cake_wallet/src/stores/subaddress_creation/subaddress_creation_store.dart';
31 +import 'package:cake_wallet/src/stores/subaddress_list/subaddress_list_store.dart';
32 +import 'package:cake_wallet/src/stores/sync/sync_store.dart';
33 +import 'package:cake_wallet/src/stores/user/user_store.dart';
34 +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
35 +import 'package:cake_wallet/src/stores/wallet_creation/wallet_creation_store.dart';
36 +import 'package:cake_wallet/src/stores/wallet_list/wallet_list_store.dart';
37 +import 'package:cake_wallet/src/stores/wallet_restoration/wallet_restoration_store.dart';
38 +import 'package:cake_wallet/src/stores/account_list/account_list_store.dart';
39 +import 'package:cake_wallet/src/stores/address_book/address_book_store.dart';
40 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
41 +import 'package:cake_wallet/src/stores/wallet/wallet_keys_store.dart';
42 +import 'package:cake_wallet/src/stores/exchange_trade/exchange_trade_store.dart';
43 +import 'package:cake_wallet/src/stores/exchange/exchange_store.dart';
44 +import 'package:cake_wallet/src/stores/rescan/rescan_wallet_store.dart';
45 +import 'package:cake_wallet/src/stores/price/price_store.dart';
46 +
47 +// MARK: Import screens
48 +
49 +import 'package:cake_wallet/src/screens/auth/auth_page.dart';
50 +import 'package:cake_wallet/src/screens/nodes/new_node_page.dart';
51 +import 'package:cake_wallet/src/screens/nodes/nodes_list_page.dart';
52 +import 'package:cake_wallet/src/screens/receive/receive_page.dart';
53 +import 'package:cake_wallet/src/screens/subaddress/new_subaddress_page.dart';
54 +import 'package:cake_wallet/src/screens/wallet_list/wallet_list_page.dart';
55 +import 'package:cake_wallet/src/screens/new_wallet/new_wallet_page.dart';
56 +import 'package:cake_wallet/src/screens/setup_pin_code/setup_pin_code.dart';
57 +import 'package:cake_wallet/src/screens/restore/restore_options_page.dart';
58 +import 'package:cake_wallet/src/screens/restore/restore_wallet_options_page.dart';
59 +import 'package:cake_wallet/src/screens/restore/restore_wallet_from_seed_page.dart';
60 +import 'package:cake_wallet/src/screens/restore/restore_wallet_from_keys_page.dart';
61 +import 'package:cake_wallet/src/screens/send/send_page.dart';
62 +import 'package:cake_wallet/src/screens/disclaimer/disclaimer_page.dart';
63 +import 'package:cake_wallet/src/screens/seed_alert/seed_alert.dart';
64 +import 'package:cake_wallet/src/screens/transaction_details/transaction_details_page.dart';
65 +import 'package:cake_wallet/src/screens/accounts/account_page.dart';
66 +import 'package:cake_wallet/src/screens/accounts/account_list_page.dart';
67 +import 'package:cake_wallet/src/screens/address_book/address_book_page.dart';
68 +import 'package:cake_wallet/src/screens/address_book/contact_page.dart';
69 +import 'package:cake_wallet/src/screens/show_keys/show_keys_page.dart';
70 +import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dart';
71 +import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_page.dart';
72 +import 'package:cake_wallet/src/screens/subaddress/subaddress_list_page.dart';
73 +import 'package:cake_wallet/src/screens/settings/change_language.dart';
74 +import 'package:cake_wallet/src/screens/restore/restore_wallet_from_seed_details.dart';
75 +import 'package:cake_wallet/src/screens/exchange/exchange_page.dart';
76 +import 'package:cake_wallet/src/screens/settings/settings.dart';
77 +import 'package:cake_wallet/src/screens/rescan/rescan_page.dart';
78 +import 'package:cake_wallet/src/screens/faq/faq_page.dart';
79 +import 'package:cake_wallet/src/screens/trade_details/trade_details_page.dart';
80 +import 'package:cake_wallet/src/screens/auth/create_unlock_page.dart';
81 +import 'package:cake_wallet/src/screens/auth/create_login_page.dart';
82 +import 'package:cake_wallet/src/screens/seed/create_seed_page.dart';
83 +import 'package:cake_wallet/src/screens/dashboard/create_dashboard_page.dart';
84 +import 'package:cake_wallet/src/screens/welcome/create_welcome_page.dart';
85 +
86 +class Router {
87 + static Route<dynamic> generateRoute(
88 + {SharedPreferences sharedPreferences,
89 + WalletListService walletListService,
90 + WalletService walletService,
91 + UserService userService,
92 + RouteSettings settings,
93 + PriceStore priceStore,
94 + WalletStore walletStore,
95 + SyncStore syncStore,
96 + BalanceStore balanceStore,
97 + SettingsStore settingsStore,
98 + Box<Contact> contacts,
99 + Box<Node> nodes,
100 + Box<TransactionDescription> transactionDescriptions,
101 + Box<Trade> trades}) {
102 + switch (settings.name) {
103 + case Routes.welcome:
104 + return MaterialPageRoute(builder: (_) => createWelcomePage());
105 +
106 + case Routes.newWalletFromWelcome:
107 + return CupertinoPageRoute(
108 + builder: (_) => Provider(
109 + create: (_) => UserStore(
110 + accountService: UserService(
111 + secureStorage: FlutterSecureStorage(),
112 + sharedPreferences: sharedPreferences)),
113 + child: SetupPinCodePage(
114 + onPinCodeSetup: (context, _) =>
115 + Navigator.pushNamed(context, Routes.newWallet))));
116 +
117 + case Routes.newWallet:
118 + return CupertinoPageRoute(
119 + builder:
120 + (_) =>
121 + ProxyProvider<AuthenticationStore, WalletCreationStore>(
122 + update: (_, authStore, __) => WalletCreationStore(
123 + authStore: authStore,
124 + sharedPreferences: sharedPreferences,
125 + walletListService: walletListService),
126 + child: NewWalletPage(
127 + walletsService: walletListService,
128 + walletService: walletService,
129 + sharedPreferences: sharedPreferences)));
130 +
131 + case Routes.setupPin:
132 + Function(BuildContext, String) callback;
133 +
134 + if (settings.arguments is Function(BuildContext, String)) {
135 + callback = settings.arguments;
136 + }
137 +
138 + return CupertinoPageRoute(
139 + builder: (_) => Provider(
140 + create: (_) => UserStore(
141 + accountService: UserService(
142 + secureStorage: FlutterSecureStorage(),
143 + sharedPreferences: sharedPreferences)),
144 + child: SetupPinCodePage(
145 + onPinCodeSetup: (context, pin) =>
146 + callback == null ? null : callback(context, pin))),
147 + fullscreenDialog: true);
148 +
149 + case Routes.restoreOptions:
150 + return CupertinoPageRoute(builder: (_) => RestoreOptionsPage());
151 +
152 + case Routes.restoreWalletOptions:
153 + return CupertinoPageRoute(builder: (_) => RestoreWalletOptionsPage());
154 +
155 + case Routes.restoreWalletOptionsFromWelcome:
156 + return CupertinoPageRoute(
157 + builder: (_) => Provider(
158 + create: (_) => UserStore(
159 + accountService: UserService(
160 + secureStorage: FlutterSecureStorage(),
161 + sharedPreferences: sharedPreferences)),
162 + child: SetupPinCodePage(
163 + onPinCodeSetup: (context, _) => Navigator.pushNamed(
164 + context, Routes.restoreWalletOptions))));
165 +
166 + case Routes.seed:
167 + return MaterialPageRoute(
168 + builder: (_) => createSeedPage(
169 + settingsStore: settingsStore,
170 + walletService: walletService,
171 + callback: settings.arguments));
172 +
173 + case Routes.restoreWalletFromSeed:
174 + return CupertinoPageRoute(
175 + builder: (_) =>
176 + ProxyProvider<AuthenticationStore, WalletRestorationStore>(
177 + update: (_, authStore, __) => WalletRestorationStore(
178 + authStore: authStore,
179 + sharedPreferences: sharedPreferences,
180 + walletListService: walletListService),
181 + child: RestoreWalletFromSeedPage(
182 + walletsService: walletListService,
183 + walletService: walletService,
184 + sharedPreferences: sharedPreferences)));
185 +
186 + case Routes.restoreWalletFromKeys:
187 + return CupertinoPageRoute(
188 + builder: (_) =>
189 + ProxyProvider<AuthenticationStore, WalletRestorationStore>(
190 + update: (_, authStore, __) => WalletRestorationStore(
191 + authStore: authStore,
192 + sharedPreferences: sharedPreferences,
193 + walletListService: walletListService),
194 + child: RestoreWalletFromKeysPage(
195 + walletsService: walletListService,
196 + walletService: walletService,
197 + sharedPreferences: sharedPreferences)));
198 +
199 + case Routes.dashboard:
200 + return CupertinoPageRoute(
201 + builder: (_) => createDashboardPage(
202 + walletService: walletService,
203 + priceStore: priceStore,
204 + settingsStore: settingsStore,
205 + trades: trades,
206 + transactionDescriptions: transactionDescriptions,
207 + walletStore: walletStore));
208 +
209 + case Routes.send:
210 + return CupertinoPageRoute(
211 + fullscreenDialog: true,
212 + builder: (_) => MultiProvider(providers: [
213 + ProxyProvider<SettingsStore, BalanceStore>(
214 + update: (_, settingsStore, __) => BalanceStore(
215 + walletService: walletService,
216 + settingsStore: settingsStore,
217 + priceStore: priceStore),
218 + ),
219 + Provider(
220 + create: (_) => SyncStore(walletService: walletService),
221 + ),
222 + Provider(
223 + create: (_) => SendStore(
224 + walletService: walletService,
225 + priceStore: priceStore,
226 + transactionDescriptions: transactionDescriptions)),
227 + ], child: SendPage()));
228 +
229 + case Routes.receive:
230 + return CupertinoPageRoute(
231 + fullscreenDialog: true,
232 + builder: (_) => MultiProvider(providers: [
233 + Provider(
234 + create: (_) =>
235 + SubaddressListStore(walletService: walletService))
236 + ], child: ReceivePage()));
237 +
238 + case Routes.transactionDetails:
239 + return CupertinoPageRoute(
240 + fullscreenDialog: true,
241 + builder: (_) =>
242 + TransactionDetailsPage(transactionInfo: settings.arguments));
243 +
244 + case Routes.newSubaddress:
245 + return CupertinoPageRoute(
246 + builder: (_) => Provider(
247 + create: (_) =>
248 + SubadrressCreationStore(walletService: walletService),
249 + child: NewSubaddressPage()));
250 +
251 + case Routes.disclaimer:
252 + return CupertinoPageRoute(builder: (_) => DisclaimerPage());
253 +
254 + case Routes.readDisclaimer:
255 + return CupertinoPageRoute(
256 + builder: (_) => DisclaimerPage(isReadOnly: true));
257 +
258 + case Routes.seedAlert:
259 + return CupertinoPageRoute(builder: (_) => SeedAlert());
260 +
261 + case Routes.walletList:
262 + return MaterialPageRoute(
263 + fullscreenDialog: true,
264 + builder: (_) => Provider(
265 + create: (_) => WalletListStore(
266 + walletListService: walletListService,
267 + walletService: walletService),
268 + child: WalletListPage()));
269 +
270 + case Routes.auth:
271 + return MaterialPageRoute(
272 + fullscreenDialog: true,
273 + builder: (_) => Provider(
274 + create: (_) => AuthStore(
275 + sharedPreferences: sharedPreferences,
276 + userService: userService,
277 + walletService: walletService),
278 + child: AuthPage(onAuthenticationFinished: settings.arguments),
279 + ));
280 +
281 + case Routes.unlock:
282 + return MaterialPageRoute(
283 + fullscreenDialog: true,
284 + builder: (_) => createUnlockPage(
285 + sharedPreferences: sharedPreferences,
286 + userService: userService,
287 + walletService: walletService,
288 + onAuthenticationFinished: settings.arguments));
289 +
290 + case Routes.nodeList:
291 + return CupertinoPageRoute(builder: (context) {
292 + return Provider(
293 + create: (_) => NodeListStore(nodesSource: nodes),
294 + child: NodeListPage());
295 + });
296 +
297 + case Routes.newNode:
298 + return CupertinoPageRoute(
299 + builder: (_) => Provider<NodeListStore>(
300 + create: (_) => NodeListStore(nodesSource: nodes),
301 + child: NewNodePage()));
302 +
303 + case Routes.login:
304 + return CupertinoPageRoute(builder: (context) {
305 + final authenticationStore = Provider.of<AuthenticationStore>(context);
306 +
307 + return createLoginPage(
308 + sharedPreferences: sharedPreferences,
309 + userService: userService,
310 + walletService: walletService,
311 + walletListService: walletListService,
312 + authenticationStore: authenticationStore);
313 + });
314 +
315 + case Routes.accountList:
316 + return MaterialPageRoute(
317 + builder: (context) {
318 + return MultiProvider(providers: [
319 + Provider(
320 + create: (_) =>
321 + AccountListStore(walletService: walletService)),
322 + ], child: AccountListPage());
323 + },
324 + fullscreenDialog: true);
325 +
326 + case Routes.accountCreation:
327 + return CupertinoPageRoute(builder: (context) {
328 + return Provider(
329 + create: (_) => AccountListStore(walletService: walletService),
330 + child: AccountPage(account: settings.arguments));
331 + });
332 +
333 + case Routes.addressBook:
334 + return MaterialPageRoute(builder: (context) {
335 + return MultiProvider(
336 + providers: [
337 + Provider(
338 + create: (_) =>
339 + AccountListStore(walletService: walletService)),
340 + Provider(create: (_) => AddressBookStore(contacts: contacts))
341 + ],
342 + child: AddressBookPage(),
343 + );
344 + });
345 +
346 + case Routes.pickerAddressBook:
347 + return MaterialPageRoute(builder: (context) {
348 + return MultiProvider(
349 + providers: [
350 + Provider(
351 + create: (_) =>
352 + AccountListStore(walletService: walletService)),
353 + Provider(create: (_) => AddressBookStore(contacts: contacts))
354 + ],
355 + child: AddressBookPage(isEditable: false),
356 + );
357 + });
358 +
359 + case Routes.addressBookAddContact:
360 + return CupertinoPageRoute(builder: (context) {
361 + return MultiProvider(
362 + providers: [
363 + Provider(
364 + create: (_) =>
365 + AccountListStore(walletService: walletService)),
366 + Provider(create: (_) => AddressBookStore(contacts: contacts))
367 + ],
368 + child: ContactPage(contact: settings.arguments),
369 + );
370 + });
371 +
372 + case Routes.showKeys:
373 + return MaterialPageRoute(
374 + builder: (context) {
375 + return Provider(
376 + create: (_) => WalletKeysStore(walletService: walletService),
377 + child: ShowKeysPage(),
378 + );
379 + },
380 + fullscreenDialog: true);
381 +
382 + case Routes.exchangeTrade:
383 + return CupertinoPageRoute(
384 + builder: (_) => MultiProvider(
385 + providers: [
386 + ProxyProvider<SettingsStore, ExchangeTradeStore>(
387 + update: (_, settingsStore, __) => ExchangeTradeStore(
388 + trade: settings.arguments, walletStore: walletStore),
389 + ),
390 + ProxyProvider<SettingsStore, SendStore>(
391 + update: (_, settingsStore, __) => SendStore(
392 + transactionDescriptions: transactionDescriptions,
393 + walletService: walletService,
394 + settingsStore: settingsStore,
395 + priceStore: priceStore)),
396 + ],
397 + child: ExchangeTradePage(),
398 + ));
399 +
400 + case Routes.exchangeConfirm:
401 + return MaterialPageRoute(
402 + builder: (_) => ExchangeConfirmPage(trade: settings.arguments));
403 +
404 + case Routes.tradeDetails:
405 + return MaterialPageRoute(builder: (context) {
406 + return MultiProvider(providers: [
407 + ProxyProvider<SettingsStore, ExchangeTradeStore>(
408 + update: (_, settingsStore, __) => ExchangeTradeStore(
409 + trade: settings.arguments, walletStore: walletStore),
410 + )
411 + ], child: TradeDetailsPage());
412 + });
413 +
414 + case Routes.subaddressList:
415 + return MaterialPageRoute(
416 + builder: (_) => MultiProvider(providers: [
417 + Provider(
418 + create: (_) =>
419 + SubaddressListStore(walletService: walletService))
420 + ], child: SubaddressListPage()));
421 +
422 + case Routes.restoreWalletFromSeedDetails:
423 + return CupertinoPageRoute(
424 + builder: (_) =>
425 + ProxyProvider<AuthenticationStore, WalletRestorationStore>(
426 + update: (_, authStore, __) => WalletRestorationStore(
427 + authStore: authStore,
428 + sharedPreferences: sharedPreferences,
429 + walletListService: walletListService,
430 + seed: settings.arguments),
431 + child: RestoreWalletFromSeedDetailsPage()));
432 + case Routes.exchange:
433 + return MaterialPageRoute(
434 + builder: (_) => MultiProvider(providers: [
435 + Provider(create: (_) {
436 + final xmrtoprovider = XMRTOExchangeProvider();
437 +
438 + return ExchangeStore(
439 + initialProvider: xmrtoprovider,
440 + initialDepositCurrency: CryptoCurrency.xmr,
441 + initialReceiveCurrency: CryptoCurrency.btc,
442 + trades: trades,
443 + providerList: [
444 + xmrtoprovider,
445 + ChangeNowExchangeProvider()
446 + ],
447 + walletStore: walletStore);
448 + }),
449 + ], child: ExchangePage()));
450 +
451 + case Routes.settings:
452 + return MaterialPageRoute(
453 + builder: (_) => Provider(
454 + create: (_) => NodeListStore(nodesSource: nodes),
455 + child: SettingsPage()));
456 +
457 + case Routes.rescan:
458 + return MaterialPageRoute(
459 + builder: (_) => Provider(
460 + create: (_) => RescanWalletStore(walletService: walletService),
461 + child: RescanPage()));
462 +
463 + case Routes.faq:
464 + return MaterialPageRoute(builder: (_) => FaqPage());
465 +
466 + case Routes.changeLanguage:
467 + return MaterialPageRoute(builder: (_) => ChangeLanguage());
468 +
469 + default:
470 + return MaterialPageRoute(
471 + builder: (_) => Scaffold(
472 + body: Center(
473 + child: Text(S.current.router_no_route(settings.name))),
474 + ));
475 + }
476 + }
477 +}
lib/routes.dart new
+47
@@ -0,0 +1,47 @@
1 +class Routes {
2 + static const welcome = '/welcome';
3 + static const newWallet = '/new_wallet';
4 + static const setupPin = '/setup_pin_code';
5 + static const newWalletFromWelcome = '/new_wallet_from_welcome';
6 + static const restoreFromWelcome = '/restore_from_welcome';
7 + static const seed = '/seed';
8 + static const restoreOptions = '/restore_options';
9 + static const restoreOptionsFromWelcome = '/restore_options_from_welcome';
10 + static const restoreWalletOptions = '/restore_seed_keys';
11 + static const restoreWalletOptionsFromWelcome = '/restore_wallet_options_from_welcome';
12 + static const restoreWalletFromSeed = '/restore_wallet_from_seed';
13 + static const restoreWalletFromKeys = '/restore_wallet_from_keys';
14 + static const dashboard = '/dashboard';
15 + static const send = '/send';
16 + static const transactionDetails = '/transaction_info';
17 + static const receive = '/receive';
18 + static const newSubaddress = '/new_subaddress';
19 + static const disclaimer = '/disclaimer';
20 + static const readDisclaimer = '/read_disclaimer';
21 + static const seedAlert = '/seed_alert';
22 + static const walletList = '/wallet_list';
23 + static const auth = '/auth';
24 + static const nodeList = '/node_list';
25 + static const newNode = '/new_node_list';
26 + static const login = '/login';
27 + static const splash = '/splash';
28 + static const accountList = '/account_list';
29 + static const accountCreation = '/account_new';
30 + static const addressBook = '/address_book';
31 + static const pickerAddressBook = '/picker_address_book';
32 + static const addressBookAddContact = '/address_book_add_contact';
33 + static const showKeys = '/show_keys';
34 + static const exchangeConfirm = '/exchange_confirm';
35 + static const tradeHistory = '/trade_history';
36 + static const tradeDetails = '/trade_details';
37 + static const exchangeFunds = '/exchange_funds';
38 + static const exchangeTrade = '/exchange_trade';
39 + static const subaddressList = '/subaddress_list';
40 + static const restoreWalletFromSeedDetails = '/restore_from_seed_details';
41 + static const exchange = '/exchange';
42 + static const settings = '/settings';
43 + static const unlock = '/auth_not_closable';
44 + static const rescan = '/rescan';
45 + static const faq = '/faq';
46 + static const changeLanguage = '/change_language';
47 +}
\ No newline at end of file
lib/src/domain/common/balance.dart new
+1
@@ -0,0 +1 @@
1 +abstract class Balance {}
\ No newline at end of file
lib/src/domain/common/balance_display_mode.dart new
+46
@@ -0,0 +1,46 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:cake_wallet/generated/i18n.dart';
3 +import 'package:cake_wallet/src/domain/common/enumerable_item.dart';
4 +
5 +class BalanceDisplayMode extends EnumerableItem<int> with Serializable<int> {
6 + static const all = [
7 + BalanceDisplayMode.fullBalance,
8 + BalanceDisplayMode.availableBalance,
9 + BalanceDisplayMode.hiddenBalance
10 + ];
11 + static const fullBalance = BalanceDisplayMode(raw: 0, title: 'Full Balance');
12 + static const availableBalance =
13 + BalanceDisplayMode(raw: 1, title: 'Available Balance');
14 + static const hiddenBalance =
15 + BalanceDisplayMode(raw: 2, title: 'Hidden Balance');
16 +
17 + static BalanceDisplayMode deserialize({int raw}) {
18 + switch (raw) {
19 + case 0:
20 + return fullBalance;
21 + case 1:
22 + return availableBalance;
23 + case 2:
24 + return hiddenBalance;
25 + default:
26 + return null;
27 + }
28 + }
29 +
30 + const BalanceDisplayMode({@required String title, @required int raw})
31 + : super(title: title, raw: raw);
32 +
33 + @override
34 + String toString() {
35 + switch (this) {
36 + case BalanceDisplayMode.fullBalance:
37 + return S.current.xmr_full_balance;
38 + case BalanceDisplayMode.availableBalance:
39 + return S.current.xmr_available_balance;
40 + case BalanceDisplayMode.hiddenBalance:
41 + return S.current.xmr_hidden;
42 + default:
43 + return '';
44 + }
45 + }
46 +}
lib/src/domain/common/calculate_estimated_fee.dart new
+25
@@ -0,0 +1,25 @@
1 +import 'package:cake_wallet/src/domain/common/transaction_priority.dart';
2 +
3 +double calculateEstimatedFee({TransactionPriority priority}) {
4 + if (priority == TransactionPriority.slow) {
5 + return 0.00002459;
6 + }
7 +
8 + if (priority == TransactionPriority.regular) {
9 + return 0.00012305;
10 + }
11 +
12 + if (priority == TransactionPriority.medium) {
13 + return 0.00024503;
14 + }
15 +
16 + if (priority == TransactionPriority.fast) {
17 + return 0.00061453;
18 + }
19 +
20 + if (priority == TransactionPriority.fastest) {
21 + return 0.0260216;
22 + }
23 +
24 + return 0;
25 +}
\ No newline at end of file
lib/src/domain/common/calculate_fiat_amount.dart new
+14
@@ -0,0 +1,14 @@
1 +String calculateFiatAmount({double price, String cryptoAmount}) {
2 + if (price == null || cryptoAmount == null) {
3 + return '0.00';
4 + }
5 +
6 + final _amount = double.parse(cryptoAmount);
7 + final result = price * _amount;
8 +
9 + if (result == 0.0) {
10 + return '0.00';
11 + }
12 +
13 + return result > 0.01 ? result.toStringAsFixed(2) : '< 0.01';
14 +}
\ No newline at end of file
lib/src/domain/common/calculate_fiat_amount_raw.dart new
+13
@@ -0,0 +1,13 @@
1 +String calculateFiatAmountRaw({double price, double cryptoAmount}) {
2 + if (price == null) {
3 + return '0.00';
4 + }
5 +
6 + final result = price * cryptoAmount;
7 +
8 + if (result == 0.0) {
9 + return '0.00';
10 + }
11 +
12 + return result > 0.01 ? result.toStringAsFixed(2) : '< 0.01';
13 +}
\ No newline at end of file
lib/src/domain/common/contact.dart new
+30
@@ -0,0 +1,30 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:hive/hive.dart';
3 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
4 +
5 +part 'contact.g.dart';
6 +
7 +@HiveType()
8 +class Contact extends HiveObject {
9 + static const boxName = 'Contacts';
10 +
11 + @HiveField(0)
12 + String name;
13 +
14 + @HiveField(1)
15 + String address;
16 +
17 + @HiveField(2)
18 + int raw;
19 +
20 + CryptoCurrency get type => CryptoCurrency.deserialize(raw: raw);
21 +
22 + Contact(
23 + {@required this.name,
24 + @required this.address,
25 + CryptoCurrency type})
26 + : raw = type?.raw;
27 +
28 + updateCryptoCurrency({@required CryptoCurrency currency}) =>
29 + raw = currency.raw;
30 +}
lib/src/domain/common/crypto_currency.dart new
+66
@@ -0,0 +1,66 @@
1 +import 'package:cake_wallet/src/domain/common/enumerable_item.dart';
2 +import 'package:hive/hive.dart';
3 +
4 +part 'crypto_currency.g.dart';
5 +
6 +@HiveType()
7 +class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
8 + static const all = [
9 + CryptoCurrency.xmr,
10 + CryptoCurrency.btc,
11 + CryptoCurrency.eth,
12 + CryptoCurrency.ltc,
13 + CryptoCurrency.bch,
14 + CryptoCurrency.dash
15 + ];
16 + static const xmr = CryptoCurrency(title: 'XMR', raw: 0);
17 + static const btc = CryptoCurrency(title: 'BTC', raw: 1);
18 + static const eth = CryptoCurrency(title: 'ETH', raw: 2);
19 + static const ltc = CryptoCurrency(title: 'LTC', raw: 3);
20 + static const bch = CryptoCurrency(title: 'BCH', raw: 4);
21 + static const dash = CryptoCurrency(title: 'DASH', raw: 5);
22 +
23 + static CryptoCurrency deserialize({int raw}) {
24 + switch (raw) {
25 + case 0:
26 + return xmr;
27 + case 1:
28 + return btc;
29 + case 2:
30 + return eth;
31 + case 3:
32 + return ltc;
33 + case 4:
34 + return bch;
35 + case 5:
36 + return dash;
37 + default:
38 + return null;
39 + }
40 + }
41 +
42 + static CryptoCurrency fromString(String raw) {
43 + switch (raw.toLowerCase()) {
44 + case 'xmr':
45 + return xmr;
46 + case 'btc':
47 + return btc;
48 + case 'eth':
49 + return eth;
50 + case 'ltc':
51 + return ltc;
52 + case 'bch':
53 + return bch;
54 + case 'dash':
55 + return dash;
56 + default:
57 + return null;
58 + }
59 + }
60 +
61 + const CryptoCurrency({final String title, final int raw})
62 + : super(title: title, raw: raw);
63 +
64 + @override
65 + String toString() => title;
66 +}
lib/src/domain/common/currency_formatter.dart new
+10
@@ -0,0 +1,10 @@
1 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
2 +
3 +String cryptoToString(CryptoCurrency crypto) {
4 + switch (crypto) {
5 + case CryptoCurrency.xmr:
6 + return 'XMR';
7 + default:
8 + return '';
9 + }
10 +}
\ No newline at end of file
lib/src/domain/common/default_settings_migration.dart new
+46
@@ -0,0 +1,46 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:hive/hive.dart';
3 +import 'package:shared_preferences/shared_preferences.dart';
4 +import 'package:cake_wallet/src/domain/common/node.dart';
5 +import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
6 +import 'package:cake_wallet/src/domain/common/fiat_currency.dart';
7 +import 'package:cake_wallet/src/domain/common/node_list.dart';
8 +import 'package:cake_wallet/src/domain/common/transaction_priority.dart';
9 +
10 +Future defaultSettingsMigration(
11 + {@required int version,
12 + @required SharedPreferences sharedPreferences,
13 + @required Box<Node> nodes}) async {
14 + int currentVersion =
15 + sharedPreferences.getInt('current_default_settings_migration_version') ??
16 + 0;
17 +
18 + if (currentVersion >= version) {
19 + return;
20 + }
21 +
22 + try {
23 + switch (version) {
24 + case 1:
25 + sharedPreferences.setString(
26 + 'current_fiat_currency', FiatCurrency.usd.toString());
27 + sharedPreferences.setInt(
28 + 'current_fee_priority', TransactionPriority.standart.raw);
29 + sharedPreferences.setInt('current_balance_display_mode',
30 + BalanceDisplayMode.availableBalance.raw);
31 + sharedPreferences.setInt(
32 + 'current_default_settings_migration_version', 1);
33 + sharedPreferences.setBool('save_recipient_address', false);
34 + await resetToDefault(nodes);
35 + sharedPreferences.setInt('current_node_id', 0);
36 + break;
37 + default:
38 + break;
39 + }
40 + } catch (e) {
41 + print('Migration error: ${e.toString()}');
42 + }
43 +
44 + sharedPreferences.setInt(
45 + 'current_default_settings_migration_version', version);
46 +}
lib/src/domain/common/digest_request.dart new
+102
@@ -0,0 +1,102 @@
1 +import 'dart:convert';
2 +import 'package:dio/dio.dart' as Dio;
3 +import 'package:crypto/crypto.dart' as crypto;
4 +import 'dart:math' as math;
5 +
6 +class DigestRequest {
7 + final md5 = crypto.md5;
8 +
9 + String generateCnonce() {
10 + final rnd = math.Random.secure();
11 + var values = List<int>.generate(32, (i) => rnd.nextInt(256));
12 + return base64Url.encode(values).substring(0, 8);
13 + }
14 +
15 + String generateHA1({String realm, String username, String password}) {
16 + final ha1CredentialsData =
17 + Utf8Encoder().convert('$username:$realm:$password');
18 + final ha1 = md5.convert(ha1CredentialsData).toString();
19 +
20 + return ha1;
21 + }
22 +
23 + String generateHA2({String method, String uri}) {
24 + final ha2Data = Utf8Encoder().convert('$method:$uri');
25 + final ha2 = md5.convert(ha2Data).toString();
26 +
27 + return ha2;
28 + }
29 +
30 + String generateResponseString(
31 + {String ha1,
32 + String ha2,
33 + String nonce,
34 + String nonceCount,
35 + String cnonce,
36 + String qop}) {
37 + final responseData =
38 + Utf8Encoder().convert('$ha1:$nonce:$nonceCount:$cnonce:$qop:$ha2');
39 + final response = md5.convert(responseData).toString();
40 +
41 + return response;
42 + }
43 +
44 + Map<String, String> parsetAuthorizationHeader({String source}) {
45 + final authHeaderParts =
46 + source.substring(7).split(',').map((item) => item.trim());
47 + var authenticate = Map<String, String>();
48 +
49 + for (final part in authHeaderParts) {
50 + final kv = part.split('=');
51 + authenticate[kv[0]] =
52 + kv.getRange(1, kv.length).join('=').replaceAll('"', '');
53 + }
54 +
55 + return authenticate;
56 + }
57 +
58 + Future<Dio.Response> request(
59 + {String uri, String login, String password}) async {
60 + final path = '/json_rpc';
61 + final method = 'POST';
62 + final url = Uri.http(uri, path);
63 + final dio = Dio.Dio();
64 +
65 + Map<String, String> headers = {'Content-type': 'application/json'};
66 + String body =
67 + json.encode({"jsonrpc": "2.0", "id": "0", "method": "get_info"});
68 +
69 + var credentialsResponse = await dio.post(url.toString(),
70 + options: Dio.Options(headers: headers, validateStatus: (_) => true));
71 + var resHeaeders = credentialsResponse.headers;
72 + final authenticate =
73 + parsetAuthorizationHeader(source: resHeaeders['www-authenticate'].first);
74 + final qop = authenticate['qop'];
75 + final algorithm = 'MD5';
76 + final realm = 'monero-rpc';
77 + final nonce = authenticate['nonce'];
78 + final cnonce = generateCnonce();
79 +
80 + var nonceCount = '00000001';
81 +
82 + final ha1 = generateHA1(realm: realm, username: login, password: password);
83 + final ha2 = generateHA2(method: method, uri: path);
84 + final response = generateResponseString(
85 + ha1: ha1,
86 + ha2: ha2,
87 + nonce: nonce,
88 + nonceCount: nonceCount,
89 + cnonce: cnonce,
90 + qop: qop);
91 +
92 + final authorizationHeaders = {
93 + 'Content-type': 'application/json',
94 + 'Authorization':
95 + 'Digest username="$login",realm="$realm",nonce="$nonce",uri="$path",algorithm="$algorithm",qop=$qop,nc=$nonceCount,cnonce="$cnonce",response="$response"'
96 + };
97 +
98 + final res = await dio.post(url.toString(),
99 + options: Dio.Options(headers: authorizationHeaders), data: body);
100 + return res;
101 + }
102 +}
\ No newline at end of file
lib/src/domain/common/encrypt.dart new
+54
@@ -0,0 +1,54 @@
1 +import 'package:encrypt/encrypt.dart';
2 +import 'package:password/password.dart';
3 +import 'package:cake_wallet/.secrets.g.dart' as secrets;
4 +
5 +String encrypt({String source, String key, int keyLength = 16}) {
6 + final _key = Key.fromUtf8(key);
7 + final iv = IV.fromLength(keyLength);
8 + final encrypter = Encrypter(AES(_key));
9 + final encrypted = encrypter.encrypt(source, iv: iv);
10 +
11 + return encrypted.base64;
12 +}
13 +
14 +String decrypt({String source, String key, int keyLength = 16}) {
15 + final _key = Key.fromUtf8(key);
16 + final iv = IV.fromLength(keyLength);
17 + final encrypter = Encrypter(AES(_key));
18 + final decrypted = encrypter.decrypt64(source, iv: iv);
19 +
20 + return decrypted;
21 +}
22 +
23 +String hash({String source}) {
24 + final algorithm = PBKDF2();
25 + final hash = Password.hash(source, algorithm);
26 +
27 + return hash;
28 +}
29 +
30 +String encodedPinCode({String pin}) {
31 + final source = '${secrets.salt}$pin';
32 +
33 + return encrypt(source: source, key: secrets.key);
34 +}
35 +
36 +String decodedPinCode({String pin}) {
37 + final decrypted = decrypt(source: pin, key: secrets.key);
38 +
39 + return decrypted.substring(secrets.key.length, decrypted.length);
40 +}
41 +
42 +String encodeWalletPassword({String password}) {
43 + final source = password;
44 + final _key = secrets.shortKey + secrets.walletSalt;
45 +
46 + return encrypt(source: source, key: _key);
47 +}
48 +
49 +String decodeWalletPassword({String password}) {
50 + final source = password;
51 + final _key = secrets.shortKey + secrets.walletSalt;
52 +
53 + return decrypt(source: source, key: _key);
54 +}
lib/src/domain/common/enumerable_item.dart new
+16
@@ -0,0 +1,16 @@
1 +import 'package:flutter/foundation.dart';
2 +
3 +abstract class EnumerableItem<T> {
4 + final T raw;
5 + final String title;
6 +
7 + const EnumerableItem({@required this.title, @required this.raw});
8 +
9 + @override
10 + String toString() => title;
11 +}
12 +
13 +mixin Serializable<T> on EnumerableItem<T> {
14 + static Serializable deserialize<T>({T raw}) => null;
15 + T serialize() => raw;
16 +}
lib/src/domain/common/fetch_price.dart new
+37
@@ -0,0 +1,37 @@
1 +import 'dart:convert';
2 +import 'package:http/http.dart';
3 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
4 +import 'package:cake_wallet/src/domain/common/fiat_currency.dart';
5 +import 'package:cake_wallet/src/domain/common/currency_formatter.dart';
6 +
7 +const fiatApiAuthority = 'fiat-api.cakewallet.com';
8 +const fiatApiPath = '/v1/rates';
9 +
10 +Future<double> fetchPriceFor({CryptoCurrency crypto, FiatCurrency fiat}) async {
11 + double price = 0.0;
12 +
13 + try {
14 + final fiatStringified = fiat.toString();
15 + final uri =
16 + Uri.https(fiatApiAuthority, fiatApiPath, {'convert': fiatStringified});
17 + final response = await get(uri.toString());
18 +
19 + if (response.statusCode != 200) {
20 + return 0.0;
21 + }
22 +
23 + final responseJSON = json.decode(response.body);
24 + final data = responseJSON['data'];
25 +
26 + for (final item in data) {
27 + if (item['symbol'] == cryptoToString(crypto)) {
28 + price = item['quote'][fiatStringified]['price'];
29 + break;
30 + }
31 + }
32 +
33 + return price;
34 + } catch (e) {
35 + return price;
36 + }
37 +}
lib/src/domain/common/fiat_currency.dart new
+80
@@ -0,0 +1,80 @@
1 +import 'package:cake_wallet/src/domain/common/enumerable_item.dart';
2 +
3 +class FiatCurrency extends EnumerableItem<String> with Serializable<String> {
4 + static const all = [
5 + FiatCurrency.aud,
6 + FiatCurrency.bgn,
7 + FiatCurrency.brl,
8 + FiatCurrency.cad,
9 + FiatCurrency.chf,
10 + FiatCurrency.cny,
11 + FiatCurrency.czk,
12 + FiatCurrency.eur,
13 + FiatCurrency.dkk,
14 + FiatCurrency.gbp,
15 + FiatCurrency.hkd,
16 + FiatCurrency.hrk,
17 + FiatCurrency.huf,
18 + FiatCurrency.idr,
19 + FiatCurrency.ils,
20 + FiatCurrency.inr,
21 + FiatCurrency.isk,
22 + FiatCurrency.jpy,
23 + FiatCurrency.krw,
24 + FiatCurrency.mxn,
25 + FiatCurrency.myr,
26 + FiatCurrency.nok,
27 + FiatCurrency.nzd,
28 + FiatCurrency.php,
29 + FiatCurrency.pln,
30 + FiatCurrency.ron,
31 + FiatCurrency.rub,
32 + FiatCurrency.sek,
33 + FiatCurrency.sgd,
34 + FiatCurrency.thb,
35 + FiatCurrency.usd,
36 + FiatCurrency.zar,
37 + FiatCurrency.vef
38 + ];
39 +
40 + static const aud = FiatCurrency(symbol: 'AUD');
41 + static const bgn = FiatCurrency(symbol: 'BGN');
42 + static const brl = FiatCurrency(symbol: 'BRL');
43 + static const cad = FiatCurrency(symbol: 'CAD');
44 + static const chf = FiatCurrency(symbol: 'CHF');
45 + static const cny = FiatCurrency(symbol: 'CNY');
46 + static const czk = FiatCurrency(symbol: 'CZK');
47 + static const eur = FiatCurrency(symbol: 'EUR');
48 + static const dkk = FiatCurrency(symbol: 'DKK');
49 + static const gbp = FiatCurrency(symbol: 'GBP');
50 + static const hkd = FiatCurrency(symbol: 'HKD');
51 + static const hrk = FiatCurrency(symbol: 'HRK');
52 + static const huf = FiatCurrency(symbol: 'HUF');
53 + static const idr = FiatCurrency(symbol: 'IDR');
54 + static const ils = FiatCurrency(symbol: 'ILS');
55 + static const inr = FiatCurrency(symbol: 'INR');
56 + static const isk = FiatCurrency(symbol: 'ISK');
57 + static const jpy = FiatCurrency(symbol: 'JPY');
58 + static const krw = FiatCurrency(symbol: 'KRW');
59 + static const mxn = FiatCurrency(symbol: 'MXN');
60 + static const myr = FiatCurrency(symbol: 'MYR');
61 + static const nok = FiatCurrency(symbol: 'NOK');
62 + static const nzd = FiatCurrency(symbol: 'NZD');
63 + static const php = FiatCurrency(symbol: 'PHP');
64 + static const pln = FiatCurrency(symbol: 'PLN');
65 + static const ron = FiatCurrency(symbol: 'RON');
66 + static const rub = FiatCurrency(symbol: 'RUB');
67 + static const sek = FiatCurrency(symbol: 'SEK');
68 + static const sgd = FiatCurrency(symbol: 'SGD');
69 + static const thb = FiatCurrency(symbol: 'THB');
70 + static const usd = FiatCurrency(symbol: 'USD');
71 + static const zar = FiatCurrency(symbol: 'ZAR');
72 + static const vef = FiatCurrency(symbol: 'VEF');
73 +
74 + const FiatCurrency({String symbol}) : super(title: symbol, raw: symbol);
75 +
76 + operator ==(o) => o is FiatCurrency && o.raw == raw;
77 +
78 + @override
79 + int get hashCode => raw.hashCode ^ title.hashCode;
80 +}
lib/src/domain/common/get_encryption_key.dart new
+23
@@ -0,0 +1,23 @@
1 +import 'package:flutter_secure_storage/flutter_secure_storage.dart';
2 +import 'package:hive/hive.dart';
3 +
4 +Future<List<int>> getEncryptionKey(
5 + {String forKey, FlutterSecureStorage secureStorage}) async {
6 + final stringifiedKey =
7 + await secureStorage.read(key: 'transactionDescriptionsBoxKey');
8 + List<int> key;
9 +
10 + if (stringifiedKey == null) {
11 + key = Hive.generateSecureKey();
12 + final keyStringified = key.join(',');
13 + await secureStorage.write(
14 + key: 'transactionDescriptionsBoxKey', value: keyStringified);
15 + } else {
16 + key = stringifiedKey
17 + .split(',')
18 + .map((i) => int.parse(i))
19 + .toList();
20 + }
21 +
22 + return key;
23 +}
\ No newline at end of file
lib/src/domain/common/language.dart new
+16
@@ -0,0 +1,16 @@
1 +import 'package:flutter/material.dart';
2 +
3 +class Language with ChangeNotifier {
4 +
5 + String _currentLanguage;
6 +
7 + Language(this._currentLanguage);
8 +
9 + getCurrentLanguage() => _currentLanguage;
10 +
11 + setCurrentLanguage(String language){
12 + _currentLanguage = language;
13 + notifyListeners();
14 + }
15 +
16 +}
\ No newline at end of file
lib/src/domain/common/mnemotic_item.dart new
+19
@@ -0,0 +1,19 @@
1 +class MnemoticItem {
2 + String get text => _text;
3 + final List<String> dic;
4 +
5 + String _text;
6 +
7 + MnemoticItem({String text, this.dic}) {
8 + _text = text;
9 + }
10 +
11 + bool isCorrect() => dic.contains(text);
12 +
13 + void changeText(String text) {
14 + _text = text;
15 + }
16 +
17 + @override
18 + String toString() => text;
19 +}
\ No newline at end of file
lib/src/domain/common/node.dart new
+49
@@ -0,0 +1,49 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'dart:convert';
3 +import 'package:http/http.dart' as http;
4 +import 'package:hive/hive.dart';
5 +import 'package:cake_wallet/src/domain/common/digest_request.dart';
6 +
7 +part 'node.g.dart';
8 +
9 +@HiveType()
10 +class Node extends HiveObject {
11 + static const boxName = 'Nodes';
12 +
13 + @HiveField(0)
14 + String uri;
15 +
16 + @HiveField(1)
17 + String login;
18 +
19 + @HiveField(2)
20 + String password;
21 +
22 + Node({@required this.uri, this.login, this.password});
23 +
24 + Node.fromMap(Map map)
25 + : uri = map['uri'] ?? '',
26 + login = map['login'],
27 + password = map['password'];
28 +
29 + Future<bool> requestNode(String uri, {String login, String password}) async {
30 + var resBody;
31 +
32 + if (login != null && password != null) {
33 + final digestRequest = DigestRequest();
34 + var response = await digestRequest.request(
35 + uri: uri, login: login, password: password);
36 + resBody = response.data;
37 + } else {
38 + final url = Uri.http(uri, '/json_rpc');
39 + Map<String, String> headers = {'Content-type': 'application/json'};
40 + String body =
41 + json.encode({"jsonrpc": "2.0", "id": "0", "method": "get_info"});
42 + var response =
43 + await http.post(url.toString(), headers: headers, body: body);
44 + resBody = json.decode(response.body);
45 + }
46 +
47 + return !resBody["result"]["offline"];
48 + }
49 +}
lib/src/domain/common/node_list.dart new
+23
@@ -0,0 +1,23 @@
1 +import 'package:flutter/services.dart';
2 +import 'package:hive/hive.dart';
3 +import "package:yaml/yaml.dart";
4 +import 'package:cake_wallet/src/domain/common/node.dart';
5 +
6 +Future<List<Node>> loadDefaultNodes() async {
7 + String nodesRaw = await rootBundle.loadString('assets/node_list.yml');
8 + List nodes = loadYaml(nodesRaw);
9 + return nodes.map((raw) => Node.fromMap(raw)).toList();
10 +}
11 +
12 +Future resetToDefault(Box<Node> nodeSource) async {
13 + final nodes = await loadDefaultNodes();
14 + await nodeSource.clear();
15 +
16 + Map<int, Node> enteties = {};
17 +
18 + for (var i = 0; i < nodes.length; i++) {
19 + enteties[i] = nodes[i];
20 + }
21 +
22 + await nodeSource.putAll(enteties);
23 +}
\ No newline at end of file
lib/src/domain/common/parseBoolFromString.dart new
+3
@@ -0,0 +1,3 @@
1 +bool parseBoolFromString(String string) {
2 + return string.toString() == 'true';
3 +}
\ No newline at end of file
lib/src/domain/common/pending_transaction.dart new
+25
@@ -0,0 +1,25 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:cw_monero/transaction_history.dart' as transactionHistory;
3 +import 'package:cw_monero/structs/pending_transaction.dart';
4 +import 'package:cake_wallet/src/domain/monero/monero_amount_format.dart';
5 +
6 +class PendingTransaction {
7 + final String amount;
8 + final String fee;
9 + final String hash;
10 +
11 + int _pointerAddress;
12 +
13 + PendingTransaction(
14 + {@required this.amount, @required this.fee, @required this.hash});
15 +
16 + PendingTransaction.fromTransactionDescription(
17 + PendingTransactionDescription transactionDescription)
18 + : amount = moneroAmountToString(amount: transactionDescription.amount),
19 + fee = moneroAmountToString(amount: transactionDescription.fee),
20 + hash = transactionDescription.hash,
21 + _pointerAddress = transactionDescription.pointerAddress;
22 +
23 + Future commit() async => transactionHistory
24 + .commitTransactionFromPointerAddress(address: _pointerAddress);
25 +}
lib/src/domain/common/qr_scanner.dart new
+15
@@ -0,0 +1,15 @@
1 +import 'package:barcode_scan/barcode_scan.dart';
2 +
3 +var isQrScannerShown = false;
4 +
5 +Future<String> presentQRScanner() async {
6 + isQrScannerShown = true;
7 + try {
8 + final result = await BarcodeScanner.scan();
9 + isQrScannerShown = false;
10 + return result;
11 + } catch (e) {
12 + isQrScannerShown = false;
13 + throw e;
14 + }
15 +}
lib/src/domain/common/secret_store_key.dart new
+27
@@ -0,0 +1,27 @@
1 +enum SecretStoreKey { moneroWalletPassword, pinCodePassword }
2 +
3 +const moneroWalletPassword = "MONERO_WALLET_PASSWORD";
4 +const pinCodePassword = "PIN_CODE_PASSWORD";
5 +
6 +String generateStoreKeyFor({SecretStoreKey key, String walletName = "",}) {
7 + var _key = "";
8 +
9 + switch (key) {
10 + case SecretStoreKey.moneroWalletPassword:
11 + {
12 + _key = moneroWalletPassword + "_" + walletName.toUpperCase();
13 + }
14 + break;
15 +
16 + case SecretStoreKey.pinCodePassword:
17 + {
18 + _key = pinCodePassword;
19 + }
20 + break;
21 +
22 + default:
23 + {}
24 + }
25 +
26 + return _key;
27 +}
\ No newline at end of file
lib/src/domain/common/sync_status.dart new
+66
@@ -0,0 +1,66 @@
1 +import 'package:cake_wallet/generated/i18n.dart';
2 +
3 +abstract class SyncStatus {
4 + const SyncStatus();
5 +
6 + double progress();
7 +
8 + String title();
9 +}
10 +
11 +class SyncingSyncStatus extends SyncStatus {
12 + final int height;
13 + final int blockchainHeight;
14 + final int refreshHeight;
15 +
16 + SyncingSyncStatus(this.height, this.blockchainHeight, this.refreshHeight);
17 +
18 + double progress() {
19 + final line = blockchainHeight - refreshHeight;
20 + final diff = line - (blockchainHeight - height);
21 + return diff <= 0 ? 0.0 : diff / line;
22 + }
23 +
24 + String title() => S.current.sync_status_syncronizing;
25 +
26 + @override
27 + String toString() => '${blockchainHeight - height}';
28 +}
29 +
30 +class SyncedSyncStatus extends SyncStatus {
31 + double progress() => 1.0;
32 +
33 + String title() => S.current.sync_status_syncronized;
34 +}
35 +
36 +class NotConnectedSyncStatus extends SyncStatus {
37 + const NotConnectedSyncStatus();
38 +
39 + double progress() => 0.0;
40 +
41 + String title() => S.current.sync_status_not_connected;
42 +}
43 +
44 +class StartingSyncStatus extends SyncStatus {
45 + double progress() => 0.0;
46 +
47 + String title() => S.current.sync_status_starting_sync;
48 +}
49 +
50 +class FailedSyncStatus extends SyncStatus {
51 + double progress() => 1.0;
52 +
53 + String title() => S.current.sync_status_failed_connect;
54 +}
55 +
56 +class ConnectingSyncStatus extends SyncStatus {
57 + double progress() => 0.0;
58 +
59 + String title() => S.current.sync_status_connecting;
60 +}
61 +
62 +class ConnectedSyncStatus extends SyncStatus {
63 + double progress() => 0.0;
64 +
65 + String title() => S.current.sync_status_connected;
66 +}
\ No newline at end of file
lib/src/domain/common/transaction_creation_credentials.dart new
+1
@@ -0,0 +1 @@
1 +abstract class TransactionCreationCredentials {}
\ No newline at end of file
lib/src/domain/common/transaction_direction.dart new
+17
@@ -0,0 +1,17 @@
1 +enum TransactionDirection { incoming, outgoing }
2 +
3 +TransactionDirection parseTransactionDirectionFromInt(int raw) {
4 + switch (raw) {
5 + case 0: return TransactionDirection.incoming;
6 + case 1: return TransactionDirection.outgoing;
7 + default: return null;
8 + }
9 +}
10 +
11 +TransactionDirection parseTransactionDirectionFromNumber(String raw) {
12 + switch (raw) {
13 + case "0": return TransactionDirection.incoming;
14 + case "1": return TransactionDirection.outgoing;
15 + default: return null;
16 + }
17 +}
\ No newline at end of file
lib/src/domain/common/transaction_history.dart new
+10
@@ -0,0 +1,10 @@
1 +import 'package:rxdart/rxdart.dart';
2 +import 'package:cake_wallet/src/domain/common/transaction_info.dart';
3 +
4 +abstract class TransactionHistory {
5 + Observable<List<TransactionInfo>> transactions;
6 + Future<List<TransactionInfo>> getAll();
7 + Future<int> count();
8 + Future refresh();
9 + Future update();
10 +}
lib/src/domain/common/transaction_info.dart new
+46
@@ -0,0 +1,46 @@
1 +import 'package:cake_wallet/src/domain/monero/monero_amount_format.dart';
2 +import 'package:cw_monero/structs/transaction_info_row.dart';
3 +import 'package:cake_wallet/src/domain/common/parseBoolFromString.dart';
4 +import 'package:cake_wallet/src/domain/common/transaction_direction.dart';
5 +
6 +class TransactionInfo {
7 + final String id;
8 + final int height;
9 + final TransactionDirection direction;
10 + final DateTime date;
11 + final int accountIndex;
12 + final bool isPending;
13 + final int amount;
14 + String recipientAddress;
15 + String _fiatAmount;
16 +
17 + TransactionInfo.fromMap(Map map)
18 + : id = map['hash'] ?? '',
19 + height = map['height'] ?? '',
20 + direction = parseTransactionDirectionFromNumber(map['direction']) ??
21 + TransactionDirection.incoming,
22 + date = DateTime.fromMillisecondsSinceEpoch(
23 + (int.parse(map['timestamp']) ?? 0) * 1000),
24 + isPending = parseBoolFromString(map['isPending']),
25 + amount = map['amount'],
26 + accountIndex = int.parse(map['accountIndex']);
27 +
28 + TransactionInfo.fromRow(TransactionInfoRow row)
29 + : id = row.getHash(),
30 + height = row.blockHeight,
31 + direction = parseTransactionDirectionFromInt(row.direction) ??
32 + TransactionDirection.incoming,
33 + date = DateTime.fromMillisecondsSinceEpoch(row.getDatetime() * 1000),
34 + isPending = row.isPending != 0,
35 + amount = row.getAmount(),
36 + accountIndex = row.subaddrAccount;
37 +
38 + TransactionInfo(this.id, this.height, this.direction, this.date,
39 + this.isPending, this.amount, this.accountIndex);
40 +
41 + String amountFormatted() => '${moneroAmountToString(amount: amount)} XMR';
42 +
43 + String fiatAmount() => _fiatAmount ?? '';
44 +
45 + changeFiatAmount(String amount) => _fiatAmount = amount;
46 +}
lib/src/domain/common/transaction_priority.dart new
+56
@@ -0,0 +1,56 @@
1 +import 'package:cake_wallet/generated/i18n.dart';
2 +import 'package:cake_wallet/src/domain/common/enumerable_item.dart';
3 +
4 +class TransactionPriority extends EnumerableItem<int> with Serializable<int> {
5 + static const all = [
6 + TransactionPriority.slow,
7 + TransactionPriority.regular,
8 + TransactionPriority.medium,
9 + TransactionPriority.fast,
10 + TransactionPriority.fastest
11 + ];
12 + static const slow = TransactionPriority(title: 'Slow', raw: 0);
13 + static const regular = TransactionPriority(title: 'Regular', raw: 1);
14 + static const medium = TransactionPriority(title: 'Medium', raw: 2);
15 + static const fast = TransactionPriority(title: 'Fast', raw: 3);
16 + static const fastest = TransactionPriority(title: 'Fastest', raw: 4);
17 + static const standart = slow;
18 +
19 + static TransactionPriority deserialize({int raw}) {
20 + switch (raw) {
21 + case 0:
22 + return slow;
23 + case 1:
24 + return regular;
25 + case 2:
26 + return medium;
27 + case 3:
28 + return fast;
29 + case 4:
30 + return fastest;
31 + default:
32 + return null;
33 + }
34 + }
35 +
36 + const TransactionPriority({String title, int raw})
37 + : super(title: title, raw: raw);
38 +
39 + @override
40 + String toString() {
41 + switch (this) {
42 + case TransactionPriority.slow:
43 + return S.current.transaction_priority_slow;
44 + case TransactionPriority.regular:
45 + return S.current.transaction_priority_regular;
46 + case TransactionPriority.medium:
47 + return S.current.transaction_priority_medium;
48 + case TransactionPriority.fast:
49 + return S.current.transaction_priority_fast;
50 + case TransactionPriority.fastest:
51 + return S.current.transaction_priority_fastest;
52 + default:
53 + return '';
54 + }
55 + }
56 +}
lib/src/domain/common/wallet.dart new
+61
@@ -0,0 +1,61 @@
1 +import 'package:rxdart/rxdart.dart';
2 +import 'package:cake_wallet/src/domain/common/sync_status.dart';
3 +import 'package:cake_wallet/src/domain/common/transaction_history.dart';
4 +import 'package:cake_wallet/src/domain/common/wallet_type.dart';
5 +import 'package:cake_wallet/src/domain/common/transaction_creation_credentials.dart';
6 +import 'package:cake_wallet/src/domain/common/pending_transaction.dart';
7 +import 'package:cake_wallet/src/domain/common/balance.dart';
8 +import 'package:cake_wallet/src/domain/common/node.dart';
9 +
10 +abstract class Wallet {
11 + WalletType getType();
12 +
13 + WalletType walletType;
14 +
15 + Observable<Balance> onBalanceChange;
16 +
17 + Observable<SyncStatus> syncStatus;
18 +
19 + Observable<String> get onNameChange;
20 +
21 + Observable<String> get onAddressChange;
22 +
23 + String get name;
24 +
25 + String get address;
26 +
27 + Future updateInfo();
28 +
29 + Future<String> getFilename();
30 +
31 + Future<String> getName();
32 +
33 + Future<String> getAddress();
34 +
35 + Future<String> getSeed();
36 +
37 + Future<Map<String, String>> getKeys();
38 +
39 + Future<String> getFullBalance();
40 +
41 + Future<String> getUnlockedBalance();
42 +
43 + Future<int> getCurrentHeight();
44 +
45 + Future<int> getNodeHeight();
46 +
47 + Future<bool> isConnected();
48 +
49 + Future close();
50 +
51 + TransactionHistory getHistory();
52 +
53 + Future connectToNode({Node node, bool useSSL = false, bool isLightWallet = false});
54 +
55 + Future startSync();
56 +
57 + Future<PendingTransaction> createTransaction(
58 + TransactionCreationCredentials credentials);
59 +
60 + Future rescan({int restoreHeight = 0});
61 +}
lib/src/domain/common/wallet_description.dart new
+8
@@ -0,0 +1,8 @@
1 +import 'package:cake_wallet/src/domain/common/wallet_type.dart';
2 +
3 +class WalletDescription {
4 + final String name;
5 + final WalletType type;
6 +
7 + WalletDescription({this.name, this.type});
8 +}
\ No newline at end of file
lib/src/domain/common/wallet_info.dart new
+27
@@ -0,0 +1,27 @@
1 +import 'package:cake_wallet/src/domain/common/wallet_type.dart';
2 +import 'package:hive/hive.dart';
3 +
4 +part 'wallet_info.g.dart';
5 +
6 +@HiveType()
7 +class WalletInfo extends HiveObject {
8 + static const boxName = 'WalletInfo';
9 +
10 + @HiveField(0)
11 + String id;
12 +
13 + @HiveField(1)
14 + String name;
15 +
16 + @HiveField(2)
17 + WalletType type;
18 +
19 + @HiveField(3)
20 + bool isRecovery;
21 +
22 + @HiveField(4)
23 + int restoreHeight;
24 +
25 + WalletInfo(
26 + {this.id, this.name, this.type, this.isRecovery, this.restoreHeight});
27 +}
lib/src/domain/common/wallet_type.dart new
+39
@@ -0,0 +1,39 @@
1 +import 'package:hive/hive.dart';
2 +
3 +part 'wallet_type.g.dart';
4 +
5 +@HiveType()
6 +enum WalletType {
7 + @HiveField(0)
8 + monero,
9 +
10 + @HiveField(1)
11 + none
12 +}
13 +
14 +int serializeToInt(WalletType type) {
15 + switch (type) {
16 + case WalletType.monero:
17 + return 0;
18 + default:
19 + return -1;
20 + }
21 +}
22 +
23 +WalletType deserializeToInt(int raw) {
24 + switch (raw) {
25 + case 0:
26 + return WalletType.monero;
27 + default:
28 + return null;
29 + }
30 +}
31 +
32 +String walletTypeToString(WalletType type) {
33 + switch (type) {
34 + case WalletType.monero:
35 + return 'Monero';
36 + default:
37 + return '';
38 + }
39 +}
\ No newline at end of file
lib/src/domain/common/wallets_manager.dart new
+18
@@ -0,0 +1,18 @@
1 +import 'package:cake_wallet/src/domain/common/wallet.dart';
2 +import 'package:cake_wallet/src/domain/common/wallet_description.dart';
3 +
4 +abstract class WalletsManager {
5 + Future<Wallet> create(String name, String password);
6 +
7 + Future<Wallet> restoreFromSeed(
8 + String name, String password, String seed, int restoreHeight);
9 +
10 + Future<Wallet> restoreFromKeys(String name, String password,
11 + int restoreHeight, String address, String viewKey, String spendKey);
12 +
13 + Future<Wallet> openWallet(String name, String password);
14 +
15 + Future<bool> isWalletExit(String name);
16 +
17 + Future remove(WalletDescription wallet);
18 +}
\ No newline at end of file
lib/src/domain/exchange/changenow/changenow_exchange_provider.dart new
+139
@@ -0,0 +1,139 @@
1 +import 'dart:convert';
2 +import 'package:cake_wallet/src/domain/exchange/trade_not_found_exeption.dart';
3 +import 'package:flutter/foundation.dart';
4 +import 'package:http/http.dart';
5 +import 'package:cake_wallet/.secrets.g.dart' as secrets;
6 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
7 +import 'package:cake_wallet/src/domain/exchange/exchange_pair.dart';
8 +import 'package:cake_wallet/src/domain/exchange/exchange_provider.dart';
9 +import 'package:cake_wallet/src/domain/exchange/limits.dart';
10 +import 'package:cake_wallet/src/domain/exchange/trade.dart';
11 +import 'package:cake_wallet/src/domain/exchange/trade_request.dart';
12 +import 'package:cake_wallet/src/domain/exchange/trade_state.dart';
13 +import 'package:cake_wallet/src/domain/exchange/changenow/changenow_request.dart';
14 +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
15 +import 'package:cake_wallet/src/domain/exchange/trade_not_created_exeption.dart';
16 +
17 +class ChangeNowExchangeProvider extends ExchangeProvider {
18 + static const apiUri = 'https://changenow.io/api/v1';
19 + static const apiKey = secrets.change_now_api_key;
20 + static const _exchangeAmountUriSufix = '/exchange-amount/';
21 + static const _transactionsUriSufix = '/transactions/';
22 + static const _minAmountUriSufix = '/min-amount/';
23 +
24 + String get title => 'ChangeNOW';
25 + ExchangeProviderDescription get description =>
26 + ExchangeProviderDescription.changeNow;
27 +
28 + ChangeNowExchangeProvider() {
29 + pairList = CryptoCurrency.all
30 + .map((i) {
31 + return CryptoCurrency.all.map((k) {
32 + if (i == CryptoCurrency.btc && k == CryptoCurrency.xmr) {
33 + return ExchangePair(from: i, to: k, reverse: false);
34 + }
35 +
36 + if (i == CryptoCurrency.xmr && k == CryptoCurrency.btc) {
37 + return null;
38 + }
39 +
40 + return ExchangePair(from: i, to: k, reverse: true);
41 + }).where((c) => c != null);
42 + })
43 + .expand((i) => i)
44 + .toList();
45 + }
46 +
47 + Future<Limits> fetchLimits({CryptoCurrency from, CryptoCurrency to}) async {
48 + final symbol = from.toString() + '_' + to.toString();
49 + final url = apiUri + _minAmountUriSufix + symbol;
50 + final response = await get(url);
51 + final responseJSON = json.decode(response.body);
52 + final double min = responseJSON['minAmount'];
53 +
54 + return Limits(min: min, max: null);
55 + }
56 +
57 + Future<Trade> createTrade({TradeRequest request}) async {
58 + const url = apiUri + _transactionsUriSufix + apiKey;
59 + final _request = request as ChangeNowRequest;
60 + final body = {
61 + 'from': _request.from.toString(),
62 + 'to': _request.to.toString(),
63 + 'address': _request.address,
64 + 'amount': _request.amount,
65 + 'refundAddress': _request.refundAddress
66 + };
67 +
68 + final response = await post(url,
69 + headers: {'Content-Type': 'application/json'}, body: json.encode(body));
70 +
71 + if (response.statusCode != 200) {
72 + if (response.statusCode == 400) {
73 + final responseJSON = json.decode(response.body);
74 + final error = responseJSON['message'];
75 + throw TradeNotCreatedException(description, description: error);
76 + }
77 +
78 + throw TradeNotCreatedException(description);
79 + }
80 +
81 + final responseJSON = json.decode(response.body);
82 +
83 + return Trade(
84 + id: responseJSON['id'],
85 + from: _request.from,
86 + to: _request.to,
87 + provider: description,
88 + inputAddress: responseJSON['payinAddress'],
89 + refundAddress: responseJSON['refundAddress'],
90 + extraId: responseJSON["payinExtraId"],
91 + createdAt: DateTime.now(),
92 + amount: _request.amount,
93 + state: TradeState.created);
94 + }
95 +
96 + Future<Trade> findTradeById({@required String id}) async {
97 + final url = apiUri + _transactionsUriSufix + id + '/' + apiKey;
98 + final response = await get(url);
99 +
100 + if (response.statusCode != 200) {
101 + if (response.statusCode == 400) {
102 + final responseJSON = json.decode(response.body);
103 + final error = responseJSON['message'];
104 + throw TradeNotFoundException(id,
105 + provider: description, description: error);
106 + }
107 +
108 + throw TradeNotFoundException(id, provider: description);
109 + }
110 +
111 + final responseJSON = json.decode(response.body);
112 +
113 + return Trade(
114 + id: id,
115 + from: CryptoCurrency.fromString(responseJSON['fromCurrency']),
116 + to: CryptoCurrency.fromString(responseJSON['toCurrency']),
117 + provider: description,
118 + inputAddress: responseJSON['payinAddress'],
119 + amount: responseJSON['expectedSendAmount'].toString(),
120 + state: TradeState.deserialize(raw: responseJSON['status']),
121 + extraId: responseJSON['payinExtraId'],
122 + outputTransaction: responseJSON['payoutHash']);
123 + }
124 +
125 + Future<double> calculateAmount(
126 + {CryptoCurrency from, CryptoCurrency to, double amount}) async {
127 + final url = apiUri +
128 + _exchangeAmountUriSufix +
129 + amount.toString() +
130 + '/' +
131 + from.toString() +
132 + '_' +
133 + to.toString();
134 + final response = await get(url);
135 + final responseJSON = json.decode(response.body);
136 +
137 + return responseJSON['estimatedAmount'];
138 + }
139 +}
lib/src/domain/exchange/changenow/changenow_request.dart new
+18
@@ -0,0 +1,18 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
3 +import 'package:cake_wallet/src/domain/exchange/trade_request.dart';
4 +
5 +class ChangeNowRequest extends TradeRequest {
6 + CryptoCurrency from;
7 + CryptoCurrency to;
8 + String address;
9 + String amount;
10 + String refundAddress;
11 +
12 + ChangeNowRequest(
13 + {@required this.from,
14 + @required this.to,
15 + @required this.address,
16 + @required this.amount,
17 + @required this.refundAddress});
18 +}
lib/src/domain/exchange/exchange_pair.dart new
+9
@@ -0,0 +1,9 @@
1 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
2 +
3 +class ExchangePair {
4 + final CryptoCurrency from;
5 + final CryptoCurrency to;
6 + final bool reverse;
7 +
8 + ExchangePair({this.from, this.to, this.reverse = true});
9 +}
\ No newline at end of file
lib/src/domain/exchange/exchange_provider.dart new
+22
@@ -0,0 +1,22 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
3 +import 'package:cake_wallet/src/domain/exchange/trade_request.dart';
4 +import 'package:cake_wallet/src/domain/exchange/exchange_pair.dart';
5 +import 'package:cake_wallet/src/domain/exchange/limits.dart';
6 +import 'package:cake_wallet/src/domain/exchange/trade.dart';
7 +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
8 +
9 +abstract class ExchangeProvider {
10 + String get title;
11 + List<ExchangePair> pairList;
12 + ExchangeProviderDescription description;
13 +
14 + @override
15 + String toString() => title;
16 +
17 + Future<Limits> fetchLimits({CryptoCurrency from, CryptoCurrency to});
18 + Future<Trade> createTrade({TradeRequest request});
19 + Future<Trade> findTradeById({@required String id});
20 + Future<double> calculateAmount(
21 + {CryptoCurrency from, CryptoCurrency to, double amount});
22 +}
lib/src/domain/exchange/exchange_provider_description.dart new
+24
@@ -0,0 +1,24 @@
1 +import 'package:cake_wallet/src/domain/common/enumerable_item.dart';
2 +
3 +class ExchangeProviderDescription extends EnumerableItem<int>
4 + with Serializable<int> {
5 + static const xmrto = ExchangeProviderDescription(title: 'XMR.TO', raw: 0);
6 + static const changeNow =
7 + ExchangeProviderDescription(title: 'ChangeNOW', raw: 1);
8 +
9 + static ExchangeProviderDescription deserialize({int raw}) {
10 + switch (raw) {
11 + case 0:
12 + return xmrto;
13 + case 1:
14 + return changeNow;
15 + default:
16 + return null;
17 + }
18 + }
19 +
20 + final String title;
21 +
22 + const ExchangeProviderDescription({this.title, int raw})
23 + : super(title: title, raw: raw);
24 +}
lib/src/domain/exchange/limits.dart new
+6
@@ -0,0 +1,6 @@
1 +class Limits {
2 + final double min;
3 + final double max;
4 +
5 + const Limits({this.min, this.max});
6 +}
\ No newline at end of file
lib/src/domain/exchange/trade.dart new
+103
@@ -0,0 +1,103 @@
1 +import 'package:hive/hive.dart';
2 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
3 +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
4 +import 'package:cake_wallet/src/domain/exchange/trade_state.dart';
5 +
6 +part 'trade.g.dart';
7 +
8 +@HiveType()
9 +class Trade extends HiveObject {
10 + static const boxName = 'Trades';
11 +
12 + @HiveField(0)
13 + String id;
14 +
15 + @HiveField(1)
16 + int providerRaw;
17 +
18 + ExchangeProviderDescription get provider =>
19 + ExchangeProviderDescription.deserialize(raw: providerRaw);
20 +
21 + @HiveField(2)
22 + int fromRaw;
23 +
24 + CryptoCurrency get from => CryptoCurrency.deserialize(raw: fromRaw);
25 +
26 + @HiveField(3)
27 + int toRaw;
28 +
29 + CryptoCurrency get to => CryptoCurrency.deserialize(raw: toRaw);
30 +
31 + @HiveField(4)
32 + String stateRaw;
33 +
34 + TradeState get state => TradeState.deserialize(raw: stateRaw);
35 +
36 + @HiveField(5)
37 + DateTime createdAt;
38 +
39 + @HiveField(6)
40 + DateTime expiredAt;
41 +
42 + @HiveField(7)
43 + String amount;
44 +
45 + @HiveField(8)
46 + String inputAddress;
47 +
48 + @HiveField(9)
49 + String extraId;
50 +
51 + @HiveField(10)
52 + String outputTransaction;
53 +
54 + @HiveField(11)
55 + String refundAddress;
56 +
57 + @HiveField(12)
58 + String walletId;
59 +
60 + static Trade fromMap(Map map) {
61 + return Trade(
62 + id: map['id'],
63 + provider: ExchangeProviderDescription.deserialize(raw: map['provider']),
64 + from: CryptoCurrency.deserialize(raw: map['input']),
65 + to: CryptoCurrency.deserialize(raw: map['output']),
66 + createdAt: map['date'] != null
67 + ? DateTime.fromMillisecondsSinceEpoch(map['date'])
68 + : null,
69 + amount: map['amount'],
70 + walletId: map['wallet_id']);
71 + }
72 +
73 + Trade(
74 + {this.id,
75 + ExchangeProviderDescription provider,
76 + CryptoCurrency from,
77 + CryptoCurrency to,
78 + TradeState state,
79 + this.createdAt,
80 + this.expiredAt,
81 + this.amount,
82 + this.inputAddress,
83 + this.extraId,
84 + this.outputTransaction,
85 + this.refundAddress,
86 + this.walletId})
87 + : providerRaw = provider?.raw,
88 + fromRaw = from?.raw,
89 + toRaw = to?.raw,
90 + stateRaw = state?.raw;
91 +
92 + Map<String, dynamic> toMap() {
93 + return {
94 + 'id': id,
95 + 'provider': provider.serialize(),
96 + 'input': from.serialize(),
97 + 'output': to.serialize(),
98 + 'date': createdAt != null ? createdAt.millisecondsSinceEpoch : null,
99 + 'amount': amount,
100 + 'wallet_id': walletId
101 + };
102 + }
103 +}
lib/src/domain/exchange/trade_not_created_exeption.dart new
+19
@@ -0,0 +1,19 @@
1 +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
2 +import 'package:cake_wallet/generated/i18n.dart';
3 +
4 +class TradeNotCreatedException implements Exception {
5 + ExchangeProviderDescription provider;
6 + String description;
7 +
8 + TradeNotCreatedException(this.provider, {this.description = ''});
9 +
10 + @override
11 + String toString() {
12 + var text = provider != null
13 + ? S.current.trade_for_not_created(provider.title)
14 + : S.current.trade_not_created;
15 + text += ' $description';
16 +
17 + return text;
18 + }
19 +}
lib/src/domain/exchange/trade_not_found_exeption.dart new
+20
@@ -0,0 +1,20 @@
1 +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
2 +import 'package:cake_wallet/generated/i18n.dart';
3 +
4 +class TradeNotFoundException implements Exception {
5 + String tradeId;
6 + ExchangeProviderDescription provider;
7 + String description;
8 +
9 + TradeNotFoundException(this.tradeId, {this.provider, this.description = ''});
10 +
11 + @override
12 + String toString() {
13 + var text = tradeId != null && provider != null
14 + ? S.current.trade_id_not_found(tradeId, provider.title)
15 + : S.current.trade_not_found;
16 + text += ' $description';
17 +
18 + return text;
19 + }
20 +}
lib/src/domain/exchange/trade_request.dart new
+1
@@ -0,0 +1 @@
1 +abstract class TradeRequest {}
\ No newline at end of file
lib/src/domain/exchange/trade_state.dart new
+68
@@ -0,0 +1,68 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:cake_wallet/src/domain/common/enumerable_item.dart';
3 +
4 +class TradeState extends EnumerableItem<String> with Serializable<String> {
5 + static const pending = TradeState(raw: 'pending', title: 'Pending');
6 + static const confirming = TradeState(raw: 'confirming', title: 'Confirming');
7 + static const trading = TradeState(raw: 'trading', title: 'Trading');
8 + static const traded = TradeState(raw: 'traded', title: 'Traded');
9 + static const complete = TradeState(raw: 'complete', title: 'Complete');
10 + static const toBeCreated =
11 + TradeState(raw: 'TO_BE_CREATED', title: 'To be created');
12 + static const unpaid = TradeState(raw: 'UNPAID', title: 'Unpaid');
13 + static const underpaid = TradeState(raw: 'UNDERPAID', title: 'Underpaid');
14 + static const paidUnconfirmed =
15 + TradeState(raw: 'PAID_UNCONFIRMED', title: 'Paid unconfirmed');
16 + static const paid = TradeState(raw: 'PAID', title: 'Paid');
17 + static const btcSent = TradeState(raw: 'BTC_SENT', title: 'Btc sent');
18 + static const timeout = TradeState(raw: 'TIMED_OUT', title: 'Timeout');
19 + static const notFound = TradeState(raw: 'NOT_FOUND', title: 'Not found');
20 + static const created = TradeState(raw: 'created', title: 'Created');
21 + static const finished = TradeState(raw: 'finished', title: 'Finished');
22 + static const waiting = TradeState(raw: 'waiting', title: 'Waiting');
23 +
24 + static TradeState deserialize({String raw}) {
25 + switch (raw) {
26 + case 'pending':
27 + return pending;
28 + case 'confirming':
29 + return confirming;
30 + case 'trading':
31 + return trading;
32 + case 'traded':
33 + return traded;
34 + case 'complete':
35 + return complete;
36 + case 'TO_BE_CREATED':
37 + return toBeCreated;
38 + case 'UNPAID':
39 + return unpaid;
40 + case 'UNDERPAID':
41 + return underpaid;
42 + case 'PAID_UNCONFIRMED':
43 + return paidUnconfirmed;
44 + case 'PAID':
45 + return paid;
46 + case 'BTC_SENT':
47 + return btcSent;
48 + case 'TIMED_OUT':
49 + return timeout;
50 + case 'created':
51 + return created;
52 + case 'finished':
53 + return finished;
54 + case 'waiting':
55 + return waiting;
56 + default:
57 + return null;
58 + }
59 + }
60 +
61 + const TradeState({@required String raw, @required String title})
62 + : super(raw: raw, title: title);
63 +
64 + operator ==(o) => o is TradeState && o.raw == raw;
65 +
66 + @override
67 + int get hashCode => raw.hashCode ^ title.hashCode;
68 +}
lib/src/domain/exchange/xmrto/xmrto_exchange_provider.dart new
+170
@@ -0,0 +1,170 @@
1 +import 'dart:convert';
2 +import 'package:flutter/foundation.dart';
3 +import 'package:http/http.dart';
4 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
5 +import 'package:cake_wallet/src/domain/exchange/exchange_pair.dart';
6 +import 'package:cake_wallet/src/domain/exchange/exchange_provider.dart';
7 +import 'package:cake_wallet/src/domain/exchange/limits.dart';
8 +import 'package:cake_wallet/src/domain/exchange/trade.dart';
9 +import 'package:cake_wallet/src/domain/exchange/trade_request.dart';
10 +import 'package:cake_wallet/src/domain/exchange/trade_state.dart';
11 +import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_trade_request.dart';
12 +import 'package:cake_wallet/src/domain/exchange/trade_not_created_exeption.dart';
13 +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
14 +import 'package:cake_wallet/src/domain/exchange/trade_not_found_exeption.dart';
15 +
16 +class XMRTOExchangeProvider extends ExchangeProvider {
17 + static const userAgent = 'CakeWallet/XMR iOS';
18 + static const originalApiUri = 'https://xmr.to/api/v2/xmr2btc';
19 + static const proxyApiUri = 'https://xmrproxy.net/api/v2/xmr2btc';
20 + static const _orderParameterUriSufix = '/order_parameter_query';
21 + static const _orderStatusUriSufix = '/order_status_query/';
22 + static const _orderCreateUriSufix = '/order_create/';
23 + static String _apiUri = '';
24 +
25 + static Future<String> getApiUri() async {
26 + if (_apiUri != null && _apiUri.isNotEmpty) {
27 + return _apiUri;
28 + }
29 +
30 + const url = originalApiUri + _orderParameterUriSufix;
31 + final response =
32 + await get(url, headers: {'Content-Type': 'application/json'});
33 + _apiUri = response.statusCode == 403 ? proxyApiUri : originalApiUri;
34 +
35 + return _apiUri;
36 + }
37 +
38 + String get title => 'XMR.TO';
39 +
40 + ExchangeProviderDescription get description =>
41 + ExchangeProviderDescription.xmrto;
42 +
43 + List<ExchangePair> pairList = [
44 + ExchangePair(
45 + from: CryptoCurrency.xmr, to: CryptoCurrency.btc, reverse: false)
46 + ];
47 +
48 + double _rate = 0;
49 +
50 + Future<Limits> fetchLimits({CryptoCurrency from, CryptoCurrency to}) async {
51 + final url = await getApiUri() + _orderParameterUriSufix;
52 + final response = await get(url);
53 +
54 + if (response.statusCode != 200) {
55 + return Limits(min: 0, max: 0);
56 + }
57 +
58 + final responseJSON = json.decode(response.body);
59 + final double min = responseJSON['lower_limit'];
60 + final double max = responseJSON['upper_limit'];
61 +
62 + return Limits(min: min, max: max);
63 + }
64 +
65 + Future<Trade> createTrade({TradeRequest request}) async {
66 + final _request = request as XMRTOTradeRequest;
67 + final url = await getApiUri() + _orderCreateUriSufix;
68 + final body = {
69 + 'btc_amount': _request.amount,
70 + 'btc_dest_address': _request.address
71 + };
72 + final response = await post(url,
73 + headers: {'Content-Type': 'application/json'}, body: json.encode(body));
74 +
75 + if (response.statusCode != 201) {
76 + if (response.statusCode == 400) {
77 + final responseJSON = json.decode(response.body);
78 + throw TradeNotCreatedException(description,
79 + description: responseJSON['error_msg']);
80 + }
81 +
82 + throw TradeNotCreatedException(description);
83 + }
84 +
85 + final responseJSON = json.decode(response.body);
86 + final uuid = responseJSON["uuid"];
87 +
88 + return Trade(
89 + id: uuid,
90 + provider: description,
91 + from: _request.from,
92 + to: _request.to,
93 + state: TradeState.created,
94 + amount: _request.amount,
95 + createdAt: DateTime.now());
96 + }
97 +
98 + Future<Trade> findTradeById({@required String id}) async {
99 + const headers = {
100 + 'Content-Type': 'application/json',
101 + 'User-Agent': userAgent
102 + };
103 + final url = await getApiUri() + _orderStatusUriSufix;
104 + final body = {'uuid': id};
105 + final response = await post(url, headers: headers, body: json.encode(body));
106 +
107 + if (response.statusCode != 200) {
108 + if (response.statusCode == 400) {
109 + final responseJSON = json.decode(response.body);
110 + final error = responseJSON['error_msg'];
111 + throw TradeNotFoundException(id,
112 + provider: description, description: error);
113 + }
114 +
115 + throw TradeNotFoundException(id, provider: description);
116 + }
117 +
118 + final responseJSON = json.decode(response.body);
119 + final address = responseJSON['xmr_receiving_integrated_address'];
120 + final paymentId = responseJSON['xmr_required_payment_id_short'];
121 + final amount = responseJSON['xmr_amount_total'].toString();
122 + final stateRaw = responseJSON['state'];
123 + final expiredAtRaw = responseJSON['expires_at'];
124 + final expiredAt = DateTime.parse(expiredAtRaw).toLocal();
125 + final outputTransaction = responseJSON['btc_transaction_id'];
126 + final state = TradeState.deserialize(raw: stateRaw);
127 +
128 + return Trade(
129 + id: id,
130 + provider: description,
131 + from: CryptoCurrency.xmr,
132 + to: CryptoCurrency.btc,
133 + inputAddress: address,
134 + extraId: paymentId,
135 + expiredAt: expiredAt,
136 + amount: amount,
137 + state: state,
138 + outputTransaction: outputTransaction);
139 + }
140 +
141 + Future<double> calculateAmount(
142 + {CryptoCurrency from, CryptoCurrency to, double amount}) async {
143 + if (from != CryptoCurrency.xmr && to != CryptoCurrency.btc) {
144 + return 0;
145 + }
146 +
147 + if (_rate == null || _rate == 0) {
148 + _rate = await _fetchRates();
149 + }
150 +
151 + final double result = _rate * amount;
152 +
153 + return double.parse(result.toStringAsFixed(12));
154 + }
155 +
156 + Future<double> _fetchRates() async {
157 + try {
158 + final url = await getApiUri() + _orderParameterUriSufix;
159 + final response =
160 + await get(url, headers: {'Content-Type': 'application/json'});
161 + final responseJSON = json.decode(response.body);
162 + double btcprice = responseJSON['price'];
163 + double price = 1 / btcprice;
164 + return price;
165 + } catch (e) {
166 + print(e.toString());
167 + return 0.0;
168 + }
169 + }
170 +}
lib/src/domain/exchange/xmrto/xmrto_trade_request.dart new
+18
@@ -0,0 +1,18 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
3 +import 'package:cake_wallet/src/domain/exchange/trade_request.dart';
4 +
5 +class XMRTOTradeRequest extends TradeRequest {
6 + final CryptoCurrency from;
7 + final CryptoCurrency to;
8 + final String amount;
9 + final String address;
10 + final String refundAddress;
11 +
12 + XMRTOTradeRequest(
13 + {@required this.from,
14 + @required this.to,
15 + @required this.amount,
16 + @required this.address,
17 + @required this.refundAddress});
18 +}
lib/src/domain/monero/account.dart new
+16
@@ -0,0 +1,16 @@
1 +import 'package:cw_monero/structs/account_row.dart';
2 +
3 +class Account {
4 + final int id;
5 + final String label;
6 +
7 + Account({this.id, this.label});
8 +
9 + Account.fromMap(Map map)
10 + : this.id = map['id'] == null ? 0 : int.parse(map['id']),
11 + this.label = map['label'] ?? '';
12 +
13 + Account.fromRow(AccountRow row)
14 + : this.id = row.getId(),
15 + this.label = row.getLabel();
16 +}
lib/src/domain/monero/account_list.dart new
+67
@@ -0,0 +1,67 @@
1 +import 'package:rxdart/rxdart.dart';
2 +import 'package:cw_monero/account_list.dart' as accountListAPI;
3 +import 'package:cake_wallet/src/domain/monero/account.dart';
4 +
5 +class AccountList {
6 + get accounts => _accounts.stream;
7 + BehaviorSubject<List<Account>> _accounts;
8 +
9 + bool _isRefreshing;
10 + bool _isUpdating;
11 +
12 + AccountList() {
13 + _isRefreshing = false;
14 + _isUpdating = false;
15 + _accounts = BehaviorSubject<List<Account>>();
16 + }
17 +
18 + Future update() async {
19 + if (_isUpdating) {
20 + return;
21 + }
22 +
23 + try {
24 + _isUpdating = true;
25 + await refresh();
26 + final accounts = getAll();
27 + _accounts.add(accounts);
28 + _isUpdating = false;
29 + } catch (e) {
30 + _isUpdating = false;
31 + throw e;
32 + }
33 + }
34 +
35 + List<Account> getAll() {
36 + return accountListAPI
37 + .getAllAccount()
38 + .map((accountRow) => Account.fromRow(accountRow))
39 + .toList();
40 + }
41 +
42 + Future addAccount({String label}) async {
43 + await accountListAPI.addAccount(label: label);
44 + await update();
45 + }
46 +
47 + Future setLabelSubaddress({int accountIndex, String label}) async {
48 + await accountListAPI.setLabelForAccount(accountIndex: accountIndex, label: label);
49 + await update();
50 + }
51 +
52 + refresh() {
53 + if (_isRefreshing) {
54 + return;
55 + }
56 +
57 + try {
58 + _isRefreshing = true;
59 + accountListAPI.refreshAccounts();
60 + _isRefreshing = false;
61 + } catch (e) {
62 + _isRefreshing = false;
63 + print(e);
64 + throw e;
65 + }
66 + }
67 +}
lib/src/domain/monero/get_height_by_date.dart new
+101
@@ -0,0 +1,101 @@
1 +import 'package:intl/intl.dart';
2 +
3 +final dateFormat = DateFormat('yyyy-MM');
4 +final dates = {
5 + "2014-5": 18844,
6 + "2014-6": 65406,
7 + "2014-7": 108882,
8 + "2014-8": 153594,
9 + "2014-9": 198072,
10 + "2014-10": 241088,
11 + "2014-11": 285305,
12 + "2014-12": 328069,
13 + "2015-1": 372369,
14 + "2015-2": 416505,
15 + "2015-3": 456631,
16 + "2015-4": 501084,
17 + "2015-5": 543973,
18 + "2015-6": 588326,
19 + "2015-7": 631187,
20 + "2015-8": 675484,
21 + "2015-9": 719725,
22 + "2015-10": 762463,
23 + "2015-11": 806528,
24 + "2015-12": 849041,
25 + "2016-1": 892866,
26 + "2016-2": 936736,
27 + "2016-3": 977691,
28 + "2016-4": 1015848,
29 + "2016-5": 1037417,
30 + "2016-6": 1059651,
31 + "2016-7": 1081269,
32 + "2016-8": 1103630,
33 + "2016-9": 1125983,
34 + "2016-10": 1147617,
35 + "2016-11": 1169779,
36 + "2016-12": 1191402,
37 + "2017-1": 1213861,
38 + "2017-2": 1236197,
39 + "2017-3": 1256358,
40 + "2017-4": 1278622,
41 + "2017-5": 1300239,
42 + "2017-6": 1322564,
43 + "2017-7": 1344225,
44 + "2017-8": 1366664,
45 + "2017-9": 1389113,
46 + "2017-10": 1410738,
47 + "2017-11": 1433039,
48 + "2017-12": 1454639,
49 + "2018-1": 1477201,
50 + "2018-2": 1499599,
51 + "2018-3": 1519796,
52 + "2018-4": 1542067,
53 + "2018-5": 1562861,
54 + "2018-6": 1585135,
55 + "2018-7": 1606715,
56 + "2018-8": 1629017,
57 + "2018-9": 1651347,
58 + "2018-10": 1673031,
59 + "2018-11": 1695128,
60 + "2018-12": 1716687,
61 + "2019-1": 1738923,
62 + "2019-2": 1761435,
63 + "2019-3": 1781681,
64 + "2019-4": 1803081,
65 + "2019-5": 1824671,
66 + "2019-6": 1847005,
67 + "2019-7": 1868590,
68 + "2019-8": 1888590,
69 + "2019-9": 1898590,
70 +};
71 +
72 +int getHeigthByDate({DateTime date}) {
73 + final raw = '${date.year}' + '-' + '${date.month}';
74 + var endHeight = dates[raw] ?? 0;
75 + int preLastYear = date.year;
76 + int preLastMonth = date.month - 1;
77 +
78 + if (endHeight <= 0) {
79 + endHeight = dates.values.toList()[dates.length - 1];
80 + final preLastDate = dateFormat.parse(dates.keys.elementAt(dates.keys.length - 2));
81 + preLastYear = preLastDate.year;
82 + preLastMonth = preLastDate.month;
83 + } else {
84 + preLastYear = date.year;
85 + preLastMonth = date.month - 1;
86 + }
87 +
88 + if (preLastMonth <= 0) {
89 + preLastMonth = 12;
90 + preLastYear -= 1;
91 + }
92 +
93 + var startRaw = '$preLastYear' + '-' + '$preLastMonth';
94 + var startHeight = dates[startRaw];
95 + var diff = endHeight - startHeight;
96 + var heightPerDay = diff / 30;
97 + var daysHeight = date.day * heightPerDay.round();
98 + var height = endHeight + daysHeight;
99 +
100 + return height;
101 +}
lib/src/domain/monero/mnemonics/english.dart new
+1630
@@ -0,0 +1,1630 @@
1 +class EnglishMnemonics {
2 + static const words = [
3 + "abbey",
4 + "abducts",
5 + "ability",
6 + "ablaze",
7 + "abnormal",
8 + "abort",
9 + "abrasive",
10 + "absorb",
11 + "abyss",
12 + "academy",
13 + "aces",
14 + "aching",
15 + "acidic",
16 + "acoustic",
17 + "acquire",
18 + "across",
19 + "actress",
20 + "acumen",
21 + "adapt",
22 + "addicted",
23 + "adept",
24 + "adhesive",
25 + "adjust",
26 + "adopt",
27 + "adrenalin",
28 + "adult",
29 + "adventure",
30 + "aerial",
31 + "afar",
32 + "affair",
33 + "afield",
34 + "afloat",
35 + "afoot",
36 + "afraid",
37 + "after",
38 + "against",
39 + "agenda",
40 + "aggravate",
41 + "agile",
42 + "aglow",
43 + "agnostic",
44 + "agony",
45 + "agreed",
46 + "ahead",
47 + "aided",
48 + "ailments",
49 + "aimless",
50 + "airport",
51 + "aisle",
52 + "ajar",
53 + "akin",
54 + "alarms",
55 + "album",
56 + "alchemy",
57 + "alerts",
58 + "algebra",
59 + "alkaline",
60 + "alley",
61 + "almost",
62 + "aloof",
63 + "alpine",
64 + "already",
65 + "also",
66 + "altitude",
67 + "alumni",
68 + "always",
69 + "amaze",
70 + "ambush",
71 + "amended",
72 + "amidst",
73 + "ammo",
74 + "amnesty",
75 + "among",
76 + "amply",
77 + "amused",
78 + "anchor",
79 + "android",
80 + "anecdote",
81 + "angled",
82 + "ankle",
83 + "annoyed",
84 + "answers",
85 + "antics",
86 + "anvil",
87 + "anxiety",
88 + "anybody",
89 + "apart",
90 + "apex",
91 + "aphid",
92 + "aplomb",
93 + "apology",
94 + "apply",
95 + "apricot",
96 + "aptitude",
97 + "aquarium",
98 + "arbitrary",
99 + "archer",
100 + "ardent",
101 + "arena",
102 + "argue",
103 + "arises",
104 + "army",
105 + "around",
106 + "arrow",
107 + "arsenic",
108 + "artistic",
109 + "ascend",
110 + "ashtray",
111 + "aside",
112 + "asked",
113 + "asleep",
114 + "aspire",
115 + "assorted",
116 + "asylum",
117 + "athlete",
118 + "atlas",
119 + "atom",
120 + "atrium",
121 + "attire",
122 + "auburn",
123 + "auctions",
124 + "audio",
125 + "august",
126 + "aunt",
127 + "austere",
128 + "autumn",
129 + "avatar",
130 + "avidly",
131 + "avoid",
132 + "awakened",
133 + "awesome",
134 + "awful",
135 + "awkward",
136 + "awning",
137 + "awoken",
138 + "axes",
139 + "axis",
140 + "axle",
141 + "aztec",
142 + "azure",
143 + "baby",
144 + "bacon",
145 + "badge",
146 + "baffles",
147 + "bagpipe",
148 + "bailed",
149 + "bakery",
150 + "balding",
151 + "bamboo",
152 + "banjo",
153 + "baptism",
154 + "basin",
155 + "batch",
156 + "bawled",
157 + "bays",
158 + "because",
159 + "beer",
160 + "befit",
161 + "begun",
162 + "behind",
163 + "being",
164 + "below",
165 + "bemused",
166 + "benches",
167 + "berries",
168 + "bested",
169 + "betting",
170 + "bevel",
171 + "beware",
172 + "beyond",
173 + "bias",
174 + "bicycle",
175 + "bids",
176 + "bifocals",
177 + "biggest",
178 + "bikini",
179 + "bimonthly",
180 + "binocular",
181 + "biology",
182 + "biplane",
183 + "birth",
184 + "biscuit",
185 + "bite",
186 + "biweekly",
187 + "blender",
188 + "blip",
189 + "bluntly",
190 + "boat",
191 + "bobsled",
192 + "bodies",
193 + "bogeys",
194 + "boil",
195 + "boldly",
196 + "bomb",
197 + "border",
198 + "boss",
199 + "both",
200 + "bounced",
201 + "bovine",
202 + "bowling",
203 + "boxes",
204 + "boyfriend",
205 + "broken",
206 + "brunt",
207 + "bubble",
208 + "buckets",
209 + "budget",
210 + "buffet",
211 + "bugs",
212 + "building",
213 + "bulb",
214 + "bumper",
215 + "bunch",
216 + "business",
217 + "butter",
218 + "buying",
219 + "buzzer",
220 + "bygones",
221 + "byline",
222 + "bypass",
223 + "cabin",
224 + "cactus",
225 + "cadets",
226 + "cafe",
227 + "cage",
228 + "cajun",
229 + "cake",
230 + "calamity",
231 + "camp",
232 + "candy",
233 + "casket",
234 + "catch",
235 + "cause",
236 + "cavernous",
237 + "cease",
238 + "cedar",
239 + "ceiling",
240 + "cell",
241 + "cement",
242 + "cent",
243 + "certain",
244 + "chlorine",
245 + "chrome",
246 + "cider",
247 + "cigar",
248 + "cinema",
249 + "circle",
250 + "cistern",
251 + "citadel",
252 + "civilian",
253 + "claim",
254 + "click",
255 + "clue",
256 + "coal",
257 + "cobra",
258 + "cocoa",
259 + "code",
260 + "coexist",
261 + "coffee",
262 + "cogs",
263 + "cohesive",
264 + "coils",
265 + "colony",
266 + "comb",
267 + "cool",
268 + "copy",
269 + "corrode",
270 + "costume",
271 + "cottage",
272 + "cousin",
273 + "cowl",
274 + "criminal",
275 + "cube",
276 + "cucumber",
277 + "cuddled",
278 + "cuffs",
279 + "cuisine",
280 + "cunning",
281 + "cupcake",
282 + "custom",
283 + "cycling",
284 + "cylinder",
285 + "cynical",
286 + "dabbing",
287 + "dads",
288 + "daft",
289 + "dagger",
290 + "daily",
291 + "damp",
292 + "dangerous",
293 + "dapper",
294 + "darted",
295 + "dash",
296 + "dating",
297 + "dauntless",
298 + "dawn",
299 + "daytime",
300 + "dazed",
301 + "debut",
302 + "decay",
303 + "dedicated",
304 + "deepest",
305 + "deftly",
306 + "degrees",
307 + "dehydrate",
308 + "deity",
309 + "dejected",
310 + "delayed",
311 + "demonstrate",
312 + "dented",
313 + "deodorant",
314 + "depth",
315 + "desk",
316 + "devoid",
317 + "dewdrop",
318 + "dexterity",
319 + "dialect",
320 + "dice",
321 + "diet",
322 + "different",
323 + "digit",
324 + "dilute",
325 + "dime",
326 + "dinner",
327 + "diode",
328 + "diplomat",
329 + "directed",
330 + "distance",
331 + "ditch",
332 + "divers",
333 + "dizzy",
334 + "doctor",
335 + "dodge",
336 + "does",
337 + "dogs",
338 + "doing",
339 + "dolphin",
340 + "domestic",
341 + "donuts",
342 + "doorway",
343 + "dormant",
344 + "dosage",
345 + "dotted",
346 + "double",
347 + "dove",
348 + "down",
349 + "dozen",
350 + "dreams",
351 + "drinks",
352 + "drowning",
353 + "drunk",
354 + "drying",
355 + "dual",
356 + "dubbed",
357 + "duckling",
358 + "dude",
359 + "duets",
360 + "duke",
361 + "dullness",
362 + "dummy",
363 + "dunes",
364 + "duplex",
365 + "duration",
366 + "dusted",
367 + "duties",
368 + "dwarf",
369 + "dwelt",
370 + "dwindling",
371 + "dying",
372 + "dynamite",
373 + "dyslexic",
374 + "each",
375 + "eagle",
376 + "earth",
377 + "easy",
378 + "eating",
379 + "eavesdrop",
380 + "eccentric",
381 + "echo",
382 + "eclipse",
383 + "economics",
384 + "ecstatic",
385 + "eden",
386 + "edgy",
387 + "edited",
388 + "educated",
389 + "eels",
390 + "efficient",
391 + "eggs",
392 + "egotistic",
393 + "eight",
394 + "either",
395 + "eject",
396 + "elapse",
397 + "elbow",
398 + "eldest",
399 + "eleven",
400 + "elite",
401 + "elope",
402 + "else",
403 + "eluded",
404 + "emails",
405 + "ember",
406 + "emerge",
407 + "emit",
408 + "emotion",
409 + "empty",
410 + "emulate",
411 + "energy",
412 + "enforce",
413 + "enhanced",
414 + "enigma",
415 + "enjoy",
416 + "enlist",
417 + "enmity",
418 + "enough",
419 + "enraged",
420 + "ensign",
421 + "entrance",
422 + "envy",
423 + "epoxy",
424 + "equip",
425 + "erase",
426 + "erected",
427 + "erosion",
428 + "error",
429 + "eskimos",
430 + "espionage",
431 + "essential",
432 + "estate",
433 + "etched",
434 + "eternal",
435 + "ethics",
436 + "etiquette",
437 + "evaluate",
438 + "evenings",
439 + "evicted",
440 + "evolved",
441 + "examine",
442 + "excess",
443 + "exhale",
444 + "exit",
445 + "exotic",
446 + "exquisite",
447 + "extra",
448 + "exult",
449 + "fabrics",
450 + "factual",
451 + "fading",
452 + "fainted",
453 + "faked",
454 + "fall",
455 + "family",
456 + "fancy",
457 + "farming",
458 + "fatal",
459 + "faulty",
460 + "fawns",
461 + "faxed",
462 + "fazed",
463 + "feast",
464 + "february",
465 + "federal",
466 + "feel",
467 + "feline",
468 + "females",
469 + "fences",
470 + "ferry",
471 + "festival",
472 + "fetches",
473 + "fever",
474 + "fewest",
475 + "fiat",
476 + "fibula",
477 + "fictional",
478 + "fidget",
479 + "fierce",
480 + "fifteen",
481 + "fight",
482 + "films",
483 + "firm",
484 + "fishing",
485 + "fitting",
486 + "five",
487 + "fixate",
488 + "fizzle",
489 + "fleet",
490 + "flippant",
491 + "flying",
492 + "foamy",
493 + "focus",
494 + "foes",
495 + "foggy",
496 + "foiled",
497 + "folding",
498 + "fonts",
499 + "foolish",
500 + "fossil",
501 + "fountain",
502 + "fowls",
503 + "foxes",
504 + "foyer",
505 + "framed",
506 + "friendly",
507 + "frown",
508 + "fruit",
509 + "frying",
510 + "fudge",
511 + "fuel",
512 + "fugitive",
513 + "fully",
514 + "fuming",
515 + "fungal",
516 + "furnished",
517 + "fuselage",
518 + "future",
519 + "fuzzy",
520 + "gables",
521 + "gadget",
522 + "gags",
523 + "gained",
524 + "galaxy",
525 + "gambit",
526 + "gang",
527 + "gasp",
528 + "gather",
529 + "gauze",
530 + "gave",
531 + "gawk",
532 + "gaze",
533 + "gearbox",
534 + "gecko",
535 + "geek",
536 + "gels",
537 + "gemstone",
538 + "general",
539 + "geometry",
540 + "germs",
541 + "gesture",
542 + "getting",
543 + "geyser",
544 + "ghetto",
545 + "ghost",
546 + "giant",
547 + "giddy",
548 + "gifts",
549 + "gigantic",
550 + "gills",
551 + "gimmick",
552 + "ginger",
553 + "girth",
554 + "giving",
555 + "glass",
556 + "gleeful",
557 + "glide",
558 + "gnaw",
559 + "gnome",
560 + "goat",
561 + "goblet",
562 + "godfather",
563 + "goes",
564 + "goggles",
565 + "going",
566 + "goldfish",
567 + "gone",
568 + "goodbye",
569 + "gopher",
570 + "gorilla",
571 + "gossip",
572 + "gotten",
573 + "gourmet",
574 + "governing",
575 + "gown",
576 + "greater",
577 + "grunt",
578 + "guarded",
579 + "guest",
580 + "guide",
581 + "gulp",
582 + "gumball",
583 + "guru",
584 + "gusts",
585 + "gutter",
586 + "guys",
587 + "gymnast",
588 + "gypsy",
589 + "gyrate",
590 + "habitat",
591 + "hacksaw",
592 + "haggled",
593 + "hairy",
594 + "hamburger",
595 + "happens",
596 + "hashing",
597 + "hatchet",
598 + "haunted",
599 + "having",
600 + "hawk",
601 + "haystack",
602 + "hazard",
603 + "hectare",
604 + "hedgehog",
605 + "heels",
606 + "hefty",
607 + "height",
608 + "hemlock",
609 + "hence",
610 + "heron",
611 + "hesitate",
612 + "hexagon",
613 + "hickory",
614 + "hiding",
615 + "highway",
616 + "hijack",
617 + "hiker",
618 + "hills",
619 + "himself",
620 + "hinder",
621 + "hippo",
622 + "hire",
623 + "history",
624 + "hitched",
625 + "hive",
626 + "hoax",
627 + "hobby",
628 + "hockey",
629 + "hoisting",
630 + "hold",
631 + "honked",
632 + "hookup",
633 + "hope",
634 + "hornet",
635 + "hospital",
636 + "hotel",
637 + "hounded",
638 + "hover",
639 + "howls",
640 + "hubcaps",
641 + "huddle",
642 + "huge",
643 + "hull",
644 + "humid",
645 + "hunter",
646 + "hurried",
647 + "husband",
648 + "huts",
649 + "hybrid",
650 + "hydrogen",
651 + "hyper",
652 + "iceberg",
653 + "icing",
654 + "icon",
655 + "identity",
656 + "idiom",
657 + "idled",
658 + "idols",
659 + "igloo",
660 + "ignore",
661 + "iguana",
662 + "illness",
663 + "imagine",
664 + "imbalance",
665 + "imitate",
666 + "impel",
667 + "inactive",
668 + "inbound",
669 + "incur",
670 + "industrial",
671 + "inexact",
672 + "inflamed",
673 + "ingested",
674 + "initiate",
675 + "injury",
676 + "inkling",
677 + "inline",
678 + "inmate",
679 + "innocent",
680 + "inorganic",
681 + "input",
682 + "inquest",
683 + "inroads",
684 + "insult",
685 + "intended",
686 + "inundate",
687 + "invoke",
688 + "inwardly",
689 + "ionic",
690 + "irate",
691 + "iris",
692 + "irony",
693 + "irritate",
694 + "island",
695 + "isolated",
696 + "issued",
697 + "italics",
698 + "itches",
699 + "items",
700 + "itinerary",
701 + "itself",
702 + "ivory",
703 + "jabbed",
704 + "jackets",
705 + "jaded",
706 + "jagged",
707 + "jailed",
708 + "jamming",
709 + "january",
710 + "jargon",
711 + "jaunt",
712 + "javelin",
713 + "jaws",
714 + "jazz",
715 + "jeans",
716 + "jeers",
717 + "jellyfish",
718 + "jeopardy",
719 + "jerseys",
720 + "jester",
721 + "jetting",
722 + "jewels",
723 + "jigsaw",
724 + "jingle",
725 + "jittery",
726 + "jive",
727 + "jobs",
728 + "jockey",
729 + "jogger",
730 + "joining",
731 + "joking",
732 + "jolted",
733 + "jostle",
734 + "journal",
735 + "joyous",
736 + "jubilee",
737 + "judge",
738 + "juggled",
739 + "juicy",
740 + "jukebox",
741 + "july",
742 + "jump",
743 + "junk",
744 + "jury",
745 + "justice",
746 + "juvenile",
747 + "kangaroo",
748 + "karate",
749 + "keep",
750 + "kennel",
751 + "kept",
752 + "kernels",
753 + "kettle",
754 + "keyboard",
755 + "kickoff",
756 + "kidneys",
757 + "king",
758 + "kiosk",
759 + "kisses",
760 + "kitchens",
761 + "kiwi",
762 + "knapsack",
763 + "knee",
764 + "knife",
765 + "knowledge",
766 + "knuckle",
767 + "koala",
768 + "laboratory",
769 + "ladder",
770 + "lagoon",
771 + "lair",
772 + "lakes",
773 + "lamb",
774 + "language",
775 + "laptop",
776 + "large",
777 + "last",
778 + "later",
779 + "launching",
780 + "lava",
781 + "lawsuit",
782 + "layout",
783 + "lazy",
784 + "lectures",
785 + "ledge",
786 + "leech",
787 + "left",
788 + "legion",
789 + "leisure",
790 + "lemon",
791 + "lending",
792 + "leopard",
793 + "lesson",
794 + "lettuce",
795 + "lexicon",
796 + "liar",
797 + "library",
798 + "licks",
799 + "lids",
800 + "lied",
801 + "lifestyle",
802 + "light",
803 + "likewise",
804 + "lilac",
805 + "limits",
806 + "linen",
807 + "lion",
808 + "lipstick",
809 + "liquid",
810 + "listen",
811 + "lively",
812 + "loaded",
813 + "lobster",
814 + "locker",
815 + "lodge",
816 + "lofty",
817 + "logic",
818 + "loincloth",
819 + "long",
820 + "looking",
821 + "lopped",
822 + "lordship",
823 + "losing",
824 + "lottery",
825 + "loudly",
826 + "love",
827 + "lower",
828 + "loyal",
829 + "lucky",
830 + "luggage",
831 + "lukewarm",
832 + "lullaby",
833 + "lumber",
834 + "lunar",
835 + "lurk",
836 + "lush",
837 + "luxury",
838 + "lymph",
839 + "lynx",
840 + "lyrics",
841 + "macro",
842 + "madness",
843 + "magically",
844 + "mailed",
845 + "major",
846 + "makeup",
847 + "malady",
848 + "mammal",
849 + "maps",
850 + "masterful",
851 + "match",
852 + "maul",
853 + "maverick",
854 + "maximum",
855 + "mayor",
856 + "maze",
857 + "meant",
858 + "mechanic",
859 + "medicate",
860 + "meeting",
861 + "megabyte",
862 + "melting",
863 + "memoir",
864 + "menu",
865 + "merger",
866 + "mesh",
867 + "metro",
868 + "mews",
869 + "mice",
870 + "midst",
871 + "mighty",
872 + "mime",
873 + "mirror",
874 + "misery",
875 + "mittens",
876 + "mixture",
877 + "moat",
878 + "mobile",
879 + "mocked",
880 + "mohawk",
881 + "moisture",
882 + "molten",
883 + "moment",
884 + "money",
885 + "moon",
886 + "mops",
887 + "morsel",
888 + "mostly",
889 + "motherly",
890 + "mouth",
891 + "movement",
892 + "mowing",
893 + "much",
894 + "muddy",
895 + "muffin",
896 + "mugged",
897 + "mullet",
898 + "mumble",
899 + "mundane",
900 + "muppet",
901 + "mural",
902 + "musical",
903 + "muzzle",
904 + "myriad",
905 + "mystery",
906 + "myth",
907 + "nabbing",
908 + "nagged",
909 + "nail",
910 + "names",
911 + "nanny",
912 + "napkin",
913 + "narrate",
914 + "nasty",
915 + "natural",
916 + "nautical",
917 + "navy",
918 + "nearby",
919 + "necklace",
920 + "needed",
921 + "negative",
922 + "neither",
923 + "neon",
924 + "nephew",
925 + "nerves",
926 + "nestle",
927 + "network",
928 + "neutral",
929 + "never",
930 + "newt",
931 + "nexus",
932 + "nibs",
933 + "niche",
934 + "niece",
935 + "nifty",
936 + "nightly",
937 + "nimbly",
938 + "nineteen",
939 + "nirvana",
940 + "nitrogen",
941 + "nobody",
942 + "nocturnal",
943 + "nodes",
944 + "noises",
945 + "nomad",
946 + "noodles",
947 + "northern",
948 + "nostril",
949 + "noted",
950 + "nouns",
951 + "novelty",
952 + "nowhere",
953 + "nozzle",
954 + "nuance",
955 + "nucleus",
956 + "nudged",
957 + "nugget",
958 + "nuisance",
959 + "null",
960 + "number",
961 + "nuns",
962 + "nurse",
963 + "nutshell",
964 + "nylon",
965 + "oaks",
966 + "oars",
967 + "oasis",
968 + "oatmeal",
969 + "obedient",
970 + "object",
971 + "obliged",
972 + "obnoxious",
973 + "observant",
974 + "obtains",
975 + "obvious",
976 + "occur",
977 + "ocean",
978 + "october",
979 + "odds",
980 + "odometer",
981 + "offend",
982 + "often",
983 + "oilfield",
984 + "ointment",
985 + "okay",
986 + "older",
987 + "olive",
988 + "olympics",
989 + "omega",
990 + "omission",
991 + "omnibus",
992 + "onboard",
993 + "oncoming",
994 + "oneself",
995 + "ongoing",
996 + "onion",
997 + "online",
998 + "onslaught",
999 + "onto",
1000 + "onward",
1001 + "oozed",
1002 + "opacity",
1003 + "opened",
1004 + "opposite",
1005 + "optical",
1006 + "opus",
1007 + "orange",
1008 + "orbit",
1009 + "orchid",
1010 + "orders",
1011 + "organs",
1012 + "origin",
1013 + "ornament",
1014 + "orphans",
1015 + "oscar",
1016 + "ostrich",
1017 + "otherwise",
1018 + "otter",
1019 + "ouch",
1020 + "ought",
1021 + "ounce",
1022 + "ourselves",
1023 + "oust",
1024 + "outbreak",
1025 + "oval",
1026 + "oven",
1027 + "owed",
1028 + "owls",
1029 + "owner",
1030 + "oxidant",
1031 + "oxygen",
1032 + "oyster",
1033 + "ozone",
1034 + "pact",
1035 + "paddles",
1036 + "pager",
1037 + "pairing",
1038 + "palace",
1039 + "pamphlet",
1040 + "pancakes",
1041 + "paper",
1042 + "paradise",
1043 + "pastry",
1044 + "patio",
1045 + "pause",
1046 + "pavements",
1047 + "pawnshop",
1048 + "payment",
1049 + "peaches",
1050 + "pebbles",
1051 + "peculiar",
1052 + "pedantic",
1053 + "peeled",
1054 + "pegs",
1055 + "pelican",
1056 + "pencil",
1057 + "people",
1058 + "pepper",
1059 + "perfect",
1060 + "pests",
1061 + "petals",
1062 + "phase",
1063 + "pheasants",
1064 + "phone",
1065 + "phrases",
1066 + "physics",
1067 + "piano",
1068 + "picked",
1069 + "pierce",
1070 + "pigment",
1071 + "piloted",
1072 + "pimple",
1073 + "pinched",
1074 + "pioneer",
1075 + "pipeline",
1076 + "pirate",
1077 + "pistons",
1078 + "pitched",
1079 + "pivot",
1080 + "pixels",
1081 + "pizza",
1082 + "playful",
1083 + "pledge",
1084 + "pliers",
1085 + "plotting",
1086 + "plus",
1087 + "plywood",
1088 + "poaching",
1089 + "pockets",
1090 + "podcast",
1091 + "poetry",
1092 + "point",
1093 + "poker",
1094 + "polar",
1095 + "ponies",
1096 + "pool",
1097 + "popular",
1098 + "portents",
1099 + "possible",
1100 + "potato",
1101 + "pouch",
1102 + "poverty",
1103 + "powder",
1104 + "pram",
1105 + "present",
1106 + "pride",
1107 + "problems",
1108 + "pruned",
1109 + "prying",
1110 + "psychic",
1111 + "public",
1112 + "puck",
1113 + "puddle",
1114 + "puffin",
1115 + "pulp",
1116 + "pumpkins",
1117 + "punch",
1118 + "puppy",
1119 + "purged",
1120 + "push",
1121 + "putty",
1122 + "puzzled",
1123 + "pylons",
1124 + "pyramid",
1125 + "python",
1126 + "queen",
1127 + "quick",
1128 + "quote",
1129 + "rabbits",
1130 + "racetrack",
1131 + "radar",
1132 + "rafts",
1133 + "rage",
1134 + "railway",
1135 + "raking",
1136 + "rally",
1137 + "ramped",
1138 + "randomly",
1139 + "rapid",
1140 + "rarest",
1141 + "rash",
1142 + "rated",
1143 + "ravine",
1144 + "rays",
1145 + "razor",
1146 + "react",
1147 + "rebel",
1148 + "recipe",
1149 + "reduce",
1150 + "reef",
1151 + "refer",
1152 + "regular",
1153 + "reheat",
1154 + "reinvest",
1155 + "rejoices",
1156 + "rekindle",
1157 + "relic",
1158 + "remedy",
1159 + "renting",
1160 + "reorder",
1161 + "repent",
1162 + "request",
1163 + "reruns",
1164 + "rest",
1165 + "return",
1166 + "reunion",
1167 + "revamp",
1168 + "rewind",
1169 + "rhino",
1170 + "rhythm",
1171 + "ribbon",
1172 + "richly",
1173 + "ridges",
1174 + "rift",
1175 + "rigid",
1176 + "rims",
1177 + "ringing",
1178 + "riots",
1179 + "ripped",
1180 + "rising",
1181 + "ritual",
1182 + "river",
1183 + "roared",
1184 + "robot",
1185 + "rockets",
1186 + "rodent",
1187 + "rogue",
1188 + "roles",
1189 + "romance",
1190 + "roomy",
1191 + "roped",
1192 + "roster",
1193 + "rotate",
1194 + "rounded",
1195 + "rover",
1196 + "rowboat",
1197 + "royal",
1198 + "ruby",
1199 + "rudely",
1200 + "ruffled",
1201 + "rugged",
1202 + "ruined",
1203 + "ruling",
1204 + "rumble",
1205 + "runway",
1206 + "rural",
1207 + "rustled",
1208 + "ruthless",
1209 + "sabotage",
1210 + "sack",
1211 + "sadness",
1212 + "safety",
1213 + "saga",
1214 + "sailor",
1215 + "sake",
1216 + "salads",
1217 + "sample",
1218 + "sanity",
1219 + "sapling",
1220 + "sarcasm",
1221 + "sash",
1222 + "satin",
1223 + "saucepan",
1224 + "saved",
1225 + "sawmill",
1226 + "saxophone",
1227 + "sayings",
1228 + "scamper",
1229 + "scenic",
1230 + "school",
1231 + "science",
1232 + "scoop",
1233 + "scrub",
1234 + "scuba",
1235 + "seasons",
1236 + "second",
1237 + "sedan",
1238 + "seeded",
1239 + "segments",
1240 + "seismic",
1241 + "selfish",
1242 + "semifinal",
1243 + "sensible",
1244 + "september",
1245 + "sequence",
1246 + "serving",
1247 + "session",
1248 + "setup",
1249 + "seventh",
1250 + "sewage",
1251 + "shackles",
1252 + "shelter",
1253 + "shipped",
1254 + "shocking",
1255 + "shrugged",
1256 + "shuffled",
1257 + "shyness",
1258 + "siblings",
1259 + "sickness",
1260 + "sidekick",
1261 + "sieve",
1262 + "sifting",
1263 + "sighting",
1264 + "silk",
1265 + "simplest",
1266 + "sincerely",
1267 + "sipped",
1268 + "siren",
1269 + "situated",
1270 + "sixteen",
1271 + "sizes",
1272 + "skater",
1273 + "skew",
1274 + "skirting",
1275 + "skulls",
1276 + "skydive",
1277 + "slackens",
1278 + "sleepless",
1279 + "slid",
1280 + "slower",
1281 + "slug",
1282 + "smash",
1283 + "smelting",
1284 + "smidgen",
1285 + "smog",
1286 + "smuggled",
1287 + "snake",
1288 + "sneeze",
1289 + "sniff",
1290 + "snout",
1291 + "snug",
1292 + "soapy",
1293 + "sober",
1294 + "soccer",
1295 + "soda",
1296 + "software",
1297 + "soggy",
1298 + "soil",
1299 + "solved",
1300 + "somewhere",
1301 + "sonic",
1302 + "soothe",
1303 + "soprano",
1304 + "sorry",
1305 + "southern",
1306 + "sovereign",
1307 + "sowed",
1308 + "soya",
1309 + "space",
1310 + "speedy",
1311 + "sphere",
1312 + "spiders",
1313 + "splendid",
1314 + "spout",
1315 + "sprig",
1316 + "spud",
1317 + "spying",
1318 + "square",
1319 + "stacking",
1320 + "stellar",
1321 + "stick",
1322 + "stockpile",
1323 + "strained",
1324 + "stunning",
1325 + "stylishly",
1326 + "subtly",
1327 + "succeed",
1328 + "suddenly",
1329 + "suede",
1330 + "suffice",
1331 + "sugar",
1332 + "suitcase",
1333 + "sulking",
1334 + "summon",
1335 + "sunken",
1336 + "superior",
1337 + "surfer",
1338 + "sushi",
1339 + "suture",
1340 + "swagger",
1341 + "swept",
1342 + "swiftly",
1343 + "sword",
1344 + "swung",
1345 + "syllabus",
1346 + "symptoms",
1347 + "syndrome",
1348 + "syringe",
1349 + "system",
1350 + "taboo",
1351 + "tacit",
1352 + "tadpoles",
1353 + "tagged",
1354 + "tail",
1355 + "taken",
1356 + "talent",
1357 + "tamper",
1358 + "tanks",
1359 + "tapestry",
1360 + "tarnished",
1361 + "tasked",
1362 + "tattoo",
1363 + "taunts",
1364 + "tavern",
1365 + "tawny",
1366 + "taxi",
1367 + "teardrop",
1368 + "technical",
1369 + "tedious",
1370 + "teeming",
1371 + "tell",
1372 + "template",
1373 + "tender",
1374 + "tepid",
1375 + "tequila",
1376 + "terminal",
1377 + "testing",
1378 + "tether",
1379 + "textbook",
1380 + "thaw",
1381 + "theatrics",
1382 + "thirsty",
1383 + "thorn",
1384 + "threaten",
1385 + "thumbs",
1386 + "thwart",
1387 + "ticket",
1388 + "tidy",
1389 + "tiers",
1390 + "tiger",
1391 + "tilt",
1392 + "timber",
1393 + "tinted",
1394 + "tipsy",
1395 + "tirade",
1396 + "tissue",
1397 + "titans",
1398 + "toaster",
1399 + "tobacco",
1400 + "today",
1401 + "toenail",
1402 + "toffee",
1403 + "together",
1404 + "toilet",
1405 + "token",
1406 + "tolerant",
1407 + "tomorrow",
1408 + "tonic",
1409 + "toolbox",
1410 + "topic",
1411 + "torch",
1412 + "tossed",
1413 + "total",
1414 + "touchy",
1415 + "towel",
1416 + "toxic",
1417 + "toyed",
1418 + "trash",
1419 + "trendy",
1420 + "tribal",
1421 + "trolling",
1422 + "truth",
1423 + "trying",
1424 + "tsunami",
1425 + "tubes",
1426 + "tucks",
1427 + "tudor",
1428 + "tuesday",
1429 + "tufts",
1430 + "tugs",
1431 + "tuition",
1432 + "tulips",
1433 + "tumbling",
1434 + "tunnel",
1435 + "turnip",
1436 + "tusks",
1437 + "tutor",
1438 + "tuxedo",
1439 + "twang",
1440 + "tweezers",
1441 + "twice",
1442 + "twofold",
1443 + "tycoon",
1444 + "typist",
1445 + "tyrant",
1446 + "ugly",
1447 + "ulcers",
1448 + "ultimate",
1449 + "umbrella",
1450 + "umpire",
1451 + "unafraid",
1452 + "unbending",
1453 + "uncle",
1454 + "under",
1455 + "uneven",
1456 + "unfit",
1457 + "ungainly",
1458 + "unhappy",
1459 + "union",
1460 + "unjustly",
1461 + "unknown",
1462 + "unlikely",
1463 + "unmask",
1464 + "unnoticed",
1465 + "unopened",
1466 + "unplugs",
1467 + "unquoted",
1468 + "unrest",
1469 + "unsafe",
1470 + "until",
1471 + "unusual",
1472 + "unveil",
1473 + "unwind",
1474 + "unzip",
1475 + "upbeat",
1476 + "upcoming",
1477 + "update",
1478 + "upgrade",
1479 + "uphill",
1480 + "upkeep",
1481 + "upload",
1482 + "upon",
1483 + "upper",
1484 + "upright",
1485 + "upstairs",
1486 + "uptight",
1487 + "upwards",
1488 + "urban",
1489 + "urchins",
1490 + "urgent",
1491 + "usage",
1492 + "useful",
1493 + "usher",
1494 + "using",
1495 + "usual",
1496 + "utensils",
1497 + "utility",
1498 + "utmost",
1499 + "utopia",
1500 + "uttered",
1501 + "vacation",
1502 + "vague",
1503 + "vain",
1504 + "value",
1505 + "vampire",
1506 + "vane",
1507 + "vapidly",
1508 + "vary",
1509 + "vastness",
1510 + "vats",
1511 + "vaults",
1512 + "vector",
1513 + "veered",
1514 + "vegan",
1515 + "vehicle",
1516 + "vein",
1517 + "velvet",
1518 + "venomous",
1519 + "verification",
1520 + "vessel",
1521 + "veteran",
1522 + "vexed",
1523 + "vials",
1524 + "vibrate",
1525 + "victim",
1526 + "video",
1527 + "viewpoint",
1528 + "vigilant",
1529 + "viking",
1530 + "village",
1531 + "vinegar",
1532 + "violin",
1533 + "vipers",
1534 + "virtual",
1535 + "visited",
1536 + "vitals",
1537 + "vivid",
1538 + "vixen",
1539 + "vocal",
1540 + "vogue",
1541 + "voice",
1542 + "volcano",
1543 + "vortex",
1544 + "voted",
1545 + "voucher",
1546 + "vowels",
1547 + "voyage",
1548 + "vulture",
1549 + "wade",
1550 + "waffle",
1551 + "wagtail",
1552 + "waist",
1553 + "waking",
1554 + "wallets",
1555 + "wanted",
1556 + "warped",
1557 + "washing",
1558 + "water",
1559 + "waveform",
1560 + "waxing",
1561 + "wayside",
1562 + "weavers",
1563 + "website",
1564 + "wedge",
1565 + "weekday",
1566 + "weird",
1567 + "welders",
1568 + "went",
1569 + "wept",
1570 + "were",
1571 + "western",
1572 + "wetsuit",
1573 + "whale",
1574 + "when",
1575 + "whipped",
1576 + "whole",
1577 + "wickets",
1578 + "width",
1579 + "wield",
1580 + "wife",
1581 + "wiggle",
1582 + "wildly",
1583 + "winter",
1584 + "wipeout",
1585 + "wiring",
1586 + "wise",
1587 + "withdrawn",
1588 + "wives",
1589 + "wizard",
1590 + "wobbly",
1591 + "woes",
1592 + "woken",
1593 + "wolf",
1594 + "womanly",
1595 + "wonders",
1596 + "woozy",
1597 + "worry",
1598 + "wounded",
1599 + "woven",
1600 + "wrap",
1601 + "wrist",
1602 + "wrong",
1603 + "yacht",
1604 + "yahoo",
1605 + "yanks",
1606 + "yard",
1607 + "yawning",
1608 + "yearbook",
1609 + "yellow",
1610 + "yesterday",
1611 + "yeti",
1612 + "yields",
1613 + "yodel",
1614 + "yoga",
1615 + "younger",
1616 + "yoyo",
1617 + "zapped",
1618 + "zeal",
1619 + "zebra",
1620 + "zero",
1621 + "zesty",
1622 + "zigzags",
1623 + "zinger",
1624 + "zippers",
1625 + "zodiac",
1626 + "zombie",
1627 + "zones",
1628 + "zoom"
1629 + ];
1630 +}
lib/src/domain/monero/monero_amount_format.dart new
+12
@@ -0,0 +1,12 @@
1 +import 'package:intl/intl.dart';
2 +
3 +const moneroAmountLength = 12;
4 +const moneroAmountDivider = 1000000000000;
5 +final moneroAmountFormat = NumberFormat()
6 + ..maximumFractionDigits = moneroAmountLength
7 + ..minimumFractionDigits = 1;
8 +
9 +String moneroAmountToString({int amount}) =>
10 + moneroAmountFormat.format(amount / moneroAmountDivider);
11 +
12 +double moneroAmountToDouble({int amount}) => amount / moneroAmountDivider;
lib/src/domain/monero/monero_balance.dart new
+9
@@ -0,0 +1,9 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:cake_wallet/src/domain/common/balance.dart';
3 +
4 +class MoneroBalance extends Balance {
5 + final String fullBalance;
6 + final String unlockedBalance;
7 +
8 + MoneroBalance({@required this.fullBalance, @required this.unlockedBalance});
9 +}
lib/src/domain/monero/monero_transaction_creation_credentials.dart new
+13
@@ -0,0 +1,13 @@
1 +import 'package:cake_wallet/src/domain/common/transaction_creation_credentials.dart';
2 +import 'package:cake_wallet/src/domain/common/transaction_priority.dart';
3 +
4 +class MoneroTransactionCreationCredentials
5 + extends TransactionCreationCredentials {
6 + final String address;
7 + final String paymentId;
8 + final String amount;
9 + final TransactionPriority priority;
10 +
11 + MoneroTransactionCreationCredentials(
12 + {this.address, this.paymentId, this.priority, this.amount});
13 +}
\ No newline at end of file
lib/src/domain/monero/monero_transaction_history.dart new
+65
@@ -0,0 +1,65 @@
1 +import 'dart:core';
2 +import 'package:flutter/services.dart';
3 +import 'package:rxdart/rxdart.dart';
4 +import 'package:cw_monero/transaction_history.dart' as moneroTransactionHistory;
5 +import 'package:cake_wallet/src/domain/common/transaction_history.dart';
6 +import 'package:cake_wallet/src/domain/common/transaction_info.dart';
7 +
8 +List<TransactionInfo> _getAllTransactions(_) => moneroTransactionHistory
9 + .getAllTransations()
10 + .map((row) => TransactionInfo.fromRow(row))
11 + .toList();
12 +
13 +class MoneroTransactionHistory extends TransactionHistory {
14 + get transactions => _transactions.stream;
15 + BehaviorSubject<List<TransactionInfo>> _transactions;
16 +
17 + bool _isUpdating = false;
18 + bool _isRefreshing = false;
19 + bool _needToCheckForRefresh = false;
20 +
21 + MoneroTransactionHistory()
22 + : _transactions = BehaviorSubject<List<TransactionInfo>>.seeded([]);
23 +
24 + Future update() async {
25 + if (_isUpdating) {
26 + return;
27 + }
28 +
29 + try {
30 + _isUpdating = true;
31 + await refresh();
32 + _transactions.value = await getAll(force: true);
33 + _isUpdating = false;
34 +
35 + if (!_needToCheckForRefresh) {
36 + _needToCheckForRefresh = true;
37 + }
38 + } catch (e) {
39 + _isUpdating = false;
40 + print(e);
41 + throw e;
42 + }
43 + }
44 +
45 + Future<List<TransactionInfo>> getAll({bool force = false}) async =>
46 + _getAllTransactions(null);
47 +
48 + Future<int> count() async => moneroTransactionHistory.countOfTransactions();
49 +
50 + Future refresh() async {
51 + if (_isRefreshing) {
52 + return;
53 + }
54 +
55 + try {
56 + _isRefreshing = true;
57 + moneroTransactionHistory.refreshTransactions();
58 + _isRefreshing = false;
59 + } on PlatformException catch (e) {
60 + _isRefreshing = false;
61 + print(e);
62 + throw e;
63 + }
64 + }
65 +}
lib/src/domain/monero/monero_wallet.dart new
+396
@@ -0,0 +1,396 @@
1 +import 'dart:async';
2 +import 'package:flutter/foundation.dart';
3 +import 'package:flutter/services.dart';
4 +import 'package:hive/hive.dart';
5 +import 'package:rxdart/rxdart.dart';
6 +import 'package:cw_monero/wallet.dart' as moneroWallet;
7 +import 'package:cw_monero/transaction_history.dart' as transactionHistory;
8 +import 'package:cake_wallet/src/domain/common/wallet_info.dart';
9 +import 'package:cake_wallet/src/domain/common/wallet.dart';
10 +import 'package:cake_wallet/src/domain/common/sync_status.dart';
11 +import 'package:cake_wallet/src/domain/common/transaction_history.dart';
12 +import 'package:cake_wallet/src/domain/common/transaction_creation_credentials.dart';
13 +import 'package:cake_wallet/src/domain/common/pending_transaction.dart';
14 +import 'package:cake_wallet/src/domain/common/wallet_type.dart';
15 +import 'package:cake_wallet/src/domain/common/node.dart';
16 +import 'package:cake_wallet/src/domain/monero/monero_amount_format.dart';
17 +import 'package:cake_wallet/src/domain/monero/account.dart';
18 +import 'package:cake_wallet/src/domain/monero/account_list.dart';
19 +import 'package:cake_wallet/src/domain/monero/subaddress_list.dart';
20 +import 'package:cake_wallet/src/domain/monero/monero_transaction_creation_credentials.dart';
21 +import 'package:cake_wallet/src/domain/monero/monero_transaction_history.dart';
22 +import 'package:cake_wallet/src/domain/monero/subaddress.dart';
23 +import 'package:cake_wallet/src/domain/common/balance.dart';
24 +import 'package:cake_wallet/src/domain/monero/monero_balance.dart';
25 +
26 +const monero_block_size = 1000;
27 +
28 +class MoneroWallet extends Wallet {
29 + static Future<MoneroWallet> createdWallet(
30 + {Box<WalletInfo> walletInfoSource,
31 + String name,
32 + bool isRecovery = false,
33 + int restoreHeight = 0}) async {
34 + const type = WalletType.monero;
35 + final id = walletTypeToString(type).toLowerCase() + '_' + name;
36 + final walletInfo = WalletInfo(
37 + id: id,
38 + name: name,
39 + type: type,
40 + isRecovery: isRecovery,
41 + restoreHeight: restoreHeight);
42 + await walletInfoSource.add(walletInfo);
43 +
44 + return await configured(
45 + walletInfo: walletInfo, walletInfoSource: walletInfoSource);
46 + }
47 +
48 + static Future<MoneroWallet> load(
49 + Box<WalletInfo> walletInfoSource, String name, WalletType type) async {
50 + final id = walletTypeToString(type).toLowerCase() + '_' + name;
51 + final walletInfo =
52 + walletInfoSource.values.firstWhere((info) => info.id == id, orElse: () => null);
53 + return await configured(
54 + walletInfoSource: walletInfoSource, walletInfo: walletInfo);
55 + }
56 +
57 + static Future<MoneroWallet> configured(
58 + {@required Box<WalletInfo> walletInfoSource,
59 + @required WalletInfo walletInfo}) async {
60 + final wallet = MoneroWallet(
61 + walletInfoSource: walletInfoSource, walletInfo: walletInfo);
62 +
63 + if (walletInfo.isRecovery) {
64 + await wallet.setRecoveringFromSeed();
65 +
66 + if (walletInfo.restoreHeight != null) {
67 + await wallet.setRefreshFromBlockHeight(
68 + height: walletInfo.restoreHeight);
69 + }
70 + }
71 +
72 + return wallet;
73 + }
74 +
75 + WalletType getType() => WalletType.monero;
76 + bool get isRecovery => walletInfo.isRecovery;
77 + Observable<SyncStatus> get syncStatus => _syncStatus.stream;
78 + Observable<Balance> get onBalanceChange => _onBalanceChange.stream;
79 + Observable<Account> get onAccountChange => _account.stream;
80 + Observable<String> get onNameChange => _name.stream;
81 + Observable<String> get onAddressChange => _address.stream;
82 + Observable<Subaddress> get subaddress => _subaddress.stream;
83 +
84 + Account get account => _account.value;
85 + String get address => _address.value;
86 + String get name => _name.value;
87 +
88 + Box<WalletInfo> walletInfoSource;
89 + WalletInfo walletInfo;
90 +
91 + BehaviorSubject<Account> _account;
92 + BehaviorSubject<MoneroBalance> _onBalanceChange;
93 + BehaviorSubject<SyncStatus> _syncStatus;
94 + BehaviorSubject<String> _name;
95 + BehaviorSubject<String> _address;
96 + BehaviorSubject<Subaddress> _subaddress;
97 + int _cachedBlockchainHeight;
98 + bool _isSaving;
99 + int _lastSaveTime;
100 + int _lastRefreshTime;
101 + int _refreshHeight;
102 + int _lastSyncHeight;
103 +
104 + TransactionHistory _cachedTransactionHistory;
105 + SubaddressList _cachedSubaddressList;
106 + AccountList _cachedAccountList;
107 +
108 + MoneroWallet(
109 + {this.walletInfoSource, this.walletInfo}) {
110 + _cachedBlockchainHeight = 0;
111 + _isSaving = false;
112 + _lastSaveTime = 0;
113 + _lastRefreshTime = 0;
114 + _refreshHeight = 0;
115 + _lastSyncHeight = 0;
116 + _name = BehaviorSubject<String>();
117 + _address = BehaviorSubject<String>();
118 + _syncStatus = BehaviorSubject<SyncStatus>();
119 + _onBalanceChange = BehaviorSubject<MoneroBalance>();
120 + _account = BehaviorSubject<Account>()..add(Account(id: 0));
121 + _subaddress = BehaviorSubject<Subaddress>();
122 + setListeners();
123 + }
124 +
125 + Future updateInfo() async {
126 + _name.value = await getName();
127 + final acccountList = getAccountList();
128 + await acccountList.refresh();
129 + _account.value = acccountList.getAll().first;
130 + final subaddressList = getSubaddress();
131 + await subaddressList.refresh(
132 + accountIndex: _account.value != null ? _account.value.id : 0);
133 + final subaddresses = subaddressList.getAll();
134 + _subaddress.value = subaddresses.first;
135 + _address.value = await getAddress();
136 + }
137 +
138 + Future<String> getFilename() async => moneroWallet.getFilename();
139 +
140 + Future<String> getName() async => getFilename()
141 + .then((filename) => filename.split('/'))
142 + .then((splitted) => splitted.last);
143 +
144 + Future<String> getAddress() async => moneroWallet.getAddress(
145 + accountIndex: _account.value.id, addressIndex: _subaddress.value.id);
146 +
147 + Future<String> getSeed() async => moneroWallet.getSeed();
148 +
149 + Future<String> getFullBalance() async => moneroAmountToString(
150 + amount: moneroWallet.getFullBalance(accountIndex: _account.value.id));
151 +
152 + Future<String> getUnlockedBalance() async => moneroAmountToString(
153 + amount: moneroWallet.getUnlockedBalance(accountIndex: _account.value.id));
154 +
155 + Future<int> getCurrentHeight() async => moneroWallet.getCurrentHeight();
156 +
157 + Future<int> getNodeHeight() async => moneroWallet.getNodeHeight();
158 +
159 + Future<Map<String, String>> getKeys() async => {
160 + 'publicViewKey': moneroWallet.getPublicViewKey(),
161 + 'privateViewKey': moneroWallet.getSecretViewKey(),
162 + 'publicSpendKey': moneroWallet.getPublicSpendKey(),
163 + 'privateSpendKey': moneroWallet.getSecretSpendKey()
164 + };
165 +
166 + Future close() async {
167 + moneroWallet.closeListeners();
168 + moneroWallet.closeCurrentWallet();
169 + }
170 +
171 + Future connectToNode(
172 + {Node node, bool useSSL = false, bool isLightWallet = false}) async {
173 + try {
174 + _syncStatus.value = ConnectingSyncStatus();
175 + await moneroWallet.setupNode(
176 + address: node.uri,
177 + login: node.login,
178 + password: node.password,
179 + useSSL: useSSL,
180 + isLightWallet: isLightWallet);
181 + _syncStatus.value = ConnectedSyncStatus();
182 + } catch (e) {
183 + _syncStatus.value = FailedSyncStatus();
184 + print(e);
185 + }
186 + }
187 +
188 + Future startSync() async {
189 + try {
190 + _syncStatus.value = StartingSyncStatus();
191 + moneroWallet.startRefresh();
192 + } on PlatformException catch (e) {
193 + _syncStatus.value = FailedSyncStatus();
194 + print(e);
195 + throw e;
196 + }
197 + }
198 +
199 + TransactionHistory getHistory() {
200 + if (_cachedTransactionHistory == null) {
201 + _cachedTransactionHistory = MoneroTransactionHistory();
202 + }
203 +
204 + return _cachedTransactionHistory;
205 + }
206 +
207 + SubaddressList getSubaddress() {
208 + if (_cachedSubaddressList == null) {
209 + _cachedSubaddressList = SubaddressList();
210 + }
211 +
212 + return _cachedSubaddressList;
213 + }
214 +
215 + AccountList getAccountList() {
216 + if (_cachedAccountList == null) {
217 + _cachedAccountList = AccountList();
218 + }
219 +
220 + return _cachedAccountList;
221 + }
222 +
223 + Future askForSave() async {
224 + final diff = DateTime.now().millisecondsSinceEpoch - _lastSaveTime;
225 +
226 + if (_lastSaveTime != 0 && diff < 120000) {
227 + return;
228 + }
229 +
230 + await store();
231 + }
232 +
233 + Future<int> getNodeHeightOrUpdate(int baseHeight) async {
234 + if (_cachedBlockchainHeight < baseHeight) {
235 + _cachedBlockchainHeight = await getNodeHeight();
236 + }
237 +
238 + return _cachedBlockchainHeight;
239 + }
240 +
241 + Future<PendingTransaction> createTransaction(
242 + TransactionCreationCredentials credentials) async {
243 + MoneroTransactionCreationCredentials _credentials =
244 + credentials as MoneroTransactionCreationCredentials;
245 +
246 + final transactionDescription = await transactionHistory.createTransaction(
247 + address: _credentials.address,
248 + paymentId: _credentials.paymentId,
249 + amount: _credentials.amount,
250 + priorityRaw: _credentials.priority.serialize(),
251 + accountIndex: _account.value.id);
252 +
253 + return PendingTransaction.fromTransactionDescription(
254 + transactionDescription);
255 + }
256 +
257 + setRecoveringFromSeed() =>
258 + moneroWallet.setRecoveringFromSeed(isRecovery: true);
259 +
260 + setRefreshFromBlockHeight({int height}) =>
261 + moneroWallet.setRefreshFromBlockHeight(height: height);
262 +
263 + Future<bool> isConnected() async => moneroWallet.isConnected();
264 +
265 + Future setAsRecovered() async {
266 + walletInfo.isRecovery = false;
267 + await walletInfo.save();
268 + }
269 +
270 + Future askForUpdateBalance() async {
271 + final fullBalance = await getFullBalance();
272 + final unlockedBalance = await getUnlockedBalance();
273 + final needToChange = _onBalanceChange.value != null
274 + ? _onBalanceChange.value.fullBalance != fullBalance ||
275 + _onBalanceChange.value.unlockedBalance != unlockedBalance
276 + : true;
277 +
278 + if (!needToChange) {
279 + return;
280 + }
281 +
282 + _onBalanceChange.add(MoneroBalance(
283 + fullBalance: fullBalance, unlockedBalance: unlockedBalance));
284 + }
285 +
286 + Future askForUpdateTransactionHistory() async => await getHistory().update();
287 +
288 + Future rescan({int restoreHeight = 0}) async {
289 + _syncStatus.value = StartingSyncStatus();
290 + setRefreshFromBlockHeight(height: restoreHeight);
291 + moneroWallet.rescanBlockchainAsync();
292 + _syncStatus.value = StartingSyncStatus();
293 + }
294 +
295 + changeCurrentSubaddress(Subaddress subaddress) =>
296 + _subaddress.value = subaddress;
297 +
298 + changeAccount(Account account) {
299 + _account.add(account);
300 +
301 + getSubaddress()
302 + .refresh(accountIndex: account.id)
303 + .then((_) => getSubaddress().getAll())
304 + .then((subaddresses) => _subaddress.value = subaddresses[0]);
305 + }
306 +
307 + Future store() async {
308 + if (_isSaving) {
309 + return;
310 + }
311 +
312 + try {
313 + _isSaving = true;
314 + moneroWallet.store();
315 + _isSaving = false;
316 + } on PlatformException catch (e) {
317 + print(e);
318 + _isSaving = false;
319 + throw e;
320 + }
321 + }
322 +
323 + setListeners() => moneroWallet.setListeners(
324 + _onNewBlock, _onNeedToRefresh, _onNewTransaction);
325 +
326 + Future _onNewBlock(int height) async {
327 + try {
328 + final nodeHeight = await getNodeHeightOrUpdate(height);
329 +
330 + if (isRecovery && _refreshHeight <= 0) {
331 + _refreshHeight = height;
332 + }
333 +
334 + if (isRecovery &&
335 + (_lastSyncHeight == 0 ||
336 + (height - _lastSyncHeight) > monero_block_size)) {
337 + _lastSyncHeight = height;
338 + askForUpdateBalance();
339 + askForUpdateTransactionHistory();
340 + }
341 +
342 + if (height > 0 && ((nodeHeight - height) < monero_block_size)) {
343 + _syncStatus.add(SyncedSyncStatus());
344 + } else {
345 + _syncStatus.add(SyncingSyncStatus(height, nodeHeight, _refreshHeight));
346 + }
347 + } catch (e) {
348 + print(e);
349 + }
350 + }
351 +
352 + Future _onNeedToRefresh() async {
353 + try {
354 + final currentHeight = await getCurrentHeight();
355 + final nodeHeight = await getNodeHeightOrUpdate(currentHeight);
356 +
357 + // no blocks - maybe we're not connected to the node ?
358 + if (currentHeight <= 1 || nodeHeight == 0) {
359 + return;
360 + }
361 +
362 + if (_syncStatus.value is FailedSyncStatus) {
363 + return;
364 + }
365 +
366 + askForUpdateBalance();
367 +
368 + _syncStatus.add(SyncedSyncStatus());
369 +
370 + if (isRecovery) {
371 + askForUpdateTransactionHistory();
372 + }
373 +
374 + if (isRecovery && (nodeHeight - currentHeight < monero_block_size)) {
375 + await setAsRecovered();
376 + }
377 +
378 + final now = DateTime.now().millisecondsSinceEpoch;
379 + final diff = now - _lastRefreshTime;
380 +
381 + if (diff >= 0 && diff < 60000) {
382 + return;
383 + }
384 +
385 + await store();
386 + _lastRefreshTime = now;
387 + } catch (e) {
388 + print(e);
389 + }
390 + }
391 +
392 + Future _onNewTransaction() async {
393 + await askForUpdateBalance();
394 + await askForUpdateTransactionHistory();
395 + }
396 +}
lib/src/domain/monero/monero_wallets_manager.dart new
+160
@@ -0,0 +1,160 @@
1 +import 'dart:async';
2 +import 'dart:io';
3 +import 'package:flutter/foundation.dart';
4 +import 'package:hive/hive.dart';
5 +import 'package:path_provider/path_provider.dart';
6 +import 'package:cw_monero/wallet_manager.dart' as moneroWalletManager;
7 +import 'package:cake_wallet/src/domain/common/wallet_info.dart';
8 +import 'package:cake_wallet/src/domain/common/wallet_type.dart';
9 +import 'package:cake_wallet/src/domain/common/wallets_manager.dart';
10 +import 'package:cake_wallet/src/domain/common/wallet.dart';
11 +import 'package:cake_wallet/src/domain/monero/monero_wallet.dart';
12 +import 'package:cake_wallet/src/domain/common/wallet_description.dart';
13 +
14 +Future<String> pathForWallet({String name}) async {
15 + final directory = await getApplicationDocumentsDirectory();
16 + final pathDir = directory.path + '/$name';
17 + final dir = Directory(pathDir);
18 +
19 + if (!await dir.exists()) {
20 + await dir.create();
21 + }
22 +
23 + return pathDir + '/$name';
24 +}
25 +
26 +class MoneroWalletsManager extends WalletsManager {
27 + static const type = WalletType.monero;
28 +
29 + Box<WalletInfo> walletInfoSource;
30 +
31 + MoneroWalletsManager({@required this.walletInfoSource});
32 +
33 + Future<Wallet> create(String name, String password) async {
34 + try {
35 + const isRecovery = false;
36 + final path = await pathForWallet(name: name);
37 +
38 + await moneroWalletManager.createWallet(path: path, password: password);
39 +
40 + final wallet = await MoneroWallet.createdWallet(
41 + walletInfoSource: walletInfoSource, name: name, isRecovery: isRecovery)
42 + ..updateInfo();
43 +
44 + return wallet;
45 + } catch (e) {
46 + print('MoneroWalletsManager Error: $e');
47 + throw e;
48 + }
49 + }
50 +
51 + Future<Wallet> restoreFromSeed(
52 + String name, String password, String seed, int restoreHeight) async {
53 + try {
54 + const isRecovery = true;
55 + final path = await pathForWallet(name: name);
56 +
57 + await moneroWalletManager.restoreFromSeed(
58 + path: path,
59 + password: password,
60 + seed: seed,
61 + restoreHeight: restoreHeight);
62 +
63 + return await MoneroWallet.createdWallet(
64 + walletInfoSource: walletInfoSource,
65 + name: name,
66 + isRecovery: isRecovery,
67 + restoreHeight: restoreHeight)
68 + ..updateInfo();
69 + } catch (e) {
70 + print('MoneroWalletsManager Error: $e');
71 + throw e;
72 + }
73 + }
74 +
75 + Future<Wallet> restoreFromKeys(
76 + String name,
77 + String password,
78 + int restoreHeight,
79 + String address,
80 + String viewKey,
81 + String spendKey) async {
82 + try {
83 + const isRecovery = true;
84 + final path = await pathForWallet(name: name);
85 +
86 + await moneroWalletManager.restoreFromKeys(
87 + path: path,
88 + password: password,
89 + restoreHeight: restoreHeight,
90 + address: address,
91 + viewKey: viewKey,
92 + spendKey: spendKey);
93 +
94 + final wallet = await MoneroWallet.createdWallet(
95 + walletInfoSource: walletInfoSource,
96 + name: name,
97 + isRecovery: isRecovery,
98 + restoreHeight: restoreHeight)
99 + ..updateInfo();
100 +
101 + return wallet;
102 + } catch (e) {
103 + print('MoneroWalletsManager Error: $e');
104 + throw e;
105 + }
106 + }
107 +
108 + Future<Wallet> openWallet(String name, String password) async {
109 + try {
110 + final path = await pathForWallet(name: name);
111 + await moneroWalletManager.openWallet(path: path, password: password);
112 + final wallet = await MoneroWallet.load(walletInfoSource, name, type)
113 + ..updateInfo();
114 +
115 + return wallet;
116 + } catch (e) {
117 + print('MoneroWalletsManager Error: $e');
118 + throw e;
119 + }
120 + }
121 +
122 + Future<bool> isWalletExit(String name) async {
123 + try {
124 + final path = await pathForWallet(name: name);
125 + return moneroWalletManager.isWalletExist(path: path);
126 + } catch (e) {
127 + print('MoneroWalletsManager Error: $e');
128 + throw e;
129 + }
130 + }
131 +
132 + Future remove(WalletDescription wallet) async {
133 + final dir = await getApplicationDocumentsDirectory();
134 + final root = dir.path.replaceAll('app_flutter', 'files');
135 + final walletFilePath = root + '/cw_monero/' + wallet.name;
136 + final keyPath = walletFilePath + '.keys';
137 + final addressFilePath = walletFilePath + '.address.txt';
138 + final walletFile = File(walletFilePath);
139 + final keyFile = File(keyPath);
140 + final addressFile = File(addressFilePath);
141 +
142 + if (await walletFile.exists()) {
143 + await walletFile.delete();
144 + }
145 +
146 + if (await keyFile.exists()) {
147 + await keyFile.delete();
148 + }
149 +
150 + if (await addressFile.exists()) {
151 + await addressFile.delete();
152 + }
153 +
154 + final id =
155 + walletTypeToString(wallet.type).toLowerCase() + '_' + wallet.name;
156 + final info = walletInfoSource.values.firstWhere((info) => info.id == id, orElse: () => null);
157 +
158 + await info?.delete();
159 + }
160 +}
lib/src/domain/monero/subaddress.dart new
+19
@@ -0,0 +1,19 @@
1 +import 'package:cw_monero/structs/subaddress_row.dart';
2 +
3 +class Subaddress {
4 + final int id;
5 + final String address;
6 + final String label;
7 +
8 + Subaddress({this.id, this.address, this.label});
9 +
10 + Subaddress.fromMap(Map map)
11 + : this.id = map['id'] == null ? 0 : int.parse(map['id']),
12 + this.address = map['address'] ?? '',
13 + this.label = map['label'] ?? '';
14 +
15 + Subaddress.fromRow(SubaddressRow row)
16 + : this.id = row.getId(),
17 + this.address = row.getAddress(),
18 + this.label = row.getLabel();
19 +}
lib/src/domain/monero/subaddress_list.dart new
+70
@@ -0,0 +1,70 @@
1 +import 'package:flutter/services.dart';
2 +import 'package:rxdart/rxdart.dart';
3 +import 'package:cw_monero/subaddress_list.dart' as subaddressListAPI;
4 +import 'package:cake_wallet/src/domain/monero/subaddress.dart';
5 +
6 +class SubaddressList {
7 + get subaddresses => _subaddress.stream;
8 + BehaviorSubject<List<Subaddress>> _subaddress;
9 +
10 + bool _isRefreshing;
11 + bool _isUpdating;
12 +
13 + SubaddressList() {
14 + _isRefreshing = false;
15 + _isUpdating = false;
16 + _subaddress = BehaviorSubject<List<Subaddress>>();
17 + }
18 +
19 + Future update({int accountIndex}) async {
20 + if (_isUpdating) {
21 + return;
22 + }
23 +
24 + try {
25 + _isUpdating = true;
26 + await refresh(accountIndex: accountIndex);
27 + final subaddresses = getAll();
28 + _subaddress.add(subaddresses);
29 + _isUpdating = false;
30 + } catch (e) {
31 + _isUpdating = false;
32 + throw e;
33 + }
34 + }
35 +
36 + List<Subaddress> getAll() {
37 + return subaddressListAPI
38 + .getAllSubaddresses()
39 + .map((subaddressRow) => Subaddress.fromRow(subaddressRow))
40 + .toList();
41 + }
42 +
43 + Future addSubaddress({int accountIndex, String label}) async {
44 + await subaddressListAPI.addSubaddress(accountIndex: accountIndex, label: label);
45 + await update(accountIndex: accountIndex);
46 + }
47 +
48 + Future setLabelSubaddress(
49 + {int accountIndex, int addressIndex, String label}) async {
50 + await subaddressListAPI.setLabelForSubaddress(
51 + accountIndex: accountIndex, addressIndex: addressIndex, label: label);
52 + await update();
53 + }
54 +
55 + Future refresh({int accountIndex}) async {
56 + if (_isRefreshing) {
57 + return;
58 + }
59 +
60 + try {
61 + _isRefreshing = true;
62 + subaddressListAPI.refreshSubaddresses(accountIndex: accountIndex);
63 + _isRefreshing = false;
64 + } on PlatformException catch (e) {
65 + _isRefreshing = false;
66 + print(e);
67 + throw e;
68 + }
69 + }
70 +}
lib/src/domain/monero/transaction_description.dart new
+16
@@ -0,0 +1,16 @@
1 +import 'package:hive/hive.dart';
2 +
3 +part 'transaction_description.g.dart';
4 +
5 +@HiveType()
6 +class TransactionDescription extends HiveObject {
7 + static const boxName = 'TransactionDescriptions';
8 +
9 + @HiveField(0)
10 + String id;
11 +
12 + @HiveField(1)
13 + String recipientAddress;
14 +
15 + TransactionDescription({this.id, this.recipientAddress});
16 +}
\ No newline at end of file
lib/src/domain/services/user_service.dart new
+46
@@ -0,0 +1,46 @@
1 +import 'package:flutter_secure_storage/flutter_secure_storage.dart';
2 +import 'package:shared_preferences/shared_preferences.dart';
3 +import 'package:cake_wallet/src/domain/common/secret_store_key.dart';
4 +import 'package:cake_wallet/src/domain/common/encrypt.dart';
5 +
6 +class UserService {
7 + final FlutterSecureStorage secureStorage;
8 + final SharedPreferences sharedPreferences;
9 +
10 + UserService({this.sharedPreferences, this.secureStorage});
11 +
12 + Future setPassword(String password) async {
13 + final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
14 +
15 + try {
16 + final encodedPassord = encodedPinCode(pin: password);
17 +
18 + await secureStorage.write(key: key, value: encodedPassord);
19 + } catch (e) {
20 + print(e);
21 + }
22 + }
23 +
24 + Future<bool> canAuthenticate() async {
25 + final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
26 + final sharedPreferences = await SharedPreferences.getInstance();
27 + final walletName = sharedPreferences.getString("current_wallet_name") ?? "";
28 + var password = '';
29 +
30 + try {
31 + password = await secureStorage.read(key: key);
32 + } catch (e) {
33 + print(e);
34 + }
35 +
36 + return walletName.isNotEmpty && password.isNotEmpty;
37 + }
38 +
39 + Future<bool> authenticate(String pin) async {
40 + final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
41 + final encodedPin = await secureStorage.read(key: key);
42 + final decodedPin = decodedPinCode(pin: encodedPin);
43 +
44 + return decodedPin == pin;
45 + }
46 +}
lib/src/domain/services/wallet_list_service.dart new
+145
@@ -0,0 +1,145 @@
1 +import 'dart:async';
2 +import 'package:cake_wallet/src/domain/common/wallet_info.dart';
3 +import 'package:flutter/foundation.dart';
4 +import 'package:hive/hive.dart';
5 +import 'package:flutter_secure_storage/flutter_secure_storage.dart';
6 +import 'package:uuid/uuid.dart';
7 +import 'package:shared_preferences/shared_preferences.dart';
8 +import 'package:cake_wallet/src/domain/common/encrypt.dart';
9 +import 'package:cake_wallet/src/domain/common/wallet.dart';
10 +import 'package:cake_wallet/src/domain/common/wallet_description.dart';
11 +import 'package:cake_wallet/src/domain/common/wallets_manager.dart';
12 +import 'package:cake_wallet/src/domain/common/secret_store_key.dart';
13 +import 'package:cake_wallet/src/domain/common/wallet_type.dart';
14 +import 'package:cake_wallet/src/domain/monero/monero_wallets_manager.dart';
15 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
16 +
17 +class WalletIsExistException implements Exception {
18 + String name;
19 +
20 + WalletIsExistException(this.name);
21 +
22 + @override
23 + String toString() => "Wallet with name $name is already exist!";
24 +}
25 +
26 +class WalletListService {
27 + final FlutterSecureStorage secureStorage;
28 + final WalletService walletService;
29 + final Box<WalletInfo> walletInfoSource;
30 + final SharedPreferences sharedPreferences;
31 + WalletsManager walletsManager;
32 +
33 + WalletListService(
34 + {this.secureStorage,
35 + this.walletInfoSource,
36 + this.walletsManager,
37 + @required this.walletService,
38 + @required this.sharedPreferences});
39 +
40 + Future<List<WalletDescription>> getAll() async => walletInfoSource.values
41 + .map((info) => WalletDescription(name: info.name, type: info.type))
42 + .toList();
43 +
44 + Future create(String name) async {
45 + if (await walletsManager.isWalletExit(name)) {
46 + throw WalletIsExistException(name);
47 + }
48 +
49 + if (walletService.currentWallet != null) {
50 + await walletService.close();
51 + }
52 +
53 + final password = Uuid().v4();
54 + await saveWalletPassword(password: password, walletName: name);
55 +
56 + final wallet = await walletsManager.create(name, password);
57 +
58 + await onWalletChange(wallet);
59 + }
60 +
61 + Future restoreFromSeed(String name, String seed, int restoreHeight) async {
62 + if (await walletsManager.isWalletExit(name)) {
63 + throw WalletIsExistException(name);
64 + }
65 +
66 + if (walletService.currentWallet != null) {
67 + await walletService.close();
68 + }
69 +
70 + final password = Uuid().v4();
71 + await saveWalletPassword(password: password, walletName: name);
72 +
73 + final wallet = await walletsManager.restoreFromSeed(
74 + name, password, seed, restoreHeight);
75 +
76 + await onWalletChange(wallet);
77 + }
78 +
79 + Future restoreFromKeys(String name, int restoreHeight, String address,
80 + String viewKey, String spendKey) async {
81 + if (await walletsManager.isWalletExit(name)) {
82 + throw WalletIsExistException(name);
83 + }
84 +
85 + if (walletService.currentWallet != null) {
86 + await walletService.close();
87 + }
88 +
89 + final password = Uuid().v4();
90 + await saveWalletPassword(password: password, walletName: name);
91 +
92 + final wallet = await walletsManager.restoreFromKeys(
93 + name, password, restoreHeight, address, viewKey, spendKey);
94 +
95 + await onWalletChange(wallet);
96 + }
97 +
98 + Future openWallet(String name) async {
99 + if (walletService.currentWallet != null) {
100 + await walletService.close();
101 + }
102 +
103 + final password = await getWalletPassword(walletName: name);
104 + final wallet = await walletsManager.openWallet(name, password);
105 +
106 + await onWalletChange(wallet);
107 + }
108 +
109 + Future changeWalletManger({WalletType walletType}) async {
110 + switch (walletType) {
111 + case WalletType.monero:
112 + walletsManager =
113 + MoneroWalletsManager(walletInfoSource: walletInfoSource);
114 + break;
115 + case WalletType.none:
116 + walletsManager = null;
117 + break;
118 + }
119 + }
120 +
121 + Future onWalletChange(Wallet wallet) async {
122 + walletService.currentWallet = wallet;
123 + final walletName = await wallet.getName();
124 + await sharedPreferences.setString('current_wallet_name', walletName);
125 + }
126 +
127 + Future remove(WalletDescription wallet) async =>
128 + await walletsManager.remove(wallet);
129 +
130 + Future<String> getWalletPassword({String walletName}) async {
131 + final key = generateStoreKeyFor(
132 + key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
133 + final encodedPassword = await secureStorage.read(key: key);
134 +
135 + return decodeWalletPassword(password: encodedPassword);
136 + }
137 +
138 + Future saveWalletPassword({String walletName, String password}) async {
139 + final key = generateStoreKeyFor(
140 + key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
141 + final encodedPassword = encodeWalletPassword(password: password);
142 +
143 + await secureStorage.write(key: key, value: encodedPassword);
144 + }
145 +}
lib/src/domain/services/wallet_service.dart new
+98
@@ -0,0 +1,98 @@
1 +import 'package:rxdart/rxdart.dart';
2 +import 'package:cake_wallet/src/domain/common/balance.dart';
3 +import 'package:cake_wallet/src/domain/common/wallet_description.dart';
4 +import 'package:cake_wallet/src/domain/common/wallet.dart';
5 +import 'package:cake_wallet/src/domain/common/transaction_history.dart';
6 +import 'package:cake_wallet/src/domain/common/wallet_type.dart';
7 +import 'package:cake_wallet/src/domain/common/sync_status.dart';
8 +import 'package:cake_wallet/src/domain/common/transaction_creation_credentials.dart';
9 +import 'package:cake_wallet/src/domain/common/pending_transaction.dart';
10 +import 'package:cake_wallet/src/domain/common/node.dart';
11 +
12 +class WalletService extends Wallet {
13 + Observable<Wallet> get onWalletChange => _onWalletChanged.stream;
14 + Observable<Balance> get onBalanceChange => _onBalanceChange.stream;
15 + Observable<SyncStatus> get syncStatus => _syncStatus.stream;
16 + Observable<String> get onAddressChange => _currentWallet.onAddressChange;
17 + Observable<String> get onNameChange => _currentWallet.onNameChange;
18 + String get address => _currentWallet.address;
19 + String get name => _currentWallet.name;
20 + SyncStatus get syncStatusValue => _syncStatus.value;
21 + WalletType get walletType => _currentWallet.walletType;
22 +
23 + get currentWallet => _currentWallet;
24 +
25 + set currentWallet(Wallet wallet) {
26 + _currentWallet = wallet;
27 +
28 + if (wallet == null) {
29 + return;
30 + }
31 +
32 + _currentWallet.onBalanceChange
33 + .listen((wallet) => _onBalanceChange.add(wallet));
34 + _currentWallet.syncStatus.listen((status) => _syncStatus.add(status));
35 + _onWalletChanged.add(wallet);
36 +
37 + final type = wallet.getType();
38 + wallet.getName().then(
39 + (name) => description = WalletDescription(name: name, type: type));
40 + }
41 +
42 + BehaviorSubject<Wallet> _onWalletChanged;
43 + BehaviorSubject<Balance> _onBalanceChange;
44 + BehaviorSubject<SyncStatus> _syncStatus;
45 + Wallet _currentWallet;
46 +
47 + WalletService() {
48 + _currentWallet = null;
49 + walletType = WalletType.none;
50 + _syncStatus = BehaviorSubject<SyncStatus>();
51 + _onBalanceChange = BehaviorSubject<Balance>();
52 + _onWalletChanged = BehaviorSubject<Wallet>();
53 + }
54 +
55 + WalletDescription description;
56 +
57 + WalletType getType() => WalletType.monero;
58 +
59 + Future<String> getFilename() => _currentWallet.getFilename();
60 +
61 + Future<String> getName() => _currentWallet.getName();
62 +
63 + Future<String> getAddress() => _currentWallet.getAddress();
64 +
65 + Future<String> getSeed() => _currentWallet.getSeed();
66 +
67 + Future<Map<String, String>> getKeys() => _currentWallet.getKeys();
68 +
69 + Future<String> getFullBalance() => _currentWallet.getFullBalance();
70 +
71 + Future<String> getUnlockedBalance() => _currentWallet.getUnlockedBalance();
72 +
73 + Future<int> getCurrentHeight() => _currentWallet.getCurrentHeight();
74 +
75 + Future<int> getNodeHeight() => _currentWallet.getNodeHeight();
76 +
77 + Future<bool> isConnected() => _currentWallet.isConnected();
78 +
79 + Future close() => _currentWallet.close();
80 +
81 + Future connectToNode({Node node, bool useSSL = false, bool isLightWallet = false}) =>
82 + _currentWallet.connectToNode(
83 + node: node,
84 + useSSL: useSSL,
85 + isLightWallet: isLightWallet);
86 +
87 + Future startSync() => _currentWallet.startSync();
88 +
89 + TransactionHistory getHistory() => _currentWallet.getHistory();
90 +
91 + Future<PendingTransaction> createTransaction(
92 + TransactionCreationCredentials credentials) =>
93 + _currentWallet.createTransaction(credentials);
94 +
95 + Future updateInfo() async => _currentWallet.updateInfo();
96 +
97 + Future rescan({int restoreHeight = 0}) async => _currentWallet.rescan(restoreHeight: restoreHeight);
98 +}
lib/src/reactions/set_reactions.dart new
+86
@@ -0,0 +1,86 @@
1 +import 'dart:async';
2 +import 'package:flutter/foundation.dart';
3 +import 'package:mobx/mobx.dart';
4 +import 'package:cake_wallet/src/domain/common/sync_status.dart';
5 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
6 +import 'package:cake_wallet/src/start_updating_price.dart';
7 +import 'package:cake_wallet/src/stores/sync/sync_store.dart';
8 +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
9 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
10 +import 'package:cake_wallet/src/stores/price/price_store.dart';
11 +import 'package:cake_wallet/src/stores/authentication/authentication_store.dart';
12 +import 'package:cake_wallet/src/stores/login/login_store.dart';
13 +
14 +setReactions(
15 + {@required SettingsStore settingsStore,
16 + @required PriceStore priceStore,
17 + @required SyncStore syncStore,
18 + @required WalletStore walletStore,
19 + @required WalletService walletService,
20 + @required AuthenticationStore authenticationStore,
21 + @required LoginStore loginStore}) {
22 + connectToNode(settingsStore: settingsStore, walletStore: walletStore);
23 + onSyncStatusChange(
24 + syncStore: syncStore,
25 + walletStore: walletStore,
26 + settingsStore: settingsStore);
27 + onCurrentWalletChange(
28 + walletStore: walletStore,
29 + settingsStore: settingsStore,
30 + priceStore: priceStore);
31 + autorun((_) async {
32 + if (authenticationStore.state == AuthenticationState.allowed) {
33 + await loginStore.loadCurrentWallet();
34 + authenticationStore.state = AuthenticationState.readyToLogin;
35 + }
36 + });
37 +}
38 +
39 +connectToNode({SettingsStore settingsStore, WalletStore walletStore}) =>
40 + reaction((_) => settingsStore.node,
41 + (node) async => await walletStore.connectToNode(node: node));
42 +
43 +onSyncStatusChange(
44 + {SyncStore syncStore,
45 + WalletStore walletStore,
46 + SettingsStore settingsStore}) =>
47 + reaction((_) => syncStore.status, (status) async {
48 + if (status is ConnectedSyncStatus) {
49 + await walletStore.startSync();
50 + }
51 +
52 + // Reconnect to the node if the app is not started sync after 30 seconds
53 + if (status is StartingSyncStatus) {
54 + await startReconnectionObserver(
55 + syncStore: syncStore, walletStore: walletStore);
56 + }
57 + });
58 +
59 +Timer _reconnectionTimer;
60 +
61 +startReconnectionObserver({SyncStore syncStore, WalletStore walletStore}) {
62 + if (_reconnectionTimer != null) {
63 + _reconnectionTimer.cancel();
64 + }
65 +
66 + _reconnectionTimer = Timer.periodic(Duration(minutes: 1), (_) async {
67 + try {
68 + final isConnected = await walletStore.isConnected();
69 +
70 + if (!isConnected) {
71 + await walletStore.reconnect();
72 + }
73 + } catch (e) {
74 + print(e);
75 + }
76 + });
77 +}
78 +
79 +onCurrentWalletChange(
80 + {WalletStore walletStore,
81 + SettingsStore settingsStore,
82 + PriceStore priceStore}) =>
83 + reaction((_) => walletStore.name, (_) {
84 + walletStore.connectToNode(node: settingsStore.node);
85 + startUpdatingPrice(settingsStore: settingsStore, priceStore: priceStore);
86 + });
lib/src/screens/accounts/account_list_page.dart new
+120
@@ -0,0 +1,120 @@
1 +import 'package:provider/provider.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:flutter/cupertino.dart';
4 +import 'package:flutter_mobx/flutter_mobx.dart';
5 +import 'package:flutter_slidable/flutter_slidable.dart';
6 +import 'package:cake_wallet/palette.dart';
7 +import 'package:cake_wallet/routes.dart';
8 +import 'package:cake_wallet/generated/i18n.dart';
9 +import 'package:cake_wallet/src/stores/account_list/account_list_store.dart';
10 +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
11 +import 'package:cake_wallet/src/screens/base_page.dart';
12 +
13 +class AccountListPage extends BasePage {
14 + String get title => S.current.accounts;
15 +
16 + @override
17 + Widget trailing(BuildContext context) {
18 + final accountListStore = Provider.of<AccountListStore>(context);
19 +
20 + return Container(
21 + width: 28.0,
22 + height: 28.0,
23 + decoration: BoxDecoration(
24 + shape: BoxShape.circle,
25 + color: Theme.of(context).selectedRowColor),
26 + child: Stack(
27 + alignment: Alignment.center,
28 + children: <Widget>[
29 + Icon(Icons.add, color: Palette.violet, size: 22.0),
30 + ButtonTheme(
31 + minWidth: 28.0,
32 + height: 28.0,
33 + child: FlatButton(
34 + shape: CircleBorder(),
35 + onPressed: () async {
36 + await Navigator.of(context)
37 + .pushNamed(Routes.accountCreation);
38 + await accountListStore.updateAccountList();
39 + },
40 + child: Offstage()),
41 + )
42 + ],
43 + ));
44 + }
45 +
46 + @override
47 + Widget body(BuildContext context) {
48 + final accountListStore = Provider.of<AccountListStore>(context);
49 + final walletStore = Provider.of<WalletStore>(context);
50 +
51 + final currentColor = Theme.of(context).selectedRowColor;
52 + final notCurrentColor = Theme.of(context).backgroundColor;
53 +
54 + return Container(
55 + padding: EdgeInsets.only(top: 10, bottom: 20),
56 + child: Observer(
57 + builder: (_) {
58 + final accounts = accountListStore.accounts;
59 + return ListView.builder(
60 + itemCount: accounts == null
61 + ? 0
62 + : accounts.length,
63 + itemBuilder: (BuildContext context, int index) {
64 + final account = accounts[index];
65 +
66 + return Observer(builder: (_) {
67 + final isCurrent = walletStore.account.id == account.id;
68 +
69 + return Slidable(
70 + key: Key(account.id.toString()),
71 + actionPane: SlidableDrawerActionPane(),
72 + child: Container(
73 + color: isCurrent ? currentColor : notCurrentColor,
74 + child: Column(
75 + children: <Widget>[
76 + ListTile(
77 + title: Text(
78 + account.label,
79 + style: TextStyle(
80 + fontSize: 16.0,
81 + color: Theme.of(context).primaryTextTheme.headline.color),
82 + ),
83 + onTap: () {
84 + if (isCurrent) {
85 + return;
86 + }
87 +
88 + walletStore.setAccount(account);
89 + Navigator.of(context).pop();
90 + },
91 + ),
92 + Divider(
93 + color: Theme.of(context).dividerTheme.color,
94 + height: 1.0,
95 + )
96 + ],
97 + ),
98 + ),
99 + secondaryActions: <Widget>[
100 + IconSlideAction(
101 + caption: S.of(context).edit,
102 + color: Colors.blue,
103 + icon: Icons.edit,
104 + onTap: () async {
105 + await Navigator.of(context)
106 + .pushNamed(Routes.accountCreation, arguments: account);
107 + // await accountListStore.updateAccountList().then((_) {
108 + // if (isCurrent) walletStore.setAccount(accountListStore.accounts[index]);
109 + // });
110 + },
111 + )
112 + ],
113 + );
114 + });
115 + });
116 + }
117 + ),
118 + );
119 + }
120 +}
lib/src/screens/accounts/account_page.dart new
+110
@@ -0,0 +1,110 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter/cupertino.dart';
3 +import 'package:flutter_mobx/flutter_mobx.dart';
4 +import 'package:provider/provider.dart';
5 +import 'package:cake_wallet/generated/i18n.dart';
6 +import 'package:cake_wallet/src/stores/account_list/account_list_store.dart';
7 +import 'package:cake_wallet/src/widgets/primary_button.dart';
8 +import 'package:cake_wallet/src/screens/base_page.dart';
9 +import 'package:cake_wallet/src/domain/monero/account.dart';
10 +import 'package:cake_wallet/palette.dart';
11 +
12 +class AccountPage extends BasePage {
13 + String get title => 'Account';
14 + final Account account;
15 +
16 + AccountPage({this.account});
17 +
18 + @override
19 + Widget body(BuildContext context) => AccountForm(account);
20 +}
21 +
22 +class AccountForm extends StatefulWidget {
23 + final Account account;
24 +
25 + AccountForm(this.account);
26 +
27 + @override
28 + createState() => AccountFormState();
29 +}
30 +
31 +class AccountFormState extends State<AccountForm> {
32 + final _formKey = GlobalKey<FormState>();
33 + final _textController = TextEditingController();
34 +
35 + @override
36 + void initState() {
37 + if (widget.account != null) _textController.text = widget.account.label;
38 + super.initState();
39 + }
40 +
41 + @override
42 + void dispose() {
43 + _textController.dispose();
44 + super.dispose();
45 + }
46 +
47 + @override
48 + Widget build(BuildContext context) {
49 + final accountListStore = Provider.of<AccountListStore>(context);
50 +
51 + return Form(
52 + key: _formKey,
53 + child: Container(
54 + padding: EdgeInsets.all(20.0),
55 + child: Column(
56 + children: <Widget>[
57 + Expanded(
58 + child: Center(
59 + child: TextFormField(
60 + decoration: InputDecoration(
61 + hintStyle: TextStyle(color: Theme.of(context).hintColor),
62 + hintText: S.of(context).account,
63 + focusedBorder: UnderlineInputBorder(
64 + borderSide: BorderSide(
65 + color: Palette.cakeGreen, width: 2.0)),
66 + enabledBorder: UnderlineInputBorder(
67 + borderSide: BorderSide(
68 + color: Theme.of(context).focusColor, width: 1.0))),
69 + controller: _textController,
70 + validator: (value) {
71 + accountListStore.validateAccountName(value);
72 + return accountListStore.errorMessage;
73 + },
74 + ),
75 + )),
76 + Observer(
77 + builder: (_) => LoadingPrimaryButton(
78 + onPressed: () async {
79 + if (!_formKey.currentState.validate()) {
80 + return;
81 + }
82 +
83 + if (widget.account != null) {
84 + await accountListStore.renameAccount(
85 + index: widget.account.id,
86 + label: _textController.text);
87 + } else {
88 + await accountListStore.addAccount(
89 + label: _textController.text);
90 + }
91 + Navigator.pop(context, _textController.text);
92 + },
93 + text:
94 + widget.account != null ? 'Rename' : S.of(context).add,
95 + color: Theme.of(context)
96 + .primaryTextTheme
97 + .button
98 + .backgroundColor,
99 + borderColor: Theme.of(context)
100 + .primaryTextTheme
101 + .button
102 + .decorationColor,
103 + isLoading: accountListStore.isAccountCreating,
104 + ))
105 + ],
106 + ),
107 + ),
108 + );
109 + }
110 +}
lib/src/screens/address_book/address_book_page.dart new
+261
@@ -0,0 +1,261 @@
1 +import 'package:provider/provider.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:flutter/cupertino.dart';
4 +import 'package:flutter/services.dart';
5 +import 'package:flutter_mobx/flutter_mobx.dart';
6 +import 'package:flutter_slidable/flutter_slidable.dart';
7 +import 'package:cake_wallet/routes.dart';
8 +import 'package:cake_wallet/palette.dart';
9 +import 'package:cake_wallet/generated/i18n.dart';
10 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
11 +import 'package:cake_wallet/src/stores/address_book/address_book_store.dart';
12 +import 'package:cake_wallet/src/screens/base_page.dart';
13 +
14 +class AddressBookPage extends BasePage {
15 + bool get isModalBackButton => true;
16 + String get title => S.current.address_book;
17 + AppBarStyle get appBarStyle => AppBarStyle.withShadow;
18 +
19 + final bool isEditable;
20 +
21 + AddressBookPage({this.isEditable = true});
22 +
23 + @override
24 + Widget trailing(BuildContext context) {
25 + if (!isEditable) {
26 + return null;
27 + }
28 +
29 + final addressBookStore = Provider.of<AddressBookStore>(context);
30 +
31 + return Container(
32 + width: 28.0,
33 + height: 28.0,
34 + decoration: BoxDecoration(
35 + shape: BoxShape.circle,
36 + color: Theme.of(context).selectedRowColor),
37 + child: Stack(
38 + alignment: Alignment.center,
39 + children: <Widget>[
40 + Icon(Icons.add, color: Palette.violet, size: 22.0),
41 + ButtonTheme(
42 + minWidth: 28.0,
43 + height: 28.0,
44 + child: FlatButton(
45 + shape: CircleBorder(),
46 + onPressed: () async {
47 + await Navigator.of(context)
48 + .pushNamed(Routes.addressBookAddContact);
49 + await addressBookStore.updateContactList();
50 + },
51 + child: Offstage()),
52 + )
53 + ],
54 + ));
55 + }
56 +
57 + @override
58 + Widget body(BuildContext context) {
59 + final addressBookStore = Provider.of<AddressBookStore>(context);
60 +
61 + return Container(
62 + padding: EdgeInsets.only(top: 20.0, bottom: 20.0),
63 + child: Observer(
64 + builder: (_) => ListView.separated(
65 + separatorBuilder: (_, __) => Divider(
66 + color: Theme.of(context).dividerTheme.color,
67 + height: 1.0,
68 + ),
69 + itemCount: addressBookStore.contactList == null
70 + ? 0
71 + : addressBookStore.contactList.length,
72 + itemBuilder: (BuildContext context, int index) {
73 + final contact = addressBookStore.contactList[index];
74 +
75 + final content = ListTile(
76 + onTap: () async {
77 + if (!isEditable) {
78 + Navigator.of(context).pop(contact);
79 + return;
80 + }
81 +
82 + bool isCopied = await showNameAndAddressDialog(context, contact.name, contact.address);
83 + if (isCopied) {
84 + Clipboard.setData(ClipboardData(text: contact.address));
85 + Scaffold.of(context).showSnackBar(
86 + SnackBar(
87 + content:
88 + Text('Copied to Clipboard'),
89 + backgroundColor: Colors.green,
90 + duration:
91 + Duration(milliseconds: 1500),
92 + ),
93 + );
94 + }
95 + },
96 + leading: Container(
97 + height: 25.0,
98 + width: 48.0,
99 + alignment: Alignment.center,
100 + decoration: BoxDecoration(
101 + color: _getCurrencyBackgroundColor(contact.type),
102 + borderRadius: BorderRadius.circular(6.0),
103 + ),
104 + child: Text(
105 + contact.type.toString(),
106 + style: TextStyle(
107 + fontSize: 11.0,
108 + color: _getCurrencyTextColor(contact.type),
109 + ),
110 + ),
111 + ),
112 + title: Text(
113 + contact.name,
114 + style: TextStyle(
115 + fontSize: 16.0,
116 + color: Theme.of(context).primaryTextTheme.title.color),
117 + ),
118 + );
119 +
120 + return !isEditable ? content
121 + : Slidable(
122 + key: Key('1'),// Key(contact.id.toString()),
123 + actionPane: SlidableDrawerActionPane(),
124 + child: content,
125 + secondaryActions: <Widget>[
126 + IconSlideAction(
127 + caption: 'Edit',
128 + color: Colors.blue,
129 + icon: Icons.edit,
130 + onTap: () async {
131 + await Navigator.of(context)
132 + .pushNamed(Routes.addressBookAddContact, arguments: contact);
133 + await addressBookStore.updateContactList();
134 + },
135 + ),
136 + IconSlideAction(
137 + caption: 'Delete',
138 + color: Colors.red,
139 + icon: CupertinoIcons.delete,
140 + onTap: () async {
141 + await showAlertDialog(context).then((isDelete) async{
142 + if (isDelete != null && isDelete) {
143 + await addressBookStore.delete(contact: contact);
144 + await addressBookStore.updateContactList();
145 + }
146 + });
147 + },
148 + ),
149 + ],
150 + dismissal: SlidableDismissal(
151 + child: SlidableDrawerDismissal(),
152 + onDismissed: (actionType) async {
153 + await addressBookStore.delete(contact: contact);
154 + await addressBookStore.updateContactList();
155 + },
156 + onWillDismiss: (actionType) async {
157 + return await showAlertDialog(context);
158 + },
159 + ),
160 +
161 + );
162 + }),
163 + ));
164 + }
165 +
166 + Color _getCurrencyBackgroundColor(CryptoCurrency currency) {
167 + Color color;
168 + switch (currency) {
169 + case CryptoCurrency.xmr:
170 + color = Palette.cakeGreenWithOpacity;
171 + break;
172 + case CryptoCurrency.btc:
173 + color = Colors.orange;
174 + break;
175 + case CryptoCurrency.eth:
176 + color = Colors.black;
177 + break;
178 + case CryptoCurrency.ltc:
179 + color = Colors.blue[200];
180 + break;
181 + case CryptoCurrency.bch:
182 + color = Colors.orangeAccent;
183 + break;
184 + case CryptoCurrency.dash:
185 + color = Colors.blue;
186 + break;
187 + default:
188 + color = Colors.white;
189 + }
190 + return color;
191 + }
192 +
193 + Color _getCurrencyTextColor(CryptoCurrency currency) {
194 + Color color;
195 + switch (currency) {
196 + case CryptoCurrency.xmr:
197 + color = Palette.cakeGreen;
198 + break;
199 + case CryptoCurrency.ltc:
200 + color = Palette.lightBlue;
201 + break;
202 + default:
203 + color = Colors.white;
204 + }
205 + return color;
206 + }
207 +
208 + Future<bool> showAlertDialog(BuildContext context) async {
209 + return await showDialog(
210 + context: context,
211 + builder: (BuildContext context) {
212 + return AlertDialog(
213 + title: const Text(
214 + 'Remove contact',
215 + textAlign: TextAlign.center,
216 + ),
217 + content: const Text(
218 + 'Are you sure that you want to remove selected contact?',
219 + textAlign: TextAlign.center,
220 + ),
221 + actions: <Widget>[
222 + FlatButton(
223 + onPressed: () =>
224 + Navigator.pop(context, false),
225 + child: const Text('Cancel')),
226 + FlatButton(
227 + onPressed: () =>
228 + Navigator.pop(context, true),
229 + child: const Text('Remove')),
230 + ],
231 + );
232 + });
233 + }
234 +
235 + showNameAndAddressDialog(BuildContext context, String name, String address) async {
236 + return await showDialog(
237 + context: context,
238 + builder: (BuildContext context) {
239 + return AlertDialog(
240 + title: Text(
241 + name,
242 + textAlign: TextAlign.center,
243 + style: TextStyle(fontWeight: FontWeight.bold),
244 + ),
245 + content: Text(
246 + address,
247 + textAlign: TextAlign.center,
248 + ),
249 + actions: <Widget>[
250 + FlatButton(
251 + onPressed: () => Navigator.of(context).pop(false),
252 + child: Text('Cancel')),
253 + FlatButton(
254 + onPressed: () => Navigator.of(context).pop(true),
255 + child: Text('Copy'))
256 + ],
257 + );
258 + }
259 + );
260 + }
261 +}
lib/src/screens/address_book/contact_page.dart new
+254
@@ -0,0 +1,254 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter/cupertino.dart';
3 +import 'package:provider/provider.dart';
4 +import 'package:cake_wallet/generated/i18n.dart';
5 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
6 +import 'package:cake_wallet/src/domain/common/contact.dart';
7 +import 'package:cake_wallet/src/stores/address_book/address_book_store.dart';
8 +import 'package:cake_wallet/src/screens/base_page.dart';
9 +import 'package:cake_wallet/src/widgets/primary_button.dart';
10 +import 'package:cake_wallet/src/widgets/address_text_field.dart';
11 +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
12 +import 'package:cake_wallet/palette.dart';
13 +
14 +class ContactPage extends BasePage {
15 + String get title => S.current.contact;
16 + final Contact contact;
17 +
18 + ContactPage({this.contact});
19 +
20 + @override
21 + Widget body(BuildContext context) => ContactForm(contact);
22 +}
23 +
24 +class ContactForm extends StatefulWidget {
25 + final Contact contact;
26 +
27 + ContactForm(this.contact);
28 +
29 + @override
30 + createState() => ContactFormState();
31 +}
32 +
33 +class ContactFormState extends State<ContactForm> {
34 + final _formKey = GlobalKey<FormState>();
35 + final _contactNameController = TextEditingController();
36 + final _currencyTypeController = TextEditingController();
37 + final _addressController = TextEditingController();
38 +
39 + CryptoCurrency _selectectCrypto = CryptoCurrency.xmr;
40 +
41 + @override
42 + void initState() {
43 + super.initState();
44 + if (widget.contact == null) {
45 + _currencyTypeController.text = _selectectCrypto.toString();
46 + } else {
47 + _selectectCrypto = widget.contact.type;
48 + _contactNameController.text = widget.contact.name;
49 + _currencyTypeController.text = _selectectCrypto.toString();
50 + _addressController.text = widget.contact.address;
51 + }
52 + }
53 +
54 + @override
55 + void dispose() {
56 + _contactNameController.dispose();
57 + _currencyTypeController.dispose();
58 + _addressController.dispose();
59 + super.dispose();
60 + }
61 +
62 + _setCurrencyType(BuildContext context) async {
63 + String currencyType = CryptoCurrency.all[0].toString();
64 + CryptoCurrency selectedCurrency = CryptoCurrency.all[0];
65 + await showDialog(
66 + context: context,
67 + builder: (BuildContext context) {
68 + return AlertDialog(
69 + title: Text(S.of(context).please_select),
70 + backgroundColor: Theme.of(context).backgroundColor,
71 + content: Container(
72 + height: 150.0,
73 + child: CupertinoPicker(
74 + backgroundColor: Theme.of(context).backgroundColor,
75 + itemExtent: 45.0,
76 + onSelectedItemChanged: (int index) {
77 + selectedCurrency = CryptoCurrency.all[index];
78 + currencyType = CryptoCurrency.all[index].toString();
79 + },
80 + children:
81 + List.generate(CryptoCurrency.all.length, (int index) {
82 + return Center(
83 + child: Text(
84 + CryptoCurrency.all[index].toString(),
85 + style: TextStyle(
86 + color: Theme.of(context)
87 + .primaryTextTheme
88 + .caption
89 + .color),
90 + ),
91 + );
92 + })),
93 + ),
94 + actions: <Widget>[
95 + FlatButton(
96 + onPressed: () {
97 + Navigator.pop(context);
98 + },
99 + child: Text(S.of(context).cancel)),
100 + FlatButton(
101 + onPressed: () {
102 + _selectectCrypto = selectedCurrency;
103 + _currencyTypeController.text = currencyType;
104 + Navigator.of(context).pop();
105 + },
106 + child: Text(S.of(context).ok))
107 + ],
108 + );
109 + });
110 + }
111 +
112 + @override
113 + Widget build(BuildContext context) {
114 + final addressBookStore = Provider.of<AddressBookStore>(context);
115 +
116 + return ScrollableWithBottomSection(
117 + content: Form(
118 + key: _formKey,
119 + child: Column(
120 + mainAxisSize: MainAxisSize.min,
121 + children: <Widget>[
122 + TextFormField(
123 + style: TextStyle(
124 + fontSize: 14.0,
125 + color: Theme.of(context).primaryTextTheme.headline.color),
126 + decoration: InputDecoration(
127 + hintStyle: TextStyle(color: Theme.of(context).hintColor),
128 + hintText: S.of(context).contact_name,
129 + focusedBorder: UnderlineInputBorder(
130 + borderSide: BorderSide(
131 + color: Palette.cakeGreen, width: 2.0)),
132 + enabledBorder: UnderlineInputBorder(
133 + borderSide: BorderSide(
134 + color: Theme.of(context).focusColor, width: 1.0))),
135 + controller: _contactNameController,
136 + validator: (value) {
137 + addressBookStore.validateContactName(value);
138 + return addressBookStore.errorMessage;
139 + },
140 + ),
141 + SizedBox(height: 14.0),
142 + Container(
143 + child: InkWell(
144 + onTap: () => _setCurrencyType(context),
145 + child: IgnorePointer(
146 + child: TextFormField(
147 + style: TextStyle(
148 + fontSize: 14.0,
149 + color: Theme.of(context)
150 + .primaryTextTheme
151 + .headline
152 + .color),
153 + decoration: InputDecoration(
154 + focusedBorder: UnderlineInputBorder(
155 + borderSide: BorderSide(
156 + color: Palette.cakeGreen,
157 + width: 2.0)),
158 + enabledBorder: UnderlineInputBorder(
159 + borderSide: BorderSide(
160 + color: Theme.of(context).focusColor,
161 + width: 1.0))),
162 + controller: _currencyTypeController,
163 + ),
164 + ),
165 + ),
166 + ),
167 + SizedBox(height: 14.0),
168 + AddressTextField(
169 + controller: _addressController,
170 + options: [AddressTextFieldOption.qrCode],
171 + validator: (value) {
172 + addressBookStore.validateAddress(value,
173 + cryptoCurrency: _selectectCrypto);
174 + return addressBookStore.errorMessage;
175 + },
176 + )
177 + ],
178 + ),
179 + ),
180 + bottomSection: Row(
181 + children: <Widget>[
182 + Expanded(
183 + child: PrimaryButton(
184 + onPressed: () {
185 + setState(() {
186 + _selectectCrypto = CryptoCurrency.xmr;
187 + _contactNameController.text = '';
188 + _currencyTypeController.text =
189 + _selectectCrypto.toString();
190 + _addressController.text = '';
191 + });
192 + },
193 + text: S.of(context).reset,
194 + color:
195 + Theme.of(context).accentTextTheme.button.backgroundColor,
196 + borderColor:
197 + Theme.of(context).accentTextTheme.button.decorationColor),
198 + ),
199 + SizedBox(width: 20),
200 + Expanded(
201 + child: PrimaryButton(
202 + onPressed: () async {
203 + if (!_formKey.currentState.validate()) {
204 + return;
205 + }
206 +
207 + try {
208 + if (widget.contact == null) {
209 + final newContact = Contact(
210 + name: _contactNameController.text,
211 + address: _addressController.text,
212 + type: _selectectCrypto);
213 +
214 + await addressBookStore.add(contact: newContact);
215 + } else {
216 + widget.contact.name = _contactNameController.text;
217 + widget.contact.address = _addressController.text;
218 + widget.contact.updateCryptoCurrency(currency: _selectectCrypto);
219 +
220 + await addressBookStore.update(contact: widget.contact);
221 + }
222 + Navigator.pop(context);
223 + } catch (e) {
224 + await showDialog(
225 + context: context,
226 + builder: (BuildContext context) {
227 + return AlertDialog(
228 + title: Text(
229 + e.toString(),
230 + textAlign: TextAlign.center,
231 + ),
232 + actions: <Widget>[
233 + FlatButton(
234 + onPressed: () =>
235 + Navigator.of(context).pop(),
236 + child: Text(S.of(context).ok))
237 + ],
238 + );
239 + });
240 + }
241 + },
242 + text: S.of(context).save,
243 + color: Theme.of(context)
244 + .primaryTextTheme
245 + .button
246 + .backgroundColor,
247 + borderColor: Theme.of(context)
248 + .primaryTextTheme
249 + .button
250 + .decorationColor))
251 + ],
252 + ));
253 + }
254 +}
lib/src/screens/auth/auth_page.dart new
+95
@@ -0,0 +1,95 @@
1 +import 'package:mobx/mobx.dart';
2 +import 'package:provider/provider.dart';
3 +import 'package:flutter/material.dart';
4 +import 'package:flutter/cupertino.dart';
5 +import 'package:cake_wallet/generated/i18n.dart';
6 +import 'package:cake_wallet/src/stores/auth/auth_state.dart';
7 +import 'package:cake_wallet/src/stores/auth/auth_store.dart';
8 +import 'package:cake_wallet/src/screens/pin_code/pin_code.dart';
9 +
10 +
11 +class AuthPage extends StatefulWidget {
12 + final Function(bool, AuthPageState) onAuthenticationFinished;
13 + final bool closable;
14 +
15 + AuthPage({this.onAuthenticationFinished, this.closable = true});
16 +
17 + @override
18 + AuthPageState createState() => AuthPageState();
19 +}
20 +
21 +class AuthPageState extends State<AuthPage> {
22 + final _key = GlobalKey<ScaffoldState>();
23 + final _pinCodeKey = GlobalKey<PinCodeState>();
24 +
25 + void changeProcessText(String text) {
26 + _key.currentState.showSnackBar(
27 + SnackBar(content: Text(text), backgroundColor: Colors.green));
28 + }
29 +
30 + void close() => Navigator.of(_key.currentContext).pop();
31 +
32 + @override
33 + Widget build(BuildContext context) {
34 + final authStore = Provider.of<AuthStore>(context);
35 +
36 + reaction((_) => authStore.state, (state) {
37 + if (state is AuthenticatedSuccessfully) {
38 + WidgetsBinding.instance.addPostFrameCallback((_) {
39 + if (widget.onAuthenticationFinished != null) {
40 + widget.onAuthenticationFinished(true, this);
41 + } else {
42 + _key.currentState.showSnackBar(
43 + SnackBar(
44 + content: Text(S.of(context).authenticated),
45 + backgroundColor: Colors.green,
46 + ),
47 + );
48 + }
49 + });
50 + }
51 +
52 + if (state is AuthenticationInProgress) {
53 + WidgetsBinding.instance.addPostFrameCallback((_) {
54 + _key.currentState.showSnackBar(
55 + SnackBar(
56 + content: Text(S.of(context).authentication),
57 + backgroundColor: Colors.green,
58 + ),
59 + );
60 + });
61 + }
62 +
63 + if (state is AuthenticationFailure || state is AuthenticationBanned) {
64 + WidgetsBinding.instance.addPostFrameCallback((_) {
65 + _pinCodeKey.currentState.clear();
66 + _key.currentState.hideCurrentSnackBar();
67 + _key.currentState.showSnackBar(
68 + SnackBar(
69 + content: Text(S.of(context).failed_authentication(state.error)),
70 + backgroundColor: Colors.red,
71 + ),
72 + );
73 +
74 + if (widget.onAuthenticationFinished != null) {
75 + widget.onAuthenticationFinished(false, this);
76 + }
77 + });
78 + }
79 + });
80 +
81 + return Scaffold(
82 + key: _key,
83 + appBar: CupertinoNavigationBar(
84 + leading: widget.closable ? CloseButton() : Container(),
85 + backgroundColor: Theme.of(context).backgroundColor,
86 + border: null,
87 + ),
88 + resizeToAvoidBottomPadding: false,
89 + body: PinCode(
90 + (pin, _) => authStore.auth(
91 + password: pin.fold('', (ac, val) => ac + '$val')),
92 + false,
93 + _pinCodeKey));
94 + }
95 +}
lib/src/screens/auth/create_login_page.dart new
+28
@@ -0,0 +1,28 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:provider/provider.dart';
3 +import 'package:shared_preferences/shared_preferences.dart';
4 +import 'package:cake_wallet/src/domain/services/user_service.dart';
5 +import 'package:cake_wallet/src/domain/services/wallet_list_service.dart';
6 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
7 +import 'package:cake_wallet/src/screens/auth/auth_page.dart';
8 +import 'package:cake_wallet/src/stores/auth/auth_store.dart';
9 +import 'package:cake_wallet/src/stores/authentication/authentication_store.dart';
10 +
11 +Widget createLoginPage(
12 + {@required SharedPreferences sharedPreferences,
13 + @required UserService userService,
14 + @required WalletService walletService,
15 + @required WalletListService walletListService,
16 + @required AuthenticationStore authenticationStore}) =>
17 + Provider(
18 + create: (_) => AuthStore(
19 + sharedPreferences: sharedPreferences,
20 + userService: userService,
21 + walletService: walletService),
22 + child: AuthPage(
23 + onAuthenticationFinished: (isAuthenticated, state) {
24 + if (isAuthenticated) {
25 + authenticationStore.loggedIn();
26 + }
27 + },
28 + closable: false));
lib/src/screens/auth/create_unlock_page.dart new
+23
@@ -0,0 +1,23 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:provider/provider.dart';
3 +import 'package:shared_preferences/shared_preferences.dart';
4 +import 'package:cake_wallet/src/domain/services/user_service.dart';
5 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
6 +import 'package:cake_wallet/src/screens/auth/auth_page.dart';
7 +import 'package:cake_wallet/src/stores/auth/auth_store.dart';
8 +
9 +Widget createUnlockPage(
10 + {@required SharedPreferences sharedPreferences,
11 + @required UserService userService,
12 + @required WalletService walletService,
13 + @required Function(bool, AuthPageState) onAuthenticationFinished}) =>
14 + WillPopScope(
15 + onWillPop: () async => false,
16 + child: Provider(
17 + create: (_) => AuthStore(
18 + sharedPreferences: sharedPreferences,
19 + userService: userService,
20 + walletService: walletService),
21 + child: AuthPage(
22 + onAuthenticationFinished: onAuthenticationFinished,
23 + closable: false)));
\ No newline at end of file
lib/src/screens/base_page.dart new
+125
@@ -0,0 +1,125 @@
1 +import 'package:flutter/cupertino.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:cake_wallet/src/widgets/nav_bar.dart';
4 +import 'package:provider/provider.dart';
5 +import 'package:cake_wallet/themes.dart';
6 +import 'package:cake_wallet/theme_changer.dart';
7 +
8 +enum AppBarStyle { regular, withShadow }
9 +
10 +abstract class BasePage extends StatelessWidget {
11 + String get title => null;
12 + bool get isModalBackButton => false;
13 + Color get backgroundColor => Colors.white;
14 + bool get resizeToAvoidBottomPadding => true;
15 + AppBarStyle get appBarStyle => AppBarStyle.regular;
16 +
17 + final _backArrowImage = Image.asset('assets/images/back_arrow.png');
18 + final _backArrowImageDarkTheme =
19 + Image.asset('assets/images/back_arrow_dark_theme.png');
20 + final _closeButtonImage = Image.asset('assets/images/close_button.png');
21 + final _closeButtonImageDarkTheme =
22 + Image.asset('assets/images/close_button_dark_theme.png');
23 +
24 + void onClose(BuildContext context) => Navigator.of(context).pop();
25 +
26 + Widget leading(BuildContext context) {
27 + if (ModalRoute.of(context).isFirst) {
28 + return null;
29 + }
30 +
31 + ThemeChanger _themeChanger = Provider.of<ThemeChanger>(context);
32 + Image _closeButton, _backButton;
33 +
34 + if (_themeChanger.getTheme() == Themes.darkTheme) {
35 + _backButton = _backArrowImageDarkTheme;
36 + _closeButton = _closeButtonImageDarkTheme;
37 + } else {
38 + _backButton = _backArrowImage;
39 + _closeButton = _closeButtonImage;
40 + }
41 +
42 + return SizedBox(
43 + height: 37,
44 + width: isModalBackButton ? 37 : 20,
45 + child: ButtonTheme(
46 + minWidth: double.minPositive,
47 + child: FlatButton(
48 + highlightColor: Colors.transparent,
49 + splashColor: Colors.transparent,
50 + padding: EdgeInsets.all(0),
51 + onPressed: () => onClose(context),
52 + child: isModalBackButton ? _closeButton : _backButton),
53 + ),
54 + );
55 + }
56 +
57 + Widget middle(BuildContext context) {
58 + return title == null
59 + ? null
60 + : Text(
61 + title,
62 + style: TextStyle(
63 + fontSize: 16.0,
64 + fontWeight: FontWeight.w600,
65 + color: Theme.of(context).primaryTextTheme.title.color),
66 + );
67 + }
68 +
69 + Widget trailing(BuildContext context) => null;
70 +
71 + Widget floatingActionButton(BuildContext context) => null;
72 +
73 + Widget appBar(BuildContext context) {
74 + final _themeChanger = Provider.of<ThemeChanger>(context);
75 + final _isDarkTheme = _themeChanger.getTheme() == Themes.darkTheme;
76 +
77 + switch (appBarStyle) {
78 + case AppBarStyle.regular:
79 + return NavBar(
80 + context: context,
81 + leading: leading(context),
82 + middle: middle(context),
83 + trailing: trailing(context),
84 + backgroundColor: _isDarkTheme
85 + ? Theme.of(context).backgroundColor
86 + : backgroundColor);
87 +
88 + case AppBarStyle.withShadow:
89 + return NavBar.withShadow(
90 + context: context,
91 + leading: leading(context),
92 + middle: middle(context),
93 + trailing: trailing(context),
94 + backgroundColor: _isDarkTheme
95 + ? Theme.of(context).backgroundColor
96 + : backgroundColor);
97 +
98 + default:
99 + return NavBar(
100 + context: context,
101 + leading: leading(context),
102 + middle: middle(context),
103 + trailing: trailing(context),
104 + backgroundColor: _isDarkTheme
105 + ? Theme.of(context).backgroundColor
106 + : backgroundColor);
107 + }
108 + }
109 +
110 + Widget body(BuildContext context);
111 +
112 + @override
113 + Widget build(BuildContext context) {
114 + final _themeChanger = Provider.of<ThemeChanger>(context);
115 + final _isDarkTheme = _themeChanger.getTheme() == Themes.darkTheme;
116 +
117 + return Scaffold(
118 + backgroundColor:
119 + _isDarkTheme ? Theme.of(context).backgroundColor : backgroundColor,
120 + resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
121 + appBar: appBar(context),
122 + body: SafeArea(child: body(context)),
123 + floatingActionButton: floatingActionButton(context));
124 + }
125 +}
lib/src/screens/dashboard/create_dashboard_page.dart new
+31
@@ -0,0 +1,31 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:hive/hive.dart';
3 +import 'package:provider/provider.dart';
4 +import 'package:cake_wallet/src/domain/exchange/trade.dart';
5 +import 'package:cake_wallet/src/domain/monero/transaction_description.dart';
6 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
7 +import 'package:cake_wallet/src/screens/dashboard/dashboard_page.dart';
8 +import 'package:cake_wallet/src/stores/action_list/action_list_store.dart';
9 +import 'package:cake_wallet/src/stores/action_list/trade_filter_store.dart';
10 +import 'package:cake_wallet/src/stores/action_list/transaction_filter_store.dart';
11 +import 'package:cake_wallet/src/stores/price/price_store.dart';
12 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
13 +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
14 +
15 +Widget createDashboardPage(
16 + {@required WalletService walletService,
17 + @required PriceStore priceStore,
18 + @required Box<TransactionDescription> transactionDescriptions,
19 + @required SettingsStore settingsStore,
20 + @required Box<Trade> trades,
21 + @required WalletStore walletStore}) =>
22 + Provider(
23 + create: (_) => ActionListStore(
24 + walletService: walletService,
25 + settingsStore: settingsStore,
26 + priceStore: priceStore,
27 + tradesSource: trades,
28 + transactionFilterStore: TransactionFilterStore(),
29 + tradeFilterStore: TradeFilterStore(walletStore: walletStore),
30 + transactionDescriptions: transactionDescriptions),
31 + child: DashboardPage());
lib/src/screens/dashboard/dashboard_page.dart new
+584
@@ -0,0 +1,584 @@
1 +import 'package:provider/provider.dart';
2 +import 'package:intl/intl.dart';
3 +import 'package:date_range_picker/date_range_picker.dart' as DateRagePicker;
4 +import 'package:flutter/material.dart';
5 +import 'package:flutter/cupertino.dart';
6 +import 'package:flutter_mobx/flutter_mobx.dart';
7 +import 'package:cake_wallet/routes.dart';
8 +import 'package:cake_wallet/palette.dart';
9 +import 'package:cake_wallet/generated/i18n.dart';
10 +import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
11 +import 'package:cake_wallet/src/domain/common/sync_status.dart';
12 +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
13 +import 'package:cake_wallet/src/stores/action_list/action_list_store.dart';
14 +import 'package:cake_wallet/src/stores/balance/balance_store.dart';
15 +import 'package:cake_wallet/src/stores/sync/sync_store.dart';
16 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
17 +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
18 +import 'package:cake_wallet/src/stores/action_list/date_section_item.dart';
19 +import 'package:cake_wallet/src/stores/action_list/trade_list_item.dart';
20 +import 'package:cake_wallet/src/stores/action_list/transaction_list_item.dart';
21 +import 'package:cake_wallet/src/screens/base_page.dart';
22 +import 'package:cake_wallet/src/screens/dashboard/date_section_raw.dart';
23 +import 'package:cake_wallet/src/screens/dashboard/trade_row.dart';
24 +import 'package:cake_wallet/src/screens/dashboard/transaction_raw.dart';
25 +import 'package:cake_wallet/src/widgets/primary_button.dart';
26 +import 'package:cake_wallet/src/screens/dashboard/wallet_menu.dart';
27 +import 'package:cake_wallet/src/widgets/picker.dart';
28 +
29 +class DashboardPage extends BasePage {
30 + final _bodyKey = GlobalKey();
31 +
32 + @override
33 + Widget leading(BuildContext context) {
34 + return SizedBox(
35 + width: 30,
36 + child: FlatButton(
37 + padding: EdgeInsets.all(0),
38 + onPressed: () => _presentWalletMenu(context),
39 + child: Image.asset('assets/images/more.png',
40 + color: Theme.of(context).primaryTextTheme.caption.color,
41 + width: 30)));
42 + }
43 +
44 + @override
45 + Widget middle(BuildContext context) {
46 + final walletStore = Provider.of<WalletStore>(context);
47 +
48 + return Observer(builder: (_) {
49 + return Column(
50 + mainAxisAlignment: MainAxisAlignment.center,
51 + children: <Widget>[
52 + Text(
53 + walletStore.name,
54 + style: TextStyle(
55 + color: Theme.of(context).primaryTextTheme.title.color),
56 + ),
57 + SizedBox(height: 5),
58 + Text(
59 + walletStore.account != null ? '${walletStore.account.label}' : '',
60 + style: TextStyle(
61 + fontWeight: FontWeight.w400,
62 + fontSize: 10,
63 + color: Theme.of(context).primaryTextTheme.title.color),
64 + ),
65 + ]);
66 + });
67 + }
68 +
69 + @override
70 + Widget trailing(BuildContext context) {
71 + return SizedBox(
72 + width: 20,
73 + child: FlatButton(
74 + padding: EdgeInsets.all(0),
75 + onPressed: () => Navigator.of(context).pushNamed(Routes.settings),
76 + child: Image.asset('assets/images/settings_icon.png',
77 + color: Colors.grey, height: 20)),
78 + );
79 + }
80 +
81 + @override
82 + Widget body(BuildContext context) => DashboardPageBody(key: _bodyKey);
83 +
84 + @override
85 + Widget floatingActionButton(BuildContext context) => FloatingActionButton(
86 + child: Image.asset('assets/images/exchange_icon.png',
87 + color: Colors.white, height: 26, width: 22),
88 + backgroundColor: Palette.floatingActionButton,
89 + onPressed: () async {
90 + final actionListStore = Provider.of<ActionListStore>(context);
91 +
92 + await Navigator.of(context, rootNavigator: true)
93 + .pushNamed(Routes.exchange);
94 + actionListStore.updateTradeList();
95 + });
96 +
97 + void _presentWalletMenu(BuildContext bodyContext) {
98 + final walletMenu = WalletMenu(bodyContext);
99 +
100 + showDialog(
101 + builder: (_) => Picker(
102 + items: walletMenu.items,
103 + selectedAtIndex: -1,
104 + title: S.of(bodyContext).wallet_menu,
105 + pickerHeight: 510,
106 + onItemSelected: (item) =>
107 + walletMenu.action(walletMenu.items.indexOf(item))),
108 + context: bodyContext);
109 + }
110 +}
111 +
112 +class DashboardPageBody extends StatefulWidget {
113 + DashboardPageBody({Key key}) : super(key: key);
114 +
115 + @override
116 + DashboardPageBodyState createState() => DashboardPageBodyState();
117 +}
118 +
119 +class DashboardPageBodyState extends State<DashboardPageBody> {
120 + static final transactionDateFormat = DateFormat("MMM d, yyyy HH:mm");
121 +
122 + final _connectionStatusObserverKey = GlobalKey();
123 + final _balanceObserverKey = GlobalKey();
124 + final _balanceTitleObserverKey = GlobalKey();
125 + final _syncingObserverKey = GlobalKey();
126 + final _listObserverKey = GlobalKey();
127 + final _listKey = GlobalKey();
128 +
129 + @override
130 + Widget build(BuildContext context) {
131 + final balanceStore = Provider.of<BalanceStore>(context);
132 + final actionListStore = Provider.of<ActionListStore>(context);
133 + final syncStore = Provider.of<SyncStore>(context);
134 + final settingsStore = Provider.of<SettingsStore>(context);
135 +
136 + return Observer(
137 + key: _listObserverKey,
138 + builder: (_) {
139 + final items =
140 + actionListStore.items == null ? [] : actionListStore.items;
141 + final itemsCount = items.length + 2;
142 +
143 + return ListView.builder(
144 + key: _listKey,
145 + padding: EdgeInsets.only(bottom: 15),
146 + itemCount: itemsCount,
147 + itemBuilder: (context, index) {
148 + if (index == 0) {
149 + return Container(
150 + margin: EdgeInsets.only(bottom: 20),
151 + decoration: BoxDecoration(
152 + color: Theme.of(context).backgroundColor,
153 + boxShadow: [
154 + BoxShadow(
155 + color: Palette.shadowGreyWithOpacity,
156 + blurRadius: 10,
157 + offset: Offset(0, 12))
158 + ]),
159 + child: Column(
160 + children: <Widget>[
161 + Observer(
162 + key: _syncingObserverKey,
163 + builder: (_) {
164 + final status = syncStore.status;
165 + final statusText = status.title();
166 + final progress = syncStore.status.progress();
167 + final isFialure = status is FailedSyncStatus;
168 +
169 + var descriptionText = '';
170 +
171 + if (status is SyncingSyncStatus) {
172 + descriptionText = S
173 + .of(context)
174 + .Blocks_remaining(
175 + syncStore.status.toString());
176 + }
177 +
178 + if (status is FailedSyncStatus) {
179 + descriptionText = S
180 + .of(context)
181 + .please_try_to_connect_to_another_node;
182 + }
183 +
184 + return Container(
185 + child: Column(
186 + children: [
187 + SizedBox(
188 + height: 3,
189 + child: LinearProgressIndicator(
190 + backgroundColor: Palette.separator,
191 + valueColor:
192 + AlwaysStoppedAnimation<Color>(
193 + Palette.cakeGreen),
194 + value: progress,
195 + ),
196 + ),
197 + SizedBox(height: 10),
198 + Text(statusText,
199 + style: TextStyle(
200 + fontSize: 14,
201 + fontWeight: FontWeight.bold,
202 + color: isFialure
203 + ? Palette.failure
204 + : Palette.cakeGreen)),
205 + Text(descriptionText,
206 + style: TextStyle(
207 + fontSize: 11,
208 + color: Palette.wildDarkBlue,
209 + height: 2.0))
210 + ],
211 + ),
212 + );
213 + }),
214 + GestureDetector(
215 + onTapUp: (_) => balanceStore.isReversing = false,
216 + onTapDown: (_) => balanceStore.isReversing = true,
217 + child: Container(
218 + padding: EdgeInsets.only(top: 40, bottom: 40),
219 + color: Colors.transparent,
220 + child: Column(
221 + children: <Widget>[
222 + Container(width: double.infinity),
223 + Observer(
224 + key: _balanceTitleObserverKey,
225 + builder: (_) {
226 + final savedDisplayMode =
227 + settingsStore.balanceDisplayMode;
228 + final displayMode =
229 + balanceStore.isReversing
230 + ? (savedDisplayMode ==
231 + BalanceDisplayMode
232 + .availableBalance
233 + ? BalanceDisplayMode
234 + .fullBalance
235 + : BalanceDisplayMode
236 + .availableBalance)
237 + : savedDisplayMode;
238 + var title = displayMode.toString();
239 +
240 + return Text(title,
241 + style: TextStyle(
242 + color: Palette.violet,
243 + fontSize: 16));
244 + }),
245 + Observer(
246 + key: _connectionStatusObserverKey,
247 + builder: (_) {
248 + final savedDisplayMode =
249 + settingsStore.balanceDisplayMode;
250 + var balance = '---';
251 + final displayMode =
252 + balanceStore.isReversing
253 + ? (savedDisplayMode ==
254 + BalanceDisplayMode
255 + .availableBalance
256 + ? BalanceDisplayMode
257 + .fullBalance
258 + : BalanceDisplayMode
259 + .availableBalance)
260 + : savedDisplayMode;
261 +
262 + if (displayMode ==
263 + BalanceDisplayMode.availableBalance) {
264 + balance =
265 + balanceStore.unlockedBalance ??
266 + '0.0';
267 + }
268 +
269 + if (displayMode ==
270 + BalanceDisplayMode.fullBalance) {
271 + balance =
272 + balanceStore.fullBalance ?? '0.0';
273 + }
274 +
275 + return Text(
276 + balance,
277 + style: TextStyle(
278 + color: Theme.of(context)
279 + .primaryTextTheme
280 + .caption
281 + .color,
282 + fontSize: 42),
283 + );
284 + }),
285 + Padding(
286 + padding: EdgeInsets.only(top: 7),
287 + child: Observer(
288 + key: _balanceObserverKey,
289 + builder: (_) {
290 + final savedDisplayMode =
291 + settingsStore.balanceDisplayMode;
292 + final displayMode =
293 + balanceStore.isReversing
294 + ? (savedDisplayMode ==
295 + BalanceDisplayMode
296 + .availableBalance
297 + ? BalanceDisplayMode
298 + .fullBalance
299 + : BalanceDisplayMode
300 + .availableBalance)
301 + : savedDisplayMode;
302 + final symbol = settingsStore
303 + .fiatCurrency
304 + .toString();
305 + var balance = '---';
306 +
307 + if (displayMode ==
308 + BalanceDisplayMode
309 + .availableBalance) {
310 + balance =
311 + '${balanceStore.fiatUnlockedBalance} $symbol';
312 + }
313 +
314 + if (displayMode ==
315 + BalanceDisplayMode.fullBalance) {
316 + balance =
317 + '${balanceStore.fiatFullBalance} $symbol';
318 + }
319 +
320 + return Text(balance,
321 + style: TextStyle(
322 + color: Palette.wildDarkBlue,
323 + fontSize: 16));
324 + }))
325 + ],
326 + ),
327 + ),
328 + ),
329 + Padding(
330 + padding: const EdgeInsets.only(
331 + left: 35, right: 35, bottom: 30),
332 + child: Container(
333 + child: Row(
334 + mainAxisAlignment:
335 + MainAxisAlignment.spaceBetween,
336 + children: <Widget>[
337 + Expanded(
338 + child: PrimaryImageButton(
339 + image: Image.asset(
340 + 'assets/images/send_icon.png',
341 + height: 25,
342 + width: 25),
343 + text: S.of(context).send,
344 + onPressed: () => Navigator.of(context,
345 + rootNavigator: true)
346 + .pushNamed(Routes.send),
347 + color: Theme.of(context)
348 + .primaryTextTheme
349 + .button
350 + .backgroundColor,
351 + borderColor: Theme.of(context)
352 + .primaryTextTheme
353 + .button
354 + .decorationColor,
355 + )),
356 + SizedBox(width: 10),
357 + Expanded(
358 + child: PrimaryImageButton(
359 + image: Image.asset(
360 + 'assets/images/receive_icon.png',
361 + height: 25,
362 + width: 25),
363 + text: S.of(context).receive,
364 + onPressed: () => Navigator.of(context,
365 + rootNavigator: true)
366 + .pushNamed(Routes.receive),
367 + color: Theme.of(context)
368 + .accentTextTheme
369 + .caption
370 + .backgroundColor,
371 + borderColor: Theme.of(context)
372 + .accentTextTheme
373 + .caption
374 + .decorationColor,
375 + ))
376 + ],
377 + ),
378 + )),
379 + ],
380 + ),
381 + );
382 + }
383 +
384 + if (index == 1 && actionListStore.totalCount > 0) {
385 + return Padding(
386 + padding: EdgeInsets.only(right: 20, top: 10, bottom: 20),
387 + child: Row(
388 + mainAxisAlignment: MainAxisAlignment.end,
389 + children: <Widget>[
390 + PopupMenuButton<int>(
391 + itemBuilder: (context) => [
392 + PopupMenuItem(
393 + enabled: false,
394 + value: -1,
395 + child: Text(S.of(context).transactions,
396 + style: TextStyle(
397 + fontWeight: FontWeight.bold,
398 + color: Colors.black))),
399 + PopupMenuItem(
400 + value: 0,
401 + child: Observer(
402 + builder: (_) => Row(
403 + mainAxisAlignment:
404 + MainAxisAlignment
405 + .spaceBetween,
406 + children: [
407 + Text(S.of(context).incoming),
408 + Checkbox(
409 + value: actionListStore
410 + .transactionFilterStore
411 + .displayIncoming,
412 + onChanged: (value) =>
413 + actionListStore
414 + .transactionFilterStore
415 + .toggleIncoming(),
416 + )
417 + ]))),
418 + PopupMenuItem(
419 + value: 1,
420 + child: Observer(
421 + builder: (_) => Row(
422 + mainAxisAlignment:
423 + MainAxisAlignment
424 + .spaceBetween,
425 + children: [
426 + Text(S.of(context).outgoing),
427 + Checkbox(
428 + value: actionListStore
429 + .transactionFilterStore
430 + .displayOutgoing,
431 + onChanged: (value) =>
432 + actionListStore
433 + .transactionFilterStore
434 + .toggleOutgoing(),
435 + )
436 + ]))),
437 + PopupMenuItem(
438 + value: 2,
439 + child:
440 + Text(S.of(context).transactions_by_date)),
441 + PopupMenuDivider(),
442 + PopupMenuItem(
443 + enabled: false,
444 + value: -1,
445 + child: Text(S.of(context).trades,
446 + style: TextStyle(
447 + fontWeight: FontWeight.bold,
448 + color: Colors.black))),
449 + PopupMenuItem(
450 + value: 3,
451 + child: Observer(
452 + builder: (_) => Row(
453 + mainAxisAlignment:
454 + MainAxisAlignment
455 + .spaceBetween,
456 + children: [
457 + Text('XMR.TO'),
458 + Checkbox(
459 + value: actionListStore
460 + .tradeFilterStore
461 + .displayXMRTO,
462 + onChanged: (value) =>
463 + actionListStore
464 + .tradeFilterStore
465 + .toggleDisplayExchange(
466 + ExchangeProviderDescription
467 + .xmrto),
468 + )
469 + ]))),
470 + PopupMenuItem(
471 + value: 4,
472 + child: Observer(
473 + builder: (_) => Row(
474 + mainAxisAlignment:
475 + MainAxisAlignment
476 + .spaceBetween,
477 + children: [
478 + Text('Change.NOW'),
479 + Checkbox(
480 + value: actionListStore
481 + .tradeFilterStore
482 + .displayChangeNow,
483 + onChanged: (value) =>
484 + actionListStore
485 + .tradeFilterStore
486 + .toggleDisplayExchange(
487 + ExchangeProviderDescription
488 + .changeNow),
489 + )
490 + ])))
491 + ],
492 + child: Text(S.of(context).filters,
493 + style: TextStyle(
494 + fontSize: 16.0,
495 + color: Theme.of(context)
496 + .primaryTextTheme
497 + .subtitle
498 + .color)),
499 + onSelected: (item) async {
500 + if (item == 2) {
501 + final List<DateTime> picked =
502 + await DateRagePicker.showDatePicker(
503 + context: context,
504 + initialFirstDate: DateTime.now()
505 + .subtract(Duration(days: 1)),
506 + initialLastDate: (DateTime.now()),
507 + firstDate: DateTime(2015),
508 + lastDate: DateTime.now()
509 + .add(Duration(days: 1)));
510 +
511 + if (picked != null && picked.length == 2) {
512 + actionListStore.transactionFilterStore
513 + .changeStartDate(picked.first);
514 + actionListStore.transactionFilterStore
515 + .changeEndDate(picked.last);
516 + }
517 + }
518 + },
519 + )
520 + ]),
521 + );
522 + }
523 +
524 + index -= 2;
525 +
526 + if (index < 0 || index >= items.length) {
527 + return Container();
528 + }
529 +
530 + final item = items[index];
531 +
532 + if (item is DateSectionItem) {
533 + return DateSectionRaw(date: item.date);
534 + }
535 +
536 + if (item is TransactionListItem) {
537 + final transaction = item.transaction;
538 + final savedDisplayMode = settingsStore.balanceDisplayMode;
539 + final formattedAmount =
540 + savedDisplayMode == BalanceDisplayMode.hiddenBalance
541 + ? '---'
542 + : transaction.amountFormatted();
543 + final formattedFiatAmount =
544 + savedDisplayMode == BalanceDisplayMode.hiddenBalance
545 + ? '---'
546 + : transaction.fiatAmount();
547 +
548 + return TransactionRow(
549 + onTap: () => Navigator.of(context).pushNamed(
550 + Routes.transactionDetails,
551 + arguments: transaction),
552 + direction: transaction.direction,
553 + formattedDate:
554 + transactionDateFormat.format(transaction.date),
555 + formattedAmount: formattedAmount,
556 + formattedFiatAmount: formattedFiatAmount,
557 + isPending: transaction.isPending);
558 + }
559 +
560 + if (item is TradeListItem) {
561 + final trade = item.trade;
562 + final savedDisplayMode = settingsStore.balanceDisplayMode;
563 + final formattedAmount = trade.amount != null
564 + ? savedDisplayMode == BalanceDisplayMode.hiddenBalance
565 + ? '---'
566 + : trade.amount
567 + : trade.amount;
568 +
569 + return TradeRow(
570 + onTap: () => Navigator.of(context)
571 + .pushNamed(Routes.tradeDetails, arguments: trade),
572 + provider: trade.provider,
573 + from: trade.from,
574 + to: trade.to,
575 + createdAtFormattedDate:
576 + DateFormat("dd.MM.yyyy, H:m").format(trade.createdAt),
577 + formattedAmount: formattedAmount);
578 + }
579 +
580 + return Container();
581 + });
582 + });
583 + }
584 +}
lib/src/screens/dashboard/date_section_raw.dart new
+38
@@ -0,0 +1,38 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:cake_wallet/palette.dart';
3 +import 'package:intl/intl.dart';
4 +import 'package:cake_wallet/generated/i18n.dart';
5 +
6 +class DateSectionRaw extends StatelessWidget {
7 + static final dateSectionDateFormat = DateFormat("d MMM");
8 + static final nowDate = DateTime.now();
9 +
10 + final DateTime date;
11 +
12 + DateSectionRaw({this.date});
13 +
14 + @override
15 + Widget build(BuildContext context) {
16 + final diffDays = date.difference(nowDate).inDays;
17 + final isToday = nowDate.day == date.day && nowDate.month == date.month && nowDate.year == date.year;
18 + var title = "";
19 +
20 + if (isToday) {
21 + title = S.of(context).today;
22 + } else if (diffDays == 0) {
23 + title = S.of(context).yesterday;
24 + } else if (diffDays > -7 && diffDays < 0) {
25 + final dateFormat = DateFormat("EEEE");
26 + title = dateFormat.format(date);
27 + } else {
28 + title = dateSectionDateFormat.format(date);
29 + }
30 +
31 + return Padding(
32 + padding: const EdgeInsets.only(top: 10, bottom: 10),
33 + child: Center(
34 + child: Text(title,
35 + style: TextStyle(fontSize: 16, color: Palette.wildDarkBlue))),
36 + );
37 + }
38 +}
lib/src/screens/dashboard/trade_row.dart new
+87
@@ -0,0 +1,87 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:cake_wallet/palette.dart';
3 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
4 +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
5 +
6 +class TradeRow extends StatelessWidget {
7 + final VoidCallback onTap;
8 + final ExchangeProviderDescription provider;
9 + final CryptoCurrency from;
10 + final CryptoCurrency to;
11 + final String createdAtFormattedDate;
12 + final String formattedAmount;
13 +
14 + TradeRow(
15 + {this.provider,
16 + this.from,
17 + this.to,
18 + this.createdAtFormattedDate,
19 + this.formattedAmount,
20 + @required this.onTap});
21 +
22 + @override
23 + Widget build(BuildContext context) {
24 + final amountCrypto = provider == ExchangeProviderDescription.xmrto
25 + ? to.toString()
26 + : from.toString();
27 +
28 + return InkWell(
29 + onTap: onTap,
30 + child: Container(
31 + padding: EdgeInsets.only(top: 14, bottom: 14, left: 20, right: 20),
32 + decoration: BoxDecoration(
33 + border: Border(
34 + bottom: BorderSide(
35 + color: PaletteDark.darkGrey,
36 + width: 0.5,
37 + style: BorderStyle.solid))),
38 + child: Row(children: <Widget>[
39 + _getPoweredImage(provider),
40 + Expanded(
41 + child: Padding(
42 + padding: const EdgeInsets.only(left: 10, right: 10),
43 + child: Column(
44 + children: <Widget>[
45 + Row(
46 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
47 + children: <Widget>[
48 + Text('${from.toString()} → ${to.toString()}',
49 + style: TextStyle(
50 + fontSize: 16,
51 + color: Theme.of(context).primaryTextTheme.subhead.color)),
52 + formattedAmount != null
53 + ? Text(formattedAmount + ' ' + amountCrypto,
54 + style: const TextStyle(
55 + fontSize: 16, color: Palette.purpleBlue))
56 + : Container()
57 + ]),
58 + SizedBox(height: 6),
59 + Row(
60 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
61 + children: <Widget>[
62 + Text(createdAtFormattedDate,
63 + style: const TextStyle(
64 + fontSize: 13, color: Palette.blueGrey))
65 + ]),
66 + ],
67 + ),
68 + ))
69 + ]),
70 + ));
71 + }
72 +
73 + Image _getPoweredImage(ExchangeProviderDescription provider) {
74 + Image image;
75 + switch (provider) {
76 + case ExchangeProviderDescription.xmrto:
77 + image = Image.asset('assets/images/xmr_btc.png');
78 + break;
79 + case ExchangeProviderDescription.changeNow:
80 + image = Image.asset('assets/images/change_now.png');
81 + break;
82 + default:
83 + image = null;
84 + }
85 + return image;
86 + }
87 +}
lib/src/screens/dashboard/transaction_raw.dart new
+78
@@ -0,0 +1,78 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:cake_wallet/palette.dart';
3 +import 'package:cake_wallet/src/domain/common/transaction_direction.dart';
4 +import 'package:cake_wallet/generated/i18n.dart';
5 +
6 +class TransactionRow extends StatelessWidget {
7 + final VoidCallback onTap;
8 + final TransactionDirection direction;
9 + final String formattedDate;
10 + final String formattedAmount;
11 + final String formattedFiatAmount;
12 + final bool isPending;
13 +
14 + TransactionRow(
15 + {this.direction,
16 + this.formattedDate,
17 + this.formattedAmount,
18 + this.formattedFiatAmount,
19 + this.isPending,
20 + @required this.onTap});
21 +
22 + @override
23 + Widget build(BuildContext context) {
24 + return InkWell(
25 + onTap: onTap,
26 + child: Container(
27 + padding: EdgeInsets.only(top: 14, bottom: 14, left: 20, right: 20),
28 + decoration: BoxDecoration(
29 + border: Border(
30 + bottom: BorderSide(
31 + color: PaletteDark.darkGrey,
32 + width: 0.5,
33 + style: BorderStyle.solid))),
34 + child: Row(children: <Widget>[
35 + Image.asset(
36 + direction == TransactionDirection.incoming
37 + ? 'assets/images/transaction_incoming.png'
38 + : 'assets/images/transaction_outgoing.png',
39 + height: 25,
40 + width: 25),
41 + Expanded(
42 + child: Padding(
43 + padding: const EdgeInsets.only(left: 10, right: 10),
44 + child: Column(
45 + children: <Widget>[
46 + Row(
47 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
48 + children: <Widget>[
49 + Text(
50 + (direction == TransactionDirection.incoming
51 + ? S.of(context).received
52 + : S.of(context).sent) +
53 + (isPending ? S.of(context).pending : ''),
54 + style: TextStyle(
55 + fontSize: 16,
56 + color: Theme.of(context).primaryTextTheme.subhead.color)),
57 + Text(formattedAmount,
58 + style: const TextStyle(
59 + fontSize: 16, color: Palette.purpleBlue))
60 + ]),
61 + SizedBox(height: 6),
62 + Row(
63 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
64 + children: <Widget>[
65 + Text(formattedDate,
66 + style: const TextStyle(
67 + fontSize: 13, color: Palette.blueGrey)),
68 + Text(formattedFiatAmount,
69 + style: const TextStyle(
70 + fontSize: 14, color: Palette.blueGrey))
71 + ]),
72 + ],
73 + ),
74 + ))
75 + ]),
76 + ));
77 + }
78 +}
lib/src/screens/dashboard/wallet_menu.dart new
+86
@@ -0,0 +1,86 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:cake_wallet/routes.dart';
3 +import 'package:provider/provider.dart';
4 +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
5 +import 'package:cake_wallet/generated/i18n.dart';
6 +
7 +class WalletMenu {
8 + final List<String> items = [
9 + S.current.reconnect,
10 + S.current.rescan,
11 + S.current.wallets,
12 + S.current.show_seed,
13 + S.current.show_keys,
14 + S.current.accounts,
15 + S.current.address_book_menu
16 + ];
17 + final BuildContext context;
18 +
19 + WalletMenu(this.context);
20 +
21 + void action(int index) {
22 + switch (index) {
23 + case 0:
24 + _presentReconnectAlert(context);
25 + break;
26 + case 1:
27 + Navigator.of(context).pushNamed(Routes.rescan);
28 + break;
29 + case 2:
30 + Navigator.of(context).pushNamed(Routes.walletList);
31 +
32 + break;
33 + case 3:
34 + Navigator.of(context).pushNamed(Routes.auth,
35 + arguments: (isAuthenticatedSuccessfully, auth) =>
36 + isAuthenticatedSuccessfully
37 + ? Navigator.of(auth.context).popAndPushNamed(Routes.seed)
38 + : null);
39 +
40 + break;
41 + case 4:
42 + Navigator.of(context).pushNamed(Routes.auth,
43 + arguments: (isAuthenticatedSuccessfully, auth) =>
44 + isAuthenticatedSuccessfully
45 + ? Navigator.of(auth.context)
46 + .popAndPushNamed(Routes.showKeys)
47 + : null);
48 + break;
49 + case 5:
50 + Navigator.of(context).pushNamed(Routes.accountList);
51 + break;
52 + case 6:
53 + Navigator.of(context).pushNamed(Routes.addressBook);
54 + break;
55 + default:
56 + break;
57 + }
58 + }
59 +
60 + Future _presentReconnectAlert(BuildContext context) async {
61 + final walletStore = Provider.of<WalletStore>(context);
62 +
63 + await showDialog(
64 + context: context,
65 + builder: (BuildContext context) {
66 + return AlertDialog(
67 + title: Text(
68 + S.of(context).reconnection,
69 + textAlign: TextAlign.center,
70 + ),
71 + content: Text(S.of(context).reconnect_alert_text),
72 + actions: <Widget>[
73 + FlatButton(
74 + onPressed: () => Navigator.of(context).pop(),
75 + child: Text(S.of(context).cancel)),
76 + FlatButton(
77 + onPressed: () {
78 + walletStore.reconnect();
79 + Navigator.of(context).pop();
80 + },
81 + child: Text(S.of(context).ok))
82 + ],
83 + );
84 + });
85 + }
86 +}
lib/src/screens/disclaimer/disclaimer_page.dart new
+305
@@ -0,0 +1,305 @@
1 +import 'dart:ui';
2 +import 'package:flutter/material.dart';
3 +import 'package:flutter/cupertino.dart';
4 +import 'package:flutter/services.dart';
5 +import 'package:cake_wallet/palette.dart';
6 +import 'package:url_launcher/url_launcher.dart';
7 +import 'package:cake_wallet/src/screens/base_page.dart';
8 +import 'package:cake_wallet/src/widgets/primary_button.dart';
9 +
10 +class DisclaimerPage extends BasePage {
11 + final bool isReadOnly;
12 +
13 + DisclaimerPage({this.isReadOnly = false});
14 +
15 + @override
16 + bool get isModalBackButton => false;
17 +
18 + @override
19 + String get title => 'Terms of Use';
20 +
21 + @override
22 + Widget body(BuildContext context) => DisclaimerPageBody(isReadOnly: true);
23 +}
24 +
25 +class DisclaimerPageBody extends StatefulWidget {
26 + final bool isReadOnly;
27 +
28 + DisclaimerPageBody({this.isReadOnly = true});
29 +
30 + @override
31 + createState() => DisclaimerBodyState(false);
32 +}
33 +
34 +class DisclaimerBodyState extends State<DisclaimerPageBody> {
35 + static const xmrto_url = 'https://xmr.to/app_static/html/tos.html';
36 + static const changenow_url = 'https://changenow.io/terms-of-use';
37 +
38 + bool _isAccepted;
39 + bool _checked = false;
40 + String _fileText = '';
41 +
42 + DisclaimerBodyState(this._isAccepted);
43 +
44 + launchUrl(String url) async {
45 + if (await canLaunch(url)) await launch(url);
46 + }
47 +
48 + Future getFileLines() async {
49 + _fileText = await rootBundle.loadString('assets/text/Terms_of_Use.txt');
50 + setState(() {});
51 + }
52 +
53 + _showAlertDialog(BuildContext context) async {
54 + await showDialog(
55 + context: context,
56 + builder: (BuildContext context) {
57 + return AlertDialog(
58 + title: Text(
59 + 'Terms and conditions',
60 + textAlign: TextAlign.center,
61 + ),
62 + content: Text(
63 + 'By using this app, you agree to the Terms of Agreement set forth to below',
64 + textAlign: TextAlign.center,
65 + ),
66 + actions: <Widget>[
67 + FlatButton(
68 + onPressed: () {
69 + Navigator.pop(context);
70 + },
71 + child: Text('OK')),
72 + ],
73 + );
74 + });
75 + }
76 +
77 + _afterLayout(_) {
78 + _showAlertDialog(context);
79 + }
80 +
81 + @override
82 + void initState() {
83 + super.initState();
84 + getFileLines();
85 + if (_isAccepted) WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
86 + }
87 +
88 + @override
89 + Widget build(BuildContext context) {
90 +
91 + return Column(
92 + children: <Widget>[
93 + SizedBox(height: 10.0),
94 + Expanded(
95 + child: Stack(
96 + children: <Widget>[
97 + SingleChildScrollView(
98 + padding: EdgeInsets.only(left: 25.0, right: 25.0),
99 + child: Column(
100 + children: <Widget>[
101 + !_isAccepted
102 + ? Row(
103 + children: <Widget>[
104 + Expanded(
105 + child: Text(
106 + 'Terms and conditions',
107 + textAlign: TextAlign.center,
108 + style: TextStyle(
109 + fontSize: 20.0,
110 + fontWeight: FontWeight.bold),
111 + ),
112 + )
113 + ],
114 + )
115 + : Offstage(),
116 + !_isAccepted
117 + ? SizedBox(
118 + height: 20.0,
119 + )
120 + : Offstage(),
121 + Row(
122 + children: <Widget>[
123 + Expanded(
124 + child: Text(
125 + 'Legal Disclaimer\nAnd\nTerms of Use',
126 + textAlign: TextAlign.center,
127 + style: TextStyle(
128 + fontSize: 12.0, fontWeight: FontWeight.bold),
129 + ),
130 + )
131 + ],
132 + ),
133 + SizedBox(
134 + height: 16.0,
135 + ),
136 + Row(
137 + children: <Widget>[
138 + Expanded(
139 + child: Text(
140 + _fileText,
141 + style: TextStyle(fontSize: 12.0),
142 + ))
143 + ],
144 + ),
145 + SizedBox(
146 + height: 16.0,
147 + ),
148 + Row(
149 + mainAxisAlignment: MainAxisAlignment.start,
150 + children: <Widget>[
151 + Expanded(
152 + child: Text(
153 + 'Other Terms and Conditions',
154 + textAlign: TextAlign.left,
155 + style: TextStyle(
156 + fontSize: 14.0, fontWeight: FontWeight.bold),
157 + ),
158 + )
159 + ],
160 + ),
161 + SizedBox(
162 + height: 16.0,
163 + ),
164 + Row(
165 + mainAxisAlignment: MainAxisAlignment.start,
166 + children: <Widget>[
167 + Expanded(
168 + child: GestureDetector(
169 + onTap: () => launchUrl(xmrto_url),
170 + child: Text(
171 + xmrto_url,
172 + textAlign: TextAlign.left,
173 + style: TextStyle(
174 + color: Colors.blue,
175 + fontSize: 14.0,
176 + fontWeight: FontWeight.normal,
177 + decoration: TextDecoration.underline),
178 + ),
179 + ))
180 + ],
181 + ),
182 + SizedBox(
183 + height: 16.0,
184 + ),
185 + Row(
186 + mainAxisAlignment: MainAxisAlignment.start,
187 + children: <Widget>[
188 + Expanded(
189 + child: GestureDetector(
190 + onTap: () => launchUrl(changenow_url),
191 + child: Text(
192 + changenow_url,
193 + textAlign: TextAlign.left,
194 + style: TextStyle(
195 + color: Colors.blue,
196 + fontSize: 14.0,
197 + fontWeight: FontWeight.normal,
198 + decoration: TextDecoration.underline),
199 + ),
200 + ))
201 + ],
202 + ),
203 + SizedBox(
204 + height: 16.0,
205 + )
206 + ],
207 + ),
208 + ),
209 + Container(
210 + alignment: Alignment.bottomCenter,
211 + child: Container(
212 + height: 12.0,
213 + child: ClipRect(
214 + child: BackdropFilter(
215 + filter: ImageFilter.blur(sigmaX: 0.7, sigmaY: 0.7),
216 + child: Container(
217 + decoration: BoxDecoration(
218 + gradient: LinearGradient(
219 + colors: [
220 + Theme.of(context).backgroundColor.withOpacity(0.0),
221 + Theme.of(context).backgroundColor,
222 + ],
223 + begin: FractionalOffset.topCenter,
224 + end: FractionalOffset.bottomCenter,
225 + ),
226 + ),
227 + ),
228 + ),
229 + ),
230 + ),
231 + )
232 + ],
233 + )),
234 + if (!widget.isReadOnly) ...[
235 + !_isAccepted
236 + ? Row(
237 + children: <Widget>[
238 + Expanded(
239 + child: Container(
240 + padding: EdgeInsets.only(
241 + left: 25.0, top: 10.0, right: 25.0, bottom: 10.0),
242 + child: InkWell(
243 + onTap: () {
244 + setState(() {
245 + _checked = !_checked;
246 + });
247 + },
248 + child: Row(
249 + mainAxisAlignment: MainAxisAlignment.start,
250 + children: <Widget>[
251 + Container(
252 + height: 25.0,
253 + width: 25.0,
254 + margin: EdgeInsets.only(
255 + right: 10.0,
256 + ),
257 + decoration: BoxDecoration(
258 + border: Border.all(
259 + color: Palette.lightGrey, width: 1.0),
260 + borderRadius: BorderRadius.all(
261 + Radius.circular(8.0)),
262 + color: Theme.of(context).backgroundColor),
263 + child: _checked
264 + ? Icon(
265 + Icons.check,
266 + color: Colors.blue,
267 + size: 20.0,
268 + )
269 + : null,
270 + ),
271 + Text(
272 + 'I agree to Terms of Use',
273 + style: TextStyle(
274 + fontWeight: FontWeight.bold,
275 + fontSize: 14.0),
276 + )
277 + ],
278 + ),
279 + )),
280 + ),
281 + ],
282 + )
283 + : Offstage(),
284 + !_isAccepted
285 + ? Container(
286 + padding:
287 + EdgeInsets.only(left: 25.0, right: 25.0, bottom: 25.0),
288 + child: PrimaryButton(
289 + onPressed: _checked ? () {} : null,
290 + text: 'Accept',
291 + color: Theme.of(context).primaryTextTheme.button.backgroundColor,
292 + borderColor: Theme.of(context).primaryTextTheme.button.decorationColor,
293 + ),
294 + )
295 + : Offstage(),
296 + _isAccepted
297 + ? SizedBox(
298 + height: 20.0,
299 + )
300 + : Offstage()
301 + ],
302 + ],
303 + );
304 + }
305 +}
lib/src/screens/exchange/exchange_page.dart new
+486
@@ -0,0 +1,486 @@
1 +import 'dart:ui';
2 +import 'package:flutter/material.dart';
3 +import 'package:flutter_mobx/flutter_mobx.dart';
4 +import 'package:mobx/mobx.dart';
5 +import 'package:provider/provider.dart';
6 +import 'package:cake_wallet/palette.dart';
7 +import 'package:cake_wallet/routes.dart';
8 +import 'package:cake_wallet/generated/i18n.dart';
9 +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
10 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
11 +import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart';
12 +import 'package:cake_wallet/src/stores/exchange/exchange_trade_state.dart';
13 +import 'package:cake_wallet/src/stores/exchange/limits_state.dart';
14 +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
15 +import 'package:cake_wallet/src/stores/exchange/exchange_store.dart';
16 +import 'package:cake_wallet/src/screens/base_page.dart';
17 +import 'package:cake_wallet/src/screens/exchange/widgets/exchange_card.dart';
18 +import 'package:cake_wallet/src/widgets/primary_button.dart';
19 +import 'package:cake_wallet/src/widgets/picker.dart';
20 +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
21 +
22 +class ExchangePage extends BasePage {
23 + String get title => S.current.exchange;
24 +
25 + @override
26 + bool get isModalBackButton => true;
27 +
28 + final Image arrowBottomPurple = Image.asset(
29 + 'assets/images/arrow_bottom_purple_icon.png',
30 + height: 8,
31 + );
32 +
33 + @override
34 + Widget middle(BuildContext context) {
35 + final exchangeStore = Provider.of<ExchangeStore>(context);
36 +
37 + return FlatButton(
38 + onPressed: () => _presentProviderPicker(context),
39 + highlightColor: Colors.transparent,
40 + splashColor: Colors.transparent,
41 + child: Column(
42 + crossAxisAlignment: CrossAxisAlignment.center,
43 + mainAxisAlignment: MainAxisAlignment.center,
44 + children: <Widget>[
45 + Row(
46 + mainAxisAlignment: MainAxisAlignment.center,
47 + crossAxisAlignment: CrossAxisAlignment.center,
48 + children: [
49 + Text(S.of(context).exchange,
50 + style: TextStyle(
51 + fontSize: 16.0,
52 + fontWeight: FontWeight.w400,
53 + color: Theme.of(context).primaryTextTheme.title.color)),
54 + SizedBox(width: 5),
55 + arrowBottomPurple
56 + ]),
57 + Observer(
58 + builder: (_) => Text('${exchangeStore.provider.title}',
59 + style: TextStyle(
60 + fontSize: 10.0,
61 + fontWeight: FontWeight.w400,
62 + color:
63 + Theme.of(context).primaryTextTheme.headline.color)))
64 + ],
65 + ),
66 + );
67 + }
68 +
69 + @override
70 + Widget trailing(BuildContext context) {
71 + final exchangeStore = Provider.of<ExchangeStore>(context);
72 +
73 + return ButtonTheme(
74 + minWidth: double.minPositive,
75 + child: FlatButton(
76 + padding: EdgeInsets.all(0),
77 + child: Text(
78 + S.of(context).clear,
79 + style: TextStyle(
80 + color: Theme.of(context).accentTextTheme.caption.color,
81 + fontWeight: FontWeight.w500,
82 + fontSize: 16),
83 + ),
84 + onPressed: () => exchangeStore.reset()),
85 + );
86 + }
87 +
88 + @override
89 + Widget body(BuildContext context) => ExchangeForm();
90 +
91 + void _presentProviderPicker(BuildContext context) {
92 + final exchangeStore = Provider.of<ExchangeStore>(context);
93 + final items = exchangeStore.providersForCurrentPair();
94 + final selectedItem = items.indexOf(exchangeStore.provider);
95 +
96 + showDialog(
97 + builder: (_) => Picker(
98 + items: items,
99 + selectedAtIndex: selectedItem,
100 + title: S.of(context).change_exchange_provider,
101 + onItemSelected: (provider) =>
102 + exchangeStore.changeProvider(provider: provider)),
103 + context: context);
104 + }
105 +}
106 +
107 +class ExchangeForm extends StatefulWidget {
108 + @override
109 + State<StatefulWidget> createState() => ExchangeFormState();
110 +}
111 +
112 +class ExchangeFormState extends State<ExchangeForm> {
113 + final depositKey = GlobalKey<ExchangeCardState>();
114 + final receiveKey = GlobalKey<ExchangeCardState>();
115 + final _formKey = GlobalKey<FormState>();
116 + var _isReactionsSet = false;
117 +
118 + final Image arrowBottomPurple = Image.asset(
119 + 'assets/images/arrow_bottom_purple_icon.png',
120 + height: 8,
121 + );
122 + final Image arrowBottomCakeGreen = Image.asset(
123 + 'assets/images/arrow_bottom_cake_green.png',
124 + height: 8,
125 + );
126 +
127 + @override
128 + Widget build(BuildContext context) {
129 + final exchangeStore = Provider.of<ExchangeStore>(context);
130 + final walletStore = Provider.of<WalletStore>(context);
131 +
132 + final depositWalletName =
133 + exchangeStore.depositCurrency == CryptoCurrency.xmr
134 + ? walletStore.name
135 + : null;
136 + final receiveWalletName =
137 + exchangeStore.receiveCurrency == CryptoCurrency.xmr
138 + ? walletStore.name
139 + : null;
140 +
141 + WidgetsBinding.instance.addPostFrameCallback(
142 + (_) => _setReactions(context, exchangeStore, walletStore));
143 +
144 + return Form(
145 + key: _formKey,
146 + child: ScrollableWithBottomSection(
147 + contentPadding: EdgeInsets.only(left: 20, right: 20),
148 + content: SingleChildScrollView(
149 + child: Column(
150 + mainAxisAlignment: MainAxisAlignment.spaceAround,
151 + children: <Widget>[
152 + Padding(
153 + padding: EdgeInsets.only(top: 10, bottom: 20),
154 + child: Text(
155 + S.of(context).you_will_send,
156 + style: TextStyle(
157 + fontWeight: FontWeight.bold,
158 + fontSize: 18,
159 + height: 1.1,
160 + color: Theme.of(context).primaryTextTheme.title.color),
161 + ),
162 + ),
163 + ExchangeCard(
164 + key: depositKey,
165 + initialCurrency: exchangeStore.depositCurrency,
166 + initialWalletName: depositWalletName,
167 + initialAddress:
168 + exchangeStore.depositCurrency == walletStore.type
169 + ? walletStore.address
170 + : null,
171 + initialIsAmountEditable:
172 + !(exchangeStore.provider is XMRTOExchangeProvider),
173 + initialIsAddressEditable:
174 + !(exchangeStore.provider is XMRTOExchangeProvider),
175 + isAmountEstimated:
176 + exchangeStore.provider is XMRTOExchangeProvider,
177 + currencies: CryptoCurrency.all,
178 + onCurrencySelected: (currency) =>
179 + exchangeStore.changeDepositCurrency(currency: currency),
180 + imageArrow: arrowBottomPurple,
181 + currencyValueValidator: (value) {
182 + exchangeStore.validateCryptoCurrency(value);
183 + return exchangeStore.errorMessage;
184 + },
185 + addressTextFieldValidator: (value) {
186 + exchangeStore.validateAddress(value,
187 + cryptoCurrency: exchangeStore.depositCurrency);
188 + return exchangeStore.errorMessage;
189 + },
190 + ),
191 + SizedBox(height: 35),
192 + Padding(
193 + padding: EdgeInsets.only(bottom: 20),
194 + child: Text(
195 + S.of(context).you_will_get,
196 + style: TextStyle(
197 + fontWeight: FontWeight.bold,
198 + fontSize: 18,
199 + height: 1.1,
200 + color:
201 + Theme.of(context).primaryTextTheme.title.color),
202 + )),
203 + Observer(
204 + builder: (_) => ExchangeCard(
205 + key: receiveKey,
206 + initialCurrency: exchangeStore.receiveCurrency,
207 + initialWalletName: receiveWalletName,
208 + initialAddress:
209 + exchangeStore.receiveCurrency == walletStore.type
210 + ? walletStore.address
211 + : null,
212 + initialIsAmountEditable:
213 + exchangeStore.provider is XMRTOExchangeProvider,
214 + initialIsAddressEditable:
215 + exchangeStore.provider is XMRTOExchangeProvider,
216 + isAmountEstimated: !(exchangeStore.provider
217 + is XMRTOExchangeProvider),
218 + currencies: CryptoCurrency.all,
219 + onCurrencySelected: (currency) => exchangeStore
220 + .changeReceiveCurrency(currency: currency),
221 + imageArrow: arrowBottomCakeGreen,
222 + currencyValueValidator: (value) {
223 + exchangeStore.validateCryptoCurrency(value);
224 + return exchangeStore.errorMessage;
225 + },
226 + addressTextFieldValidator: (value) {
227 + exchangeStore.validateAddress(value,
228 + cryptoCurrency: exchangeStore.receiveCurrency);
229 + return exchangeStore.errorMessage;
230 + },
231 + )),
232 + ],
233 + ),
234 + ),
235 + bottomSectionPadding: EdgeInsets.only(top: 35, left: 20, right: 20),
236 + bottomSection: Column(children: <Widget>[
237 + Padding(
238 + padding: EdgeInsets.only(bottom: 15),
239 + child: Observer(builder: (_) {
240 + final description =
241 + exchangeStore.provider is XMRTOExchangeProvider
242 + ? S.of(context).amount_is_guaranteed
243 + : S.of(context).amount_is_estimate;
244 + return Center(
245 + child: Text(
246 + description,
247 + style: TextStyle(color: Palette.blueGrey, fontSize: 12),
248 + ),
249 + );
250 + }),
251 + ),
252 + Observer(
253 + builder: (_) => LoadingPrimaryButton(
254 + text: S.of(context).exchange,
255 + onPressed: () {
256 + if (_formKey.currentState.validate())
257 + exchangeStore.createTrade();
258 + },
259 + color: Theme.of(context)
260 + .primaryTextTheme
261 + .button
262 + .backgroundColor,
263 + borderColor: Theme.of(context)
264 + .primaryTextTheme
265 + .button
266 + .decorationColor,
267 + isLoading: exchangeStore.tradeState is TradeIsCreating,
268 + )),
269 + Observer(builder: (_) {
270 + final title = exchangeStore.provider.description.title;
271 + var imageSrc = '';
272 +
273 + switch (exchangeStore.provider.description) {
274 + case ExchangeProviderDescription.xmrto:
275 + imageSrc = 'assets/images/xmr_btc.png';
276 + break;
277 + case ExchangeProviderDescription.changeNow:
278 + imageSrc = 'assets/images/change_now.png';
279 + break;
280 + }
281 +
282 + return Padding(
283 + padding: EdgeInsets.only(top: 20, bottom: 20),
284 + child: Row(
285 + mainAxisAlignment: MainAxisAlignment.center,
286 + children: <Widget>[
287 + Image.asset(imageSrc),
288 + SizedBox(width: 10),
289 + Text(
290 + S.of(context).powered_by(title),
291 + style: TextStyle(fontSize: 14, color: Palette.powered),
292 + )
293 + ],
294 + ),
295 + );
296 + })
297 + ]),
298 + ));
299 + }
300 +
301 + void _setReactions(
302 + BuildContext context, ExchangeStore store, WalletStore walletStore) {
303 + if (_isReactionsSet) {
304 + return;
305 + }
306 +
307 + final depositAddressController = depositKey.currentState.addressController;
308 + final depositAmountController = depositKey.currentState.amountController;
309 + final receiveAddressController = receiveKey.currentState.addressController;
310 + final receiveAmountController = receiveKey.currentState.amountController;
311 + final limitsState = store.limitsState;
312 +
313 + if (limitsState is LimitsLoadedSuccessfully) {
314 + final min = limitsState.limits.min != null
315 + ? limitsState.limits.min.toString()
316 + : null;
317 + final max = limitsState.limits.max != null
318 + ? limitsState.limits.max.toString()
319 + : null;
320 + final key =
321 + store.provider is XMRTOExchangeProvider ? receiveKey : depositKey;
322 + key.currentState.changeLimits(min: min, max: max);
323 + }
324 +
325 + _onCurrencyChange(store.receiveCurrency, walletStore, receiveKey);
326 + _onCurrencyChange(store.depositCurrency, walletStore, depositKey);
327 +
328 + reaction(
329 + (_) => walletStore.name,
330 + (_) => _onWalletNameChange(
331 + walletStore, store.receiveCurrency, receiveKey));
332 +
333 + reaction(
334 + (_) => walletStore.name,
335 + (_) => _onWalletNameChange(
336 + walletStore, store.depositCurrency, depositKey));
337 +
338 + reaction((_) => store.receiveCurrency,
339 + (currency) => _onCurrencyChange(currency, walletStore, receiveKey));
340 +
341 + reaction((_) => store.depositCurrency,
342 + (currency) => _onCurrencyChange(currency, walletStore, depositKey));
343 +
344 + reaction((_) => store.depositAmount, (amount) {
345 + if (depositKey.currentState.amountController.text != amount) {
346 + depositKey.currentState.amountController.text = amount;
347 + }
348 + });
349 +
350 + reaction((_) => store.receiveAmount, (amount) {
351 + if (receiveKey.currentState.amountController.text !=
352 + store.receiveAmount) {
353 + receiveKey.currentState.amountController.text = amount;
354 + }
355 + });
356 +
357 + reaction((_) => store.provider, (provider) {
358 + final isReversed = provider is XMRTOExchangeProvider;
359 +
360 + if (isReversed) {
361 + receiveKey.currentState.isAddressEditable(isEditable: true);
362 + receiveKey.currentState.isAmountEditable(isEditable: true);
363 + depositKey.currentState.isAddressEditable(isEditable: false);
364 + depositKey.currentState.isAmountEditable(isEditable: false);
365 + } else {
366 + receiveKey.currentState.isAddressEditable(isEditable: true);
367 + receiveKey.currentState.isAmountEditable(isEditable: false);
368 + depositKey.currentState.isAddressEditable(isEditable: true);
369 + depositKey.currentState.isAmountEditable(isEditable: true);
370 + }
371 +
372 + depositKey.currentState.changeIsAmountEstimated(isReversed);
373 + receiveKey.currentState.changeIsAmountEstimated(!isReversed);
374 + });
375 +
376 + reaction((_) => store.tradeState, (state) {
377 + if (state is TradeIsCreatedFailure) {
378 + WidgetsBinding.instance.addPostFrameCallback((_) {
379 + showDialog(
380 + context: context,
381 + builder: (BuildContext context) {
382 + return AlertDialog(
383 + title: Text(S.of(context).error),
384 + content: Text(state.error),
385 + actions: <Widget>[
386 + FlatButton(
387 + child: Text(S.of(context).ok),
388 + onPressed: () => Navigator.of(context).pop())
389 + ],
390 + );
391 + });
392 + });
393 + }
394 + if (state is TradeIsCreatedSuccessfully) {
395 + Navigator.of(context)
396 + .pushNamed(Routes.exchangeConfirm, arguments: state.trade);
397 + }
398 + });
399 +
400 + reaction((_) => store.limitsState, (state) {
401 + final isXMRTO = store.provider is XMRTOExchangeProvider;
402 + String min;
403 + String max;
404 +
405 + if (state is LimitsLoadedSuccessfully) {
406 + min = state.limits.min != null ? state.limits.min.toString() : null;
407 + max = state.limits.max != null ? state.limits.max.toString() : null;
408 + }
409 +
410 + if (state is LimitsLoadedFailure) {
411 + min = '0';
412 + max = '0';
413 + }
414 +
415 + if (state is LimitsIsLoading) {
416 + min = '...';
417 + max = '...';
418 + }
419 +
420 + final depositMin = isXMRTO ? null : min;
421 + final depositMax = isXMRTO ? null : max;
422 + final receiveMin = isXMRTO ? min : null;
423 + final receiveMax = isXMRTO ? max : null;
424 +
425 + depositKey.currentState.changeLimits(min: depositMin, max: depositMax);
426 + receiveKey.currentState.changeLimits(min: receiveMin, max: receiveMax);
427 + });
428 +
429 + depositAddressController.addListener(
430 + () => store.depositAddress = depositAddressController.text);
431 +
432 + depositAmountController.addListener(() {
433 + if (depositAmountController.text != store.depositAmount) {
434 + store.changeDepositAmount(amount: depositAmountController.text);
435 + }
436 + });
437 +
438 + receiveAddressController.addListener(
439 + () => store.receiveAddress = receiveAddressController.text);
440 +
441 + receiveAmountController.addListener(() {
442 + if (receiveAmountController.text != store.receiveAmount) {
443 + store.changeReceiveAmount(amount: receiveAmountController.text);
444 + }
445 + });
446 +
447 + reaction((_) => walletStore.address, (address) {
448 + if (store.depositCurrency == CryptoCurrency.xmr) {
449 + depositKey.currentState.changeAddress(address: address);
450 + }
451 +
452 + if (store.receiveCurrency == CryptoCurrency.xmr) {
453 + receiveKey.currentState.changeAddress(address: address);
454 + }
455 + });
456 +
457 + _isReactionsSet = true;
458 + }
459 +
460 + void _onCurrencyChange(CryptoCurrency currency, WalletStore walletStore,
461 + GlobalKey<ExchangeCardState> key) {
462 + final isCurrentTypeWallet = currency == walletStore.type;
463 +
464 + key.currentState.changeSelectedCurrency(currency);
465 + key.currentState
466 + .changeWalletName(isCurrentTypeWallet ? walletStore.name : null);
467 +
468 + key.currentState
469 + .changeAddress(address: isCurrentTypeWallet ? walletStore.address : '');
470 +
471 + key.currentState.changeAmount(amount: '');
472 + }
473 +
474 + void _onWalletNameChange(WalletStore walletStore, CryptoCurrency currency,
475 + GlobalKey<ExchangeCardState> key) {
476 + final isCurrentTypeWallet = currency == walletStore.type;
477 +
478 + if (isCurrentTypeWallet) {
479 + key.currentState.changeWalletName(walletStore.name);
480 + key.currentState.addressController.text = walletStore.address;
481 + } else if (key.currentState.addressController.text == walletStore.address) {
482 + key.currentState.changeWalletName(null);
483 + key.currentState.addressController.text = null;
484 + }
485 + }
486 +}
lib/src/screens/exchange/widgets/exchange_card.dart new
+261
@@ -0,0 +1,261 @@
1 +import 'package:flutter/services.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:cake_wallet/palette.dart';
4 +import 'package:cake_wallet/generated/i18n.dart';
5 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
6 +import 'package:cake_wallet/src/widgets/picker.dart';
7 +import 'package:cake_wallet/src/widgets/address_text_field.dart';
8 +
9 +class ExchangeCard extends StatefulWidget {
10 + final List<CryptoCurrency> currencies;
11 + final Function(CryptoCurrency) onCurrencySelected;
12 + final CryptoCurrency initialCurrency;
13 + final String initialWalletName;
14 + final String initialAddress;
15 + final bool initialIsAmountEditable;
16 + final bool initialIsAddressEditable;
17 + final bool isAmountEstimated;
18 + final Image imageArrow;
19 + final FormFieldValidator<String> currencyValueValidator;
20 + final FormFieldValidator<String> addressTextFieldValidator;
21 +
22 + ExchangeCard(
23 + {Key key,
24 + this.initialCurrency,
25 + this.initialAddress,
26 + this.initialWalletName,
27 + this.initialIsAmountEditable,
28 + this.initialIsAddressEditable,
29 + this.isAmountEstimated,
30 + this.currencies,
31 + this.onCurrencySelected,
32 + this.imageArrow,
33 + this.currencyValueValidator,
34 + this.addressTextFieldValidator})
35 + : super(key: key);
36 +
37 + @override
38 + createState() => ExchangeCardState();
39 +}
40 +
41 +class ExchangeCardState extends State<ExchangeCard> {
42 + final addressController = TextEditingController();
43 + final amountController = TextEditingController();
44 +
45 + String _min;
46 + String _max;
47 + CryptoCurrency _selectedCurrency;
48 + String _walletName;
49 + bool _isAmountEditable;
50 + bool _isAddressEditable;
51 + bool _isAmountEstimated;
52 +
53 + @override
54 + void initState() {
55 + _isAmountEditable = widget.initialIsAmountEditable;
56 + _isAddressEditable = widget.initialIsAddressEditable;
57 + _walletName = widget.initialWalletName;
58 + _selectedCurrency = widget.initialCurrency;
59 + _isAmountEstimated = widget.isAmountEstimated;
60 + addressController.text = widget.initialAddress;
61 + super.initState();
62 + }
63 +
64 + void changeLimits({String min, String max}) {
65 + setState(() {
66 + _min = min;
67 + _max = max;
68 + });
69 + }
70 +
71 + void changeSelectedCurrency(CryptoCurrency currency) {
72 + setState(() => _selectedCurrency = currency);
73 + }
74 +
75 + void changeWalletName(String walletName) {
76 + setState(() => _walletName = walletName);
77 + }
78 +
79 + void changeIsAction(bool isActive) {
80 + setState(() => _isAmountEditable = isActive);
81 + }
82 +
83 + void isAmountEditable({bool isEditable = true}) {
84 + setState(() => _isAmountEditable = isEditable);
85 + }
86 +
87 + void isAddressEditable({bool isEditable = true}) {
88 + setState(() => _isAddressEditable = isEditable);
89 + }
90 +
91 + void changeAddress({String address}) {
92 + setState(() => addressController.text = address);
93 + }
94 +
95 + void changeAmount({String amount}) {
96 + setState(() => amountController.text = amount);
97 + }
98 +
99 + void changeIsAmountEstimated(bool isEstimated) {
100 + setState(() => _isAmountEstimated = isEstimated);
101 + }
102 +
103 + @override
104 + Widget build(BuildContext context) {
105 +
106 + return Container(
107 + padding: EdgeInsets.fromLTRB(22, 15, 22, 30),
108 + width: double.infinity,
109 + decoration: BoxDecoration(
110 + color: Theme.of(context).cardColor,
111 + borderRadius: BorderRadius.all(Radius.circular(12))),
112 + child: Column(children: <Widget>[
113 + _isAmountEstimated != null && _isAmountEstimated
114 + ? Row(mainAxisAlignment: MainAxisAlignment.end, children: <Widget>[
115 + SizedBox(
116 + height: 30,
117 + child: Container(
118 + padding: EdgeInsets.fromLTRB(10, 5, 10, 5),
119 + decoration: BoxDecoration(
120 + color: Palette.lightGrey,
121 + borderRadius: BorderRadius.circular(10.0)),
122 + child: Text(
123 + S.of(context).estimated,
124 + style: TextStyle(
125 + fontSize: 14,
126 + color: Palette.wildDarkBlue,
127 + fontWeight: FontWeight.bold),
128 + ),
129 + ),
130 + ),
131 + ])
132 + : Container(),
133 + Container(
134 + child: Row(
135 + crossAxisAlignment: CrossAxisAlignment.center,
136 + children: <Widget>[
137 + Container(
138 + height: 52,
139 + width: 80,
140 + child: InkWell(
141 + onTap: () => _presentPicker(context),
142 + child: Column(
143 + crossAxisAlignment: CrossAxisAlignment.start,
144 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
145 + children: <Widget>[
146 + Row(
147 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
148 + children: <Widget>[
149 + Text(_selectedCurrency.toString(),
150 + style: TextStyle(
151 + fontWeight: FontWeight.bold,
152 + fontSize: 24,
153 + color: Theme.of(context).primaryTextTheme.title.color)),
154 + widget.imageArrow
155 + ]),
156 + _walletName != null
157 + ? Text(_walletName,
158 + style: TextStyle(
159 + fontSize: 12,
160 + color: Palette.wildDarkBlue))
161 + : SizedBox(),
162 + ]),
163 + ),
164 + ),
165 + SizedBox(width: 10),
166 + Flexible(
167 + child: Column(
168 + children: [
169 + TextFormField(
170 + style: TextStyle(fontSize: 23, height: 1.21),
171 + controller: amountController,
172 + enabled: _isAmountEditable,
173 + textAlign: TextAlign.right,
174 + keyboardType: TextInputType.numberWithOptions(
175 + signed: false, decimal: false),
176 + inputFormatters: [BlacklistingTextInputFormatter(new RegExp('[\\-|\\ |\\,]'))],
177 + decoration: InputDecoration(
178 + hintStyle: TextStyle(
179 + color: Theme.of(context).cardTheme.color,
180 + fontSize: 23,
181 + height: 1.21),
182 + hintText: '0.00000000',
183 + focusedBorder: UnderlineInputBorder(
184 + borderSide: BorderSide(
185 + color: Palette.cakeGreen,
186 + width: 2.0)),
187 + enabledBorder: UnderlineInputBorder(
188 + borderSide: BorderSide(
189 + color: _isAmountEditable
190 + ? Palette.deepPurple
191 + : Theme.of(context).focusColor,
192 + width: 1.0))),
193 + validator: widget.currencyValueValidator),
194 + SizedBox(height: 5),
195 + SizedBox(
196 + height: 15,
197 + width: double.infinity,
198 + child: Container(
199 + child: Row(
200 + mainAxisAlignment: MainAxisAlignment.end,
201 + children: <Widget>[
202 + _min != null
203 + ? Text(
204 + S.of(context).min_value(_min, _selectedCurrency.toString()),
205 + style: TextStyle(
206 + fontSize: 10,
207 + height: 1.2,
208 + color: Theme.of(context).primaryTextTheme.subtitle.color),
209 + )
210 + : SizedBox(),
211 + _min != null ? SizedBox(width: 10) : SizedBox(),
212 + _max != null
213 + ? Text(
214 + S.of(context).max_value(_max, _selectedCurrency.toString()),
215 + style: TextStyle(
216 + fontSize: 10,
217 + height: 1.2,
218 + color: Theme.of(context).primaryTextTheme.subtitle.color))
219 + : SizedBox(),
220 + ]),
221 + ),
222 + ),
223 + ],
224 + ),
225 + ),
226 + ]),
227 + ),
228 + SizedBox(height: 10),
229 + AddressTextField(
230 + controller: addressController,
231 + isActive: _isAddressEditable,
232 + options: _isAddressEditable
233 + ? _walletName != null
234 + ? [
235 + AddressTextFieldOption.qrCode,
236 + AddressTextFieldOption.addressBook,
237 + AddressTextFieldOption.subaddressList
238 + ]
239 + : [
240 + AddressTextFieldOption.qrCode,
241 + AddressTextFieldOption.addressBook,
242 + ]
243 + : [],
244 + validator: widget.addressTextFieldValidator,
245 + )
246 + ]),
247 + );
248 + }
249 +
250 + void _presentPicker(BuildContext context) {
251 + showDialog(
252 + builder: (_) => Picker(
253 + items: widget.currencies,
254 + selectedAtIndex: widget.currencies.indexOf(_selectedCurrency),
255 + title: S.of(context).change_currency,
256 + onItemSelected: (item) => widget.onCurrencySelected != null
257 + ? widget.onCurrencySelected(item)
258 + : null),
259 + context: context);
260 + }
261 +}
lib/src/screens/exchange_trade/exchange_confirm_page.dart new
+91
@@ -0,0 +1,91 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter/cupertino.dart';
3 +import 'package:flutter/services.dart';
4 +import 'package:cake_wallet/routes.dart';
5 +import 'package:cake_wallet/generated/i18n.dart';
6 +import 'package:cake_wallet/src/widgets/primary_button.dart';
7 +import 'package:cake_wallet/src/screens/base_page.dart';
8 +import 'package:cake_wallet/src/domain/exchange/trade.dart';
9 +
10 +class ExchangeConfirmPage extends BasePage {
11 + String get title => S.current.copy_id;
12 +
13 + final Trade trade;
14 +
15 + ExchangeConfirmPage({@required this.trade});
16 +
17 + @override
18 + Widget body(BuildContext context) {
19 + return Column(
20 + children: <Widget>[
21 + Expanded(
22 + child: Container(
23 + padding: EdgeInsets.only(left: 80.0, right: 80.0),
24 + child: Center(
25 + child: Column(
26 + mainAxisSize: MainAxisSize.min,
27 + children: <Widget>[
28 + Text(
29 + S.of(context).exchange_result_write_down_trade_id,
30 + textAlign: TextAlign.center,
31 + style: TextStyle(
32 + fontSize: 18.0,
33 + color: Theme.of(context)
34 + .primaryTextTheme
35 + .button
36 + .color),
37 + ),
38 + SizedBox(
39 + height: 70.0,
40 + ),
41 + Text(
42 + S.of(context).trade_id(trade.id),
43 + textAlign: TextAlign.center,
44 + style: TextStyle(
45 + fontSize: 18.0,
46 + color: Theme.of(context)
47 + .primaryTextTheme
48 + .button
49 + .color),
50 + ),
51 + SizedBox(
52 + height: 70.0,
53 + ),
54 + PrimaryButton(
55 + onPressed: () {
56 + Clipboard.setData(ClipboardData(text: trade.id));
57 + Scaffold.of(context).showSnackBar(SnackBar(
58 + content: Text(
59 + S.of(context).copied_to_clipboard,
60 + textAlign: TextAlign.center,
61 + style: TextStyle(color: Colors.white),
62 + ),
63 + backgroundColor: Colors.green,
64 + ));
65 + },
66 + text: S.of(context).copy_id,
67 + color: Theme.of(context)
68 + .accentTextTheme
69 + .caption
70 + .backgroundColor,
71 + borderColor: Theme.of(context)
72 + .accentTextTheme
73 + .caption
74 + .decorationColor)
75 + ],
76 + ),
77 + ))),
78 + Container(
79 + padding: EdgeInsets.only(left: 20.0, right: 20.0, bottom: 40.0),
80 + child: PrimaryButton(
81 + onPressed: () => Navigator.of(context)
82 + .pushReplacementNamed(Routes.exchangeTrade, arguments: trade),
83 + text: S.of(context).saved_the_trade_id,
84 + color: Theme.of(context).primaryTextTheme.button.backgroundColor,
85 + borderColor:
86 + Theme.of(context).primaryTextTheme.button.decorationColor),
87 + )
88 + ],
89 + );
90 + }
91 +}
lib/src/screens/exchange_trade/exchange_trade_page.dart new
+373
@@ -0,0 +1,373 @@
1 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
2 +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
3 +import 'package:mobx/mobx.dart';
4 +import 'package:provider/provider.dart';
5 +import 'package:flutter_mobx/flutter_mobx.dart';
6 +import 'package:flutter/material.dart';
7 +import 'package:flutter/cupertino.dart';
8 +import 'package:flutter/services.dart';
9 +import 'package:cake_wallet/palette.dart';
10 +import 'package:cake_wallet/generated/i18n.dart';
11 +import 'package:cake_wallet/src/stores/exchange_trade/exchange_trade_store.dart';
12 +import 'package:cake_wallet/src/stores/send/send_store.dart';
13 +import 'package:cake_wallet/src/stores/send/sending_state.dart';
14 +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
15 +import 'package:cake_wallet/src/screens/exchange_trade/widgets/copy_button.dart';
16 +import 'package:cake_wallet/src/screens/receive/qr_image.dart';
17 +import 'package:cake_wallet/src/screens/base_page.dart';
18 +import 'package:cake_wallet/src/screens/exchange_trade/widgets/timer_widget.dart';
19 +import 'package:cake_wallet/src/widgets/primary_button.dart';
20 +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
21 +
22 +class ExchangeTradePage extends BasePage {
23 + String get title => S.current.exchange;
24 +
25 + @override
26 + Widget body(BuildContext context) => ExchangeTradeForm();
27 +}
28 +
29 +class ExchangeTradeForm extends StatefulWidget {
30 + @override
31 + createState() => ExchangeTradeState();
32 +}
33 +
34 +class ExchangeTradeState extends State<ExchangeTradeForm> {
35 + final fetchingLabel = S.current.fetching;
36 + String get title => S.current.exchange;
37 +
38 + bool _effectsInstalled = false;
39 +
40 + @override
41 + Widget build(BuildContext context) {
42 + final tradeStore = Provider.of<ExchangeTradeStore>(context);
43 + final sendStore = Provider.of<SendStore>(context);
44 + final walletStore = Provider.of<WalletStore>(context);
45 +
46 + _setEffects(context);
47 +
48 + return ScrollableWithBottomSection(
49 + contentPadding: EdgeInsets.only(left: 20, right: 20, top: 20),
50 + content: Observer(builder: (_) {
51 + final trade = tradeStore.trade;
52 + final walletName = walletStore.name;
53 +
54 + return Column(
55 + mainAxisAlignment: MainAxisAlignment.start,
56 + crossAxisAlignment: CrossAxisAlignment.start,
57 + children: <Widget>[
58 + Container(
59 + child: Row(
60 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
61 + crossAxisAlignment: CrossAxisAlignment.start,
62 + children: [
63 + Column(
64 + crossAxisAlignment: CrossAxisAlignment.start,
65 + children: <Widget>[
66 + Row(
67 + mainAxisAlignment: MainAxisAlignment.start,
68 + children: <Widget>[
69 + Text(
70 + S.of(context).id,
71 + style: TextStyle(
72 + height: 2,
73 + fontWeight: FontWeight.bold,
74 + fontSize: 14.0,
75 + color: Theme.of(context)
76 + .primaryTextTheme
77 + .button
78 + .color),
79 + ),
80 + Text(
81 + '${trade.id ?? fetchingLabel}',
82 + style: TextStyle(
83 + fontSize: 14.0,
84 + height: 2,
85 + color: Theme.of(context)
86 + .primaryTextTheme
87 + .subtitle
88 + .color),
89 + )
90 + ],
91 + ),
92 + Row(
93 + mainAxisAlignment: MainAxisAlignment.start,
94 + children: <Widget>[
95 + Text(
96 + S.of(context).amount,
97 + style: TextStyle(
98 + height: 2,
99 + fontWeight: FontWeight.bold,
100 + fontSize: 14.0,
101 + color: Theme.of(context)
102 + .primaryTextTheme
103 + .button
104 + .color),
105 + ),
106 + Text(
107 + '${trade.amount ?? fetchingLabel}',
108 + style: TextStyle(
109 + fontSize: 14.0,
110 + height: 2,
111 + color: Theme.of(context)
112 + .primaryTextTheme
113 + .subtitle
114 + .color),
115 + )
116 + ],
117 + ),
118 + trade.extraId != null
119 + ? Row(
120 + mainAxisAlignment: MainAxisAlignment.start,
121 + children: <Widget>[
122 + Text(
123 + S.of(context).payment_id,
124 + style: TextStyle(
125 + height: 2,
126 + fontWeight: FontWeight.bold,
127 + fontSize: 14.0,
128 + color: Theme.of(context)
129 + .primaryTextTheme
130 + .button
131 + .color),
132 + ),
133 + Text(
134 + '${trade.extraId ?? fetchingLabel}',
135 + style: TextStyle(
136 + fontSize: 14.0,
137 + height: 2,
138 + color: Theme.of(context)
139 + .primaryTextTheme
140 + .subtitle
141 + .color),
142 + )
143 + ],
144 + )
145 + : Container(),
146 + Row(
147 + mainAxisAlignment: MainAxisAlignment.start,
148 + children: <Widget>[
149 + Text(
150 + S.of(context).status,
151 + style: TextStyle(
152 + fontSize: 14.0,
153 + fontWeight: FontWeight.bold,
154 + color: Theme.of(context)
155 + .primaryTextTheme
156 + .button
157 + .color,
158 + height: 2),
159 + ),
160 + Text(
161 + '${trade.state ?? fetchingLabel}',
162 + style: TextStyle(
163 + fontSize: 14.0,
164 + height: 2,
165 + color: Theme.of(context)
166 + .primaryTextTheme
167 + .subtitle
168 + .color),
169 + )
170 + ],
171 + ),
172 + trade.expiredAt != null
173 + ? Row(
174 + mainAxisAlignment: MainAxisAlignment.start,
175 + children: <Widget>[
176 + Text(
177 + S.of(context).offer_expires_in,
178 + style: TextStyle(
179 + fontSize: 14.0,
180 + color: Theme.of(context)
181 + .primaryTextTheme
182 + .button
183 + .color),
184 + ),
185 + TimerWidget(trade.expiredAt,
186 + color: Theme.of(context)
187 + .primaryTextTheme
188 + .subtitle
189 + .color)
190 + ],
191 + )
192 + : Container(),
193 + ],
194 + ),
195 + SizedBox(width: 10),
196 + Container(
197 + padding: EdgeInsets.all(5),
198 + color: Colors.white,
199 + constraints: BoxConstraints(minWidth: 65, maxWidth: 105),
200 + child: QrImage(
201 + data: trade.inputAddress ?? fetchingLabel,
202 + backgroundColor: Colors.white))
203 + ],
204 + ),
205 + ),
206 + SizedBox(
207 + height: 20.0,
208 + ),
209 + Center(
210 + child: Text(
211 + S.of(context).trade_is_powered_by(trade.provider != null
212 + ? trade.provider.title
213 + : fetchingLabel),
214 + textAlign: TextAlign.center,
215 + style: TextStyle(
216 + fontSize: 14.0,
217 + fontWeight: FontWeight.bold,
218 + color: Theme.of(context).primaryTextTheme.headline.color),
219 + ),
220 + ),
221 + Container(
222 + padding: EdgeInsets.only(top: 20, bottom: 20),
223 + child: Center(
224 + child: Text(
225 + trade.inputAddress ?? fetchingLabel,
226 + textAlign: TextAlign.center,
227 + style: TextStyle(fontSize: 14.0, color: Palette.lightViolet),
228 + ),
229 + ),
230 + ),
231 + Container(
232 + padding: EdgeInsets.only(left: 50.0, right: 50.0),
233 + child: Row(
234 + children: <Widget>[
235 + Flexible(
236 + child: Container(
237 + padding: EdgeInsets.only(right: 5.0),
238 + child: CopyButton(
239 + onPressed: () => Clipboard.setData(
240 + ClipboardData(text: trade.inputAddress)),
241 + text: S.of(context).copy_address,
242 + color: Theme.of(context)
243 + .accentTextTheme
244 + .button
245 + .backgroundColor,
246 + borderColor: Theme.of(context)
247 + .accentTextTheme
248 + .button
249 + .decorationColor),
250 + )),
251 + Flexible(
252 + child: Container(
253 + padding: EdgeInsets.only(left: 5.0),
254 + child: CopyButton(
255 + onPressed: () =>
256 + Clipboard.setData(ClipboardData(text: trade.id)),
257 + text: S.of(context).copy_id,
258 + color: Theme.of(context)
259 + .accentTextTheme
260 + .button
261 + .backgroundColor,
262 + borderColor: Theme.of(context)
263 + .accentTextTheme
264 + .button
265 + .decorationColor),
266 + ))
267 + ],
268 + ),
269 + ),
270 + Container(
271 + padding: EdgeInsets.only(top: 20),
272 + child: Text(
273 + tradeStore.isSendable
274 + ? S.of(context).exchange_result_confirm(
275 + trade.amount ?? fetchingLabel,
276 + trade.from.toString(),
277 + walletName)
278 + : S.of(context).exchange_result_description(
279 + trade.amount ?? fetchingLabel, trade.from.toString()),
280 + textAlign: TextAlign.left,
281 + style: TextStyle(
282 + fontSize: 13.0,
283 + color: Theme.of(context).primaryTextTheme.title.color),
284 + ),
285 + ),
286 + Text(
287 + S.of(context).exchange_result_write_down_ID,
288 + textAlign: TextAlign.left,
289 + style: TextStyle(
290 + fontSize: 13.0,
291 + color: Theme.of(context).accentTextTheme.title.color),
292 + )
293 + ],
294 + );
295 + }),
296 + bottomSection: Observer(
297 + builder: (_) => tradeStore.trade.from == CryptoCurrency.xmr &&
298 + !(sendStore.state is TransactionCreatedSuccessfully)
299 + ? Container(
300 + padding: EdgeInsets.only(top: 20.0, bottom: 20.0),
301 + child: LoadingPrimaryButton(
302 + isDisabled: tradeStore.trade.inputAddress == null ||
303 + tradeStore.trade.inputAddress.isEmpty,
304 + isLoading: sendStore.state is CreatingTransaction ||
305 + sendStore.state is TransactionCommitted,
306 + onPressed: () => sendStore.createTransaction(
307 + address: tradeStore.trade.inputAddress,
308 + amount: tradeStore.trade.amount),
309 + text: tradeStore.trade.provider ==
310 + ExchangeProviderDescription.xmrto
311 + ? S.of(context).confirm
312 + : S.of(context).send_xmr,
313 + color: Theme.of(context)
314 + .primaryTextTheme
315 + .button
316 + .backgroundColor,
317 + borderColor: Theme.of(context)
318 + .primaryTextTheme
319 + .button
320 + .decorationColor),
321 + )
322 + : Offstage()),
323 + );
324 + }
325 +
326 + void _setEffects(BuildContext context) {
327 + if (_effectsInstalled) {
328 + return;
329 + }
330 +
331 + final sendStore = Provider.of<SendStore>(context);
332 +
333 + reaction((_) => sendStore.state, (state) {
334 + if (state is SendingFailed) {
335 + WidgetsBinding.instance.addPostFrameCallback((_) {
336 + showDialog(
337 + context: context,
338 + builder: (BuildContext context) {
339 + return AlertDialog(
340 + title: Text(S.of(context).error),
341 + content: Text(state.error),
342 + actions: <Widget>[
343 + FlatButton(
344 + child: Text(S.of(context).ok),
345 + onPressed: () => Navigator.of(context).pop())
346 + ],
347 + );
348 + });
349 + });
350 + }
351 +
352 + if (state is TransactionCreatedSuccessfully) {
353 + WidgetsBinding.instance.addPostFrameCallback((_) {
354 + showDialog(
355 + context: context,
356 + builder: (BuildContext context) {
357 + return AlertDialog(
358 + title: Text(S.of(context).sending),
359 + content: Text(S.of(context).transaction_sent),
360 + actions: <Widget>[
361 + FlatButton(
362 + child: Text(S.of(context).ok),
363 + onPressed: () => Navigator.of(context).pop())
364 + ],
365 + );
366 + });
367 + });
368 + }
369 + });
370 +
371 + _effectsInstalled = true;
372 + }
373 +}
lib/src/screens/exchange_trade/widgets/copy_button.dart new
+30
@@ -0,0 +1,30 @@
1 +import 'package:flutter/cupertino.dart';
2 +import 'package:flutter/material.dart';
3 +
4 +class CopyButton extends StatelessWidget {
5 +
6 + final VoidCallback onPressed;
7 + final Color color;
8 + final Color borderColor;
9 + final String text;
10 +
11 + const CopyButton({
12 + @required this.onPressed,
13 + @required this.text,
14 + @required this.color,
15 + @required this.borderColor});
16 +
17 + @override
18 + Widget build(BuildContext context) {
19 + return ButtonTheme(
20 + minWidth: double.infinity,
21 + height: 44.0,
22 + child: FlatButton(
23 + onPressed: onPressed,
24 + color: color,
25 + shape: RoundedRectangleBorder(side: BorderSide(color: borderColor), borderRadius: BorderRadius.circular(10.0)),
26 + child: Text(text, style: TextStyle(fontSize: 14.0)),
27 + )
28 + );
29 + }
30 +}
\ No newline at end of file
lib/src/screens/exchange_trade/widgets/timer_widget.dart new
+66
@@ -0,0 +1,66 @@
1 +import 'package:flutter/material.dart';
2 +import 'dart:async';
3 +import 'package:cake_wallet/generated/i18n.dart';
4 +
5 +class TimerWidget extends StatefulWidget {
6 + final DateTime expiratedAt;
7 + final Color color;
8 +
9 + TimerWidget(this.expiratedAt, {this.color = Colors.black});
10 +
11 + @override
12 + createState() => TimerWidgetState();
13 +}
14 +
15 +class TimerWidgetState extends State<TimerWidget> {
16 + int _leftSeconds;
17 + int _minutes;
18 + int _seconds;
19 + bool _isExpired;
20 + Timer _timer;
21 +
22 + TimerWidgetState();
23 +
24 + @override
25 + void initState() {
26 + super.initState();
27 + final start = DateTime.now();
28 + _isExpired = false;
29 + _leftSeconds = widget.expiratedAt.difference(start).inSeconds;
30 + _recalculate();
31 +
32 + WidgetsBinding.instance.addPostFrameCallback((_) {
33 + _timer = Timer.periodic(Duration(seconds: 1), (timer) {
34 + if (_isExpired) {
35 + timer.cancel();
36 + }
37 +
38 + _leftSeconds--;
39 + _isExpired = _leftSeconds <= 0;
40 + _recalculate();
41 + setState(() {});
42 + });
43 + });
44 + }
45 +
46 + @override
47 + void dispose() {
48 + if (_timer != null) _timer.cancel();
49 + super.dispose();
50 + }
51 +
52 + @override
53 + Widget build(BuildContext context) {
54 + return _isExpired
55 + ? Text(S.of(context).expired, style: TextStyle(fontSize: 14.0, color: Colors.red))
56 + : Text(
57 + S.of(context).time(_minutes.toString(), _seconds.toString()),
58 + style: TextStyle(fontSize: 14.0, color: widget.color),
59 + );
60 + }
61 +
62 + void _recalculate() {
63 + _minutes = _leftSeconds ~/ 60;
64 + _seconds = _leftSeconds % 60;
65 + }
66 +}
lib/src/screens/faq/faq_page.dart new
+90
@@ -0,0 +1,90 @@
1 +import 'dart:convert';
2 +import 'package:flutter/material.dart';
3 +import 'package:flutter/services.dart';
4 +import 'package:provider/provider.dart';
5 +import 'package:cake_wallet/generated/i18n.dart';
6 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
7 +import 'package:cake_wallet/src/screens/base_page.dart';
8 +
9 +class FaqPage extends BasePage {
10 + String get title => S.current.faq;
11 +
12 + @override
13 + Widget body(BuildContext context) {
14 +
15 + return FutureBuilder(
16 + builder: (context, snapshot) {
17 + var faqItems = json.decode(snapshot.data.toString());
18 +
19 + return ListView.separated(
20 + itemBuilder: (BuildContext context, int index) {
21 + final itemTitle = faqItems[index]["question"];
22 + final itemChild = faqItems[index]["answer"];
23 +
24 + return ExpansionTile(
25 + title: Text(
26 + itemTitle
27 + ),
28 + children: <Widget>[
29 + Row(
30 + mainAxisAlignment: MainAxisAlignment.start,
31 + children: <Widget>[
32 + Expanded(
33 + child: Container(
34 + padding: EdgeInsets.only(
35 + left: 15.0,
36 + right: 15.0
37 + ),
38 + child: Text(
39 + itemChild,
40 + ),
41 + )
42 + )
43 + ],
44 + )
45 + ],
46 + );
47 + },
48 + separatorBuilder: (_, __) => Divider(
49 + color: Theme.of(context).dividerTheme.color,
50 + height: 1.0,
51 + ),
52 + itemCount: faqItems == null ? 0 : faqItems.length,
53 + );
54 + },
55 + future: rootBundle.loadString(getFaqPath(context)),
56 + );
57 + }
58 +
59 + String getFaqPath(BuildContext context) {
60 + final settingsStore = Provider.of<SettingsStore>(context);
61 +
62 + switch (settingsStore.languageCode) {
63 + case 'en':
64 + return 'assets/faq/faq_en.json';
65 + case 'ru':
66 + return 'assets/faq/faq_ru.json';
67 + case 'es':
68 + return 'assets/faq/faq_es.json';
69 + case 'ja':
70 + return 'assets/faq/faq_ja.json';
71 + case 'ko':
72 + return 'assets/faq/faq_ko.json';
73 + case 'hi':
74 + return 'assets/faq/faq_hi.json';
75 + case 'de':
76 + return 'assets/faq/faq_de.json';
77 + case 'zh':
78 + return 'assets/faq/faq_zh.json';
79 + case 'pt':
80 + return 'assets/faq/faq_pt.json';
81 + case 'pl':
82 + return 'assets/faq/faq_pl.json';
83 + case 'nl':
84 + return 'assets/faq/faq_nl.json';
85 + default:
86 + return 'assets/faq/faq_en.json';
87 + }
88 + }
89 +
90 +}
\ No newline at end of file
lib/src/screens/login/login_page.dart new
+114
@@ -0,0 +1,114 @@
1 +// import 'package:cake_wallet/src/stores/auth/auth_state.dart';
2 +// import 'package:cake_wallet/src/stores/login/login_store.dart';
3 +// import 'package:flutter/material.dart';
4 +// import 'package:flutter/cupertino.dart';
5 +// import 'package:mobx/mobx.dart';
6 +// import 'package:provider/provider.dart';
7 +// import 'package:cake_wallet/src/screens/pin_code/pin_code.dart';
8 +// import 'package:cake_wallet/src/screens/base_page.dart';
9 +
10 +// class LoginPage extends BasePage {
11 +// @override
12 +// Widget leading(BuildContext context) => Container();
13 +
14 +// @override
15 +// Widget body(BuildContext context) => _LoginPinCode();
16 +// }
17 +
18 +// class _LoginPinCode extends PinCode {
19 +// _LoginPinCode([Key key]) : super((_, __) => null, false, key);
20 +
21 +// @override
22 +// _LoginPinCodeState createState() => _LoginPinCodeState();
23 +// }
24 +
25 +// class _LoginPinCodeState extends PinCodeState<_LoginPinCode> {
26 +// LoginStore _loginStore;
27 +// String title = 'Enter your PIN';
28 +
29 +// @override
30 +// Future onPinCodeEntered(PinCodeState state) async {
31 +// final password = pin.fold("", (ac, val) => ac + '$val');
32 +
33 +// await _loginStore.authStore.auth(password: password);
34 +// super.onPinCodeEntered(state);
35 +// }
36 +
37 +// @override
38 +// Widget build(BuildContext context) {
39 +// _setLoginStore(store: Provider.of<LoginStore>(context));
40 +// return body(context);
41 +// }
42 +
43 +// void _setLoginStore({LoginStore store}) {
44 +// if (_loginStore != null) {
45 +// return;
46 +// }
47 +
48 +// _loginStore = store;
49 +
50 +// reaction((_) => _loginStore.authStore.state, (state) {
51 +// if (state is AuthenticationFailure) {
52 +// WidgetsBinding.instance.addPostFrameCallback((_) {
53 +// clear();
54 +// Scaffold.of(context).showSnackBar(
55 +// SnackBar(
56 +// content: Text(state.error),
57 +// backgroundColor: Colors.red,
58 +// ),
59 +// );
60 +// });
61 +// }
62 +
63 +// if (state is AuthenticationBanned) {
64 +// WidgetsBinding.instance.addPostFrameCallback((_) {
65 +// clear();
66 +// Scaffold.of(context).showSnackBar(
67 +// SnackBar(
68 +// content: Text(state.error),
69 +// backgroundColor: Colors.red,
70 +// ),
71 +// );
72 +// });
73 +// }
74 +
75 +// if (state is AuthenticationInProgress) {
76 +// WidgetsBinding.instance.addPostFrameCallback((_) {
77 +// Scaffold.of(context).hideCurrentSnackBar();
78 +// Scaffold.of(context).showSnackBar(
79 +// SnackBar(
80 +// content: Text('Authentication'),
81 +// backgroundColor: Colors.green,
82 +// ),
83 +// );
84 +// });
85 +// }
86 +// });
87 +
88 +// reaction((_) => _loginStore.state, (state) {
89 +// if (state is LoadedCurrentWalletFailure) {
90 +// WidgetsBinding.instance.addPostFrameCallback((_) {
91 +// clear();
92 +// Scaffold.of(context).showSnackBar(
93 +// SnackBar(
94 +// content: Text(state.errorMessage),
95 +// backgroundColor: Colors.red,
96 +// ),
97 +// );
98 +// });
99 +// }
100 +
101 +// if (state is LoadingCurrentWallet) {
102 +// WidgetsBinding.instance.addPostFrameCallback((_) {
103 +// Scaffold.of(context).hideCurrentSnackBar();
104 +// Scaffold.of(context).showSnackBar(
105 +// SnackBar(
106 +// content: Text('Loading your wallet'),
107 +// backgroundColor: Colors.green,
108 +// ),
109 +// );
110 +// });
111 +// }
112 +// });
113 +// }
114 +// }
lib/src/screens/new_wallet/new_wallet_page.dart new
+121
@@ -0,0 +1,121 @@
1 +import 'package:mobx/mobx.dart';
2 +import 'package:provider/provider.dart';
3 +import 'package:shared_preferences/shared_preferences.dart';
4 +import 'package:flutter_mobx/flutter_mobx.dart';
5 +import 'package:flutter/material.dart';
6 +import 'package:flutter/cupertino.dart';
7 +import 'package:cake_wallet/generated/i18n.dart';
8 +import 'package:cake_wallet/src/stores/wallet_creation/wallet_creation_store.dart';
9 +import 'package:cake_wallet/src/stores/wallet_creation/wallet_creation_state.dart';
10 +import 'package:cake_wallet/src/domain/services/wallet_list_service.dart';
11 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
12 +import 'package:cake_wallet/src/screens/base_page.dart';
13 +import 'package:cake_wallet/src/widgets/primary_button.dart';
14 +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
15 +import 'package:cake_wallet/palette.dart';
16 +
17 +class NewWalletPage extends BasePage {
18 + final WalletListService walletsService;
19 + final WalletService walletService;
20 + final SharedPreferences sharedPreferences;
21 +
22 + String get title => S.current.new_wallet;
23 +
24 + NewWalletPage(
25 + {@required this.walletsService,
26 + @required this.walletService,
27 + @required this.sharedPreferences});
28 +
29 + @override
30 + Widget body(BuildContext context) => WalletNameForm();
31 +}
32 +
33 +class WalletNameForm extends StatefulWidget {
34 + @override
35 + createState() => _WalletNameFormState();
36 +}
37 +
38 +class _WalletNameFormState extends State<WalletNameForm> {
39 + final _formKey = GlobalKey<FormState>();
40 + final nameController = TextEditingController();
41 +
42 + @override
43 + Widget build(BuildContext context) {
44 + final walletCreationStore = Provider.of<WalletCreationStore>(context);
45 +
46 + reaction((_) => walletCreationStore.state, (state) {
47 + if (state is WalletCreatedSuccessfully) {
48 + Navigator.of(context).popUntil((route) => route.isFirst);
49 + }
50 +
51 + if (state is WalletCreationFailure) {
52 + WidgetsBinding.instance.addPostFrameCallback((_) {
53 + showDialog(
54 + context: context,
55 + builder: (BuildContext context) {
56 + return AlertDialog(
57 + content: Text(state.error),
58 + actions: <Widget>[
59 + FlatButton(
60 + child: Text(S.of(context).ok),
61 + onPressed: () => Navigator.of(context).pop(),
62 + ),
63 + ],
64 + );
65 + });
66 + });
67 + }
68 + });
69 +
70 + return ScrollableWithBottomSection(
71 + content: Column(children: [
72 + Padding(
73 + padding: EdgeInsets.only(bottom: 10),
74 + child: Image.asset('assets/images/bitmap.png',
75 + height: 224, width: 400),
76 + ),
77 + Padding(
78 + padding: EdgeInsets.only(left: 20, right: 20, bottom: 20),
79 + child: Form(
80 + key: _formKey,
81 + child: TextFormField(
82 + style: TextStyle(
83 + fontSize: 24.0,
84 + color: Theme.of(context).accentTextTheme.subtitle.color),
85 + controller: nameController,
86 + decoration: InputDecoration(
87 + hintStyle: TextStyle(
88 + fontSize: 24.0, color: Theme.of(context).hintColor),
89 + hintText: S.of(context).wallet_name,
90 + focusedBorder: UnderlineInputBorder(
91 + borderSide: BorderSide(
92 + color: Palette.cakeGreen, width: 2.0)),
93 + enabledBorder: UnderlineInputBorder(
94 + borderSide: BorderSide(
95 + color: Theme.of(context).focusColor,
96 + width: 1.0))),
97 + validator: (value) {
98 + walletCreationStore.validateWalletName(value);
99 + return walletCreationStore.errorMessage;
100 + },
101 + )),
102 + )
103 + ]),
104 + bottomSection: Observer(
105 + builder: (context) {
106 + return LoadingPrimaryButton(
107 + onPressed: () {
108 + if (_formKey.currentState.validate()) {
109 + walletCreationStore.create(name: nameController.text);
110 + }
111 + },
112 + text: S.of(context).continue_text,
113 + color: Theme.of(context).primaryTextTheme.button.backgroundColor,
114 + borderColor:
115 + Theme.of(context).primaryTextTheme.button.decorationColor,
116 + isLoading: walletCreationStore.state is WalletIsCreating,
117 + );
118 + },
119 + ));
120 + }
121 +}
lib/src/screens/nodes/new_node_page.dart new
+215
@@ -0,0 +1,215 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter/cupertino.dart';
3 +import 'package:provider/provider.dart';
4 +import 'package:cake_wallet/palette.dart';
5 +import 'package:cake_wallet/generated/i18n.dart';
6 +import 'package:cake_wallet/src/stores/node_list/node_list_store.dart';
7 +import 'package:cake_wallet/src/widgets/primary_button.dart';
8 +import 'package:cake_wallet/src/screens/base_page.dart';
9 +
10 +class NewNodePage extends BasePage {
11 + @override
12 + String get title => S.current.node_new;
13 +
14 + @override
15 + Widget body(BuildContext context) => NewNodePageForm();
16 +}
17 +
18 +class NewNodePageForm extends StatefulWidget {
19 + @override
20 + createState() => NewNodeFormState();
21 +}
22 +
23 +class NewNodeFormState extends State<NewNodePageForm> {
24 + final _formKey = GlobalKey<FormState>();
25 + final _nodeAddressController = TextEditingController();
26 + final _nodePortController = TextEditingController();
27 + final _loginController = TextEditingController();
28 + final _passwordController = TextEditingController();
29 +
30 + @override
31 + void dispose() {
32 + _nodeAddressController.dispose();
33 + _nodePortController.dispose();
34 + _loginController.dispose();
35 + _passwordController.dispose();
36 + super.dispose();
37 + }
38 +
39 + @override
40 + Widget build(BuildContext context) {
41 + final nodeList = Provider.of<NodeListStore>(context);
42 +
43 + return Form(
44 + key: _formKey,
45 + child: Column(
46 + children: <Widget>[
47 + Expanded(
48 + child: Container(
49 + padding: EdgeInsets.only(left: 38.0, right: 38.0, top: 0),
50 + child: Center(
51 + child: Column(
52 + mainAxisSize: MainAxisSize.min,
53 + children: <Widget>[
54 + Row(
55 + children: <Widget>[
56 + Expanded(
57 + child: TextFormField(
58 + style: TextStyle(fontSize: 14.0),
59 + decoration: InputDecoration(
60 + hintStyle:
61 + TextStyle(color: Palette.wildDarkBlue),
62 + hintText: S.of(context).node_address,
63 + focusedBorder: UnderlineInputBorder(
64 + borderSide: BorderSide(
65 + color: Palette.cakeGreen, width: 2.0)),
66 + enabledBorder: UnderlineInputBorder(
67 + borderSide: BorderSide(
68 + color: Theme.of(context).focusColor,
69 + width: 1.0))),
70 + controller: _nodeAddressController,
71 + validator: (value) {
72 + nodeList.validateNodeAddress(value);
73 + return nodeList.errorMessage;
74 + },
75 + ),
76 + )
77 + ],
78 + ),
79 + SizedBox(height: 10.0),
80 + Row(
81 + children: <Widget>[
82 + Expanded(
83 + child: TextFormField(
84 + style: TextStyle(fontSize: 14.0),
85 + keyboardType: TextInputType.numberWithOptions(
86 + signed: false, decimal: false),
87 + decoration: InputDecoration(
88 + hintStyle:
89 + TextStyle(color: Palette.wildDarkBlue),
90 + hintText: S.of(context).node_port,
91 + focusedBorder: UnderlineInputBorder(
92 + borderSide: BorderSide(
93 + color: Palette.cakeGreen, width: 2.0)),
94 + enabledBorder: UnderlineInputBorder(
95 + borderSide: BorderSide(
96 + color: Theme.of(context).focusColor,
97 + width: 1.0))),
98 + controller: _nodePortController,
99 + validator: (value) {
100 + nodeList.validateNodePort(value);
101 + return nodeList.errorMessage;
102 + },
103 + ),
104 + )
105 + ],
106 + ),
107 + SizedBox(height: 10.0),
108 + Row(
109 + children: <Widget>[
110 + Expanded(
111 + child: TextFormField(
112 + style: TextStyle(fontSize: 14.0),
113 + decoration: InputDecoration(
114 + hintStyle:
115 + TextStyle(color: Palette.wildDarkBlue),
116 + hintText: S.of(context).login,
117 + focusedBorder: UnderlineInputBorder(
118 + borderSide: BorderSide(
119 + color: Palette.cakeGreen, width: 2.0)),
120 + enabledBorder: UnderlineInputBorder(
121 + borderSide: BorderSide(
122 + color: Theme.of(context).focusColor,
123 + width: 1.0))),
124 + controller: _loginController,
125 + validator: (value) => null,
126 + ),
127 + )
128 + ],
129 + ),
130 + SizedBox(height: 10.0),
131 + Row(
132 + children: <Widget>[
133 + Expanded(
134 + child: TextFormField(
135 + style: TextStyle(fontSize: 14.0),
136 + decoration: InputDecoration(
137 + hintStyle:
138 + TextStyle(color: Palette.wildDarkBlue),
139 + hintText: S.of(context).password,
140 + focusedBorder: UnderlineInputBorder(
141 + borderSide: BorderSide(
142 + color: Palette.cakeGreen, width: 2.0)),
143 + enabledBorder: UnderlineInputBorder(
144 + borderSide: BorderSide(
145 + color: Theme.of(context).focusColor,
146 + width: 1.0))),
147 + controller: _passwordController,
148 + validator: (value) => null,
149 + ),
150 + )
151 + ],
152 + )
153 + ],
154 + ),
155 + ),
156 + )),
157 + Container(
158 + padding: EdgeInsets.only(bottom: 20.0, left: 20.0, right: 20.0),
159 + child: Row(
160 + children: <Widget>[
161 + Flexible(
162 + child: Container(
163 + padding: EdgeInsets.only(right: 8.0),
164 + child: PrimaryButton(
165 + onPressed: () {
166 + _nodeAddressController.text = '';
167 + _nodePortController.text = '';
168 + _loginController.text = '';
169 + _passwordController.text = '';
170 + },
171 + text: S.of(context).reset,
172 + color: Theme.of(context)
173 + .accentTextTheme
174 + .button
175 + .backgroundColor,
176 + borderColor: Theme.of(context)
177 + .accentTextTheme
178 + .button
179 + .decorationColor),
180 + )),
181 + Flexible(
182 + child: Container(
183 + padding: EdgeInsets.only(left: 8.0),
184 + child: PrimaryButton(
185 + onPressed: () async {
186 + if (!_formKey.currentState.validate()) {
187 + return;
188 + }
189 +
190 + await nodeList.addNode(
191 + address: _nodeAddressController.text,
192 + port: _nodePortController.text,
193 + login: _loginController.text,
194 + password: _passwordController.text);
195 +
196 + Navigator.of(context).pop();
197 + },
198 + text: S.of(context).save,
199 + color: Theme.of(context)
200 + .primaryTextTheme
201 + .button
202 + .backgroundColor,
203 + borderColor: Theme.of(context)
204 + .primaryTextTheme
205 + .button
206 + .decorationColor,
207 + ),
208 + )),
209 + ],
210 + ),
211 + )
212 + ],
213 + ));
214 + }
215 +}
lib/src/screens/nodes/node_indicator.dart new
+19
@@ -0,0 +1,19 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:cake_wallet/palette.dart';
3 +
4 +class NodeIndicator extends StatelessWidget {
5 + final color;
6 +
7 + NodeIndicator({this.color = Palette.red});
8 +
9 + @override
10 + Widget build(BuildContext context) {
11 + return Container(
12 + width: 10.0,
13 + height: 10.0,
14 + decoration: BoxDecoration(
15 + shape: BoxShape.circle,
16 + color: color),
17 + );
18 + }
19 +}
\ No newline at end of file
lib/src/screens/nodes/nodes_list_page.dart new
+241
@@ -0,0 +1,241 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter/cupertino.dart';
3 +import 'package:provider/provider.dart';
4 +import 'package:flutter_mobx/flutter_mobx.dart';
5 +import 'package:cake_wallet/routes.dart';
6 +import 'package:cake_wallet/palette.dart';
7 +import 'package:cake_wallet/generated/i18n.dart';
8 +import 'package:cake_wallet/src/screens/nodes/node_indicator.dart';
9 +import 'package:cake_wallet/src/stores/node_list/node_list_store.dart';
10 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
11 +import 'package:cake_wallet/src/screens/base_page.dart';
12 +
13 +class NodeListPage extends BasePage {
14 + NodeListPage();
15 +
16 + String get title => S.current.nodes;
17 +
18 + @override
19 + Widget trailing(context) {
20 + final nodeList = Provider.of<NodeListStore>(context);
21 +
22 + return Row(
23 + mainAxisSize: MainAxisSize.min,
24 + children: <Widget>[
25 + ButtonTheme(
26 + minWidth: double.minPositive,
27 + child: FlatButton(
28 + onPressed: () async {
29 + await showDialog(
30 + context: context,
31 + builder: (BuildContext context) {
32 + return AlertDialog(
33 + title: Text(
34 + S.of(context).node_reset_settings_title,
35 + textAlign: TextAlign.center,
36 + ),
37 + content: Text(
38 + S.of(context).nodes_list_reset_to_default_message,
39 + textAlign: TextAlign.center,
40 + ),
41 + actions: <Widget>[
42 + FlatButton(
43 + onPressed: () {
44 + Navigator.pop(context);
45 + },
46 + child: Text(S.of(context).cancel)),
47 + FlatButton(
48 + onPressed: () async {
49 + Navigator.pop(context);
50 + await nodeList.reset();
51 + },
52 + child: Text(S.of(context).reset))
53 + ],
54 + );
55 + });
56 + },
57 + child: Text(
58 + S.of(context).reset,
59 + style: TextStyle(
60 + fontSize: 16.0,
61 + color: Theme.of(context).primaryTextTheme.subtitle.color),
62 + )),
63 + ),
64 + Container(
65 + width: 28.0,
66 + height: 28.0,
67 + decoration: BoxDecoration(
68 + shape: BoxShape.circle,
69 + color: Theme.of(context).selectedRowColor),
70 + child: Stack(
71 + alignment: Alignment.center,
72 + children: <Widget>[
73 + Icon(Icons.add, color: Palette.violet, size: 22.0),
74 + ButtonTheme(
75 + minWidth: 28.0,
76 + height: 28.0,
77 + child: FlatButton(
78 + shape: CircleBorder(),
79 + onPressed: () async {
80 + await Navigator.of(context).pushNamed(Routes.newNode);
81 + nodeList.update();
82 + },
83 + child: Offstage()),
84 + )
85 + ],
86 + )),
87 + ],
88 + );
89 + }
90 +
91 + @override
92 + Widget body(context) => NodeListPageBody();
93 +}
94 +
95 +class NodeListPageBody extends StatefulWidget {
96 + @override
97 + createState() => NodeListPageBodyState();
98 +}
99 +
100 +class NodeListPageBodyState extends State<NodeListPageBody> {
101 + @override
102 + Widget build(BuildContext context) {
103 + final nodeList = Provider.of<NodeListStore>(context);
104 + final settings = Provider.of<SettingsStore>(context);
105 +
106 + final currentColor = Theme.of(context).selectedRowColor;
107 + final notCurrentColor = Theme.of(context).backgroundColor;
108 +
109 + return Container(
110 + padding: EdgeInsets.only(bottom: 20.0),
111 + child: Column(
112 + children: <Widget>[
113 + Expanded(child: Observer(builder: (context) {
114 + return ListView.separated(
115 + separatorBuilder: (_, __) => Divider(
116 + color: Theme.of(context).dividerTheme.color, height: 1),
117 + itemCount: nodeList.nodes.length,
118 + itemBuilder: (BuildContext context, int index) {
119 + final node = nodeList.nodes[index];
120 +
121 + return Observer(builder: (_) {
122 + final isCurrent = settings.node == null
123 + ? false
124 + : node.key == settings.node.key;
125 +
126 + final content = Container(
127 + color: isCurrent ? currentColor : notCurrentColor,
128 + child: ListTile(
129 + title: Text(
130 + node.uri,
131 + style: TextStyle(
132 + fontSize: 16.0,
133 + color: Theme.of(context)
134 + .primaryTextTheme
135 + .title
136 + .color),
137 + ),
138 + trailing: FutureBuilder(
139 + future: nodeList.isNodeOnline(node),
140 + builder: (context, snapshot) {
141 + switch (snapshot.connectionState) {
142 + case ConnectionState.done:
143 + return NodeIndicator(
144 + color: snapshot.data
145 + ? Palette.green
146 + : Palette.red);
147 + default:
148 + return NodeIndicator();
149 + }
150 + }),
151 + onTap: () async {
152 + if (!isCurrent) {
153 + await showDialog(
154 + context: context,
155 + builder: (BuildContext context) {
156 + return AlertDialog(
157 + content: Text(
158 + S
159 + .of(context)
160 + .change_current_node(node.uri),
161 + textAlign: TextAlign.center,
162 + ),
163 + actions: <Widget>[
164 + FlatButton(
165 + onPressed: () =>
166 + Navigator.pop(context),
167 + child: Text(S.of(context).cancel)),
168 + FlatButton(
169 + onPressed: () async {
170 + Navigator.of(context).pop();
171 + await settings.setCurrentNode(
172 + node: node);
173 + },
174 + child: Text(S.of(context).change)),
175 + ],
176 + );
177 + });
178 + }
179 + },
180 + ));
181 +
182 + return isCurrent
183 + ? content
184 + : Dismissible(
185 + key: Key('${node.key}'),
186 + confirmDismiss: (direction) async {
187 + return await showDialog(
188 + context: context,
189 + builder: (BuildContext context) {
190 + return AlertDialog(
191 + title: Text(
192 + S.of(context).remove_node,
193 + textAlign: TextAlign.center,
194 + ),
195 + content: Text(
196 + S.of(context).remove_node_message,
197 + textAlign: TextAlign.center,
198 + ),
199 + actions: <Widget>[
200 + FlatButton(
201 + onPressed: () =>
202 + Navigator.pop(context, false),
203 + child: Text(S.of(context).cancel)),
204 + FlatButton(
205 + onPressed: () =>
206 + Navigator.pop(context, true),
207 + child: Text(S.of(context).remove)),
208 + ],
209 + );
210 + });
211 + },
212 + onDismissed: (direction) async =>
213 + await nodeList.remove(node: node),
214 + direction: DismissDirection.endToStart,
215 + background: Container(
216 + padding: EdgeInsets.only(right: 10.0),
217 + alignment: AlignmentDirectional.centerEnd,
218 + color: Palette.red,
219 + child: Column(
220 + mainAxisAlignment:
221 + MainAxisAlignment.spaceBetween,
222 + children: <Widget>[
223 + const Icon(
224 + CupertinoIcons.delete,
225 + color: Colors.white,
226 + ),
227 + Text(
228 + S.of(context).delete,
229 + style: TextStyle(color: Colors.white),
230 + )
231 + ],
232 + )),
233 + child: content);
234 + });
235 + });
236 + }))
237 + ],
238 + ),
239 + );
240 + }
241 +}
lib/src/screens/pin_code/pin_code.dart new
+245
@@ -0,0 +1,245 @@
1 +import 'package:provider/provider.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:flutter/cupertino.dart';
4 +import 'package:cake_wallet/palette.dart';
5 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
6 +import 'package:cake_wallet/generated/i18n.dart';
7 +
8 +abstract class PinCodeWidget extends StatefulWidget {
9 + final Function(List<int> pin, PinCodeState state) onPinCodeEntered;
10 + final bool hasLengthSwitcher;
11 +
12 + PinCodeWidget({Key key, this.onPinCodeEntered, this.hasLengthSwitcher})
13 + : super(key: key);
14 +}
15 +
16 +class PinCode extends PinCodeWidget {
17 + final Function(List<int> pin, PinCodeState state) onPinCodeEntered;
18 + final bool hasLengthSwitcher;
19 +
20 + PinCode(this.onPinCodeEntered, this.hasLengthSwitcher, Key key)
21 + : super(key: key);
22 +
23 + @override
24 + PinCodeState createState() => PinCodeState();
25 +}
26 +
27 +class PinCodeState<T extends PinCodeWidget> extends State<T> {
28 + static const defaultPinLength = 4;
29 + static const sixPinLength = 6;
30 + static const fourPinLength = 4;
31 + static final deleteIconImage = Image.asset('assets/images/delete_icon.png');
32 + static final backArrowImage = Image.asset('assets/images/back_arrow.png');
33 + GlobalKey _gridViewKey = GlobalKey();
34 +
35 + int pinLength = defaultPinLength;
36 + List<int> pin = List<int>.filled(defaultPinLength, null);
37 + String title = S.current.enter_your_pin;
38 + double _aspectRatio = 0;
39 +
40 + void setTitle(String title) {
41 + setState(() => this.title = title);
42 + }
43 +
44 + void clear() {
45 + setState(() => pin = List<int>.filled(pinLength, null));
46 + }
47 +
48 + void onPinCodeEntered(PinCodeState state) {
49 + widget.onPinCodeEntered(state.pin, this);
50 + }
51 +
52 + void changePinLength(int length) {
53 + List<int> newPin = List<int>.filled(length, null);
54 +
55 + setState(() {
56 + pinLength = length;
57 + pin = newPin;
58 + });
59 + }
60 +
61 + setDefaultPinLength() {
62 + final settingsStore = Provider.of<SettingsStore>(context);
63 +
64 + pinLength = settingsStore.defaultPinLength;
65 + changePinLength(pinLength);
66 + }
67 +
68 + getCurrentAspectRatio() {
69 + final RenderBox renderBox = _gridViewKey.currentContext.findRenderObject();
70 +
71 + double cellWidth = renderBox.size.width / 3;
72 + double cellHeight = renderBox.size.height / 4;
73 + if (cellWidth > 0 && cellHeight > 0) _aspectRatio = cellWidth / cellHeight;
74 + setState(() {});
75 + }
76 +
77 + @override
78 + void initState() {
79 + super.initState();
80 + WidgetsBinding.instance.addPostFrameCallback(afterLayout);
81 + }
82 +
83 + afterLayout(_) {
84 + setDefaultPinLength();
85 + getCurrentAspectRatio();
86 + }
87 +
88 + @override
89 + Widget build(BuildContext context) {
90 + return Scaffold(body: body(context));
91 + }
92 +
93 + Widget body(BuildContext context) {
94 + return SafeArea(
95 + child: Container(
96 + color: Theme.of(context).backgroundColor,
97 + padding: EdgeInsets.only(left: 40.0, right: 40.0, bottom: 40.0),
98 + child: Column(children: <Widget>[
99 + Spacer(flex: 2),
100 + Text(title,
101 + style: TextStyle(fontSize: 24, color: Palette.wildDarkBlue)),
102 + Spacer(flex: 3),
103 + Container(
104 + width: 180,
105 + child: Row(
106 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
107 + children: List.generate(pinLength, (index) {
108 + const size = 10.0;
109 + final isFilled = pin[index] != null;
110 +
111 + return Container(
112 + width: size,
113 + height: size,
114 + decoration: BoxDecoration(
115 + shape: BoxShape.circle,
116 + color: isFilled ? Palette.deepPurple : Colors.transparent,
117 + border: Border.all(color: Palette.wildDarkBlue),
118 + ));
119 + }),
120 + ),
121 + ),
122 + Spacer(flex: 2),
123 + if (widget.hasLengthSwitcher) ...[
124 + FlatButton(
125 + onPressed: () {
126 + changePinLength(pinLength == PinCodeState.fourPinLength
127 + ? PinCodeState.sixPinLength
128 + : PinCodeState.fourPinLength);
129 + },
130 + child: Text(
131 + _changePinLengthText(),
132 + style: TextStyle(fontSize: 16.0, color: Palette.wildDarkBlue),
133 + ))
134 + ],
135 + Spacer(flex: 1),
136 + Flexible(
137 + flex: 24,
138 + child: Container(
139 + key: _gridViewKey,
140 + child: _aspectRatio > 0
141 + ? GridView.count(
142 + shrinkWrap: true,
143 + crossAxisCount: 3,
144 + childAspectRatio: _aspectRatio,
145 + physics: const NeverScrollableScrollPhysics(),
146 + children: List.generate(12, (index) {
147 + const double marginRight = 15;
148 + const double marginLeft = 15;
149 +
150 + if (index == 9) {
151 + return Container(
152 + margin: EdgeInsets.only(
153 + left: marginLeft, right: marginRight),
154 + decoration: BoxDecoration(
155 + shape: BoxShape.circle,
156 + color: Theme.of(context).buttonColor,
157 + ),
158 + );
159 + } else if (index == 10) {
160 + index = 0;
161 + } else if (index == 11) {
162 + return Container(
163 + margin: EdgeInsets.only(
164 + left: marginLeft, right: marginRight),
165 + child: FlatButton(
166 + onPressed: () => _pop(),
167 + color: Theme.of(context).buttonColor,
168 + shape: CircleBorder(),
169 + child: deleteIconImage,
170 + ),
171 + );
172 + } else {
173 + index++;
174 + }
175 +
176 + return Container(
177 + margin: EdgeInsets.only(
178 + left: marginLeft, right: marginRight),
179 + child: FlatButton(
180 + onPressed: () => _push(index),
181 + color: Theme.of(context)
182 + .accentTextTheme
183 + .title
184 + .backgroundColor,
185 + shape: CircleBorder(),
186 + child: Text('$index',
187 + style: TextStyle(
188 + fontSize: 23.0, color: Palette.blueGrey)),
189 + ),
190 + );
191 + }),
192 + )
193 + : null))
194 + ]),
195 + ));
196 + }
197 +
198 + void _push(int num) {
199 + if (_pinLength() >= pinLength) {
200 + return;
201 + }
202 +
203 + for (var i = 0; i < pin.length; i++) {
204 + if (pin[i] == null) {
205 + setState(() => pin[i] = num);
206 + break;
207 + }
208 + }
209 +
210 + if (_pinLength() == pinLength) {
211 + onPinCodeEntered(this);
212 + }
213 + }
214 +
215 + void _pop() {
216 + if (_pinLength() == 0) {
217 + return;
218 + }
219 +
220 + for (var i = pin.length - 1; i >= 0; i--) {
221 + if (pin[i] != null) {
222 + setState(() => pin[i] = null);
223 + break;
224 + }
225 + }
226 + }
227 +
228 + int _pinLength() {
229 + return pin.fold(0, (v, e) {
230 + if (e != null) {
231 + return v + 1;
232 + }
233 +
234 + return v;
235 + });
236 + }
237 +
238 + String _changePinLengthText() {
239 + return S.current.use +
240 + (pinLength == PinCodeState.fourPinLength
241 + ? '${PinCodeState.sixPinLength}'
242 + : '${PinCodeState.fourPinLength}') +
243 + S.current.digit_pin;
244 + }
245 +}
lib/src/screens/receive/qr_image.dart new
+30
@@ -0,0 +1,30 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:qr/qr.dart';
3 +import 'package:cake_wallet/src/screens/receive/qr_painter.dart';
4 +
5 +class QrImage extends StatelessWidget {
6 + QrImage({
7 + @required String data,
8 + this.size = 100.0,
9 + this.backgroundColor,
10 + Color foregroundColor = Colors.black,
11 + int version = 7,
12 + int errorCorrectionLevel = QrErrorCorrectLevel.L,
13 + }) : _painter = new QrPainter(data, foregroundColor, version, errorCorrectionLevel);
14 +
15 + final QrPainter _painter;
16 + final Color backgroundColor;
17 + final double size;
18 +
19 + @override
20 + Widget build(BuildContext context) {
21 + return new Container(
22 + width: size,
23 + height: size,
24 + color: backgroundColor,
25 + child: CustomPaint(
26 + painter: _painter,
27 + ),
28 + );
29 + }
30 +}
\ No newline at end of file
lib/src/screens/receive/qr_painter.dart new
+45
@@ -0,0 +1,45 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:qr/qr.dart';
3 +
4 +class QrPainter extends CustomPainter {
5 + QrPainter(
6 + String data,
7 + this.color,
8 + this.version,
9 + this.errorCorrectionLevel,
10 + ) : this._qr = new QrCode(version, errorCorrectionLevel) {
11 + _p.color = this.color;
12 +
13 + _qr.addData(data);
14 + _qr.make();
15 + }
16 +
17 + final QrCode _qr;
18 + final _p = new Paint()..style = PaintingStyle.fill;
19 +
20 + final int version;
21 + final int errorCorrectionLevel;
22 + final Color color;
23 +
24 + @override
25 + void paint(Canvas canvas, Size size) {
26 + final squareSize = size.shortestSide / _qr.moduleCount;
27 + for (int x = 0; x < _qr.moduleCount; x++) {
28 + for (int y = 0; y < _qr.moduleCount; y++) {
29 + if (_qr.isDark(y, x)) {
30 + final squareRect = new Rect.fromLTWH(x * squareSize, y * squareSize, squareSize, squareSize);
31 + canvas.drawRect(squareRect, _p);
32 + }
33 + }
34 + }
35 + }
36 +
37 + @override
38 + bool shouldRepaint(CustomPainter oldDelegate) {
39 + if (oldDelegate is QrPainter) {
40 + return this.color != oldDelegate.color || this.errorCorrectionLevel != oldDelegate.errorCorrectionLevel ||
41 + this.version != oldDelegate.version;
42 + }
43 + return false;
44 + }
45 +}
\ No newline at end of file
lib/src/screens/receive/receive_page.dart new
+273
@@ -0,0 +1,273 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter/cupertino.dart';
3 +import 'package:flutter/services.dart';
4 +import 'package:flutter_mobx/flutter_mobx.dart';
5 +import 'package:esys_flutter_share/esys_flutter_share.dart';
6 +import 'package:provider/provider.dart';
7 +import 'package:cake_wallet/routes.dart';
8 +import 'package:cake_wallet/palette.dart';
9 +import 'package:cake_wallet/generated/i18n.dart';
10 +import 'package:cake_wallet/src/stores/subaddress_list/subaddress_list_store.dart';
11 +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
12 +import 'package:cake_wallet/src/screens/receive/qr_image.dart';
13 +import 'package:cake_wallet/src/screens/base_page.dart';
14 +
15 +class ReceivePage extends BasePage {
16 + bool get isModalBackButton => true;
17 + String get title => S.current.receive;
18 +
19 + @override
20 + Widget trailing(BuildContext context) {
21 + final walletStore = Provider.of<WalletStore>(context);
22 +
23 + return SizedBox(
24 + height: 37.0,
25 + width: 37.0,
26 + child: ButtonTheme(
27 + minWidth: double.minPositive,
28 + child: FlatButton(
29 + highlightColor: Colors.transparent,
30 + splashColor: Colors.transparent,
31 + padding: EdgeInsets.all(0),
32 + onPressed: () => Share.text(
33 + 'Share address', walletStore.subaddress.address, 'text/plain'),
34 + child: Icon(Icons.share, size: 30.0,)),
35 + ),
36 + );
37 + }
38 +
39 + @override
40 + Widget body(BuildContext context) =>
41 + SingleChildScrollView(child: ReceiveBody());
42 +}
43 +
44 +class ReceiveBody extends StatefulWidget {
45 + @override
46 + createState() => ReceiveBodyState();
47 +}
48 +
49 +class ReceiveBodyState extends State<ReceiveBody> {
50 + final amountController = TextEditingController();
51 + final _formKey = GlobalKey<FormState>();
52 +
53 + @override
54 + void dispose() {
55 + amountController.dispose();
56 + super.dispose();
57 + }
58 +
59 + @override
60 + Widget build(BuildContext context) {
61 + final walletStore = Provider.of<WalletStore>(context);
62 + final subaddressListStore = Provider.of<SubaddressListStore>(context);
63 +
64 + final currentColor = Theme.of(context).selectedRowColor;
65 + final notCurrentColor = Theme.of(context).scaffoldBackgroundColor;
66 +
67 + amountController.addListener(() {
68 + if (_formKey.currentState.validate()) {
69 + walletStore.onChangedAmountValue(amountController.text);
70 + } else
71 + walletStore.onChangedAmountValue('');
72 + });
73 +
74 + return SafeArea(
75 + child: SingleChildScrollView(
76 + child: Column(
77 + children: <Widget>[
78 + Container(
79 + padding: EdgeInsets.all(35.0),
80 + color: Theme.of(context).backgroundColor,
81 + child: Column(
82 + children: <Widget>[
83 + Observer(builder: (_) {
84 + return Row(
85 + children: <Widget>[
86 + Spacer(
87 + flex: 1,
88 + ),
89 + Flexible(
90 + flex: 2,
91 + child: AspectRatio(
92 + aspectRatio: 1.0,
93 + child: Container(
94 + padding: EdgeInsets.all(5),
95 + color: Colors.white,
96 + child: QrImage(
97 + data: walletStore.subaddress.address +
98 + walletStore.amountValue,
99 + backgroundColor: Colors.transparent,
100 + ),
101 + ),
102 + )),
103 + Spacer(
104 + flex: 1,
105 + )
106 + ],
107 + );
108 + }),
109 + Observer(builder: (_) {
110 + return Row(
111 + children: <Widget>[
112 + Expanded(
113 + child: Container(
114 + padding: EdgeInsets.all(20.0),
115 + child: Center(
116 + child: GestureDetector(
117 + onTap: () {
118 + Clipboard.setData(ClipboardData(
119 + text: walletStore.subaddress.address));
120 + Scaffold.of(context).showSnackBar(SnackBar(
121 + content: Text(
122 + S.of(context).copied_to_clipboard,
123 + style: TextStyle(color: Colors.white),
124 + ),
125 + backgroundColor: Colors.green,
126 + ));
127 + },
128 + child: Text(
129 + walletStore.subaddress.address,
130 + textAlign: TextAlign.center,
131 + style: TextStyle(
132 + fontSize: 14.0,
133 + fontWeight: FontWeight.w600,
134 + color: Theme.of(context)
135 + .primaryTextTheme
136 + .title
137 + .color),
138 + ),
139 + ),
140 + ),
141 + ))
142 + ],
143 + );
144 + }),
145 + Row(
146 + children: <Widget>[
147 + Expanded(
148 + child: Form(
149 + key: _formKey,
150 + child: TextFormField(
151 + keyboardType:
152 + TextInputType.numberWithOptions(decimal: true),
153 + inputFormatters: [
154 + BlacklistingTextInputFormatter(
155 + new RegExp('[\\-|\\ |\\,]'))
156 + ],
157 + style: TextStyle(
158 + fontSize: 14.0,
159 + ),
160 + decoration: InputDecoration(
161 + hintStyle: TextStyle(
162 + color: Theme.of(context).hintColor),
163 + hintText: S.of(context).amount,
164 + focusedBorder: UnderlineInputBorder(
165 + borderSide: BorderSide(
166 + color: Palette.cakeGreen,
167 + width: 2.0)),
168 + enabledBorder: UnderlineInputBorder(
169 + borderSide: BorderSide(
170 + color: Theme.of(context).focusColor,
171 + width: 1.0))),
172 + validator: (value) {
173 + walletStore.validateAmount(value);
174 + return walletStore.errorMessage;
175 + },
176 + autovalidate: true,
177 + controller: amountController,
178 + )))
179 + ],
180 + )
181 + ],
182 + ),
183 + ),
184 + Row(
185 + children: <Widget>[
186 + Expanded(
187 + child: Container(
188 + color: Theme.of(context).accentTextTheme.headline.color,
189 + child: Column(
190 + children: <Widget>[
191 + ListTile(
192 + title: Text(
193 + S.of(context).subaddresses,
194 + style: TextStyle(
195 + fontSize: 16.0,
196 + color: Theme.of(context)
197 + .primaryTextTheme
198 + .headline
199 + .color),
200 + ),
201 + trailing: Container(
202 + width: 28.0,
203 + height: 28.0,
204 + decoration: BoxDecoration(
205 + color: Theme.of(context).selectedRowColor,
206 + shape: BoxShape.circle),
207 + child: InkWell(
208 + onTap: () => Navigator.of(context)
209 + .pushNamed(Routes.newSubaddress),
210 + borderRadius: BorderRadius.all(Radius.circular(14.0)),
211 + child: Icon(
212 + Icons.add,
213 + color: Palette.violet,
214 + size: 22.0,
215 + ),
216 + ),
217 + ),
218 + ),
219 + Divider(
220 + color: Theme.of(context).dividerTheme.color,
221 + height: 1.0,
222 + )
223 + ],
224 + ),
225 + ))
226 + ],
227 + ),
228 + Observer(builder: (_) {
229 + return ListView.separated(
230 + shrinkWrap: true,
231 + physics: NeverScrollableScrollPhysics(),
232 + itemCount: subaddressListStore.subaddresses.length,
233 + separatorBuilder: (context, i) {
234 + return Divider(
235 + color: Theme.of(context).dividerTheme.color,
236 + height: 1.0,
237 + );
238 + },
239 + itemBuilder: (context, i) {
240 + return Observer(builder: (_) {
241 + final subaddress = subaddressListStore.subaddresses[i];
242 + final isCurrent =
243 + walletStore.subaddress.address == subaddress.address;
244 + final label = subaddress.label.isNotEmpty
245 + ? subaddress.label
246 + : subaddress.address;
247 +
248 + return InkWell(
249 + onTap: () => walletStore.setSubaddress(subaddress),
250 + child: Container(
251 + color: isCurrent ? currentColor : notCurrentColor,
252 + child: Column(children: <Widget>[
253 + ListTile(
254 + title: Text(
255 + label,
256 + style: TextStyle(
257 + fontSize: 16.0,
258 + color: Theme.of(context)
259 + .primaryTextTheme
260 + .headline
261 + .color),
262 + ),
263 + )
264 + ]),
265 + ),
266 + );
267 + });
268 + });
269 + })
270 + ],
271 + )));
272 + }
273 +}
lib/src/screens/rescan/rescan_page.dart new
+41
@@ -0,0 +1,41 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter_mobx/flutter_mobx.dart';
3 +import 'package:provider/provider.dart';
4 +import 'package:cake_wallet/src/screens/base_page.dart';
5 +import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
6 +import 'package:cake_wallet/src/widgets/primary_button.dart';
7 +import 'package:cake_wallet/src/stores/rescan/rescan_wallet_store.dart';
8 +import 'package:cake_wallet/generated/i18n.dart';
9 +
10 +class RescanPage extends BasePage {
11 + final blockchainKey = GlobalKey<BlockchainHeightState>();
12 + @override
13 + String get title => S.current.rescan;
14 +
15 + @override
16 + Widget body(BuildContext context) {
17 + final rescanWalletStore = Provider.of<RescanWalletStore>(context);
18 +
19 + return Padding(
20 + padding: EdgeInsets.only(left: 20, right: 20, bottom: 20),
21 + child:
22 + Column(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
23 + BlockchainHeightWidget(key: blockchainKey),
24 + Observer(
25 + builder: (_) => LoadingPrimaryButton(
26 + isLoading:
27 + rescanWalletStore.state == RescanWalletState.rescaning,
28 + text: S.of(context).rescan,
29 + onPressed: () async {
30 + await rescanWalletStore.rescanCurrentWallet(
31 + restoreHeight: blockchainKey.currentState.height);
32 + Navigator.of(context).pop();
33 + },
34 + color:
35 + Theme.of(context).primaryTextTheme.button.backgroundColor,
36 + borderColor:
37 + Theme.of(context).primaryTextTheme.button.decorationColor))
38 + ]),
39 + );
40 + }
41 +}
lib/src/screens/restore/restore_options_page.dart new
+54
@@ -0,0 +1,54 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:cake_wallet/palette.dart';
3 +import 'package:cake_wallet/routes.dart';
4 +import 'package:flutter/cupertino.dart';
5 +import 'package:cake_wallet/src/screens/restore/widgets/restore_button.dart';
6 +import 'package:cake_wallet/src/screens/base_page.dart';
7 +import 'package:cake_wallet/generated/i18n.dart';
8 +
9 +class RestoreOptionsPage extends BasePage {
10 + static const _aspectRatioImage = 2.086;
11 +
12 + String get title => S.current.restore_restore_wallet;
13 + Color get backgroundColor => Palette.creamyGrey;
14 +
15 + final _imageSeedKeys = Image.asset('assets/images/seedKeys.png');
16 + final _imageRestoreSeed = Image.asset('assets/images/restoreSeed.png');
17 +
18 + @override
19 + Widget body(BuildContext context) => Container(
20 + padding: EdgeInsets.only(
21 + left: 20.0,
22 + right: 20.0,
23 + ),
24 + child: Column(
25 + children: <Widget>[
26 + Flexible(
27 + child: RestoreButton(
28 + onPressed: () {
29 + Navigator.pushNamed(context, Routes.restoreWalletOptionsFromWelcome);
30 + },
31 + image: _imageSeedKeys,
32 + aspectRatioImage: _aspectRatioImage,
33 + titleColor: Palette.lightViolet,
34 + color: Palette.lightViolet,
35 + title: S.of(context).restore_title_from_seed_keys,
36 + description: S.of(context).restore_description_from_seed_keys,
37 + textButton: S.of(context).restore_next,
38 + ),
39 + ),
40 + Flexible(
41 + child: RestoreButton(
42 + onPressed: () {},
43 + image: _imageRestoreSeed,
44 + aspectRatioImage: _aspectRatioImage,
45 + titleColor: Palette.cakeGreen,
46 + color: Palette.cakeGreen,
47 + title: S.of(context).restore_title_from_backup,
48 + description: S.of(context).restore_description_from_backup,
49 + textButton: S.of(context).restore_next,
50 + ))
51 + ],
52 + ),
53 + );
54 +}
lib/src/screens/restore/restore_wallet_from_keys_page.dart new
+225
@@ -0,0 +1,225 @@
1 +import 'package:mobx/mobx.dart';
2 +import 'package:provider/provider.dart';
3 +import 'package:shared_preferences/shared_preferences.dart';
4 +import 'package:flutter/services.dart';
5 +import 'package:flutter/cupertino.dart';
6 +import 'package:flutter/material.dart';
7 +import 'package:flutter_mobx/flutter_mobx.dart';
8 +import 'package:cake_wallet/generated/i18n.dart';
9 +import 'package:cake_wallet/src/domain/services/wallet_list_service.dart';
10 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
11 +import 'package:cake_wallet/src/stores/wallet_restoration/wallet_restoration_store.dart';
12 +import 'package:cake_wallet/src/stores/wallet_restoration/wallet_restoration_state.dart';
13 +import 'package:cake_wallet/src/screens/base_page.dart';
14 +import 'package:cake_wallet/src/widgets/primary_button.dart';
15 +import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
16 +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
17 +import 'package:cake_wallet/palette.dart';
18 +
19 +class RestoreWalletFromKeysPage extends BasePage {
20 + final WalletListService walletsService;
21 + final WalletService walletService;
22 + final SharedPreferences sharedPreferences;
23 +
24 + String get title => S.current.restore_title_from_keys;
25 +
26 + RestoreWalletFromKeysPage(
27 + {@required this.walletsService,
28 + @required this.sharedPreferences,
29 + @required this.walletService});
30 +
31 + @override
32 + Widget body(BuildContext context) => RestoreFromKeysFrom();
33 +}
34 +
35 +class RestoreFromKeysFrom extends StatefulWidget {
36 + @override
37 + createState() => _RestoreFromKeysFromState();
38 +}
39 +
40 +class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
41 + final _formKey = GlobalKey<FormState>();
42 + final _blockchainHeightKey = GlobalKey<BlockchainHeightState>();
43 + final _nameController = TextEditingController();
44 + final _addressController = TextEditingController();
45 + final _viewKeyController = TextEditingController();
46 + final _spendKeyController = TextEditingController();
47 +
48 + @override
49 + Widget build(BuildContext context) {
50 + final walletRestorationStore = Provider.of<WalletRestorationStore>(context);
51 +
52 + reaction((_) => walletRestorationStore.state, (state) {
53 + if (state is WalletRestoredSuccessfully) {
54 + Navigator.of(context).popUntil((route) => route.isFirst);
55 + }
56 +
57 + if (state is WalletRestorationFailure) {
58 + WidgetsBinding.instance.addPostFrameCallback((_) {
59 + showDialog(
60 + context: context,
61 + builder: (BuildContext context) {
62 + return AlertDialog(
63 + content: Text(state.error),
64 + actions: <Widget>[
65 + FlatButton(
66 + child: Text(S.of(context).ok),
67 + onPressed: () => Navigator.of(context).pop(),
68 + ),
69 + ],
70 + );
71 + });
72 + });
73 + }
74 + });
75 +
76 + return ScrollableWithBottomSection(
77 + contentPadding: EdgeInsets.only(left: 20.0, right: 20.0, bottom: 20.0),
78 + content: Form(
79 + key: _formKey,
80 + child: Column(
81 + crossAxisAlignment: CrossAxisAlignment.start,
82 + children: <Widget>[
83 + Padding(
84 + padding: EdgeInsets.only(left: 13, right: 13),
85 + child: Column(children: <Widget>[
86 + Row(
87 + children: <Widget>[
88 + Flexible(
89 + child: Container(
90 + padding: EdgeInsets.only(top: 20.0),
91 + child: TextFormField(
92 + style: TextStyle(fontSize: 14.0),
93 + controller: _nameController,
94 + decoration: InputDecoration(
95 + hintStyle:
96 + TextStyle(color: Theme.of(context).hintColor),
97 + hintText: S.of(context).restore_wallet_name,
98 + focusedBorder: UnderlineInputBorder(
99 + borderSide: BorderSide(
100 + color: Palette.cakeGreen,
101 + width: 2.0)),
102 + enabledBorder: UnderlineInputBorder(
103 + borderSide: BorderSide(
104 + color: Theme.of(context).focusColor,
105 + width: 1.0))),
106 + validator: (value) {
107 + walletRestorationStore.validateWalletName(value);
108 + return walletRestorationStore.errorMessage;
109 + },
110 + ),
111 + ))
112 + ],
113 + ),
114 + Row(
115 + children: <Widget>[
116 + Flexible(
117 + child: Container(
118 + padding: EdgeInsets.only(top: 20.0),
119 + child: TextFormField(
120 + style: TextStyle(fontSize: 14.0),
121 + controller: _addressController,
122 + keyboardType: TextInputType.multiline,
123 + maxLines: null,
124 + decoration: InputDecoration(
125 + hintStyle:
126 + TextStyle(color: Theme.of(context).hintColor),
127 + hintText: S.of(context).restore_address,
128 + focusedBorder: UnderlineInputBorder(
129 + borderSide: BorderSide(
130 + color: Palette.cakeGreen,
131 + width: 2.0)),
132 + enabledBorder: UnderlineInputBorder(
133 + borderSide: BorderSide(
134 + color: Theme.of(context).focusColor,
135 + width: 1.0))),
136 + validator: (value) {
137 + walletRestorationStore.validateAddress(value);
138 + return walletRestorationStore.errorMessage;
139 + },
140 + ),
141 + ))
142 + ],
143 + ),
144 + Row(
145 + children: <Widget>[
146 + Flexible(
147 + child: Container(
148 + padding: EdgeInsets.only(top: 20.0),
149 + child: TextFormField(
150 + style: TextStyle(fontSize: 14.0),
151 + controller: _viewKeyController,
152 + decoration: InputDecoration(
153 + hintStyle:
154 + TextStyle(color: Theme.of(context).hintColor),
155 + hintText: S.of(context).restore_view_key_private,
156 + focusedBorder: UnderlineInputBorder(
157 + borderSide: BorderSide(
158 + color: Palette.cakeGreen,
159 + width: 2.0)),
160 + enabledBorder: UnderlineInputBorder(
161 + borderSide: BorderSide(
162 + color: Theme.of(context).focusColor,
163 + width: 1.0))),
164 + validator: (value) {
165 + walletRestorationStore.validateKeys(value);
166 + return walletRestorationStore.errorMessage;
167 + },
168 + ),
169 + ))
170 + ],
171 + ),
172 + Row(
173 + children: <Widget>[
174 + Flexible(
175 + child: Container(
176 + padding: EdgeInsets.only(top: 20.0),
177 + child: TextFormField(
178 + style: TextStyle(fontSize: 14.0),
179 + controller: _spendKeyController,
180 + decoration: InputDecoration(
181 + hintStyle:
182 + TextStyle(color: Theme.of(context).hintColor),
183 + hintText: S.of(context).restore_spend_key_private,
184 + focusedBorder: UnderlineInputBorder(
185 + borderSide: BorderSide(
186 + color: Palette.cakeGreen,
187 + width: 2.0)),
188 + enabledBorder: UnderlineInputBorder(
189 + borderSide: BorderSide(
190 + color: Theme.of(context).focusColor,
191 + width: 1.0))),
192 + validator: (value) {
193 + walletRestorationStore.validateKeys(value);
194 + return walletRestorationStore.errorMessage;
195 + },
196 + ),
197 + ))
198 + ],
199 + ),
200 + BlockchainHeightWidget(key: _blockchainHeightKey),
201 + ]),
202 + )
203 + ],
204 + ),
205 + ),
206 + bottomSection: Observer(builder: (_) {
207 + return LoadingPrimaryButton(
208 + onPressed: () {
209 + if (_formKey.currentState.validate()) {
210 + walletRestorationStore.restoreFromKeys(
211 + name: _nameController.text,
212 + address: _addressController.text,
213 + viewKey: _viewKeyController.text,
214 + spendKey: _spendKeyController.text,
215 + restoreHeight: _blockchainHeightKey.currentState.height);
216 + }
217 + },
218 + text: S.of(context).restore_recover,
219 + color: Theme.of(context).primaryTextTheme.button.backgroundColor,
220 + borderColor:
221 + Theme.of(context).primaryTextTheme.button.decorationColor);
222 + }),
223 + );
224 + }
225 +}
lib/src/screens/restore/restore_wallet_from_seed_details.dart new
+124
@@ -0,0 +1,124 @@
1 +import 'package:mobx/mobx.dart';
2 +import 'package:provider/provider.dart';
3 +import 'package:flutter/material.dart';
4 +import 'package:flutter/cupertino.dart';
5 +import 'package:flutter_mobx/flutter_mobx.dart';
6 +import 'package:cake_wallet/generated/i18n.dart';
7 +import 'package:cake_wallet/src/stores/wallet_restoration/wallet_restoration_store.dart';
8 +import 'package:cake_wallet/src/stores/wallet_restoration/wallet_restoration_state.dart';
9 +import 'package:cake_wallet/src/screens/base_page.dart';
10 +import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
11 +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
12 +import 'package:cake_wallet/src/widgets/primary_button.dart';
13 +import 'package:cake_wallet/palette.dart';
14 +
15 +class RestoreWalletFromSeedDetailsPage extends BasePage {
16 + String get title => S.current.restore_wallet_restore_description;
17 +
18 + @override
19 + Widget body(BuildContext context) => RestoreFromSeedDetailsForm();
20 +}
21 +
22 +class RestoreFromSeedDetailsForm extends StatefulWidget {
23 + @override
24 + createState() => _RestoreFromSeedDetailsFormState();
25 +}
26 +
27 +class _RestoreFromSeedDetailsFormState
28 + extends State<RestoreFromSeedDetailsForm> {
29 + final _formKey = GlobalKey<FormState>();
30 + final _blockchainHeightKey = GlobalKey<BlockchainHeightState>();
31 + final _nameController = TextEditingController();
32 +
33 + @override
34 + Widget build(BuildContext context) {
35 + final walletRestorationStore = Provider.of<WalletRestorationStore>(context);
36 +
37 + reaction((_) => walletRestorationStore.state, (state) {
38 + if (state is WalletRestoredSuccessfully) {
39 + Navigator.of(context).popUntil((route) => route.isFirst);
40 + }
41 +
42 + if (state is WalletRestorationFailure) {
43 + WidgetsBinding.instance.addPostFrameCallback((_) {
44 + showDialog(
45 + context: context,
46 + builder: (BuildContext context) {
47 + return AlertDialog(
48 + content: Text(state.error),
49 + actions: <Widget>[
50 + FlatButton(
51 + child: Text(S.of(context).ok),
52 + onPressed: () => Navigator.of(context).pop(),
53 + ),
54 + ],
55 + );
56 + });
57 + });
58 + }
59 + });
60 +
61 + return ScrollableWithBottomSection(
62 + contentPadding: EdgeInsets.only(left: 20.0, right: 20.0, bottom: 20.0),
63 + content: Form(
64 + key: _formKey,
65 + child: Column(
66 + crossAxisAlignment: CrossAxisAlignment.start,
67 + children: <Widget>[
68 + Padding(
69 + padding: EdgeInsets.only(left: 13, right: 13),
70 + child: Column(
71 + mainAxisAlignment: MainAxisAlignment.center,
72 + children: <Widget>[
73 + Row(
74 + children: <Widget>[
75 + Flexible(
76 + child: Container(
77 + padding: EdgeInsets.only(top: 20.0),
78 + child: TextFormField(
79 + style: TextStyle(fontSize: 14.0),
80 + controller: _nameController,
81 + decoration: InputDecoration(
82 + hintStyle: TextStyle(
83 + color: Theme.of(context).hintColor),
84 + hintText: S.of(context).restore_wallet_name,
85 + focusedBorder: UnderlineInputBorder(
86 + borderSide: BorderSide(
87 + color: Palette.cakeGreen,
88 + width: 2.0)),
89 + enabledBorder: UnderlineInputBorder(
90 + borderSide: BorderSide(
91 + color: Theme.of(context).focusColor,
92 + width: 1.0))),
93 + validator: (value) {
94 + walletRestorationStore
95 + .validateWalletName(value);
96 + return walletRestorationStore.errorMessage;
97 + },
98 + ),
99 + ))
100 + ],
101 + ),
102 + BlockchainHeightWidget(key: _blockchainHeightKey),
103 + ]))
104 + ],
105 + ),
106 + ),
107 + bottomSection: Observer(builder: (_) {
108 + return LoadingPrimaryButton(
109 + onPressed: () {
110 + if (_formKey.currentState.validate()) {
111 + walletRestorationStore.restoreFromSeed(
112 + name: _nameController.text,
113 + restoreHeight: _blockchainHeightKey.currentState.height);
114 + }
115 + },
116 + isLoading: walletRestorationStore.state is WalletIsRestoring,
117 + text: S.of(context).restore_recover,
118 + color: Theme.of(context).primaryTextTheme.button.backgroundColor,
119 + borderColor:
120 + Theme.of(context).primaryTextTheme.button.decorationColor);
121 + }),
122 + );
123 + }
124 +}
lib/src/screens/restore/restore_wallet_from_seed_page.dart new
+105
@@ -0,0 +1,105 @@
1 +import 'package:mobx/mobx.dart';
2 +import 'package:provider/provider.dart';
3 +import 'package:flutter/material.dart';
4 +import 'package:flutter/cupertino.dart';
5 +import 'package:flutter/services.dart';
6 +import 'package:shared_preferences/shared_preferences.dart';
7 +import 'package:cake_wallet/routes.dart';
8 +import 'package:cake_wallet/generated/i18n.dart';
9 +import 'package:cake_wallet/src/widgets/primary_button.dart';
10 +import 'package:cake_wallet/src/domain/services/wallet_list_service.dart';
11 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
12 +import 'package:cake_wallet/src/screens/base_page.dart';
13 +import 'package:cake_wallet/src/stores/wallet_restoration/wallet_restoration_store.dart';
14 +import 'package:cake_wallet/src/widgets/seed_widget.dart';
15 +
16 +class RestoreWalletFromSeedPage extends BasePage {
17 + final WalletListService walletsService;
18 + final WalletService walletService;
19 + final SharedPreferences sharedPreferences;
20 +
21 + String get title => S.current.restore_title_from_seed;
22 +
23 + RestoreWalletFromSeedPage(
24 + {@required this.walletsService,
25 + @required this.walletService,
26 + @required this.sharedPreferences});
27 +
28 + @override
29 + Widget body(BuildContext context) => RestoreFromSeedForm();
30 +}
31 +
32 +class RestoreFromSeedForm extends StatefulWidget {
33 + @override
34 + createState() => _RestoreFromSeedFormState();
35 +}
36 +
37 +class _RestoreFromSeedFormState extends State<RestoreFromSeedForm> {
38 + final _seedKey = GlobalKey<SeedWidgetState>();
39 + bool _reactionSet = false;
40 +
41 + @override
42 + Widget build(BuildContext context) {
43 + final walletRestorationStore = Provider.of<WalletRestorationStore>(context);
44 +
45 + WidgetsBinding.instance.addPostFrameCallback(
46 + (_) => _setReactions(context, walletRestorationStore));
47 +
48 + return GestureDetector(
49 + onTap: () {
50 + SystemChannels.textInput.invokeMethod('TextInput.hide');
51 + },
52 + child: Container(
53 + padding: EdgeInsets.only(left: 20.0, right: 20.0, bottom: 20.0),
54 + child: Column(
55 + children: <Widget>[
56 + Expanded(
57 + child: SeedWidget(
58 + key: _seedKey,
59 + onMnemoticChange: (seed) => walletRestorationStore.setSeed(seed),
60 + )),
61 + Container(
62 + alignment: Alignment.bottomCenter,
63 + child: PrimaryButton(
64 + onPressed: () {
65 + if (!walletRestorationStore.isValid) {
66 + return;
67 + }
68 +
69 + Navigator.of(context).pushNamed(
70 + Routes.restoreWalletFromSeedDetails,
71 + arguments: _seedKey.currentState.items);
72 + },
73 + text: S.of(context).restore_next,
74 + color: Theme.of(context)
75 + .primaryTextTheme
76 + .button
77 + .backgroundColor,
78 + borderColor: Theme.of(context)
79 + .primaryTextTheme
80 + .button
81 + .decorationColor))
82 + ],
83 + ),
84 + ),
85 + );
86 + }
87 +
88 + void _setReactions(BuildContext context, WalletRestorationStore store) {
89 + if (_reactionSet) {
90 + return;
91 + }
92 +
93 + reaction((_) => store.errorMessage, (errorMessage) {
94 + if (errorMessage == null || errorMessage.isEmpty) {
95 + _seedKey.currentState.validated();
96 + } else {
97 + _seedKey.currentState.invalidate();
98 + }
99 +
100 + _seedKey.currentState.setErrorMessage(errorMessage);
101 + });
102 +
103 + _reactionSet = true;
104 + }
105 +}
lib/src/screens/restore/restore_wallet_options_page.dart new
+53
@@ -0,0 +1,53 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter/cupertino.dart';
3 +import 'package:cake_wallet/routes.dart';
4 +import 'package:cake_wallet/palette.dart';
5 +import 'package:cake_wallet/src/screens/restore/widgets/restore_button.dart';
6 +import 'package:cake_wallet/src/screens/base_page.dart';
7 +import 'package:cake_wallet/generated/i18n.dart';
8 +
9 +class RestoreWalletOptionsPage extends BasePage {
10 + static const _aspectRatioImage = 2.086;
11 +
12 + String get title => S.current.restore_seed_keys_restore;
13 + Color get backgroundColor => Palette.creamyGrey;
14 +
15 + final _imageSeed = Image.asset('assets/images/seedIco.png');
16 + final _imageKeys = Image.asset('assets/images/keysIco.png');
17 +
18 + @override
19 + Widget body(BuildContext context) => Container(
20 + padding: EdgeInsets.only(
21 + left: 20.0,
22 + right: 20.0,
23 + ),
24 + child: Column(
25 + children: <Widget>[
26 + Flexible(
27 + child: RestoreButton(
28 + onPressed: () =>
29 + Navigator.pushNamed(context, Routes.restoreWalletFromSeed),
30 + image: _imageSeed,
31 + aspectRatioImage: _aspectRatioImage,
32 + titleColor: Palette.lightViolet,
33 + color: Palette.lightViolet,
34 + title: S.of(context).restore_title_from_seed,
35 + description: S.of(context).restore_description_from_seed,
36 + textButton: S.of(context).restore_next,
37 + )),
38 + Flexible(
39 + child: RestoreButton(
40 + onPressed: () =>
41 + Navigator.pushNamed(context, Routes.restoreWalletFromKeys),
42 + image: _imageKeys,
43 + aspectRatioImage: _aspectRatioImage,
44 + titleColor: Palette.cakeGreen,
45 + color: Palette.cakeGreen,
46 + title: S.of(context).restore_title_from_keys,
47 + description: S.of(context).restore_description_from_keys,
48 + textButton: S.of(context).restore_next,
49 + ))
50 + ],
51 + ),
52 + );
53 +}
lib/src/screens/restore/widgets/restore_button.dart new
+108
@@ -0,0 +1,108 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:cake_wallet/palette.dart';
3 +
4 +class RestoreButton extends StatelessWidget {
5 + final VoidCallback onPressed;
6 + final Image image;
7 + final double aspectRatioImage;
8 + final Color color;
9 + final Color titleColor;
10 + final String title;
11 + final String description;
12 + final String textButton;
13 +
14 + const RestoreButton(
15 + {@required this.onPressed,
16 + @required this.image,
17 + @required this.aspectRatioImage,
18 + @required this.color,
19 + @required this.titleColor,
20 + this.title = '',
21 + this.description = '',
22 + this.textButton = ''});
23 +
24 + @override
25 + Widget build(BuildContext context) {
26 +
27 + return Container(
28 + margin: EdgeInsets.only(top: 20.0, bottom: 20.0),
29 + decoration: BoxDecoration(
30 + color: Theme.of(context).accentTextTheme.headline.backgroundColor,
31 + borderRadius: BorderRadius.all(Radius.circular(20.0)),
32 + boxShadow: [
33 + BoxShadow(
34 + color: Palette.buttonShadow,
35 + blurRadius: 10,
36 + offset: Offset(
37 + 0,
38 + 12,
39 + ),
40 + )
41 + ]),
42 + child: InkWell(
43 + onTap: onPressed,
44 + borderRadius: BorderRadius.all(Radius.circular(20.0)),
45 + child: Column(
46 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
47 + children: <Widget>[
48 + Flexible(
49 + child: Container(
50 + child: AspectRatio(
51 + aspectRatio: aspectRatioImage,
52 + child: FittedBox(
53 + fit: BoxFit.contain,
54 + child: image,
55 + ),
56 + ),
57 + ),
58 + ),
59 + Column(
60 + children: <Widget>[
61 + Text(
62 + title,
63 + textAlign: TextAlign.center,
64 + style: TextStyle(
65 + color: titleColor,
66 + fontSize: 18.0,
67 + fontWeight: FontWeight.bold),
68 + ),
69 + Padding(
70 + padding: EdgeInsets.only(left: 50, right: 50, top: 10),
71 + child: Text(
72 + description,
73 + textAlign: TextAlign.center,
74 + style:
75 + TextStyle(
76 + color: Theme.of(context).accentTextTheme.subhead.color,
77 + fontSize: 14.0,
78 + height: 1.4),
79 + ),
80 + )
81 + ],
82 + ),
83 + SizedBox(
84 + height: 20.0,
85 + ),
86 + Container(
87 + height: 56.0,
88 + decoration: BoxDecoration(
89 + border: Border(
90 + top: BorderSide(
91 + color: Theme.of(context).accentTextTheme.headline.decorationColor,
92 + width: 1.15)),
93 + color: Colors.transparent,
94 + ),
95 + child: Center(
96 + child: Text(
97 + textButton,
98 + style: TextStyle(
99 + color: color,
100 + fontSize: 16.0,
101 + fontWeight: FontWeight.bold),
102 + ),
103 + ))
104 + ],
105 + )),
106 + );
107 + }
108 +}
lib/src/screens/root/root.dart new
+135
@@ -0,0 +1,135 @@
1 +import 'package:cake_wallet/src/screens/welcome/create_welcome_page.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:flutter_mobx/flutter_mobx.dart';
4 +import 'package:hive/hive.dart';
5 +import 'package:provider/provider.dart';
6 +import 'package:shared_preferences/shared_preferences.dart';
7 +import 'package:cake_wallet/routes.dart';
8 +import 'package:cake_wallet/router.dart';
9 +import 'package:cake_wallet/src/stores/authentication/authentication_store.dart';
10 +import 'package:cake_wallet/src/stores/price/price_store.dart';
11 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
12 +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
13 +import 'package:cake_wallet/src/domain/common/qr_scanner.dart';
14 +import 'package:cake_wallet/src/domain/services/user_service.dart';
15 +import 'package:cake_wallet/src/domain/services/wallet_list_service.dart';
16 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
17 +import 'package:cake_wallet/src/domain/exchange/trade.dart';
18 +import 'package:cake_wallet/src/domain/monero/transaction_description.dart';
19 +import 'package:cake_wallet/src/screens/auth/create_login_page.dart';
20 +import 'package:cake_wallet/src/screens/seed/create_seed_page.dart';
21 +import 'package:cake_wallet/src/screens/dashboard/create_dashboard_page.dart';
22 +
23 +class Root extends StatefulWidget {
24 + Root({Key key}) : super(key: key);
25 +
26 + @override
27 + RootState createState() => RootState();
28 +}
29 +
30 +class RootState extends State<Root> with WidgetsBindingObserver {
31 + bool _isInactive;
32 + bool _postFrameCallback;
33 + AuthenticationStore _authenticationStore;
34 +
35 + @override
36 + void initState() {
37 + _isInactive = false;
38 + _postFrameCallback = false;
39 + WidgetsBinding.instance.addObserver(this);
40 + super.initState();
41 + }
42 +
43 + @override
44 + void didChangeAppLifecycleState(AppLifecycleState state) {
45 + switch (state) {
46 + case AppLifecycleState.paused:
47 + if (isQrScannerShown) {
48 + return;
49 + }
50 +
51 + if (!_isInactive &&
52 + _authenticationStore.state ==
53 + AuthenticationState.authenticated ||
54 + _authenticationStore.state == AuthenticationState.active) {
55 + setState(() => _isInactive = true);
56 + }
57 +
58 + break;
59 + default:
60 + break;
61 + }
62 + }
63 +
64 + @override
65 + Widget build(BuildContext context) {
66 + _authenticationStore = Provider.of<AuthenticationStore>(context);
67 + final sharedPreferences = Provider.of<SharedPreferences>(context);
68 + final walletListService = Provider.of<WalletListService>(context);
69 + final walletService = Provider.of<WalletService>(context);
70 + final userService = Provider.of<UserService>(context);
71 + final priceStore = Provider.of<PriceStore>(context);
72 + final authenticationStore = Provider.of<AuthenticationStore>(context);
73 + final trades = Provider.of<Box<Trade>>(context);
74 + final transactionDescriptions =
75 + Provider.of<Box<TransactionDescription>>(context);
76 + final walletStore = Provider.of<WalletStore>(context);
77 + final settingsStore = Provider.of<SettingsStore>(context);
78 +
79 + if (_isInactive && !_postFrameCallback) {
80 + _postFrameCallback = true;
81 +
82 + WidgetsBinding.instance.addPostFrameCallback((_) {
83 + Navigator.of(context).pushNamed(Routes.unlock,
84 + arguments: (isAuthenticatedSuccessfully, auth) {
85 + if (!isAuthenticatedSuccessfully) {
86 + return;
87 + }
88 +
89 + setState(() {
90 + _postFrameCallback = false;
91 + _isInactive = false;
92 + });
93 + auth.close();
94 + });
95 + });
96 + }
97 +
98 + return Observer(builder: (_) {
99 + final state = _authenticationStore.state;
100 + if (state == AuthenticationState.denied) {
101 + return createWelcomePage();
102 + }
103 +
104 + if (state == AuthenticationState.readyToLogin) {
105 + return createLoginPage(
106 + sharedPreferences: sharedPreferences,
107 + userService: userService,
108 + walletService: walletService,
109 + walletListService: walletListService,
110 + authenticationStore: authenticationStore);
111 + }
112 +
113 + if (state == AuthenticationState.authenticated ||
114 + state == AuthenticationState.restored) {
115 + return createDashboardPage(
116 + walletService: walletService,
117 + priceStore: priceStore,
118 + trades: trades,
119 + transactionDescriptions: transactionDescriptions,
120 + walletStore: walletStore,
121 + settingsStore: settingsStore);
122 + }
123 +
124 + if (state == AuthenticationState.created) {
125 + return createSeedPage(
126 + settingsStore: settingsStore,
127 + walletService: walletService,
128 + callback: () =>
129 + _authenticationStore.state = AuthenticationState.authenticated);
130 + }
131 +
132 + return Container(color: Colors.white);
133 + });
134 + }
135 +}
lib/src/screens/seed/create_seed_page.dart new
+14
@@ -0,0 +1,14 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:provider/provider.dart';
3 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
4 +import 'package:cake_wallet/src/screens/seed/seed_page.dart';
5 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
6 +import 'package:cake_wallet/src/stores/wallet_seed/wallet_seed_store.dart';
7 +
8 +Widget createSeedPage(
9 + {@required SettingsStore settingsStore,
10 + @required WalletService walletService,
11 + @required void Function() callback}) =>
12 + Provider(
13 + create: (_) => WalletSeedStore(walletService: walletService),
14 + child: SeedPage(onCloseCallback: callback));
\ No newline at end of file
lib/src/screens/seed/seed_page.dart new
+162
@@ -0,0 +1,162 @@
1 +import 'package:provider/provider.dart';
2 +import 'package:esys_flutter_share/esys_flutter_share.dart';
3 +import 'package:flutter/material.dart';
4 +import 'package:flutter/cupertino.dart';
5 +import 'package:flutter/services.dart';
6 +import 'package:flutter_mobx/flutter_mobx.dart';
7 +import 'package:cake_wallet/palette.dart';
8 +import 'package:cake_wallet/generated/i18n.dart';
9 +import 'package:cake_wallet/src/widgets/primary_button.dart';
10 +import 'package:cake_wallet/src/stores/wallet_seed/wallet_seed_store.dart';
11 +import 'package:cake_wallet/src/screens/base_page.dart';
12 +
13 +class SeedPage extends BasePage {
14 + static final image = Image.asset('assets/images/seed_image.png');
15 + bool get isModalBackButton => true;
16 + String get title => S.current.seed_title;
17 +
18 + final VoidCallback onCloseCallback;
19 +
20 + SeedPage({this.onCloseCallback});
21 +
22 + void onClose(BuildContext context) =>
23 + onCloseCallback != null ? onCloseCallback() : Navigator.of(context).pop();
24 +
25 + @override
26 + Widget leading(BuildContext context) {
27 + return onCloseCallback != null ? Offstage() : super.leading(context);
28 + }
29 +
30 + @override
31 + Widget body(BuildContext context) {
32 + final walletSeedStore = Provider.of<WalletSeedStore>(context);
33 + String _seed;
34 +
35 + return Container(
36 + padding: EdgeInsets.all(30.0),
37 + child: Column(
38 + children: <Widget>[
39 + Expanded(
40 + child: Center(
41 + child: Column(
42 + mainAxisSize: MainAxisSize.min,
43 + children: <Widget>[
44 + image,
45 + Container(
46 + margin: EdgeInsets.only(left: 30.0, top: 10.0, right: 30.0),
47 + child: Observer(builder: (_) {
48 + _seed = walletSeedStore.seed;
49 + return Column(
50 + children: <Widget>[
51 + Row(
52 + children: <Widget>[
53 + Expanded(
54 + child: Container(
55 + decoration: BoxDecoration(
56 + border: Border(
57 + bottom: BorderSide(
58 + width: 1.0,
59 + color: Theme.of(context)
60 + .dividerColor))),
61 + padding: EdgeInsets.only(bottom: 20.0),
62 + margin: EdgeInsets.only(bottom: 10.0),
63 + child: Text(
64 + walletSeedStore.name,
65 + textAlign: TextAlign.center,
66 + style: TextStyle(
67 + fontSize: 18.0,
68 + color: Theme.of(context)
69 + .primaryTextTheme
70 + .button
71 + .color),
72 + ),
73 + ))
74 + ],
75 + ),
76 + SizedBox(
77 + height: 10.0,
78 + ),
79 + Text(
80 + walletSeedStore.seed,
81 + textAlign: TextAlign.center,
82 + style: TextStyle(
83 + fontSize: 14.0,
84 + color: Theme.of(context)
85 + .primaryTextTheme
86 + .title
87 + .color),
88 + )
89 + ],
90 + );
91 + }),
92 + ),
93 + Container(
94 + margin: EdgeInsets.only(top: 30.0),
95 + child: Row(
96 + children: <Widget>[
97 + Flexible(
98 + child: Container(
99 + padding: EdgeInsets.only(right: 8.0),
100 + child: PrimaryButton(
101 + onPressed: () => Share.text(
102 + S.of(context).seed_share,
103 + _seed,
104 + 'text/plain'),
105 + color: Theme.of(context)
106 + .primaryTextTheme
107 + .button
108 + .backgroundColor,
109 + borderColor: Theme.of(context)
110 + .primaryTextTheme
111 + .button
112 + .decorationColor,
113 + text: S.of(context).save),
114 + )),
115 + Flexible(
116 + child: Container(
117 + padding: EdgeInsets.only(left: 8.0),
118 + child: Builder(
119 + builder: (context) => PrimaryButton(
120 + onPressed: () {
121 + Clipboard.setData(
122 + ClipboardData(text: _seed));
123 + Scaffold.of(context).showSnackBar(
124 + SnackBar(
125 + content: Text(S
126 + .of(context)
127 + .copied_to_clipboard),
128 + backgroundColor: Colors.green,
129 + duration:
130 + Duration(milliseconds: 1500),
131 + ),
132 + );
133 + },
134 + text: S.of(context).copy,
135 + color: Theme.of(context)
136 + .accentTextTheme
137 + .caption
138 + .backgroundColor,
139 + borderColor: Theme.of(context)
140 + .accentTextTheme
141 + .caption
142 + .decorationColor),
143 + )))
144 + ],
145 + ),
146 + )
147 + ],
148 + ),
149 + ),
150 + ),
151 + onCloseCallback != null
152 + ? PrimaryButton(
153 + onPressed: () => onClose(context),
154 + text: S.of(context).restore_next,
155 + color: Palette.darkGrey,
156 + borderColor: Palette.darkGrey)
157 + : Offstage()
158 + ],
159 + ),
160 + );
161 + }
162 +}
lib/src/screens/seed_alert/seed_alert.dart new
+83
@@ -0,0 +1,83 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter/cupertino.dart';
3 +import 'package:cake_wallet/palette.dart';
4 +import 'package:cake_wallet/generated/i18n.dart';
5 +import 'package:cake_wallet/src/widgets/primary_button.dart';
6 +
7 +class SeedAlert extends StatelessWidget {
8 + final imageSeed = Image.asset('assets/images/seedIco.png');
9 +
10 + @override
11 + Widget build(BuildContext context) {
12 + return Scaffold(
13 + resizeToAvoidBottomPadding: false,
14 + backgroundColor: Theme.of(context).backgroundColor,
15 + body: SafeArea(
16 + child: Container(
17 + padding: EdgeInsets.all(20.0),
18 + child: Column(
19 + children: <Widget>[
20 + Expanded(
21 + child: Center(
22 + child: Column(
23 + mainAxisSize: MainAxisSize.min,
24 + children: <Widget>[
25 + imageSeed,
26 + Text(
27 + S.of(context).seed_alert_first_text,
28 + textAlign: TextAlign.center,
29 + style: TextStyle(fontSize: 19.0),
30 + ),
31 + SizedBox(
32 + height: 20.0,
33 + ),
34 + Text(
35 + S.of(context).seed_alert_second_text,
36 + textAlign: TextAlign.center,
37 + style: TextStyle(
38 + letterSpacing: 0.2,
39 + fontSize: 16.0,
40 + color: Palette.lightBlue),
41 + ),
42 + SizedBox(
43 + height: 20.0,
44 + ),
45 + RichText(
46 + textAlign: TextAlign.center,
47 + text: TextSpan(children: <TextSpan>[
48 + TextSpan(
49 + text: S.of(context).seed_alert_third_text,
50 + style: TextStyle(
51 + letterSpacing: 0.2,
52 + fontSize: 16.0,
53 + color: Palette.lightBlue)),
54 + TextSpan(
55 + text: S.of(context).seed_alert_settings,
56 + style: TextStyle(
57 + letterSpacing: 0.2,
58 + fontSize: 16.0,
59 + color: Palette.lightGreen)),
60 + TextSpan(
61 + text: S.of(context).seed_alert_menu,
62 + style: TextStyle(
63 + letterSpacing: 0.2,
64 + fontSize: 16.0,
65 + color: Palette.lightBlue)),
66 + ]))
67 + ],
68 + ),
69 + ),
70 + ),
71 + PrimaryButton(
72 + onPressed: () {},
73 + text: S.of(context).seed_alert_understand,
74 + color:
75 + Theme.of(context).primaryTextTheme.button.backgroundColor,
76 + borderColor:
77 + Theme.of(context).primaryTextTheme.button.decorationColor),
78 + ],
79 + ),
80 + )),
81 + );
82 + }
83 +}
lib/src/screens/send/send_page.dart new
+483
@@ -0,0 +1,483 @@
1 +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
2 +import 'package:flutter/cupertino.dart';
3 +import 'package:flutter/material.dart';
4 +import 'package:flutter/services.dart';
5 +import 'package:flutter_mobx/flutter_mobx.dart';
6 +import 'package:mobx/mobx.dart';
7 +import 'package:provider/provider.dart';
8 +import 'package:cake_wallet/palette.dart';
9 +import 'package:cake_wallet/routes.dart';
10 +import 'package:cake_wallet/src/widgets/address_text_field.dart';
11 +import 'package:cake_wallet/src/widgets/primary_button.dart';
12 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
13 +import 'package:cake_wallet/src/stores/balance/balance_store.dart';
14 +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
15 +import 'package:cake_wallet/src/stores/send/send_store.dart';
16 +import 'package:cake_wallet/src/stores/send/sending_state.dart';
17 +import 'package:cake_wallet/src/screens/base_page.dart';
18 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
19 +import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
20 +import 'package:cake_wallet/src/domain/common/calculate_estimated_fee.dart';
21 +import 'package:cake_wallet/generated/i18n.dart';
22 +import 'package:cake_wallet/src/domain/common/sync_status.dart';
23 +import 'package:cake_wallet/src/stores/sync/sync_store.dart';
24 +
25 +class SendPage extends BasePage {
26 + String get title => S.current.send_title;
27 + bool get isModalBackButton => true;
28 + bool get resizeToAvoidBottomPadding => false;
29 +
30 + @override
31 + Widget body(BuildContext context) => SendForm();
32 +}
33 +
34 +class SendForm extends StatefulWidget {
35 + @override
36 + State<StatefulWidget> createState() => SendFormState();
37 +}
38 +
39 +class SendFormState extends State<SendForm> {
40 + final _addressController = TextEditingController();
41 + final _paymentIdController = TextEditingController();
42 + final _cryptoAmountController = TextEditingController();
43 + final _fiatAmountController = TextEditingController();
44 +
45 + bool _effectsInstalled = false;
46 +
47 + final _formKey = GlobalKey<FormState>();
48 +
49 + @override
50 + Widget build(BuildContext context) {
51 + final settingsStore = Provider.of<SettingsStore>(context);
52 + final sendStore = Provider.of<SendStore>(context);
53 + sendStore.settingsStore = settingsStore;
54 + final balanceStore = Provider.of<BalanceStore>(context);
55 + final walletStore = Provider.of<WalletStore>(context);
56 + final syncStore = Provider.of<SyncStore>(context);
57 +
58 + _setEffects(context);
59 +
60 + return ScrollableWithBottomSection(
61 + contentPadding: EdgeInsets.all(0),
62 + content: Column(
63 + children: [
64 + Container(
65 + padding: EdgeInsets.only(left: 38, right: 30),
66 + decoration: BoxDecoration(
67 + color: Theme.of(context).backgroundColor,
68 + boxShadow: [
69 + BoxShadow(
70 + color: Palette.shadowGrey,
71 + blurRadius: 10,
72 + offset: Offset(0, 12),
73 + )
74 + ],
75 + border: Border(
76 + top: BorderSide(
77 + width: 1,
78 + color: Theme.of(context)
79 + .accentTextTheme
80 + .subtitle
81 + .backgroundColor))),
82 + child: SizedBox(
83 + height: 56,
84 + width: double.infinity,
85 + child: Row(
86 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
87 + children: <Widget>[
88 + Observer(builder: (_) {
89 + return Column(
90 + crossAxisAlignment: CrossAxisAlignment.start,
91 + mainAxisAlignment: MainAxisAlignment.center,
92 + children: <Widget>[
93 + Text(S.of(context).send_your_wallet,
94 + style: TextStyle(
95 + fontSize: 12, color: Palette.lightViolet)),
96 + Text(walletStore.name,
97 + style: TextStyle(
98 + fontSize: 18,
99 + color: Theme.of(context)
100 + .accentTextTheme
101 + .overline
102 + .color,
103 + height: 1.25)),
104 + ]);
105 + }),
106 + Observer(builder: (context) {
107 + final savedDisplayMode = settingsStore.balanceDisplayMode;
108 + final availableBalance =
109 + savedDisplayMode == BalanceDisplayMode.hiddenBalance
110 + ? '---'
111 + : balanceStore.unlockedBalance;
112 +
113 + return Column(
114 + mainAxisAlignment: MainAxisAlignment.center,
115 + children: <Widget>[
116 + Text(S.of(context).xmr_available_balance,
117 + style: TextStyle(
118 + fontSize: 12,
119 + color: Theme.of(context)
120 + .accentTextTheme
121 + .overline
122 + .backgroundColor,
123 + )),
124 + Text(availableBalance,
125 + style: TextStyle(
126 + fontSize: 22,
127 + color: Theme.of(context)
128 + .accentTextTheme
129 + .overline
130 + .color,
131 + height: 1.1)),
132 + ]);
133 + })
134 + ],
135 + ),
136 + ),
137 + ),
138 + Form(
139 + key: _formKey,
140 + child: Container(
141 + padding:
142 + EdgeInsets.only(left: 38, right: 33, top: 10, bottom: 30),
143 + child: Column(children: <Widget>[
144 + AddressTextField(
145 + controller: _addressController,
146 + placeholder: S.of(context).send_monero_address,
147 + onURIScanned: (uri) {
148 + var address = '';
149 + var amount = '';
150 + var paymentId = '';
151 +
152 + if (uri != null) {
153 + address = uri.path;
154 + amount = uri.queryParameters['tx_amount'];
155 + paymentId = uri.queryParameters['tx_payment_id'];
156 + } else {
157 + address = uri.toString();
158 + }
159 +
160 + _addressController.text = address;
161 + _cryptoAmountController.text = amount;
162 + _paymentIdController.text = paymentId;
163 + },
164 + options: [
165 + AddressTextFieldOption.qrCode,
166 + AddressTextFieldOption.addressBook
167 + ],
168 + validator: (value) {
169 + sendStore.validateAddress(value,
170 + cryptoCurrency: CryptoCurrency.xmr);
171 + return sendStore.errorMessage;
172 + },
173 + ),
174 + Padding(
175 + padding: const EdgeInsets.only(top: 20),
176 + child: TextFormField(
177 + style: TextStyle(
178 + fontSize: 14.0,
179 + color: Theme.of(context)
180 + .accentTextTheme
181 + .overline
182 + .backgroundColor),
183 + controller: _paymentIdController,
184 + decoration: InputDecoration(
185 + hintStyle: TextStyle(
186 + fontSize: 14.0,
187 + color: Theme.of(context).hintColor),
188 + hintText: S.of(context).send_payment_id,
189 + focusedBorder: UnderlineInputBorder(
190 + borderSide: BorderSide(
191 + color: Palette.cakeGreen, width: 2.0)),
192 + enabledBorder: UnderlineInputBorder(
193 + borderSide: BorderSide(
194 + color: Theme.of(context).focusColor,
195 + width: 1.0))),
196 + validator: (value) {
197 + sendStore.validatePaymentID(value);
198 + return sendStore.errorMessage;
199 + }),
200 + ),
201 + Padding(
202 + padding: const EdgeInsets.only(top: 20),
203 + child: TextFormField(
204 + style: TextStyle(
205 + fontSize: 18.0,
206 + color: Theme.of(context)
207 + .accentTextTheme
208 + .overline
209 + .color),
210 + controller: _cryptoAmountController,
211 + keyboardType: TextInputType.numberWithOptions(
212 + signed: false, decimal: false),
213 + inputFormatters: [
214 + BlacklistingTextInputFormatter(
215 + new RegExp('[\\-|\\ |\\,]'))
216 + ],
217 + decoration: InputDecoration(
218 + prefixIcon: Padding(
219 + padding: EdgeInsets.only(top: 12),
220 + child: Text('XMR:',
221 + style: TextStyle(
222 + fontSize: 18,
223 + color: Theme.of(context)
224 + .accentTextTheme
225 + .overline
226 + .color,
227 + )),
228 + ),
229 + suffixIcon: Container(
230 + width: 1,
231 + padding: EdgeInsets.only(top: 0),
232 + child: Center(
233 + child: InkWell(
234 + onTap: () => sendStore.setSendAll(),
235 + child: Text(S.of(context).all,
236 + style: TextStyle(
237 + fontSize: 10,
238 + color: Theme.of(context)
239 + .accentTextTheme
240 + .overline
241 + .decorationColor))),
242 + ),
243 + ),
244 + hintStyle: TextStyle(
245 + fontSize: 18.0,
246 + color: Theme.of(context).hintColor),
247 + hintText: '0.0000',
248 + focusedBorder: UnderlineInputBorder(
249 + borderSide: BorderSide(
250 + color: Palette.cakeGreen, width: 2.0)),
251 + enabledBorder: UnderlineInputBorder(
252 + borderSide: BorderSide(
253 + color: Theme.of(context).focusColor,
254 + width: 1.0))),
255 + validator: (value) {
256 + sendStore.validateXMR(
257 + value, balanceStore.unlockedBalance);
258 + return sendStore.errorMessage;
259 + }),
260 + ),
261 + Padding(
262 + padding: const EdgeInsets.only(top: 20),
263 + child: TextFormField(
264 + style: TextStyle(
265 + fontSize: 18.0,
266 + color: Theme.of(context)
267 + .accentTextTheme
268 + .overline
269 + .color),
270 + controller: _fiatAmountController,
271 + keyboardType: TextInputType.numberWithOptions(
272 + signed: false, decimal: false),
273 + inputFormatters: [
274 + BlacklistingTextInputFormatter(
275 + new RegExp('[\\-|\\ |\\,]'))
276 + ],
277 + decoration: InputDecoration(
278 + prefixIcon: Padding(
279 + padding: EdgeInsets.only(top: 12),
280 + child: Text(
281 + '${settingsStore.fiatCurrency.toString()}:',
282 + style: TextStyle(
283 + fontSize: 18,
284 + color: Theme.of(context)
285 + .accentTextTheme
286 + .overline
287 + .color,
288 + )),
289 + ),
290 + hintStyle: TextStyle(
291 + fontSize: 18.0,
292 + color: Theme.of(context).hintColor),
293 + hintText: '0.00',
294 + focusedBorder: UnderlineInputBorder(
295 + borderSide: BorderSide(
296 + color: Palette.cakeGreen, width: 2.0)),
297 + enabledBorder: UnderlineInputBorder(
298 + borderSide: BorderSide(
299 + color: Theme.of(context).focusColor,
300 + width: 1.0)))),
301 + ),
302 + Padding(
303 + padding: const EdgeInsets.only(top: 12.0, bottom: 10),
304 + child: Row(
305 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
306 + children: <Widget>[
307 + Text(S.of(context).send_estimated_fee,
308 + style: TextStyle(
309 + fontSize: 14,
310 + fontWeight: FontWeight.w500,
311 + color: Theme.of(context)
312 + .accentTextTheme
313 + .overline
314 + .backgroundColor,
315 + )),
316 + Text(
317 + '${calculateEstimatedFee(priority: settingsStore.transactionPriority)} XMR',
318 + style: TextStyle(
319 + fontSize: 14,
320 + fontWeight: FontWeight.w500,
321 + color: Theme.of(context)
322 + .primaryTextTheme
323 + .overline
324 + .backgroundColor,
325 + ))
326 + ],
327 + ),
328 + ),
329 + SizedBox(
330 + width: double.infinity,
331 + child: Text(
332 + S.of(context).send_priority(
333 + settingsStore.transactionPriority.toString()),
334 + style: TextStyle(
335 + fontSize: 12,
336 + fontWeight: FontWeight.w500,
337 + color: Theme.of(context)
338 + .primaryTextTheme
339 + .subtitle
340 + .color,
341 + height: 1.3)),
342 + ),
343 + ]),
344 + ),
345 + )
346 + ],
347 + ),
348 + bottomSection: Observer(builder: (_) {
349 + return LoadingPrimaryButton(
350 + onPressed: syncStore.status is SyncedSyncStatus
351 + ? () async {
352 + // Hack. Don't ask me.
353 + FocusScope.of(context).requestFocus(FocusNode());
354 +
355 + if (_formKey.currentState.validate()) {
356 + await showDialog(
357 + context: context,
358 + builder: (dialogContext) {
359 + return AlertDialog(
360 + title: Text(
361 + S.of(context).send_creating_transaction),
362 + content: Text(S.of(context).confirm_sending),
363 + actions: <Widget>[
364 + FlatButton(
365 + child: Text(S.of(context).send),
366 + onPressed: () async {
367 + Navigator.of(dialogContext)
368 + .popAndPushNamed(
369 + Routes.auth,
370 + arguments:
371 + (isAuthenticatedSuccessfully,
372 + auth) {
373 + if (!isAuthenticatedSuccessfully) {
374 + return;
375 + }
376 +
377 + Navigator.of(auth.context).pop();
378 +
379 + sendStore.createTransaction(
380 + address: _addressController.text,
381 + paymentId:
382 + _paymentIdController.text);
383 + });
384 + }),
385 + FlatButton(
386 + child: Text(S.of(context).cancel),
387 + onPressed: () =>
388 + Navigator.of(context).pop())
389 + ],
390 + );
391 + });
392 + }
393 + }
394 + : null,
395 + text: S.of(context).send,
396 + color: Theme.of(context).accentTextTheme.button.backgroundColor,
397 + borderColor:
398 + Theme.of(context).accentTextTheme.button.decorationColor,
399 + isLoading: sendStore.state is CreatingTransaction ||
400 + sendStore.state is TransactionCommitted);
401 + }));
402 + }
403 +
404 + void _setEffects(BuildContext context) {
405 + if (_effectsInstalled) {
406 + return;
407 + }
408 +
409 + final sendStore = Provider.of<SendStore>(context);
410 +
411 + reaction((_) => sendStore.fiatAmount, (amount) {
412 + if (amount != _fiatAmountController.text) {
413 + _fiatAmountController.text = amount;
414 + }
415 + });
416 +
417 + reaction((_) => sendStore.cryptoAmount, (amount) {
418 + if (amount != _cryptoAmountController.text) {
419 + _cryptoAmountController.text = amount;
420 + }
421 + });
422 +
423 + _fiatAmountController.addListener(() {
424 + final fiatAmount = _fiatAmountController.text;
425 +
426 + if (sendStore.fiatAmount != fiatAmount) {
427 + sendStore.changeFiatAmount(fiatAmount);
428 + }
429 + });
430 +
431 + _cryptoAmountController.addListener(() {
432 + final cryptoAmount = _cryptoAmountController.text;
433 +
434 + if (sendStore.cryptoAmount != cryptoAmount) {
435 + sendStore.changeCryptoAmount(cryptoAmount);
436 + }
437 + });
438 +
439 + reaction((_) => sendStore.state, (state) {
440 + if (state is SendingFailed) {
441 + WidgetsBinding.instance.addPostFrameCallback((_) {
442 + showDialog(
443 + context: context,
444 + builder: (BuildContext context) {
445 + return AlertDialog(
446 + title: Text(S.of(context).error),
447 + content: Text(state.error),
448 + actions: <Widget>[
449 + FlatButton(
450 + child: Text(S.of(context).ok),
451 + onPressed: () => Navigator.of(context).pop())
452 + ],
453 + );
454 + });
455 + });
456 + }
457 +
458 + if (state is TransactionCreatedSuccessfully) {
459 + WidgetsBinding.instance.addPostFrameCallback((_) {
460 + showDialog(
461 + context: context,
462 + builder: (BuildContext context) {
463 + return AlertDialog(
464 + title: Text(S.of(context).sending),
465 + content: Text(S.of(context).transaction_sent),
466 + actions: <Widget>[
467 + FlatButton(
468 + child: Text(S.of(context).ok),
469 + onPressed: () {
470 + _addressController.text = '';
471 + _cryptoAmountController.text = '';
472 + Navigator.of(context)..pop()..pop();
473 + })
474 + ],
475 + );
476 + });
477 + });
478 + }
479 + });
480 +
481 + _effectsInstalled = true;
482 + }
483 +}
lib/src/screens/settings/attributes.dart new
+1
@@ -0,0 +1 @@
1 +enum Attributes {arrow, header, link, switcher, widget, rawWidget}
\ No newline at end of file
lib/src/screens/settings/change_language.dart new
+90
@@ -0,0 +1,90 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter/cupertino.dart';
3 +import 'package:provider/provider.dart';
4 +import 'package:cake_wallet/generated/i18n.dart';
5 +import 'package:cake_wallet/src/domain/common/language.dart';
6 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
7 +import 'package:cake_wallet/src/screens/base_page.dart';
8 +
9 +const Map<String, String> _languages = {
10 + 'en': 'English',
11 + 'ru': 'Русский (Russian)',
12 + 'es': 'Español (Spanish)',
13 + 'ja': '日本 (Japanese)',
14 + 'ko': '한국어 (Korean)',
15 + 'hi': 'हिंदी (Hindi)',
16 + 'de': 'Deutsch (German)',
17 + 'zh': '中文 (Chinese)',
18 + 'pt': 'Português (Portuguese)',
19 + 'pl': 'Polski (Polish)',
20 + 'nl': 'Nederlands (Dutch)'
21 +};
22 +
23 +class ChangeLanguage extends BasePage {
24 + get title => S.current.settings_change_language;
25 +
26 + @override
27 + Widget body(BuildContext context) {
28 + final settingsStore = Provider.of<SettingsStore>(context);
29 + final currentLanguage = Provider.of<Language>(context);
30 +
31 + return Container(
32 + padding: EdgeInsets.only(top: 10.0, bottom: 10.0),
33 + child: ListView.builder(
34 + itemCount: _languages.values.length,
35 + itemBuilder: (BuildContext context, int index) {
36 + final isCurrent = settingsStore.languageCode == null
37 + ? false
38 + : _languages.keys.elementAt(index) ==
39 + settingsStore.languageCode;
40 +
41 + return Container(
42 + margin: EdgeInsets.only(top: 10.0, bottom: 10.0),
43 + color: Theme.of(context).accentTextTheme.subhead.backgroundColor,
44 + child: ListTile(
45 + title: Text(
46 + _languages.values.elementAt(index),
47 + style: TextStyle(
48 + fontSize: 16.0,
49 + color: Theme.of(context).primaryTextTheme.title.color),
50 + ),
51 + onTap: () async {
52 + if (!isCurrent) {
53 + await showDialog(
54 + context: context,
55 + builder: (BuildContext context) {
56 + return AlertDialog(
57 + title: Text(
58 + S.of(context).change_language,
59 + textAlign: TextAlign.center,
60 + ),
61 + content: Text(
62 + S.of(context).change_language_to(
63 + _languages.values.elementAt(index)),
64 + textAlign: TextAlign.center,
65 + ),
66 + actions: <Widget>[
67 + FlatButton(
68 + onPressed: () => Navigator.of(context).pop(),
69 + child: Text(S.of(context).cancel)),
70 + FlatButton(
71 + onPressed: () {
72 + settingsStore.saveLanguageCode(
73 + languageCode:
74 + _languages.keys.elementAt(index));
75 + currentLanguage.setCurrentLanguage(
76 + _languages.keys.elementAt(index));
77 + Navigator.of(context).pop();
78 + },
79 + child: Text(S.of(context).change)),
80 + ],
81 + );
82 + });
83 + }
84 + },
85 + ),
86 + );
87 + },
88 + ));
89 + }
90 +}
lib/src/screens/settings/enter_pin_code.dart new
+245
@@ -0,0 +1,245 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter/cupertino.dart';
3 +import 'package:cake_wallet/palette.dart';
4 +import 'package:flutter/foundation.dart';
5 +import 'package:provider/provider.dart';
6 +import 'package:cake_wallet/theme_changer.dart';
7 +import 'package:cake_wallet/themes.dart';
8 +import 'package:cake_wallet/generated/i18n.dart';
9 +
10 +class EnterPinCode extends StatefulWidget{
11 +
12 + final int currentPinLength;
13 + final List<int> currentPin;
14 +
15 + const EnterPinCode(this.currentPinLength, this.currentPin);
16 +
17 + @override
18 + createState() => EnterPinCodeState(currentPinLength, currentPin);
19 +
20 +}
21 +
22 +class EnterPinCodeState extends State<EnterPinCode>{
23 + GlobalKey _gridViewKey = GlobalKey();
24 +
25 + final _closeButtonImage = Image.asset('assets/images/close_button.png');
26 + final _closeButtonImageDarkTheme = Image.asset('assets/images/close_button_dark_theme.png');
27 + static final deleteIconImage = Image.asset('assets/images/delete_icon.png');
28 + final int pinLength;
29 + final List<int> currentPin;
30 + List<int> pin;
31 + double _aspectRatio = 0;
32 +
33 + EnterPinCodeState(this.pinLength, this.currentPin);
34 +
35 + _getCurrentAspectRatio(){
36 + final RenderBox renderBox = _gridViewKey.currentContext.findRenderObject();
37 +
38 + double cellWidth = renderBox.size.width/3;
39 + double cellHeight = renderBox.size.height/4;
40 + if (cellWidth > 0 && cellHeight > 0) _aspectRatio = cellWidth/cellHeight;
41 + setState(() {
42 + });
43 + }
44 +
45 + @override
46 + void initState() {
47 + super.initState();
48 + pin = List<int>.filled(pinLength, null);
49 + WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
50 + }
51 +
52 + _afterLayout(_) {
53 + _getCurrentAspectRatio();
54 + }
55 +
56 + @override
57 + Widget build(BuildContext context) {
58 +
59 + ThemeChanger _themeChanger = Provider.of<ThemeChanger>(context);
60 + bool _isDarkTheme;
61 +
62 + if (_themeChanger.getTheme() == Themes.darkTheme) _isDarkTheme = true;
63 + else _isDarkTheme = false;
64 +
65 + return Scaffold(
66 + backgroundColor: Theme.of(context).backgroundColor,
67 + appBar: CupertinoNavigationBar(
68 + leading: ButtonTheme(
69 + minWidth: double.minPositive,
70 + child: FlatButton(
71 + onPressed: (){ Navigator.pop(context, false); },
72 + child: _isDarkTheme ? _closeButtonImageDarkTheme : _closeButtonImage
73 + ),
74 + ),
75 + backgroundColor: Theme.of(context).backgroundColor,
76 + border: null,
77 + ),
78 + body: SafeArea(
79 + child: Container(
80 + padding: EdgeInsets.only(left: 40.0, right: 40.0, bottom: 40.0),
81 + child: Column(
82 + children: <Widget>[
83 + Spacer(flex: 2),
84 + Text(S.of(context).enter_your_pin,
85 + style: TextStyle(
86 + fontSize: 24,
87 + color: Palette.wildDarkBlue
88 + )
89 + ),
90 + Spacer(flex: 3),
91 + Container(
92 + width: 180,
93 + child: Row(
94 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
95 + children: List.generate(pinLength, (index) {
96 + const size = 10.0;
97 + final isFilled = pin[index] != null;
98 +
99 + return Container(
100 + width: size,
101 + height: size,
102 + decoration: BoxDecoration(
103 + shape: BoxShape.circle,
104 + color: isFilled ? Palette.deepPurple : Colors.transparent,
105 + border: Border.all(color: Palette.wildDarkBlue),
106 + ));
107 + }),
108 + ),
109 + ),
110 + Spacer(flex: 3),
111 + Flexible(
112 + flex: 24,
113 + child: Container(
114 + key: _gridViewKey,
115 + child: _aspectRatio > 0 ? GridView.count(
116 + crossAxisCount: 3,
117 + childAspectRatio: _aspectRatio,
118 + physics: const NeverScrollableScrollPhysics(),
119 + children: List.generate(12, (index) {
120 +
121 + if (index == 9) {
122 + return Container(
123 + margin: EdgeInsets.all(5.0),
124 + decoration: BoxDecoration(
125 + shape: BoxShape.circle,
126 + color: _isDarkTheme ? PaletteDark.darkThemePinButton
127 + : Palette.darkGrey,
128 + ),
129 + );
130 + } else if (index == 10) {
131 + index = 0;
132 + } else if (index == 11) {
133 + return Container(
134 + margin: EdgeInsets.all(5.0),
135 + child: FlatButton(
136 + onPressed: () { _pop(); },
137 + color: _isDarkTheme ? PaletteDark.darkThemePinButton
138 + : Palette.darkGrey,
139 + shape: CircleBorder(),
140 + child: deleteIconImage,
141 + ),
142 + );
143 + } else {
144 + index++;
145 + }
146 +
147 + return Container(
148 + margin: EdgeInsets.all(5.0),
149 + child: FlatButton(
150 + onPressed: () { _push(index); },
151 + color: _isDarkTheme ? PaletteDark.darkThemePinDigitButton
152 + : Palette.creamyGrey,
153 + shape: CircleBorder(),
154 + child: Text(
155 + '$index',
156 + style: TextStyle(
157 + fontSize: 23.0,
158 + color: Palette.blueGrey
159 + )
160 + ),
161 + ),
162 + );
163 + }),
164 + ) : null
165 + )
166 + )
167 + ],
168 + ),
169 + )
170 + ),
171 + );
172 + }
173 +
174 + _showIncorrectPinDialog(BuildContext context) async {
175 + await showDialog(
176 + context: context,
177 + builder: (BuildContext context) {
178 + return AlertDialog(
179 + content: Text(S.of(context).pin_is_incorrect),
180 + actions: <Widget>[
181 + FlatButton(
182 + child: Text(S.of(context).ok),
183 + onPressed: () {
184 + Navigator.of(context).pop();
185 + },
186 + ),
187 + ],
188 + );
189 + }
190 + );
191 + }
192 +
193 + void _push(int num) {
194 + if (_pinLength() >= pinLength) {
195 + return;
196 + }
197 +
198 + for (var i = 0; i < pin.length; i++) {
199 + if (pin[i] == null) {
200 + setState(() => pin[i] = num);
201 + break;
202 + }
203 + }
204 +
205 + if (_pinLength() == pinLength) {
206 +
207 + if (listEquals<int>(pin, currentPin)){
208 +
209 + Navigator.pop(context, true);
210 +
211 + } else {
212 +
213 + Navigator.pop(context, false);
214 +
215 + _showIncorrectPinDialog(context);
216 +
217 + }
218 +
219 + }
220 + }
221 +
222 + void _pop() {
223 + if (_pinLength() == 0) {
224 + return;
225 + }
226 +
227 + for (var i = pin.length - 1; i >= 0; i--) {
228 + if (pin[i] != null) {
229 + setState(() => pin[i] = null);
230 + break;
231 + }
232 + }
233 + }
234 +
235 + int _pinLength() {
236 + return pin.fold(0, (v, e) {
237 + if (e != null) {
238 + return v + 1;
239 + }
240 +
241 + return v;
242 + });
243 + }
244 +
245 +}
\ No newline at end of file
lib/src/screens/settings/items/item_headers.dart new
+17
@@ -0,0 +1,17 @@
1 +class ItemHeaders {
2 + static const nodes = 'Nodes';
3 + static const currentNode = 'Current node';
4 + static const wallets = 'Wallets';
5 + static const displayBalanceAs = 'Display balance as';
6 + static const currency = 'Currency';
7 + static const feePriority = 'Fee priority';
8 + static const saveRecipientAddress = 'Save recipient address';
9 + static const personal = 'Personal';
10 + static const changePIN = 'Change PIN';
11 + static const changeLanguage = 'Change language';
12 + static const allowBiometricalAuthentication = 'Allow biometrical authentication';
13 + static const darkMode = 'Dark mode';
14 + static const support = 'Support';
15 + static const termsAndConditions = 'Terms and conditions';
16 + static const faq = 'FAQ';
17 +}
\ No newline at end of file
lib/src/screens/settings/items/settings_item.dart new
+20
@@ -0,0 +1,20 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:cake_wallet/src/screens/settings/attributes.dart';
3 +
4 +class SettingsItem {
5 + final VoidCallback onTaped;
6 + final String title;
7 + final String link;
8 + final Image image;
9 + final Widget widget;
10 + final Attributes attribute;
11 + final WidgetBuilder widgetBuilder;
12 +
13 + SettingsItem({this.onTaped,
14 + this.title,
15 + this.link,
16 + this.image,
17 + this.widget,
18 + this.attribute,
19 + this.widgetBuilder});
20 +}
\ No newline at end of file
lib/src/screens/settings/settings.dart new
+445
@@ -0,0 +1,445 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter/cupertino.dart';
3 +import 'package:cake_wallet/palette.dart';
4 +import 'package:url_launcher/url_launcher.dart';
5 +import 'package:flutter_mobx/flutter_mobx.dart';
6 +import 'package:provider/provider.dart';
7 +import 'package:cake_wallet/routes.dart';
8 +import 'package:cake_wallet/generated/i18n.dart';
9 +import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
10 +import 'package:cake_wallet/src/domain/common/fiat_currency.dart';
11 +import 'package:cake_wallet/src/domain/common/transaction_priority.dart';
12 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
13 +import 'package:cake_wallet/src/stores/action_list/action_list_display_mode.dart';
14 +import 'package:cake_wallet/src/screens/base_page.dart';
15 +import 'package:cake_wallet/src/screens/settings/attributes.dart';
16 +import 'package:cake_wallet/src/screens/disclaimer/disclaimer_page.dart';
17 +import 'package:cake_wallet/src/screens/settings/items/settings_item.dart';
18 +import 'package:cake_wallet/src/screens/settings/items/item_headers.dart';
19 +// Settings widgets
20 +import 'package:cake_wallet/src/screens/settings/widgets/settings_arrow_list_row.dart';
21 +import 'package:cake_wallet/src/screens/settings/widgets/settings_header_list_row.dart';
22 +import 'package:cake_wallet/src/screens/settings/widgets/settings_link_list_row.dart';
23 +import 'package:cake_wallet/src/screens/settings/widgets/settings_switch_list_row.dart';
24 +import 'package:cake_wallet/src/screens/settings/widgets/settings_text_list_row.dart';
25 +import 'package:cake_wallet/src/screens/settings/widgets/settings_raw_widget_list_row.dart';
26 +
27 +class SettingsPage extends BasePage {
28 + String get title => S.current.settings_title;
29 + bool get isModalBackButton => true;
30 + Color get backgroundColor => Palette.lightGrey2;
31 +
32 + @override
33 + Widget body(BuildContext context) {
34 + return SettingsForm();
35 + }
36 +}
37 +
38 +class SettingsForm extends StatefulWidget {
39 + @override
40 + createState() => SettingsFormState();
41 +}
42 +
43 +class SettingsFormState extends State<SettingsForm> {
44 + final _telegramImage = Image.asset('assets/images/Telegram.png');
45 + final _twitterImage = Image.asset('assets/images/Twitter.png');
46 + final _changeNowImage = Image.asset('assets/images/change_now.png');
47 + final _xmrBtcImage = Image.asset('assets/images/xmr_btc.png');
48 +
49 + final _emailUrl = 'mailto:support@cakewallet.io';
50 + final _telegramUrl = 'https:t.me/cake_wallet';
51 + final _twitterUrl = 'https:twitter.com/CakewalletXMR';
52 + final _changeNowUrl = 'mailto:support@changenow.io';
53 + final _xmrToUrl = 'mailto:support@xmr.to';
54 +
55 + List<SettingsItem> _items = List<SettingsItem>();
56 +
57 + _launchUrl(String url) async {
58 + if (await canLaunch(url)) await launch(url);
59 + }
60 +
61 + _setSettingsList() {
62 + final settingsStore = Provider.of<SettingsStore>(context);
63 +
64 + settingsStore.setItemHeaders();
65 +
66 + _items.addAll([
67 + SettingsItem(title: ItemHeaders.nodes, attribute: Attributes.header),
68 + SettingsItem(
69 + onTaped: () => Navigator.of(context).pushNamed(Routes.nodeList),
70 + title: ItemHeaders.currentNode,
71 + widget: Observer(
72 + builder: (_) => Text(
73 + settingsStore.node == null ? '' : settingsStore.node.uri,
74 + style: TextStyle(
75 + fontSize: 16.0,
76 + color:
77 + Theme.of(context).primaryTextTheme.subtitle.color),
78 + )),
79 + attribute: Attributes.widget),
80 + SettingsItem(title: ItemHeaders.wallets, attribute: Attributes.header),
81 + SettingsItem(
82 + onTaped: () => _setBalance(context),
83 + title: ItemHeaders.displayBalanceAs,
84 + widget: Observer(
85 + builder: (_) => Text(
86 + settingsStore.balanceDisplayMode.toString(),
87 + style: TextStyle(
88 + fontSize: 16.0,
89 + color:
90 + Theme.of(context).primaryTextTheme.subtitle.color),
91 + )),
92 + attribute: Attributes.widget),
93 + SettingsItem(
94 + onTaped: () => _setCurrency(context),
95 + title: ItemHeaders.currency,
96 + widget: Observer(
97 + builder: (_) => Text(
98 + settingsStore.fiatCurrency.toString(),
99 + style: TextStyle(
100 + fontSize: 16.0,
101 + color:
102 + Theme.of(context).primaryTextTheme.subtitle.color),
103 + )),
104 + attribute: Attributes.widget),
105 + SettingsItem(
106 + onTaped: () => _setTransactionPriority(context),
107 + title: ItemHeaders.feePriority,
108 + widget: Observer(
109 + builder: (_) => Text(
110 + settingsStore.transactionPriority.toString(),
111 + style: TextStyle(
112 + fontSize: 16.0,
113 + color:
114 + Theme.of(context).primaryTextTheme.subtitle.color),
115 + )),
116 + attribute: Attributes.widget),
117 + SettingsItem(
118 + title: ItemHeaders.saveRecipientAddress,
119 + attribute: Attributes.switcher),
120 + SettingsItem(title: ItemHeaders.personal, attribute: Attributes.header),
121 + SettingsItem(
122 + onTaped: () {
123 + Navigator.of(context).pushNamed(Routes.auth,
124 + arguments: (isAuthenticatedSuccessfully, auth) =>
125 + isAuthenticatedSuccessfully
126 + ? Navigator.of(context).popAndPushNamed(Routes.setupPin,
127 + arguments: (setupPinContext, _) =>
128 + Navigator.of(context).pop())
129 + : null);
130 + },
131 + title: ItemHeaders.changePIN,
132 + attribute: Attributes.arrow),
133 + SettingsItem(
134 + onTaped: () => Navigator.pushNamed(context, Routes.changeLanguage),
135 + title: ItemHeaders.changeLanguage,
136 + attribute: Attributes.arrow),
137 + SettingsItem(
138 + title: ItemHeaders.allowBiometricalAuthentication,
139 + attribute: Attributes.switcher),
140 + SettingsItem(title: ItemHeaders.darkMode, attribute: Attributes.switcher),
141 + SettingsItem(
142 + widgetBuilder: (context) {
143 + return PopupMenuButton<ActionListDisplayMode>(
144 + itemBuilder: (context) => [
145 + PopupMenuItem(
146 + value: ActionListDisplayMode.transactions,
147 + child: Observer(
148 + builder: (_) => Row(
149 + mainAxisAlignment:
150 + MainAxisAlignment.spaceBetween,
151 + children: [
152 + Text(S
153 + .of(context)
154 + .settings_transactions),
155 + Checkbox(
156 + value: settingsStore
157 + .actionlistDisplayMode
158 + .contains(ActionListDisplayMode
159 + .transactions),
160 + onChanged: (value) => settingsStore
161 + .toggleTransactionsDisplay(),
162 + )
163 + ]))),
164 + PopupMenuItem(
165 + value: ActionListDisplayMode.trades,
166 + child: Observer(
167 + builder: (_) => Row(
168 + mainAxisAlignment:
169 + MainAxisAlignment.spaceBetween,
170 + children: [
171 + Text(S.of(context).settings_trades),
172 + Checkbox(
173 + value: settingsStore
174 + .actionlistDisplayMode
175 + .contains(
176 + ActionListDisplayMode.trades),
177 + onChanged: (value) => settingsStore
178 + .toggleTradesDisplay(),
179 + )
180 + ])))
181 + ],
182 + child: Container(
183 + height: 56,
184 + padding: EdgeInsets.only(left: 20, right: 20),
185 + child: Row(
186 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
187 + children: [
188 + Text(S.of(context).settings_display_on_dashboard_list,
189 + style: TextStyle(
190 + fontSize: 16,
191 + color: Theme.of(context)
192 + .primaryTextTheme
193 + .title
194 + .color)),
195 + Observer(builder: (_) {
196 + var title = '';
197 +
198 + if (settingsStore.actionlistDisplayMode.length ==
199 + ActionListDisplayMode.values.length) {
200 + title = S.of(context).settings_all;
201 + }
202 +
203 + if (title.isEmpty &&
204 + settingsStore.actionlistDisplayMode
205 + .contains(ActionListDisplayMode.trades)) {
206 + title = S.of(context).settings_only_trades;
207 + }
208 +
209 + if (title.isEmpty &&
210 + settingsStore.actionlistDisplayMode.contains(
211 + ActionListDisplayMode.transactions)) {
212 + title = S.of(context).settings_only_transactions;
213 + }
214 +
215 + if (title.isEmpty) {
216 + title = S.of(context).settings_none;
217 + }
218 +
219 + return Text(title,
220 + style: TextStyle(
221 + fontSize: 16.0,
222 + color: Theme.of(context)
223 + .primaryTextTheme
224 + .subtitle
225 + .color));
226 + })
227 + ]),
228 + ));
229 + },
230 + attribute: Attributes.rawWidget),
231 + SettingsItem(title: ItemHeaders.support, attribute: Attributes.header),
232 + SettingsItem(
233 + onTaped: () => _launchUrl(_emailUrl),
234 + title: 'Email',
235 + link: 'support@cakewallet.io',
236 + image: null,
237 + attribute: Attributes.link),
238 + SettingsItem(
239 + onTaped: () => _launchUrl(_telegramUrl),
240 + title: 'Telegram',
241 + link: 't.me/cake_wallet',
242 + image: _telegramImage,
243 + attribute: Attributes.link),
244 + SettingsItem(
245 + onTaped: () => _launchUrl(_twitterUrl),
246 + title: 'Twitter',
247 + link: 'twitter.com/CakewalletXMR',
248 + image: _twitterImage,
249 + attribute: Attributes.link),
250 + SettingsItem(
251 + onTaped: () => _launchUrl(_changeNowUrl),
252 + title: 'ChangeNow',
253 + link: 'support@changenow.io',
254 + image: _changeNowImage,
255 + attribute: Attributes.link),
256 + SettingsItem(
257 + onTaped: () => _launchUrl(_xmrToUrl),
258 + title: 'XMR.to',
259 + link: 'support@xmr.to',
260 + image: _xmrBtcImage,
261 + attribute: Attributes.link),
262 + SettingsItem(
263 + onTaped: () {
264 + Navigator.push(
265 + context,
266 + CupertinoPageRoute(
267 + builder: (BuildContext context) => DisclaimerPage()));
268 + },
269 + title: ItemHeaders.termsAndConditions,
270 + attribute: Attributes.arrow),
271 + SettingsItem(
272 + onTaped: () => Navigator.pushNamed(context, Routes.faq),
273 + title: ItemHeaders.faq,
274 + attribute: Attributes.arrow)
275 + ]);
276 + setState(() {});
277 + }
278 +
279 + _afterLayout(_) => _setSettingsList();
280 +
281 + @override
282 + void initState() {
283 + super.initState();
284 + WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
285 + }
286 +
287 + Widget _getWidget(SettingsItem item) {
288 + switch (item.attribute) {
289 + case Attributes.arrow:
290 + return SettingsArrowListRow(
291 + onTaped: item.onTaped,
292 + title: item.title,
293 + );
294 + case Attributes.header:
295 + return SettingsHeaderListRow(
296 + title: item.title,
297 + );
298 + case Attributes.link:
299 + return SettingsLinktListRow(
300 + onTaped: item.onTaped,
301 + title: item.title,
302 + link: item.link,
303 + image: item.image,
304 + );
305 + case Attributes.switcher:
306 + return SettingsSwitchListRow(
307 + title: item.title,
308 + );
309 + case Attributes.widget:
310 + return SettingsTextListRow(
311 + onTaped: item.onTaped,
312 + title: item.title,
313 + widget: item.widget,
314 + );
315 + case Attributes.rawWidget:
316 + return SettingRawWidgetListRow(widgetBuilder: item.widgetBuilder);
317 + default:
318 + return Offstage();
319 + }
320 + }
321 +
322 + @override
323 + Widget build(BuildContext context) {
324 + final settingsStore = Provider.of<SettingsStore>(context);
325 + settingsStore.setItemHeaders();
326 +
327 + return SingleChildScrollView(
328 + child: Column(
329 + children: <Widget>[
330 + ListView.builder(
331 + shrinkWrap: true,
332 + physics: NeverScrollableScrollPhysics(),
333 + itemCount: _items.length,
334 + itemBuilder: (context, index) {
335 + final item = _items[index];
336 + bool _isDrawDivider = true;
337 +
338 + if (item.attribute == Attributes.header)
339 + _isDrawDivider = false;
340 + else if (index < _items.length - 1) {
341 + if (_items[index + 1].attribute == Attributes.header)
342 + _isDrawDivider = false;
343 + }
344 +
345 + return Column(
346 + children: <Widget>[
347 + _getWidget(item),
348 + _isDrawDivider
349 + ? Container(
350 + color: Theme.of(context)
351 + .accentTextTheme
352 + .headline
353 + .backgroundColor,
354 + padding: EdgeInsets.only(
355 + left: 20.0,
356 + right: 20.0,
357 + ),
358 + child: Divider(
359 + color: Theme.of(context).dividerColor,
360 + height: 1.0,
361 + ),
362 + )
363 + : Offstage()
364 + ],
365 + );
366 + }),
367 + Container(
368 + height: 20.0,
369 + color: Theme.of(context).accentTextTheme.headline.backgroundColor,
370 + )
371 + ],
372 + ));
373 + }
374 +
375 + Future<T> _presentPicker<T extends Object>(
376 + BuildContext context, List<T> list) async {
377 + T _value = list[0];
378 +
379 + return await showDialog(
380 + context: context,
381 + builder: (BuildContext context) {
382 + return AlertDialog(
383 + title: Text(S.of(context).please_select),
384 + backgroundColor: Theme.of(context).backgroundColor,
385 + content: Container(
386 + height: 150.0,
387 + child: CupertinoPicker(
388 + backgroundColor: Theme.of(context).backgroundColor,
389 + itemExtent: 45.0,
390 + onSelectedItemChanged: (int index) => _value = list[index],
391 + children: List.generate(
392 + list.length,
393 + (index) => Center(
394 + child: Text(
395 + list[index].toString(),
396 + style: TextStyle(
397 + color: Theme.of(context)
398 + .primaryTextTheme
399 + .caption
400 + .color),
401 + ),
402 + ))),
403 + ),
404 + actions: <Widget>[
405 + FlatButton(
406 + onPressed: () => Navigator.of(context).pop(),
407 + child: Text(S.of(context).cancel)),
408 + FlatButton(
409 + onPressed: () => Navigator.of(context).pop(_value),
410 + child: Text(S.of(context).ok))
411 + ],
412 + );
413 + });
414 + }
415 +
416 + void _setBalance(BuildContext context) async {
417 + final settingsStore = Provider.of<SettingsStore>(context);
418 + final selectedDisplayMode =
419 + await _presentPicker(context, BalanceDisplayMode.all);
420 +
421 + if (selectedDisplayMode != null) {
422 + settingsStore.setCurrentBalanceDisplayMode(
423 + balanceDisplayMode: selectedDisplayMode);
424 + }
425 + }
426 +
427 + void _setCurrency(BuildContext context) async {
428 + final settingsStore = Provider.of<SettingsStore>(context);
429 + final selectedCurrency = await _presentPicker(context, FiatCurrency.all);
430 +
431 + if (selectedCurrency != null) {
432 + settingsStore.setCurrentFiatCurrency(currency: selectedCurrency);
433 + }
434 + }
435 +
436 + void _setTransactionPriority(BuildContext context) async {
437 + final settingsStore = Provider.of<SettingsStore>(context);
438 + final selectedPriority =
439 + await _presentPicker(context, TransactionPriority.all);
440 +
441 + if (selectedPriority != null) {
442 + settingsStore.setCurrentTransactionPriority(priority: selectedPriority);
443 + }
444 + }
445 +}
lib/src/screens/settings/widgets/settings_arrow_list_row.dart new
+32
@@ -0,0 +1,32 @@
1 +import 'package:provider/provider.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:flutter_mobx/flutter_mobx.dart';
4 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
5 +
6 +class SettingsArrowListRow extends StatelessWidget {
7 + final VoidCallback onTaped;
8 + final String title;
9 + final _cakeArrowImage = Image.asset('assets/images/cake_arrow.png');
10 +
11 + SettingsArrowListRow({@required this.onTaped, this.title});
12 +
13 + @override
14 + Widget build(BuildContext context) {
15 + final settingsStore = Provider.of<SettingsStore>(context);
16 +
17 + return Container(
18 + color: Theme.of(context).accentTextTheme.headline.backgroundColor,
19 + child: ListTile(
20 + contentPadding: EdgeInsets.only(left: 20.0, right: 20.0),
21 + title: Observer(
22 + builder: (_) => Text(
23 + settingsStore.itemHeaders[title],
24 + style: TextStyle(
25 + fontSize: 16.0,
26 + color: Theme.of(context).primaryTextTheme.title.color),
27 + )),
28 + trailing: _cakeArrowImage,
29 + onTap: onTaped),
30 + );
31 + }
32 +}
lib/src/screens/settings/widgets/settings_header_list_row.dart new
+42
@@ -0,0 +1,42 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter_mobx/flutter_mobx.dart';
3 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
4 +import 'package:cake_wallet/palette.dart';
5 +import 'package:provider/provider.dart';
6 +
7 +class SettingsHeaderListRow extends StatelessWidget {
8 + final String title;
9 +
10 + SettingsHeaderListRow({this.title});
11 +
12 + @override
13 + Widget build(BuildContext context) {
14 + final settingsStore = Provider.of<SettingsStore>(context);
15 +
16 + return Column(
17 + children: <Widget>[
18 + SizedBox(
19 + height: 28.0,
20 + ),
21 + Container(
22 + padding: EdgeInsets.only(left: 20.0),
23 + child: Row(
24 + mainAxisAlignment: MainAxisAlignment.start,
25 + children: <Widget>[
26 + Observer(
27 + builder: (_) => Text(
28 + settingsStore.itemHeaders[title],
29 + style: TextStyle(
30 + fontSize: 15.0, color: Palette.wildDarkBlue),
31 + ))
32 + ],
33 + ),
34 + ),
35 + SizedBox(
36 + height: 14.0,
37 + ),
38 + ],
39 + );
40 + }
41 +
42 +}
\ No newline at end of file
lib/src/screens/settings/widgets/settings_link_list_row.dart new
+47
@@ -0,0 +1,47 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:cake_wallet/palette.dart';
3 +
4 +class SettingsLinktListRow extends StatelessWidget {
5 + final VoidCallback onTaped;
6 + final String title;
7 + final String link;
8 + final Image image;
9 +
10 + SettingsLinktListRow({@required this.onTaped, this.title, this.link, this.image});
11 +
12 + @override
13 + Widget build(BuildContext context) {
14 +
15 + return Container(
16 + color: Theme.of(context).accentTextTheme.headline.backgroundColor,
17 + child: ListTile(
18 + contentPadding: EdgeInsets.only(left: 20.0, right: 20.0),
19 + title: Row(
20 + mainAxisAlignment: MainAxisAlignment.start,
21 + mainAxisSize: MainAxisSize.min,
22 + children: <Widget>[
23 + image != null ? image : Offstage(),
24 + Container(
25 + padding: image != null ? EdgeInsets.only(left: 10) : null,
26 + child: Text(
27 + title,
28 + style: TextStyle(
29 + fontSize: 15.0,
30 + fontWeight: FontWeight.w500,
31 + color: Theme.of(context).primaryTextTheme.title.color
32 + ),
33 + ),
34 + )
35 + ],
36 + ),
37 + trailing: Text(
38 + link,
39 + style:
40 + TextStyle(fontSize: 14.0, color: Palette.cakeGreen),
41 + ),
42 + onTap: onTaped,
43 + ),
44 + );
45 + }
46 +
47 +}
\ No newline at end of file
lib/src/screens/settings/widgets/settings_raw_widget_list_row.dart new
+16
@@ -0,0 +1,16 @@
1 +import 'package:flutter/material.dart';
2 +
3 +class SettingRawWidgetListRow extends StatelessWidget {
4 + final WidgetBuilder widgetBuilder;
5 +
6 + SettingRawWidgetListRow({@required this.widgetBuilder});
7 +
8 + @override
9 + Widget build(BuildContext context) {
10 +
11 + return Container(
12 + color: Theme.of(context).accentTextTheme.headline.backgroundColor,
13 + child: widgetBuilder(context) ?? Container(),
14 + );
15 + }
16 +}
lib/src/screens/settings/widgets/settings_switch_list_row.dart new
+76
@@ -0,0 +1,76 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:provider/provider.dart';
3 +import 'package:flutter_mobx/flutter_mobx.dart';
4 +import 'package:cake_wallet/generated/i18n.dart';
5 +import 'package:cake_wallet/theme_changer.dart';
6 +import 'package:cake_wallet/themes.dart';
7 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
8 +import 'package:cake_wallet/src/widgets/standart_switch.dart';
9 +
10 +class SettingsSwitchListRow extends StatelessWidget {
11 + final String title;
12 +
13 + SettingsSwitchListRow({@required this.title});
14 +
15 + Widget _getSwitch(BuildContext context) {
16 + final settingsStore = Provider.of<SettingsStore>(context);
17 + ThemeChanger _themeChanger = Provider.of<ThemeChanger>(context);
18 +
19 + if (settingsStore.itemHeaders[title] ==
20 + S.of(context).settings_save_recipient_address) {
21 + return Observer(
22 + builder: (_) => StandartSwitch(
23 + value: settingsStore.shouldSaveRecipientAddress,
24 + onTaped: () {
25 + bool _currentValue = !settingsStore.shouldSaveRecipientAddress;
26 + settingsStore.setSaveRecipientAddress(
27 + shouldSaveRecipientAddress: _currentValue);
28 + }));
29 + }
30 +
31 + if (settingsStore.itemHeaders[title] ==
32 + S.of(context).settings_allow_biometrical_authentication) {
33 + return Observer(
34 + builder: (_) => StandartSwitch(
35 + value: settingsStore.allowBiometricalAuthentication,
36 + onTaped: () {
37 + bool _currentValue =
38 + !settingsStore.allowBiometricalAuthentication;
39 + settingsStore.setAllowBiometricalAuthentication(
40 + allowBiometricalAuthentication: _currentValue);
41 + }));
42 + }
43 +
44 + if (settingsStore.itemHeaders[title] == S.of(context).settings_dark_mode) {
45 + return Observer(
46 + builder: (_) => StandartSwitch(
47 + value: settingsStore.isDarkTheme,
48 + onTaped: () {
49 + bool _currentValue = !settingsStore.isDarkTheme;
50 + settingsStore.saveDarkTheme(isDarkTheme: _currentValue);
51 + _themeChanger.setTheme(
52 + _currentValue ? Themes.darkTheme : Themes.lightTheme);
53 + }));
54 + }
55 +
56 + return null;
57 + }
58 +
59 + @override
60 + Widget build(BuildContext context) {
61 + final settingsStore = Provider.of<SettingsStore>(context);
62 +
63 + return Container(
64 + color: Theme.of(context).accentTextTheme.headline.backgroundColor,
65 + child: ListTile(
66 + contentPadding: EdgeInsets.only(left: 20.0, right: 20.0),
67 + title: Observer(
68 + builder: (_) => Text(settingsStore.itemHeaders[title],
69 + style: TextStyle(
70 + fontSize: 16.0,
71 + color: Theme.of(context).primaryTextTheme.title.color)),
72 + ),
73 + trailing: _getSwitch(context)),
74 + );
75 + }
76 +}
lib/src/screens/settings/widgets/settings_text_list_row.dart new
+33
@@ -0,0 +1,33 @@
1 +import 'package:provider/provider.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:flutter_mobx/flutter_mobx.dart';
4 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
5 +
6 +class SettingsTextListRow extends StatelessWidget {
7 + final VoidCallback onTaped;
8 + final String title;
9 + final Widget widget;
10 +
11 + SettingsTextListRow({@required this.onTaped, this.title, this.widget});
12 +
13 + @override
14 + Widget build(BuildContext context) {
15 + final settingsStore = Provider.of<SettingsStore>(context);
16 +
17 + return Container(
18 + color: Theme.of(context).accentTextTheme.headline.backgroundColor,
19 + child: ListTile(
20 + contentPadding: EdgeInsets.only(left: 20.0, right: 20.0),
21 + title: Observer(
22 + builder: (_) => Text(
23 + settingsStore.itemHeaders[title],
24 + style: TextStyle(
25 + fontSize: 16.0,
26 + color: Theme.of(context).primaryTextTheme.title.color),
27 + )),
28 + trailing: widget,
29 + onTap: onTaped,
30 + ),
31 + );
32 + }
33 +}
lib/src/screens/setup_pin_code/setup_pin_code.dart new
+113
@@ -0,0 +1,113 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:flutter/cupertino.dart';
4 +import 'package:provider/provider.dart';
5 +import 'package:cake_wallet/src/stores/user/user_store.dart';
6 +import 'package:cake_wallet/src/screens/pin_code/pin_code.dart';
7 +import 'package:cake_wallet/src/screens/base_page.dart';
8 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
9 +import 'package:cake_wallet/generated/i18n.dart';
10 +
11 +class SetupPinCodePage extends BasePage {
12 + final Function(BuildContext, String) onPinCodeSetup;
13 +
14 + @override
15 + String get title => S.current.setup_pin;
16 +
17 + SetupPinCodePage({this.onPinCodeSetup});
18 +
19 + @override
20 + Widget body(BuildContext context) =>
21 + SetupPinCodeForm(onPinCodeSetup: onPinCodeSetup, hasLengthSwitcher: true);
22 +}
23 +
24 +class SetupPinCodeForm extends PinCodeWidget {
25 + final Function(BuildContext, String) onPinCodeSetup;
26 + final bool hasLengthSwitcher;
27 +
28 + SetupPinCodeForm(
29 + {@required this.onPinCodeSetup, @required this.hasLengthSwitcher});
30 +
31 + @override
32 + _SetupPinCodeFormState createState() => _SetupPinCodeFormState();
33 +}
34 +
35 +class _SetupPinCodeFormState<WidgetType extends SetupPinCodeForm>
36 + extends PinCodeState<WidgetType> {
37 +
38 + bool isEnteredOriginalPin() => !(_originalPin.length == 0);
39 + Function(BuildContext) onPinCodeSetup;
40 + List<int> _originalPin = [];
41 + UserStore _userStore;
42 + SettingsStore _settingsStore;
43 +
44 + _SetupPinCodeFormState() {
45 + title = S.current.enter_your_pin;
46 + }
47 +
48 + @override
49 + void onPinCodeEntered(PinCodeState state) {
50 + if (!isEnteredOriginalPin()) {
51 + _originalPin = state.pin;
52 + state.title = S.current.enter_your_pin_again;
53 + state.clear();
54 + } else {
55 + if (listEquals<int>(state.pin, _originalPin)) {
56 + final String pin = state.pin.fold("", (ac, val) => ac + '$val');
57 + _userStore.set(password: pin);
58 + _settingsStore.setDefaultPinLength(pinLength: state.pinLength);
59 +
60 + showDialog(
61 + context: context,
62 + barrierDismissible: false,
63 + builder: (BuildContext context) {
64 + return AlertDialog(
65 + content: Text(S.of(context).setup_successful),
66 + actions: <Widget>[
67 + FlatButton(
68 + child: Text(S.of(context).ok),
69 + onPressed: () {
70 + Navigator.of(context).pop();
71 + widget.onPinCodeSetup(context, pin);
72 + reset();
73 + },
74 + ),
75 + ],
76 + );
77 + });
78 + } else {
79 + showDialog(
80 + context: context,
81 + builder: (BuildContext context) {
82 + return AlertDialog(
83 + content: Text(S.of(context).pin_is_incorrect),
84 + actions: <Widget>[
85 + FlatButton(
86 + child: Text(S.of(context).ok),
87 + onPressed: () {
88 + Navigator.of(context).pop();
89 + },
90 + ),
91 + ],
92 + );
93 + });
94 +
95 + reset();
96 + }
97 + }
98 + }
99 +
100 + void reset() {
101 + clear();
102 + setTitle(S.current.enter_your_pin);
103 + _originalPin = [];
104 + }
105 +
106 + @override
107 + Widget build(BuildContext context) {
108 + _userStore = Provider.of<UserStore>(context);
109 + _settingsStore = Provider.of<SettingsStore>(context);
110 +
111 + return body(context);
112 + }
113 +}
lib/src/screens/show_keys/show_keys_page.dart new
+68
@@ -0,0 +1,68 @@
1 +import 'package:provider/provider.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:flutter/cupertino.dart';
4 +import 'package:flutter/services.dart';
5 +import 'package:flutter_mobx/flutter_mobx.dart';
6 +import 'package:cake_wallet/palette.dart';
7 +import 'package:cake_wallet/generated/i18n.dart';
8 +import 'package:cake_wallet/src/stores/wallet/wallet_keys_store.dart';
9 +import 'package:cake_wallet/src/screens/base_page.dart';
10 +
11 +class ShowKeysPage extends BasePage {
12 + bool get isModalBackButton => true;
13 + String get title => S.current.wallet_keys;
14 +
15 + @override
16 + Widget body(BuildContext context) {
17 + final walletKeysStore = Provider.of<WalletKeysStore>(context);
18 +
19 + return Container(
20 + padding: EdgeInsets.only(top: 20.0, bottom: 20.0, left: 20, right: 20),
21 + child: Observer(
22 + builder: (_) {
23 + Map<String, String> keysMap = {
24 + S.of(context).view_key_public: walletKeysStore.publicViewKey,
25 + S.of(context).view_key_private: walletKeysStore.privateViewKey,
26 + S.of(context).spend_key_public: walletKeysStore.publicSpendKey,
27 + S.of(context).spend_key_private: walletKeysStore.privateSpendKey
28 + };
29 +
30 + return ListView.separated(
31 + separatorBuilder: (_, __) => Container(
32 + padding: EdgeInsets.only(left: 30.0, right: 20.0),
33 + child: Divider(
34 + color: Theme.of(context).dividerTheme.color,
35 + height: 1.0)),
36 + itemCount: keysMap.length,
37 + itemBuilder: (BuildContext context, int index) {
38 + final key = keysMap.keys.elementAt(index);
39 + final value = keysMap.values.elementAt(index);
40 +
41 + return ListTile(
42 + contentPadding: EdgeInsets.only(
43 + top: 10, bottom: 10, left: 30, right: 20),
44 + onTap: () {
45 + Clipboard.setData(ClipboardData(
46 + text: keysMap.values.elementAt(index)));
47 + Scaffold.of(context).showSnackBar(SnackBar(
48 + content: Text(
49 + S.of(context).copied_key_to_clipboard(key),
50 + textAlign: TextAlign.center,
51 + style: TextStyle(color: Colors.white),
52 + ),
53 + backgroundColor: Colors.green,
54 + duration: Duration(seconds: 1),
55 + ));
56 + },
57 + title: Text(key + ':', style: TextStyle(fontSize: 16.0)),
58 + subtitle: Container(
59 + padding: EdgeInsets.only(top: 5.0),
60 + child: Text(value,
61 + style: TextStyle(
62 + fontSize: 16.0, color: Palette.wildDarkBlue)),
63 + ));
64 + });
65 + },
66 + ));
67 + }
68 +}
lib/src/screens/splash/splash_page.dart new
+10
@@ -0,0 +1,10 @@
1 +import 'package:flutter/material.dart';
2 +
3 +class SplashPage extends StatelessWidget {
4 + @override
5 + Widget build(BuildContext context) {
6 + return Scaffold(
7 + body: Container()
8 + );
9 + }
10 +}
\ No newline at end of file
lib/src/screens/subaddress/new_subaddress_page.dart new
+100
@@ -0,0 +1,100 @@
1 +import 'package:mobx/mobx.dart';
2 +import 'package:provider/provider.dart';
3 +import 'package:flutter/cupertino.dart';
4 +import 'package:flutter/material.dart';
5 +import 'package:flutter_mobx/flutter_mobx.dart';
6 +import 'package:cake_wallet/generated/i18n.dart';
7 +import 'package:cake_wallet/src/stores/subaddress_creation/subaddress_creation_state.dart';
8 +import 'package:cake_wallet/src/stores/subaddress_creation/subaddress_creation_store.dart';
9 +import 'package:cake_wallet/src/widgets/primary_button.dart';
10 +import 'package:cake_wallet/src/screens/base_page.dart';
11 +import 'package:cake_wallet/palette.dart';
12 +
13 +class NewSubaddressPage extends BasePage {
14 + String get title => S.current.new_subaddress_title;
15 +
16 + @override
17 + Widget body(BuildContext context) => NewSubaddressForm();
18 +
19 + @override
20 + Widget build(BuildContext context) {
21 + final subaddressCreationStore =
22 + Provider.of<SubadrressCreationStore>(context);
23 +
24 + reaction((_) => subaddressCreationStore.state, (state) {
25 + if (state is SubaddressCreatedSuccessfully) {
26 + WidgetsBinding.instance
27 + .addPostFrameCallback((_) => Navigator.of(context).pop());
28 + }
29 + });
30 +
31 + return super.build(context);
32 + }
33 +}
34 +
35 +class NewSubaddressForm extends StatefulWidget {
36 + @override
37 + NewSubaddressFormState createState() => NewSubaddressFormState();
38 +}
39 +
40 +class NewSubaddressFormState extends State<NewSubaddressForm> {
41 + final _formKey = GlobalKey<FormState>();
42 + final _labelController = TextEditingController();
43 +
44 + @override
45 + Widget build(BuildContext context) {
46 + final subaddressCreationStore =
47 + Provider.of<SubadrressCreationStore>(context);
48 +
49 + return Form(
50 + key: _formKey,
51 + child: Stack(children: <Widget>[
52 + Center(
53 + child: Padding(
54 + padding: EdgeInsets.only(left: 35, right: 35),
55 + child: TextFormField(
56 + controller: _labelController,
57 + decoration: InputDecoration(
58 + hintStyle: TextStyle(color: Theme.of(context).hintColor),
59 + hintText: S.of(context).new_subaddress_label_name,
60 + focusedBorder: UnderlineInputBorder(
61 + borderSide: BorderSide(
62 + color: Palette.cakeGreen, width: 2.0)),
63 + enabledBorder: UnderlineInputBorder(
64 + borderSide: BorderSide(
65 + color: Theme.of(context).focusColor,
66 + width: 1.0))),
67 + validator: (value) {
68 + subaddressCreationStore.validateSubaddressName(value);
69 + return subaddressCreationStore.errorMessage;
70 + }),
71 + ),
72 + ),
73 + Positioned(
74 + bottom: 20,
75 + left: 20,
76 + right: 20,
77 + child: Observer(
78 + builder: (_) => LoadingPrimaryButton(
79 + onPressed: () async {
80 + if (_formKey.currentState.validate()) {
81 + await subaddressCreationStore.add(
82 + label: _labelController.text);
83 + Navigator.of(context).pop();
84 + }
85 + },
86 + text: S.of(context).new_subaddress_create,
87 + color: Theme.of(context)
88 + .accentTextTheme
89 + .button
90 + .backgroundColor,
91 + borderColor: Theme.of(context)
92 + .accentTextTheme
93 + .button
94 + .decorationColor,
95 + isLoading:
96 + subaddressCreationStore.state is SubaddressIsCreating),
97 + ))
98 + ]));
99 + }
100 +}
lib/src/screens/subaddress/subaddress_list_page.dart new
+66
@@ -0,0 +1,66 @@
1 +import 'package:provider/provider.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:flutter/cupertino.dart';
4 +import 'package:flutter_mobx/flutter_mobx.dart';
5 +import 'package:cake_wallet/generated/i18n.dart';
6 +import 'package:cake_wallet/src/stores/subaddress_list/subaddress_list_store.dart';
7 +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
8 +import 'package:cake_wallet/src/screens/base_page.dart';
9 +
10 +class SubaddressListPage extends BasePage {
11 + bool get isModalBackButton => true;
12 + String get title => S.current.subaddress_title;
13 + AppBarStyle get appBarStyle => AppBarStyle.withShadow;
14 +
15 + SubaddressListPage();
16 +
17 + @override
18 + Widget body(BuildContext context) {
19 + final walletStore = Provider.of<WalletStore>(context);
20 + final subaddressListStore = Provider.of<SubaddressListStore>(context);
21 +
22 + final currentColor = Theme.of(context).selectedRowColor;
23 + final notCurrentColor = Theme.of(context).backgroundColor;
24 +
25 + return Container(
26 + padding: EdgeInsets.only(top: 20.0, bottom: 20.0),
27 + child: Observer(
28 + builder: (_) => ListView.separated(
29 + separatorBuilder: (_, __) => Divider(
30 + color: Theme.of(context).dividerTheme.color,
31 + height: 1.0,
32 + ),
33 + itemCount: subaddressListStore.subaddresses == null
34 + ? 0
35 + : subaddressListStore.subaddresses.length,
36 + itemBuilder: (BuildContext context, int index) {
37 + final subaddress = subaddressListStore.subaddresses[index];
38 + final isCurrent =
39 + walletStore.subaddress.address == subaddress.address;
40 + final label = subaddress.label != null
41 + ? subaddress.label
42 + : subaddress.address;
43 +
44 + return InkWell(
45 + onTap: () => Navigator.of(context).pop(subaddress),
46 + child: Container(
47 + color: isCurrent ? currentColor : notCurrentColor,
48 + child: Column(children: <Widget>[
49 + ListTile(
50 + title: Text(
51 + label,
52 + style: TextStyle(
53 + fontSize: 16.0,
54 + color: Theme.of(context)
55 + .primaryTextTheme
56 + .headline
57 + .color),
58 + ),
59 + )
60 + ]),
61 + ),
62 + );
63 + }),
64 + ));
65 + }
66 +}
lib/src/screens/trade_details/trade_details_page.dart new
+78
@@ -0,0 +1,78 @@
1 +import 'package:provider/provider.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:flutter/cupertino.dart';
4 +import 'package:flutter/services.dart';
5 +import 'package:flutter_mobx/flutter_mobx.dart';
6 +import 'package:cake_wallet/generated/i18n.dart';
7 +import 'package:cake_wallet/src/stores/exchange_trade/exchange_trade_store.dart';
8 +import 'package:cake_wallet/src/screens/base_page.dart';
9 +import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart';
10 +import 'package:cake_wallet/src/screens/transaction_details/standart_list_row.dart';
11 +
12 +class TradeDetailsPage extends BasePage {
13 + String get title => S.current.trade_details_title;
14 + bool get isModalBackButton => true;
15 +
16 + @override
17 + Widget body(BuildContext context) {
18 + final exchangeStore = Provider.of<ExchangeTradeStore>(context);
19 +
20 + return Container(
21 + padding: EdgeInsets.only(top: 10.0, bottom: 10.0, left: 20, right: 15),
22 + child: Observer(builder: (_) {
23 + final trade = exchangeStore.trade;
24 + final items = [
25 + StandartListItem(
26 + title: S.of(context).trade_details_id, value: trade.id),
27 + StandartListItem(
28 + title: S.of(context).trade_details_state,
29 + value: trade.state != null
30 + ? trade.state.toString()
31 + : S.of(context).trade_details_fetching)
32 + ];
33 +
34 + if (trade.provider != null) {
35 + items.add(StandartListItem(
36 + title: S.of(context).trade_details_provider,
37 + value: trade.provider.toString()));
38 + }
39 +
40 + if (trade.createdAt != null) {
41 + items.add(StandartListItem(
42 + title: S.of(context).trade_details_created_at,
43 + value: trade.createdAt.toString()));
44 + }
45 +
46 + if (trade.from != null && trade.to != null) {
47 + items.add(StandartListItem(
48 + title: S.of(context).trade_details_pair,
49 + value: '${trade.from.toString()} → ${trade.to.toString()}'));
50 + }
51 +
52 + return ListView.separated(
53 + separatorBuilder: (_, __) => Divider(
54 + color: Theme.of(context).dividerTheme.color,
55 + height: 1.0,
56 + ),
57 + padding: EdgeInsets.only(left: 25, top: 10, right: 25, bottom: 15),
58 + itemCount: items.length,
59 + itemBuilder: (BuildContext context, int index) {
60 + final item = items[index];
61 + return GestureDetector(
62 + onTap: () {
63 + Clipboard.setData(ClipboardData(text: '${item.value}'));
64 + Scaffold.of(context).showSnackBar(
65 + SnackBar(
66 + content: Text(
67 + S.of(context).trade_details_copied(item.title)),
68 + backgroundColor: Colors.green,
69 + duration: Duration(milliseconds: 1500),
70 + ),
71 + );
72 + },
73 + child: StandartListRow(
74 + title: '${item.title}', value: '${item.value}'));
75 + });
76 + }));
77 + }
78 +}
lib/src/screens/transaction_details/standart_list_item.dart new
+6
@@ -0,0 +1,6 @@
1 +class StandartListItem {
2 + final String title;
3 + final String value;
4 +
5 + StandartListItem({this.title, this.value});
6 +}
\ No newline at end of file
lib/src/screens/transaction_details/standart_list_row.dart new
+33
@@ -0,0 +1,33 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:cake_wallet/palette.dart';
3 +
4 +class StandartListRow extends StatelessWidget {
5 + final String title;
6 + final String value;
7 +
8 + StandartListRow({this.title, this.value});
9 +
10 + @override
11 + Widget build(BuildContext context) {
12 +
13 + return Padding(
14 + padding: const EdgeInsets.only(top: 10, bottom: 10),
15 + child: Column(
16 + crossAxisAlignment: CrossAxisAlignment.start,
17 + children: <Widget>[
18 + Text(title,
19 + style: TextStyle(
20 + fontSize: 14,
21 + color: Theme.of(context).primaryTextTheme.overline.color),
22 + textAlign: TextAlign.left),
23 + Padding(
24 + padding: const EdgeInsets.only(top: 5),
25 + child: Text(value,
26 + style: TextStyle(
27 + fontSize: 14,
28 + color: Palette.wildDarkBlue)),
29 + )
30 + ]),
31 + );
32 + }
33 +}
lib/src/screens/transaction_details/transaction_details_page.dart new
+104
@@ -0,0 +1,104 @@
1 +import 'package:intl/intl.dart';
2 +import 'package:provider/provider.dart';
3 +import 'package:flutter/material.dart';
4 +import 'package:flutter/cupertino.dart';
5 +import 'package:flutter/services.dart';
6 +import 'package:cake_wallet/generated/i18n.dart';
7 +import 'package:cake_wallet/src/domain/common/transaction_info.dart';
8 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
9 +import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart';
10 +import 'package:cake_wallet/src/screens/transaction_details/standart_list_row.dart';
11 +import 'package:cake_wallet/src/screens/base_page.dart';
12 +
13 +class TransactionDetailsPage extends BasePage {
14 + bool get isModalBackButton => true;
15 + String get title => S.current.transaction_details_title;
16 +
17 + final TransactionInfo transactionInfo;
18 +
19 + TransactionDetailsPage({this.transactionInfo});
20 +
21 + @override
22 + Widget body(BuildContext context) {
23 + final settingsStore = Provider.of<SettingsStore>(context);
24 +
25 + return TransactionDetailsForm(
26 + transactionInfo: transactionInfo, settingsStore: settingsStore);
27 + }
28 +}
29 +
30 +class TransactionDetailsForm extends StatefulWidget {
31 + final TransactionInfo transactionInfo;
32 + final SettingsStore settingsStore;
33 +
34 + TransactionDetailsForm(
35 + {@required this.transactionInfo, @required this.settingsStore});
36 +
37 + @override
38 + createState() => TransactionDetailsFormState();
39 +}
40 +
41 +class TransactionDetailsFormState extends State<TransactionDetailsForm> {
42 + final DateFormat _dateFormat = DateFormat('dd.MM.yyyy, HH:mm');
43 + List<StandartListItem> _items = List<StandartListItem>();
44 +
45 + @override
46 + void initState() {
47 + List<StandartListItem> items = [
48 + StandartListItem(
49 + title: S.current.transaction_details_transaction_id,
50 + value: widget.transactionInfo.id),
51 + StandartListItem(
52 + title: S.current.transaction_details_date,
53 + value: _dateFormat.format(widget.transactionInfo.date)),
54 + StandartListItem(
55 + title: S.current.transaction_details_height,
56 + value: '${widget.transactionInfo.height}'),
57 + StandartListItem(
58 + title: S.current.transaction_details_amount,
59 + value: widget.transactionInfo.amountFormatted())
60 + ];
61 +
62 + if (widget.settingsStore.shouldSaveRecipientAddress && widget.transactionInfo.recipientAddress != null) {
63 + items.add(StandartListItem(
64 + title: S.current.transaction_details_recipient_address,
65 + value: widget.transactionInfo.recipientAddress));
66 + }
67 +
68 + _items.addAll(items);
69 + super.initState();
70 + }
71 +
72 + @override
73 + Widget build(BuildContext context) {
74 + return Container(
75 + padding: EdgeInsets.only(left: 20, right: 15, top: 10, bottom: 10),
76 + child: ListView.separated(
77 + separatorBuilder: (context, index) => Container(
78 + height: 1,
79 + color: Theme.of(context).dividerTheme.color,
80 + ),
81 + padding: EdgeInsets.only(left: 25, top: 10, right: 25, bottom: 15),
82 + itemCount: _items.length,
83 + itemBuilder: (context, index) {
84 + final item = _items[index];
85 +
86 + return GestureDetector(
87 + onTap: () {
88 + Clipboard.setData(ClipboardData(text: item.value));
89 + Scaffold.of(context).showSnackBar(
90 + SnackBar(
91 + content: Text(
92 + S.of(context).transaction_details_copied(item.title)),
93 + backgroundColor: Colors.green,
94 + duration: Duration(milliseconds: 1500),
95 + ),
96 + );
97 + },
98 + child:
99 + StandartListRow(title: '${item.title}:', value: item.value),
100 + );
101 + }),
102 + );
103 + }
104 +}
lib/src/screens/wallet_list/wallet_list_page.dart new
+119
@@ -0,0 +1,119 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter/cupertino.dart';
3 +import 'package:flutter_mobx/flutter_mobx.dart';
4 +import 'package:provider/provider.dart';
5 +import 'package:cake_wallet/routes.dart';
6 +import 'package:cake_wallet/palette.dart';
7 +import 'package:cake_wallet/generated/i18n.dart';
8 +import 'package:cake_wallet/src/widgets/primary_button.dart';
9 +import 'package:cake_wallet/src/domain/common/wallet_description.dart';
10 +import 'package:cake_wallet/src/screens/base_page.dart';
11 +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
12 +import 'package:cake_wallet/src/stores/wallet_list/wallet_list_store.dart';
13 +import 'package:cake_wallet/src/screens/wallet_list/wallet_menu.dart';
14 +import 'package:cake_wallet/src/widgets/picker.dart';
15 +
16 +class WalletListPage extends BasePage {
17 + bool get isModalBackButton => true;
18 + String get title => S.current.wallet_list_title;
19 + AppBarStyle get appBarStyle => AppBarStyle.withShadow;
20 +
21 + @override
22 + Widget body(BuildContext context) => WalletListBody();
23 +}
24 +
25 +class WalletListBody extends StatefulWidget {
26 + WalletListBodyState createState() => WalletListBodyState();
27 +}
28 +
29 +class WalletListBodyState extends State<WalletListBody> {
30 + WalletListStore _walletListStore;
31 +
32 + void presetMenuForWallet(WalletDescription wallet, bool isCurrentWallet,
33 + BuildContext bodyContext) {
34 + final walletMenu = WalletMenu(bodyContext);
35 + List<String> items = walletMenu.generateItemsForWalletMenu(isCurrentWallet);
36 +
37 + showDialog(
38 + context: bodyContext,
39 + builder: (_) => Picker(
40 + items: items,
41 + selectedAtIndex: -1,
42 + title: S.of(context).wallet_menu,
43 + onItemSelected: (item) => walletMenu.action(
44 + walletMenu.listItems.indexOf(item), wallet, isCurrentWallet)),
45 + );
46 + }
47 +
48 + @override
49 + Widget build(BuildContext context) {
50 + _walletListStore = Provider.of<WalletListStore>(context);
51 +
52 + return ScrollableWithBottomSection(
53 + content: Container(
54 + padding: EdgeInsets.all(20),
55 + child: Observer(
56 + builder: (_) => ListView.separated(
57 + shrinkWrap: true,
58 + physics: const NeverScrollableScrollPhysics(),
59 + separatorBuilder: (_, index) => Divider(
60 + color: Theme.of(context).dividerTheme.color, height: 1.0),
61 + itemCount: _walletListStore.wallets.length,
62 + itemBuilder: (__, index) {
63 + final wallet = _walletListStore.wallets[index];
64 + final isCurrentWallet =
65 + _walletListStore.isCurrentWallet(wallet);
66 +
67 + return InkWell(
68 + onTap: () =>
69 + presetMenuForWallet(wallet, isCurrentWallet, context),
70 + child: Container(
71 + padding: EdgeInsets.only(left: 10.0, right: 10.0),
72 + child: ListTile(
73 + title: Text(
74 + wallet.name,
75 + style: TextStyle(
76 + color: isCurrentWallet
77 + ? Palette.cakeGreen
78 + : Theme.of(context)
79 + .primaryTextTheme
80 + .headline
81 + .color,
82 + fontSize: 18.0,
83 + fontWeight: FontWeight.w600),
84 + ),
85 + trailing: isCurrentWallet
86 + ? Icon(
87 + Icons.check,
88 + color: Palette.cakeGreen,
89 + size: 20.0,
90 + )
91 + : null)));
92 + }),
93 + ),
94 + ),
95 + bottomSection: Column(children: <Widget>[
96 + PrimaryIconButton(
97 + onPressed: () =>
98 + Navigator.of(context).pushNamed(Routes.newWallet),
99 + iconData: Icons.add,
100 + color: Theme.of(context).primaryTextTheme.button.backgroundColor,
101 + borderColor:
102 + Theme.of(context).primaryTextTheme.button.decorationColor,
103 + iconColor: Palette.violet,
104 + iconBackgroundColor: Theme.of(context).primaryIconTheme.color,
105 + text: S.of(context).wallet_list_create_new_wallet),
106 + SizedBox(height: 10.0),
107 + PrimaryIconButton(
108 + onPressed: () =>
109 + Navigator.of(context).pushNamed(Routes.restoreWalletOptions),
110 + iconData: Icons.refresh,
111 + text: S.of(context).wallet_list_restore_wallet,
112 + color: Theme.of(context).accentTextTheme.button.backgroundColor,
113 + borderColor:
114 + Theme.of(context).accentTextTheme.button.decorationColor,
115 + iconColor: Theme.of(context).primaryTextTheme.caption.color,
116 + iconBackgroundColor: Theme.of(context).accentIconTheme.color)
117 + ]));
118 + }
119 +}
lib/src/screens/wallet_list/wallet_menu.dart new
+88
@@ -0,0 +1,88 @@
1 +import 'package:cake_wallet/src/domain/common/wallet_description.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:cake_wallet/routes.dart';
4 +import 'package:provider/provider.dart';
5 +import 'package:cake_wallet/src/stores/wallet_list/wallet_list_store.dart';
6 +import 'package:cake_wallet/generated/i18n.dart';
7 +
8 +class WalletMenu {
9 +
10 + final BuildContext context;
11 + final List<String> listItems = [
12 + S.current.wallet_list_load_wallet,
13 + S.current.show_seed,
14 + S.current.remove,
15 + S.current.rescan
16 + ];
17 +
18 + WalletMenu(this.context);
19 +
20 + List<String>generateItemsForWalletMenu(bool isCurrentWallet) {
21 + List<String> items = new List<String>();
22 +
23 + if (!isCurrentWallet) items.add(listItems[0]);
24 + if (isCurrentWallet) items.add(listItems[1]);
25 + if (!isCurrentWallet) items.add(listItems[2]);
26 + if (isCurrentWallet) items.add(listItems[3]);
27 +
28 + return items;
29 + }
30 +
31 + void action(int index, WalletDescription wallet, bool isCurrentWallet) {
32 + WalletListStore _walletListStore = Provider.of<WalletListStore>(context);
33 +
34 + switch (index) {
35 + case 0:
36 + Navigator.of(context).pushNamed(Routes.auth,
37 + arguments: (isAuthenticatedSuccessfully, auth) async {
38 + if (!isAuthenticatedSuccessfully) {
39 + return;
40 + }
41 +
42 + try {
43 + auth.changeProcessText(S.of(context).wallet_list_loading_wallet(wallet.name));
44 + await _walletListStore.loadWallet(wallet);
45 + auth.close();
46 + Navigator.of(context).pop();
47 + } catch (e) {
48 + auth.changeProcessText(
49 + S.of(context).wallet_list_failed_to_load(wallet.name, e.toString()));
50 + }
51 + });
52 + break;
53 + case 1:
54 + Navigator.of(context).pushNamed(Routes.auth,
55 + arguments: (isAuthenticatedSuccessfully, auth) async {
56 + if (!isAuthenticatedSuccessfully) {
57 + return;
58 + }
59 + auth.close();
60 + Navigator.of(context).pushNamed(Routes.seed);
61 + });
62 + break;
63 + case 2:
64 + Navigator.of(context).pushNamed(Routes.auth,
65 + arguments: (isAuthenticatedSuccessfully, auth) async {
66 + if (!isAuthenticatedSuccessfully) {
67 + return;
68 + }
69 +
70 + try {
71 + auth.changeProcessText(S.of(context).wallet_list_removing_wallet(wallet.name));
72 + await _walletListStore.remove(wallet);
73 + auth.close();
74 + } catch (e) {
75 + auth.changeProcessText(
76 + S.of(context).wallet_list_failed_to_remove(wallet.name, e.toString()));
77 + }
78 + });
79 + break;
80 + case 3:
81 + Navigator.of(context).pushNamed(Routes.rescan);
82 + break;
83 + default:
84 + break;
85 + }
86 + }
87 +
88 +}
\ No newline at end of file
lib/src/screens/welcome/create_welcome_page.dart new
+4
@@ -0,0 +1,4 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:cake_wallet/src/screens/welcome/welcome_page.dart';
3 +
4 +Widget createWelcomePage() => WelcomePage();
\ No newline at end of file
lib/src/screens/welcome/welcome_page.dart new
+103
@@ -0,0 +1,103 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:provider/provider.dart';
3 +import 'package:cake_wallet/palette.dart';
4 +import 'package:cake_wallet/routes.dart';
5 +import 'package:cake_wallet/src/widgets/primary_button.dart';
6 +import 'package:cake_wallet/src/screens/base_page.dart';
7 +import 'package:cake_wallet/theme_changer.dart';
8 +import 'package:cake_wallet/themes.dart';
9 +import 'package:cake_wallet/generated/i18n.dart';
10 +
11 +class WelcomePage extends BasePage {
12 + static const _aspectRatioImage = 1.26;
13 + static const _baseWidth = 411.43;
14 + final _image = Image.asset('assets/images/welcomeImg.png');
15 + final _cakeLogo = Image.asset('assets/images/cake_logo.png');
16 +
17 + @override
18 + Widget build(BuildContext context) {
19 + ThemeChanger _themeChanger = Provider.of<ThemeChanger>(context);
20 + bool _isDarkTheme = (_themeChanger.getTheme() == Themes.darkTheme);
21 +
22 + return Scaffold(
23 + backgroundColor:
24 + _isDarkTheme ? Theme.of(context).backgroundColor : backgroundColor,
25 + resizeToAvoidBottomPadding: false,
26 + body: SafeArea(child: body(context)),
27 + );
28 + }
29 +
30 + @override
31 + Widget body(BuildContext context) {
32 + final _screenWidth = MediaQuery.of(context).size.width;
33 + final textScaleFactor = _screenWidth < _baseWidth ? 0.76 : 1.0;
34 +
35 + return Column(children: <Widget>[
36 + Stack(
37 + alignment: Alignment.center,
38 + children: <Widget>[
39 + AspectRatio(
40 + aspectRatio: _aspectRatioImage,
41 + child: FittedBox(child: _image, fit: BoxFit.fill)),
42 + Positioned(bottom: 0.0, child: _cakeLogo)
43 + ],
44 + ),
45 + Expanded(
46 + child: Column(
47 + mainAxisAlignment: MainAxisAlignment.spaceEvenly,
48 + children: <Widget>[
49 + Text(
50 + S.of(context).welcome,
51 + style: TextStyle(
52 + fontSize: 30.0,
53 + fontWeight: FontWeight.bold,
54 + ),
55 + textScaleFactor: textScaleFactor,
56 + textAlign: TextAlign.center,
57 + ),
58 + Text(
59 + S.of(context).first_wallet_text,
60 + style: TextStyle(
61 + fontSize: 22.0,
62 + color: Palette.lightBlue,
63 + ),
64 + textScaleFactor: textScaleFactor,
65 + textAlign: TextAlign.center,
66 + ),
67 + Text(
68 + S.of(context).please_make_selection,
69 + style: TextStyle(
70 + fontSize: 16.0,
71 + color: Palette.lightBlue,
72 + ),
73 + textScaleFactor: textScaleFactor,
74 + textAlign: TextAlign.center,
75 + )
76 + ]),
77 + ),
78 + Container(
79 + padding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 20.0),
80 + child: Column(children: <Widget>[
81 + PrimaryButton(
82 + onPressed: () {
83 + Navigator.pushNamed(context, Routes.newWalletFromWelcome);
84 + },
85 + text: S.of(context).create_new,
86 + color:
87 + Theme.of(context).primaryTextTheme.button.backgroundColor,
88 + borderColor:
89 + Theme.of(context).primaryTextTheme.button.decorationColor),
90 + SizedBox(height: 10),
91 + PrimaryButton(
92 + onPressed: () {
93 + Navigator.pushNamed(context, Routes.restoreOptions);
94 + },
95 + color: Theme.of(context).accentTextTheme.caption.backgroundColor,
96 + borderColor:
97 + Theme.of(context).accentTextTheme.caption.decorationColor,
98 + text: S.of(context).restore_wallet,
99 + )
100 + ]))
101 + ]);
102 + }
103 +}
lib/src/start_updating_price.dart new
+34
@@ -0,0 +1,34 @@
1 +import 'dart:async';
2 +import 'package:flutter/foundation.dart';
3 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
4 +import 'package:cake_wallet/src/domain/common/fetch_price.dart';
5 +import 'package:cake_wallet/src/stores/price/price_store.dart';
6 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
7 +
8 +bool _startedUpdatingPrice = false;
9 +
10 +_updatePrice(Map args) async =>
11 + await fetchPriceFor(fiat: args['fiat'], crypto: args['crypto']);
12 +
13 +updatePrice(Map args) async => compute(_updatePrice, args);
14 +
15 +startUpdatingPrice({SettingsStore settingsStore, PriceStore priceStore}) async {
16 + if (_startedUpdatingPrice) {
17 + return;
18 + }
19 +
20 + const currentCrypto = CryptoCurrency.xmr;
21 + _startedUpdatingPrice = true;
22 +
23 + final price = await updatePrice(
24 + {'fiat': settingsStore.fiatCurrency, 'crypto': currentCrypto});
25 + priceStore.changePriceForPair(
26 + fiat: settingsStore.fiatCurrency, crypto: currentCrypto, price: price);
27 +
28 + Timer.periodic(Duration(seconds: 30), (_) async {
29 + final price = await updatePrice(
30 + {'fiat': settingsStore.fiatCurrency, 'crypto': currentCrypto});
31 + priceStore.changePriceForPair(
32 + fiat: settingsStore.fiatCurrency, crypto: currentCrypto, price: price);
33 + });
34 +}
lib/src/stores/account_list/account_list_store.dart new
+99
@@ -0,0 +1,99 @@
1 +import 'dart:async';
2 +import 'package:flutter/foundation.dart';
3 +import 'package:mobx/mobx.dart';
4 +import 'package:cake_wallet/src/domain/common/wallet.dart';
5 +import 'package:cake_wallet/src/domain/monero/monero_wallet.dart';
6 +import 'package:cake_wallet/src/domain/monero/account.dart';
7 +import 'package:cake_wallet/src/domain/monero/account_list.dart';
8 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
9 +import 'package:cake_wallet/generated/i18n.dart';
10 +
11 +part 'account_list_store.g.dart';
12 +
13 +class AccountListStore = AcountListStoreBase with _$AccountListStore;
14 +
15 +abstract class AcountListStoreBase with Store {
16 + @observable
17 + List<Account> accounts;
18 +
19 + @observable
20 + bool isValid;
21 +
22 + @observable
23 + String errorMessage;
24 +
25 + @observable
26 + bool isAccountCreating;
27 +
28 + AccountList _accountList;
29 + StreamSubscription<Wallet> _onWalletChangeSubscription;
30 + StreamSubscription<List<Account>> _onAccountsChangeSubscription;
31 +
32 + AcountListStoreBase({@required WalletService walletService}) {
33 + accounts = [];
34 + isAccountCreating = false;
35 +
36 + if (walletService.currentWallet != null) {
37 + _onWalletChanged(walletService.currentWallet);
38 + }
39 +
40 + _onWalletChangeSubscription =
41 + walletService.onWalletChange.listen(_onWalletChanged);
42 + }
43 +
44 + @override
45 + void dispose() {
46 + _onWalletChangeSubscription.cancel();
47 +
48 + if (_onAccountsChangeSubscription != null) {
49 + _onAccountsChangeSubscription.cancel();
50 + }
51 +
52 + super.dispose();
53 + }
54 +
55 + Future updateAccountList() async {
56 + await _accountList.refresh();
57 + accounts = _accountList.getAll();
58 + }
59 +
60 + Future addAccount({String label}) async {
61 + try {
62 + isAccountCreating = true;
63 + await _accountList.addAccount(label: label);
64 + await updateAccountList();
65 + isAccountCreating = false;
66 + } catch (e) {
67 + isAccountCreating = false;
68 + }
69 + }
70 +
71 + Future renameAccount({int index, String label}) async {
72 + await _accountList.setLabelSubaddress(accountIndex: index, label: label);
73 + await updateAccountList();
74 + }
75 +
76 + Future _onWalletChanged(Wallet wallet) async {
77 + if (_onAccountsChangeSubscription != null) {
78 + _onAccountsChangeSubscription.cancel();
79 + }
80 +
81 + if (wallet is MoneroWallet) {
82 + _accountList = wallet.getAccountList();
83 + _onAccountsChangeSubscription =
84 + _accountList.accounts.listen((accounts) => this.accounts = accounts);
85 + await updateAccountList();
86 +
87 + return;
88 + }
89 +
90 + print('Incorrect wallet type for this operation (AccountList)');
91 + }
92 +
93 + void validateAccountName(String value) {
94 + String p = '^[a-zA-Z0-9_]{1,15}\$';
95 + RegExp regExp = new RegExp(p);
96 + isValid = regExp.hasMatch(value);
97 + errorMessage = isValid ? null : S.current.error_text_account_name;
98 + }
99 +}
lib/src/stores/action_list/action_list_display_mode.dart new
+32
@@ -0,0 +1,32 @@
1 +enum ActionListDisplayMode { transactions, trades }
2 +
3 +int serializeActionlistDisplayModes(List<ActionListDisplayMode> modes) {
4 + var i = 0;
5 +
6 + for (final mode in modes) {
7 + switch (mode) {
8 + case ActionListDisplayMode.trades:
9 + i += 1;
10 + break;
11 + case ActionListDisplayMode.transactions:
12 + i += 10;
13 + break;
14 + }
15 + }
16 +
17 + return i;
18 +}
19 +
20 +List<ActionListDisplayMode> deserializeActionlistDisplayModes(int raw) {
21 + List<ActionListDisplayMode> modes = [];
22 +
23 + if (raw == 1 || raw - 10 == 1) {
24 + modes.add(ActionListDisplayMode.trades);
25 + }
26 +
27 + if (raw >= 10) {
28 + modes.add(ActionListDisplayMode.transactions);
29 + }
30 +
31 + return modes;
32 +}
lib/src/stores/action_list/action_list_item.dart new
+3
@@ -0,0 +1,3 @@
1 +abstract class ActionListItem {
2 + DateTime get date;
3 +}
\ No newline at end of file
lib/src/stores/action_list/action_list_store.dart new
+224
@@ -0,0 +1,224 @@
1 +import 'dart:async';
2 +import 'package:cake_wallet/src/domain/exchange/trade.dart';
3 +import 'package:hive/hive.dart';
4 +import 'package:mobx/mobx.dart';
5 +import 'package:flutter/foundation.dart';
6 +import 'package:cake_wallet/src/domain/monero/account.dart';
7 +import 'package:cake_wallet/src/domain/common/transaction_history.dart';
8 +import 'package:cake_wallet/src/domain/common/transaction_info.dart';
9 +import 'package:cake_wallet/src/domain/common/wallet.dart';
10 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
11 +import 'package:cake_wallet/src/domain/monero/monero_wallet.dart';
12 +import 'package:cake_wallet/src/domain/common/calculate_fiat_amount_raw.dart';
13 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
14 +import 'package:cake_wallet/src/domain/monero/monero_amount_format.dart';
15 +import 'package:cake_wallet/src/domain/monero/transaction_description.dart';
16 +import 'package:cake_wallet/src/stores/price/price_store.dart';
17 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
18 +import 'package:cake_wallet/src/stores/action_list/action_list_display_mode.dart';
19 +import 'package:cake_wallet/src/stores/action_list/action_list_item.dart';
20 +import 'package:cake_wallet/src/stores/action_list/date_section_item.dart';
21 +import 'package:cake_wallet/src/stores/action_list/trade_filter_store.dart';
22 +import 'package:cake_wallet/src/stores/action_list/trade_list_item.dart';
23 +import 'package:cake_wallet/src/stores/action_list/transaction_filter_store.dart';
24 +import 'package:cake_wallet/src/stores/action_list/transaction_list_item.dart';
25 +
26 +part 'action_list_store.g.dart';
27 +
28 +class ActionListStore = ActionListBase with _$ActionListStore;
29 +
30 +abstract class ActionListBase with Store {
31 + static List<ActionListItem> formattedItemsList(List<ActionListItem> items) {
32 + var formattedList = List<ActionListItem>();
33 + DateTime lastDate;
34 + items.sort((a, b) => b.date.compareTo(a.date));
35 +
36 + for (int i = 0; i < items.length; i++) {
37 + final transaction = items[i];
38 +
39 + if (lastDate == null) {
40 + lastDate = transaction.date;
41 + formattedList.add(DateSectionItem(transaction.date));
42 + formattedList.add(transaction);
43 + continue;
44 + }
45 +
46 + final isCurrentDay = lastDate.year == transaction.date.year &&
47 + lastDate.month == transaction.date.month &&
48 + lastDate.day == transaction.date.day;
49 +
50 + if (isCurrentDay) {
51 + formattedList.add(transaction);
52 + continue;
53 + }
54 +
55 + lastDate = transaction.date;
56 + formattedList.add(DateSectionItem(transaction.date));
57 + formattedList.add(transaction);
58 + }
59 +
60 + return formattedList;
61 + }
62 +
63 + @computed
64 + List<TransactionListItem> get transactions {
65 + final symbol = PriceStoreBase.generateSymbolForPair(
66 + fiat: _settingsStore.fiatCurrency, crypto: CryptoCurrency.xmr);
67 + final price = _priceStore.prices[symbol];
68 +
69 + _transactions.forEach((item) {
70 + final amount = calculateFiatAmountRaw(
71 + cryptoAmount: moneroAmountToDouble(amount: item.transaction.amount),
72 + price: price);
73 + item.transaction.changeFiatAmount(amount);
74 + });
75 +
76 + return _transactions;
77 + }
78 +
79 + @observable
80 + List<TransactionListItem> _transactions;
81 +
82 + @observable
83 + List<TradeListItem> trades;
84 +
85 + @computed
86 + List<ActionListItem> get items {
87 + var _items = List<ActionListItem>();
88 +
89 + if (_settingsStore.actionlistDisplayMode
90 + .contains(ActionListDisplayMode.transactions)) {
91 + _items
92 + .addAll(transactionFilterStore.filtered(transactions: transactions));
93 + }
94 +
95 + if (_settingsStore.actionlistDisplayMode
96 + .contains(ActionListDisplayMode.trades)) {
97 + _items.addAll(tradeFilterStore.filtered(trades: trades));
98 + }
99 +
100 + return formattedItemsList(_items);
101 + }
102 +
103 + @computed
104 + int get totalCount => transactions.length + trades.length;
105 +
106 + TransactionFilterStore transactionFilterStore;
107 + TradeFilterStore tradeFilterStore;
108 + Box<TransactionDescription> transactionDescriptions;
109 + Box<Trade> tradesSource;
110 +
111 + WalletService _walletService;
112 + TransactionHistory _history;
113 + SettingsStore _settingsStore;
114 + PriceStore _priceStore;
115 + Account _account;
116 + StreamSubscription<Wallet> _onWalletChangeSubscription;
117 + StreamSubscription<List<TransactionInfo>> _onTransactionsChangeSubscription;
118 + StreamSubscription<Account> _onAccountChangeSubscription;
119 + StreamSubscription<BoxEvent> _onTransactionDescriptions;
120 +
121 + ActionListBase(
122 + {@required WalletService walletService,
123 + @required SettingsStore settingsStore,
124 + @required PriceStore priceStore,
125 + @required this.transactionFilterStore,
126 + @required this.tradeFilterStore,
127 + @required this.transactionDescriptions,
128 + @required this.tradesSource}) {
129 + trades = List<TradeListItem>();
130 + _transactions = List<TransactionListItem>();
131 + _walletService = walletService;
132 + _settingsStore = settingsStore;
133 + _priceStore = priceStore;
134 +
135 + if (walletService.currentWallet != null) {
136 + _onWalletChanged(walletService.currentWallet);
137 + }
138 +
139 + _onWalletChangeSubscription =
140 + walletService.onWalletChange.listen(_onWalletChanged);
141 +
142 + _onTransactionDescriptions = transactionDescriptions
143 + .watch()
144 + .listen((_) async => await _updateTransactionsList());
145 +
146 + updateTradeList();
147 + }
148 +
149 + @override
150 + void dispose() {
151 + if (_onTransactionsChangeSubscription != null) {
152 + _onTransactionsChangeSubscription.cancel();
153 + }
154 +
155 + if (_onAccountChangeSubscription != null) {
156 + _onAccountChangeSubscription.cancel();
157 + }
158 +
159 + _onTransactionDescriptions?.cancel();
160 +
161 + _onWalletChangeSubscription.cancel();
162 + super.dispose();
163 + }
164 +
165 + @action
166 + Future updateTradeList() async => this.trades =
167 + tradesSource.values.map((trade) => TradeListItem(trade: trade)).toList();
168 +
169 + Future _updateTransactionsList() async {
170 + await _history.refresh();
171 + final _transactions = await _history.getAll();
172 + await _setTransactions(_transactions);
173 + }
174 +
175 + Future _onWalletChanged(Wallet wallet) async {
176 + if (_onTransactionsChangeSubscription != null) {
177 + _onTransactionsChangeSubscription.cancel();
178 + }
179 +
180 + if (_onAccountChangeSubscription != null) {
181 + _onAccountChangeSubscription.cancel();
182 + }
183 +
184 + _history = wallet.getHistory();
185 + _onTransactionsChangeSubscription = _history.transactions
186 + .listen((transactions) => _setTransactions(transactions));
187 +
188 + if (wallet is MoneroWallet) {
189 + _account = wallet.account;
190 + _onAccountChangeSubscription = wallet.onAccountChange.listen((account) {
191 + _account = account;
192 + _updateTransactionsList();
193 + });
194 + }
195 +
196 + await _updateTransactionsList();
197 + }
198 +
199 + Future _setTransactions(List<TransactionInfo> transactions) async {
200 + final wallet = _walletService.currentWallet;
201 + List<TransactionInfo> sortedTransactions = transactions.map((transaction) {
202 + if (transactionDescriptions.values.length > 0) {
203 + final description = transactionDescriptions.values.firstWhere(
204 + (desc) => desc.id == transaction.id,
205 + orElse: () => null);
206 +
207 + if (description != null && description.recipientAddress != null) {
208 + transaction.recipientAddress = description.recipientAddress;
209 + }
210 + }
211 +
212 + return transaction;
213 + }).toList();
214 +
215 + if (wallet is MoneroWallet) {
216 + sortedTransactions =
217 + transactions.where((tx) => tx.accountIndex == _account.id).toList();
218 + }
219 +
220 + this._transactions = sortedTransactions
221 + .map((transaction) => TransactionListItem(transaction: transaction))
222 + .toList();
223 + }
224 +}
lib/src/stores/action_list/date_section_item.dart new
+7
@@ -0,0 +1,7 @@
1 +import 'package:cake_wallet/src/stores/action_list/action_list_item.dart';
2 +
3 +class DateSectionItem extends ActionListItem {
4 + final DateTime date;
5 +
6 + DateSectionItem(this.date);
7 +}
\ No newline at end of file
lib/src/stores/action_list/trade_filter_store.dart new
+53
@@ -0,0 +1,53 @@
1 +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
2 +import 'package:mobx/mobx.dart';
3 +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
4 +import 'package:cake_wallet/src/stores/action_list/trade_list_item.dart';
5 +
6 +part 'trade_filter_store.g.dart';
7 +
8 +class TradeFilterStore = TradeFilterStoreBase with _$TradeFilterStore;
9 +
10 +abstract class TradeFilterStoreBase with Store {
11 + @observable
12 + bool displayXMRTO;
13 +
14 + @observable
15 + bool displayChangeNow;
16 +
17 + WalletStore walletStore;
18 +
19 + TradeFilterStoreBase(
20 + {this.displayXMRTO = true,
21 + this.displayChangeNow = true,
22 + this.walletStore});
23 +
24 + @action
25 + void toggleDisplayExchange(ExchangeProviderDescription provider) {
26 + switch (provider) {
27 + case ExchangeProviderDescription.changeNow:
28 + displayChangeNow = !displayChangeNow;
29 + break;
30 + case ExchangeProviderDescription.xmrto:
31 + displayXMRTO = !displayXMRTO;
32 + break;
33 + }
34 + }
35 +
36 + List<TradeListItem> filtered({List<TradeListItem> trades}) {
37 + List<TradeListItem> _trades =
38 + trades.where((item) => item.trade.walletId == walletStore.id).toList();
39 +
40 + final needToFilter = !displayChangeNow || !displayXMRTO;
41 +
42 + return needToFilter
43 + ? trades
44 + .where((item) =>
45 + (displayXMRTO &&
46 + item.trade.provider == ExchangeProviderDescription.xmrto) ||
47 + (displayChangeNow &&
48 + item.trade.provider ==
49 + ExchangeProviderDescription.changeNow))
50 + .toList()
51 + : _trades;
52 + }
53 +}
lib/src/stores/action_list/trade_list_item.dart new
+10
@@ -0,0 +1,10 @@
1 +import 'package:cake_wallet/src/domain/exchange/trade.dart';
2 +import 'package:cake_wallet/src/stores/action_list/action_list_item.dart';
3 +
4 +class TradeListItem extends ActionListItem {
5 + final Trade trade;
6 +
7 + DateTime get date => trade.createdAt;
8 +
9 + TradeListItem({this.trade});
10 +}
\ No newline at end of file
lib/src/stores/action_list/transaction_filter_store.dart new
+69
@@ -0,0 +1,69 @@
1 +import 'package:mobx/mobx.dart';
2 +import 'package:cake_wallet/src/domain/common/transaction_direction.dart';
3 +import 'package:cake_wallet/src/stores/action_list/transaction_list_item.dart';
4 +
5 +part 'transaction_filter_store.g.dart';
6 +
7 +class TransactionFilterStore = TransactionFilterStoreBase
8 + with _$TransactionFilterStore;
9 +
10 +abstract class TransactionFilterStoreBase with Store {
11 + @observable
12 + bool displayIncoming;
13 +
14 + @observable
15 + bool displayOutgoing;
16 +
17 + @observable
18 + DateTime startDate;
19 +
20 + @observable
21 + DateTime endDate;
22 +
23 + TransactionFilterStoreBase(
24 + {this.displayIncoming = true, this.displayOutgoing = true});
25 +
26 + @action
27 + void toggleIncoming() => displayIncoming = !displayIncoming;
28 +
29 + @action
30 + void toggleOutgoing() => displayOutgoing = !displayOutgoing;
31 +
32 + @action
33 + void changeStartDate(DateTime date) => startDate = date;
34 +
35 + @action
36 + void changeEndDate(DateTime date) => endDate = date;
37 +
38 + List<TransactionListItem> filtered({List<TransactionListItem> transactions}) {
39 + List<TransactionListItem> _transactions = [];
40 + final needToFilter = !displayOutgoing ||
41 + !displayIncoming ||
42 + (startDate != null && endDate != null);
43 +
44 + if (needToFilter) {
45 + _transactions = transactions.where((item) {
46 + var allowed = true;
47 +
48 + if (allowed && startDate != null && endDate != null) {
49 + allowed = startDate.isBefore(item.transaction.date) &&
50 + endDate.isAfter(item.transaction.date);
51 + }
52 +
53 + if (allowed && (!displayOutgoing || !displayIncoming)) {
54 + allowed = (displayOutgoing &&
55 + item.transaction.direction ==
56 + TransactionDirection.outgoing) ||
57 + (displayIncoming &&
58 + item.transaction.direction == TransactionDirection.incoming);
59 + }
60 +
61 + return allowed;
62 + }).toList();
63 + } else {
64 + _transactions = transactions;
65 + }
66 +
67 + return _transactions;
68 + }
69 +}
lib/src/stores/action_list/transaction_list_item.dart new
+10
@@ -0,0 +1,10 @@
1 +import 'package:cake_wallet/src/domain/common/transaction_info.dart';
2 +import 'package:cake_wallet/src/stores/action_list/action_list_item.dart';
3 +
4 +class TransactionListItem extends ActionListItem {
5 + final TransactionInfo transaction;
6 +
7 + DateTime get date => transaction.date;
8 +
9 + TransactionListItem({this.transaction});
10 +}
\ No newline at end of file
lib/src/stores/address_book/address_book_store.dart new
+75
@@ -0,0 +1,75 @@
1 +import 'package:mobx/mobx.dart';
2 +import 'package:flutter/foundation.dart';
3 +import 'package:cake_wallet/generated/i18n.dart';
4 +import 'package:cake_wallet/src/domain/common/contact.dart';
5 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
6 +import 'package:hive/hive.dart';
7 +
8 +part 'address_book_store.g.dart';
9 +
10 +class AddressBookStore = AddressBookStoreBase with _$AddressBookStore;
11 +
12 +abstract class AddressBookStoreBase with Store {
13 + @observable
14 + List<Contact> contactList;
15 +
16 + @observable
17 + bool isValid;
18 +
19 + @observable
20 + String errorMessage;
21 +
22 + Box<Contact> contacts;
23 +
24 + AddressBookStoreBase({@required this.contacts}) {
25 + updateContactList();
26 + }
27 +
28 + @action
29 + Future add({Contact contact}) async => contacts.add(contact);
30 +
31 + @action
32 + Future updateContactList() async => contactList = contacts.values.toList();
33 +
34 + @action
35 + Future update({Contact contact}) async => contact.save();
36 +
37 + @action
38 + Future delete({Contact contact}) async => await contact.delete();
39 +
40 + void validateContactName(String value) {
41 + String p = '''^[^`,'"]{1,32}\$''';
42 + RegExp regExp = new RegExp(p);
43 + isValid = regExp.hasMatch(value);
44 + errorMessage = isValid ? null : S.current.error_text_contact_name;
45 + }
46 +
47 + void validateAddress(String value, {CryptoCurrency cryptoCurrency}) {
48 + // XMR (95), BTC (34), ETH (42), LTC (34), BCH (42), DASH (34)
49 + String p = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$';
50 + RegExp regExp = new RegExp(p);
51 + isValid = regExp.hasMatch(value);
52 + if (isValid && cryptoCurrency != null) {
53 + switch (cryptoCurrency.toString()) {
54 + case 'XMR':
55 + isValid = (value.length == 95);
56 + break;
57 + case 'BTC':
58 + isValid = (value.length == 34);
59 + break;
60 + case 'ETH':
61 + isValid = (value.length == 42);
62 + break;
63 + case 'LTC':
64 + isValid = (value.length == 34);
65 + break;
66 + case 'BCH':
67 + isValid = (value.length == 42);
68 + break;
69 + case 'DASH':
70 + isValid = (value.length == 34);
71 + }
72 + }
73 + errorMessage = isValid ? null : S.current.error_text_address;
74 + }
75 +}
lib/src/stores/auth/auth_state.dart new
+20
@@ -0,0 +1,20 @@
1 +abstract class AuthState {}
2 +
3 +class AuthenticationStateInitial extends AuthState {}
4 +
5 +class AuthenticationInProgress extends AuthState {}
6 +
7 +class AuthenticatedSuccessfully extends AuthState {}
8 +
9 +class AuthenticationFailure extends AuthState {
10 + final String error;
11 +
12 + AuthenticationFailure({this.error});
13 +}
14 +
15 +class AuthenticationBanned extends AuthState {
16 + final String error;
17 +
18 + AuthenticationBanned({this.error});
19 +}
20 +
lib/src/stores/auth/auth_store.dart new
+94
@@ -0,0 +1,94 @@
1 +import 'dart:async';
2 +import 'package:flutter/foundation.dart';
3 +import 'package:shared_preferences/shared_preferences.dart';
4 +import 'package:mobx/mobx.dart';
5 +import 'package:cake_wallet/src/domain/services/user_service.dart';
6 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
7 +import 'package:cake_wallet/src/stores/auth/auth_state.dart';
8 +import 'package:cake_wallet/generated/i18n.dart';
9 +
10 +part 'auth_store.g.dart';
11 +
12 +class AuthStore = AuthStoreBase with _$AuthStore;
13 +
14 +abstract class AuthStoreBase with Store {
15 + static const maxFailedLogins = 3;
16 + static const banTimeout = 180; // 3 mins
17 + final banTimeoutKey = S.current.auth_store_ban_timeout;
18 +
19 + final UserService userService;
20 + final WalletService walletService;
21 +
22 + final SharedPreferences sharedPreferences;
23 +
24 + @observable
25 + AuthState state;
26 +
27 + @observable
28 + int _failureCounter;
29 +
30 + AuthStoreBase(
31 + {@required this.userService,
32 + @required this.walletService,
33 + @required this.sharedPreferences}) {
34 + state = AuthenticationStateInitial();
35 + _failureCounter = 0;
36 + }
37 +
38 + @action
39 + Future auth({String password}) async {
40 + state = AuthenticationStateInitial();
41 + final _banDuration = banDuration();
42 +
43 + if (_banDuration != null) {
44 + state = AuthenticationBanned(
45 + error: S.current.auth_store_banned_for + '${_banDuration.inMinutes}' + S.current.auth_store_banned_minutes);
46 + return;
47 + }
48 +
49 + state = AuthenticationInProgress();
50 + final isAuth = await userService.authenticate(password);
51 +
52 + if (isAuth) {
53 + state = AuthenticatedSuccessfully();
54 + _failureCounter = 0;
55 + } else {
56 + _failureCounter += 1;
57 +
58 + if (_failureCounter >= maxFailedLogins) {
59 + final banDuration = await ban();
60 + state = AuthenticationBanned(
61 + error: S.current.auth_store_banned_for + '${banDuration.inMinutes}' + S.current.auth_store_banned_minutes);
62 + return;
63 + }
64 +
65 + state = AuthenticationFailure(error: S.current.auth_store_incorrect_password);
66 + }
67 + }
68 +
69 + Duration banDuration() {
70 + final unbanTimestamp = sharedPreferences.getInt(banTimeoutKey);
71 +
72 + if (unbanTimestamp == null) {
73 + return null;
74 + }
75 +
76 + final unbanTime = DateTime.fromMillisecondsSinceEpoch(unbanTimestamp);
77 + final now = DateTime.now();
78 +
79 + if (now.isAfter(unbanTime)) {
80 + return null;
81 + }
82 +
83 + return Duration(milliseconds: unbanTimestamp - now.millisecondsSinceEpoch);
84 + }
85 +
86 + Future<Duration> ban() async {
87 + final multiplier = _failureCounter - maxFailedLogins + 1;
88 + final timeout = (multiplier * banTimeout) * 1000;
89 + final unbanTimestamp = DateTime.now().millisecondsSinceEpoch + timeout;
90 + await sharedPreferences.setInt(banTimeoutKey, unbanTimestamp);
91 +
92 + return Duration(milliseconds: timeout);
93 + }
94 +}
lib/src/stores/authentication/authentication_store.dart new
+70
@@ -0,0 +1,70 @@
1 +import 'dart:async';
2 +import 'package:flutter/foundation.dart';
3 +import 'package:mobx/mobx.dart';
4 +import 'package:cake_wallet/src/domain/services/user_service.dart';
5 +
6 +part 'authentication_store.g.dart';
7 +
8 +class AuthenticationStore = AuthenticationStoreBase with _$AuthenticationStore;
9 +
10 +enum AuthenticationState {
11 + uninitialized,
12 + allowed,
13 + denied,
14 + authenticated,
15 + unauthenticated,
16 + active,
17 + loading,
18 + created,
19 + restored,
20 + readyToLogin
21 +}
22 +
23 +abstract class AuthenticationStoreBase with Store {
24 + final UserService userService;
25 +
26 + @observable
27 + AuthenticationState state;
28 +
29 + @observable
30 + String errorMessage;
31 +
32 + AuthenticationStoreBase({@required this.userService}) {
33 + state = AuthenticationState.uninitialized;
34 + }
35 +
36 + Future started() async {
37 + final canAuth = await userService.canAuthenticate();
38 + state = canAuth ? AuthenticationState.allowed : AuthenticationState.denied;
39 + }
40 +
41 + @action
42 + void created() {
43 + state = AuthenticationState.created;
44 + }
45 +
46 + @action
47 + void restored() {
48 + state = AuthenticationState.restored;
49 + }
50 +
51 + @action
52 + void loggedIn() {
53 + state = AuthenticationState.authenticated;
54 + }
55 +
56 + @action
57 + void inactive() {
58 + state = AuthenticationState.unauthenticated;
59 + }
60 +
61 + @action
62 + void active() {
63 + state = AuthenticationState.active;
64 + }
65 +
66 + @action
67 + void loggedOut() {
68 + state = AuthenticationState.uninitialized;
69 + }
70 +}
lib/src/stores/balance/balance_store.dart new
+120
@@ -0,0 +1,120 @@
1 +import 'dart:async';
2 +import 'package:mobx/mobx.dart';
3 +import 'package:flutter/foundation.dart';
4 +import 'package:cake_wallet/src/domain/common/wallet.dart';
5 +import 'package:cake_wallet/src/domain/common/balance.dart';
6 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
7 +import 'package:cake_wallet/src/domain/monero/monero_balance.dart';
8 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
9 +import 'package:cake_wallet/src/domain/common/calculate_fiat_amount.dart';
10 +import 'package:cake_wallet/src/stores/price/price_store.dart';
11 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
12 +
13 +part 'balance_store.g.dart';
14 +
15 +class BalanceStore = BalanceStoreBase with _$BalanceStore;
16 +
17 +abstract class BalanceStoreBase with Store {
18 + @observable
19 + String fullBalance;
20 +
21 + @observable
22 + String unlockedBalance;
23 +
24 + @computed
25 + String get fiatFullBalance {
26 + if (fullBalance == null) {
27 + return '0.00';
28 + }
29 +
30 + final symbol = PriceStoreBase.generateSymbolForPair(
31 + fiat: _settingsStore.fiatCurrency, crypto: CryptoCurrency.xmr);
32 + final price = _priceStore.prices[symbol];
33 + return calculateFiatAmount(price: price, cryptoAmount: fullBalance);
34 + }
35 +
36 + @computed
37 + String get fiatUnlockedBalance {
38 + if (unlockedBalance == null) {
39 + return '0.00';
40 + }
41 +
42 + final symbol = PriceStoreBase.generateSymbolForPair(
43 + fiat: _settingsStore.fiatCurrency, crypto: CryptoCurrency.xmr);
44 + final price = _priceStore.prices[symbol];
45 + return calculateFiatAmount(price: price, cryptoAmount: unlockedBalance);
46 + }
47 +
48 + @observable
49 + bool isReversing;
50 +
51 + WalletService _walletService;
52 + StreamSubscription<Wallet> _onWalletChangeSubscription;
53 + StreamSubscription<Balance> _onBalanceChangeSubscription;
54 + SettingsStore _settingsStore;
55 + PriceStore _priceStore;
56 +
57 + BalanceStoreBase(
58 + {String fullBalance = '0.0',
59 + String unlockedBalance = '0.0',
60 + @required WalletService walletService,
61 + @required SettingsStore settingsStore,
62 + @required PriceStore priceStore}) {
63 + fullBalance = fullBalance;
64 + unlockedBalance = unlockedBalance;
65 + isReversing = false;
66 + _walletService = walletService;
67 + _settingsStore = settingsStore;
68 + _priceStore = priceStore;
69 +
70 + if (_walletService.currentWallet != null) {
71 + _onWalletChanged(_walletService.currentWallet);
72 + }
73 +
74 + _onWalletChangeSubscription = _walletService.onWalletChange
75 + .listen((wallet) => _onWalletChanged(wallet));
76 + }
77 +
78 + @override
79 + void dispose() {
80 + _onWalletChangeSubscription.cancel();
81 +
82 + if (_onBalanceChangeSubscription != null) {
83 + _onBalanceChangeSubscription.cancel();
84 + }
85 +
86 + super.dispose();
87 + }
88 +
89 + Future _onBalanceChange(Balance balance) async {
90 + final _balance = balance as MoneroBalance;
91 +
92 + if (this.fullBalance != _balance.fullBalance) {
93 + this.fullBalance = _balance.fullBalance;
94 + }
95 +
96 + if (this.unlockedBalance != _balance.unlockedBalance) {
97 + this.unlockedBalance = _balance.unlockedBalance;
98 + }
99 + }
100 +
101 + Future _onWalletChanged(Wallet wallet) async {
102 + if (_onBalanceChangeSubscription != null) {
103 + _onBalanceChangeSubscription.cancel();
104 + }
105 +
106 + _onBalanceChangeSubscription = _walletService.onBalanceChange
107 + .listen((balance) async => await _onBalanceChange(balance));
108 +
109 + await _updateBalances(wallet);
110 + }
111 +
112 + Future _updateBalances(Wallet wallet) async {
113 + if (wallet == null) {
114 + return;
115 + }
116 +
117 + fullBalance = await _walletService.getFullBalance();
118 + unlockedBalance = await _walletService.getUnlockedBalance();
119 + }
120 +}
lib/src/stores/exchange/exchange_store.dart new
+266
@@ -0,0 +1,266 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:hive/hive.dart';
3 +import 'package:mobx/mobx.dart';
4 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
5 +import 'package:cake_wallet/src/domain/exchange/changenow/changenow_exchange_provider.dart';
6 +import 'package:cake_wallet/src/domain/exchange/changenow/changenow_request.dart';
7 +import 'package:cake_wallet/src/domain/exchange/exchange_provider.dart';
8 +import 'package:cake_wallet/src/domain/exchange/trade_request.dart';
9 +import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart';
10 +import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_trade_request.dart';
11 +import 'package:cake_wallet/src/domain/exchange/trade.dart';
12 +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
13 +import 'package:cake_wallet/src/stores/exchange/exchange_trade_state.dart';
14 +import 'package:cake_wallet/src/stores/exchange/limits_state.dart';
15 +import 'package:cake_wallet/generated/i18n.dart';
16 +
17 +part 'exchange_store.g.dart';
18 +
19 +class ExchangeStore = ExchangeStoreBase with _$ExchangeStore;
20 +
21 +abstract class ExchangeStoreBase with Store {
22 + @observable
23 + ExchangeProvider provider;
24 +
25 + @observable
26 + List<ExchangeProvider> providerList;
27 +
28 + @observable
29 + CryptoCurrency depositCurrency;
30 +
31 + @observable
32 + CryptoCurrency receiveCurrency;
33 +
34 + @observable
35 + LimitsState limitsState;
36 +
37 + @observable
38 + ExchangeTradeState tradeState;
39 +
40 + @observable
41 + String depositAmount;
42 +
43 + @observable
44 + String receiveAmount;
45 +
46 + @observable
47 + bool isValid;
48 +
49 + @observable
50 + String errorMessage;
51 +
52 + Box<Trade> trades;
53 +
54 + String depositAddress;
55 +
56 + String receiveAddress;
57 +
58 + WalletStore walletStore;
59 +
60 + ExchangeStoreBase(
61 + {@required ExchangeProvider initialProvider,
62 + @required CryptoCurrency initialDepositCurrency,
63 + @required CryptoCurrency initialReceiveCurrency,
64 + @required this.providerList,
65 + @required this.trades,
66 + @required this.walletStore}) {
67 + provider = initialProvider;
68 + depositCurrency = initialDepositCurrency;
69 + receiveCurrency = initialReceiveCurrency;
70 + limitsState = LimitsInitialState();
71 + tradeState = ExchangeTradeStateInitial();
72 + loadLimits();
73 + }
74 +
75 + @action
76 + void changeProvider({ExchangeProvider provider}) {
77 + this.provider = provider;
78 + depositAmount = '';
79 + receiveAmount = '';
80 + }
81 +
82 + @action
83 + void changeDepositCurrency({CryptoCurrency currency}) {
84 + depositCurrency = currency;
85 + _onPairChange();
86 + }
87 +
88 + @action
89 + void changeReceiveCurrency({CryptoCurrency currency}) {
90 + receiveCurrency = currency;
91 + _onPairChange();
92 + }
93 +
94 + @action
95 + void changeReceiveAmount({String amount}) {
96 + receiveAmount = amount;
97 +
98 + if (amount == null || amount.isEmpty) {
99 + depositAmount = '';
100 + return;
101 + }
102 +
103 + final _amount = double.parse(amount) ?? 0;
104 +
105 + provider
106 + .calculateAmount(
107 + from: depositCurrency, to: receiveCurrency, amount: _amount)
108 + .then((amount) => amount.toString())
109 + .then((amount) => depositAmount = amount);
110 + }
111 +
112 + @action
113 + void changeDepositAmount({String amount}) {
114 + depositAmount = amount;
115 +
116 + if (amount == null || amount.isEmpty) {
117 + depositAmount = '';
118 + return;
119 + }
120 +
121 + final _amount = double.parse(amount);
122 + provider
123 + .calculateAmount(
124 + from: depositCurrency, to: receiveCurrency, amount: _amount)
125 + .then((amount) => amount.toString())
126 + .then((amount) => receiveAmount = amount);
127 + }
128 +
129 + @action
130 + Future loadLimits() async {
131 + limitsState = LimitsIsLoading();
132 +
133 + try {
134 + final limits = await provider.fetchLimits(
135 + from: depositCurrency, to: receiveCurrency);
136 + limitsState = LimitsLoadedSuccessfully(limits: limits);
137 + } catch (e) {
138 + limitsState = LimitsLoadedFailure(error: e.toString());
139 + }
140 + }
141 +
142 + @action
143 + Future createTrade() async {
144 + TradeRequest request;
145 +
146 + if (provider is XMRTOExchangeProvider) {
147 + request = XMRTOTradeRequest(
148 + to: receiveCurrency,
149 + from: depositCurrency,
150 + amount: receiveAmount,
151 + address: receiveAddress,
152 + refundAddress: depositAddress);
153 + }
154 +
155 + if (provider is ChangeNowExchangeProvider) {
156 + request = ChangeNowRequest(
157 + from: depositCurrency,
158 + to: receiveCurrency,
159 + amount: depositAmount,
160 + refundAddress: depositAddress,
161 + address: receiveAddress);
162 + }
163 +
164 + try {
165 + tradeState = TradeIsCreating();
166 + final trade = await provider.createTrade(request: request);
167 + trade.walletId = walletStore.id;
168 + await trades.add(trade);
169 + tradeState = TradeIsCreatedSuccessfully(trade: trade);
170 + } catch (e) {
171 + tradeState = TradeIsCreatedFailure(error: e.toString());
172 + }
173 + }
174 +
175 + @action
176 + void reset() {
177 + depositAmount = '';
178 + receiveAmount = '';
179 + depositAddress = '';
180 + receiveAddress = '';
181 + provider = XMRTOExchangeProvider();
182 + depositCurrency = CryptoCurrency.xmr;
183 + receiveCurrency = CryptoCurrency.btc;
184 + }
185 +
186 + List<ExchangeProvider> providersForCurrentPair() {
187 + return _providersForPair(from: depositCurrency, to: receiveCurrency);
188 + }
189 +
190 + List<ExchangeProvider> _providersForPair(
191 + {CryptoCurrency from, CryptoCurrency to}) {
192 + final providers = providerList
193 + .where((provider) =>
194 + provider.pairList
195 + .where((pair) =>
196 + pair.from == depositCurrency && pair.to == receiveCurrency)
197 + .length >
198 + 0)
199 + .toList();
200 +
201 + return providers;
202 + }
203 +
204 + void _onPairChange() {
205 + final isPairExist = provider.pairList
206 + .where((pair) =>
207 + pair.from == depositCurrency && pair.to == receiveCurrency)
208 + .length >
209 + 0;
210 +
211 + if (!isPairExist) {
212 + final provider =
213 + _providerForPair(from: depositCurrency, to: receiveCurrency);
214 +
215 + if (provider != null) {
216 + changeProvider(provider: provider);
217 + }
218 + }
219 +
220 + depositAmount = '';
221 + receiveAmount = '';
222 +
223 + loadLimits();
224 + }
225 +
226 + ExchangeProvider _providerForPair({CryptoCurrency from, CryptoCurrency to}) {
227 + final providers = _providersForPair(from: from, to: to);
228 + return providers.length > 0 ? providers[0] : null;
229 + }
230 +
231 + void validateAddress(String value, {CryptoCurrency cryptoCurrency}) {
232 + // XMR (95), BTC (34), ETH (42), LTC (34), BCH (42), DASH (34)
233 + String p = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$';
234 + RegExp regExp = new RegExp(p);
235 + isValid = regExp.hasMatch(value);
236 + if (isValid && cryptoCurrency != null) {
237 + switch (cryptoCurrency.toString()) {
238 + case 'XMR':
239 + isValid = (value.length == 95);
240 + break;
241 + case 'BTC':
242 + isValid = (value.length == 34);
243 + break;
244 + case 'ETH':
245 + isValid = (value.length == 42);
246 + break;
247 + case 'LTC':
248 + isValid = (value.length == 34);
249 + break;
250 + case 'BCH':
251 + isValid = (value.length == 42);
252 + break;
253 + case 'DASH':
254 + isValid = (value.length == 34);
255 + }
256 + }
257 + errorMessage = isValid ? null : S.current.error_text_address;
258 + }
259 +
260 + void validateCryptoCurrency(String value) {
261 + String p = '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$';
262 + RegExp regExp = new RegExp(p);
263 + isValid = regExp.hasMatch(value);
264 + errorMessage = isValid ? null : S.current.error_text_crypto_currency;
265 + }
266 +}
lib/src/stores/exchange/exchange_trade_state.dart new
+20
@@ -0,0 +1,20 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:cake_wallet/src/domain/exchange/trade.dart';
3 +
4 +abstract class ExchangeTradeState {}
5 +
6 +class ExchangeTradeStateInitial extends ExchangeTradeState {}
7 +
8 +class TradeIsCreating extends ExchangeTradeState {}
9 +
10 +class TradeIsCreatedSuccessfully extends ExchangeTradeState {
11 + final Trade trade;
12 +
13 + TradeIsCreatedSuccessfully({@required this.trade});
14 +}
15 +
16 +class TradeIsCreatedFailure extends ExchangeTradeState {
17 + final String error;
18 +
19 + TradeIsCreatedFailure({@required this.error});
20 +}
\ No newline at end of file
lib/src/stores/exchange/limits_state.dart new
+20
@@ -0,0 +1,20 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:cake_wallet/src/domain/exchange/limits.dart';
3 +
4 +abstract class LimitsState {}
5 +
6 +class LimitsInitialState extends LimitsState {}
7 +
8 +class LimitsIsLoading extends LimitsState {}
9 +
10 +class LimitsLoadedSuccessfully extends LimitsState {
11 + final Limits limits;
12 +
13 + LimitsLoadedSuccessfully({@required this.limits});
14 +}
15 +
16 +class LimitsLoadedFailure extends LimitsState {
17 + final String error;
18 +
19 + LimitsLoadedFailure({@required this.error});
20 +}
lib/src/stores/exchange_trade/exchange_trade_store.dart new
+65
@@ -0,0 +1,65 @@
1 +import 'dart:async';
2 +import 'package:mobx/mobx.dart';
3 +import 'package:flutter/foundation.dart';
4 +import 'package:cake_wallet/src/domain/exchange/trade.dart';
5 +import 'package:cake_wallet/src/domain/exchange/exchange_provider.dart';
6 +import 'package:cake_wallet/src/domain/exchange/changenow/changenow_exchange_provider.dart';
7 +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
8 +import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart';
9 +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
10 +
11 +part 'exchange_trade_store.g.dart';
12 +
13 +class ExchangeTradeStore = ExchangeTradeStoreBase with _$ExchangeTradeStore;
14 +
15 +abstract class ExchangeTradeStoreBase with Store {
16 + @observable
17 + Trade trade;
18 +
19 + @observable
20 + bool isSendable;
21 +
22 + ExchangeProvider _provider;
23 +
24 + Timer _timer;
25 +
26 + ExchangeTradeStoreBase({@required this.trade, @required WalletStore walletStore}) {
27 + isSendable = trade.from == walletStore.type || trade.provider == ExchangeProviderDescription.xmrto;
28 +
29 + switch (trade.provider) {
30 + case ExchangeProviderDescription.xmrto:
31 + _provider = XMRTOExchangeProvider();
32 + break;
33 + case ExchangeProviderDescription.changeNow:
34 + _provider = ChangeNowExchangeProvider();
35 + break;
36 + }
37 +
38 + _updateTrade();
39 + _timer = Timer.periodic(Duration(seconds: 20), (_) async => _updateTrade());
40 + }
41 +
42 + @override
43 + void dispose() {
44 + super.dispose();
45 +
46 + if (_timer != null) {
47 + _timer.cancel();
48 + }
49 + }
50 +
51 + @action
52 + Future _updateTrade() async {
53 + try {
54 + final updatedTrade = await _provider.findTradeById(id: trade.id);
55 +
56 + if (updatedTrade.createdAt == null && trade.createdAt != null) {
57 + updatedTrade.createdAt = trade.createdAt;
58 + }
59 +
60 + trade = updatedTrade;
61 + } catch (e) {
62 + print(e.toString());
63 + }
64 + }
65 +}
lib/src/stores/login/login_store.dart new
+49
@@ -0,0 +1,49 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:mobx/mobx.dart';
3 +import 'package:shared_preferences/shared_preferences.dart';
4 +import 'package:cake_wallet/src/domain/services/wallet_list_service.dart';
5 +
6 +part 'login_store.g.dart';
7 +
8 +abstract class LoginState {}
9 +
10 +class InitialLoginState extends LoginState {}
11 +
12 +class LoadingCurrentWallet extends LoginState {}
13 +
14 +class LoadedCurrentWalletSuccessfully extends LoginState {}
15 +
16 +class LoadedCurrentWalletFailure extends LoginState {
17 + final String errorMessage;
18 +
19 + LoadedCurrentWalletFailure({this.errorMessage});
20 +}
21 +
22 +class LoginStore = LoginStoreBase with _$LoginStore;
23 +
24 +abstract class LoginStoreBase with Store {
25 + final SharedPreferences sharedPreferences;
26 + final WalletListService walletsService;
27 +
28 + @observable
29 + LoginState state;
30 +
31 + LoginStoreBase(
32 + {@required this.sharedPreferences, @required this.walletsService}) {
33 + state = InitialLoginState();
34 + }
35 +
36 + @action
37 + Future loadCurrentWallet() async {
38 + state = InitialLoginState();
39 +
40 + try {
41 + state = LoadingCurrentWallet();
42 + final walletName = sharedPreferences.getString('current_wallet_name');
43 + await walletsService.openWallet(walletName);
44 + state = LoadedCurrentWalletSuccessfully();
45 + } catch (e) {
46 + state = LoadedCurrentWalletFailure(errorMessage: e.toString());
47 + }
48 + }
49 +}
lib/src/stores/node_list/node_list_store.dart new
+95
@@ -0,0 +1,95 @@
1 +import 'dart:async';
2 +import 'package:mobx/mobx.dart';
3 +import 'package:hive/hive.dart';
4 +import 'package:cake_wallet/src/domain/common/node.dart';
5 +import 'package:cake_wallet/src/domain/common/node_list.dart';
6 +import 'package:cake_wallet/generated/i18n.dart';
7 +
8 +part 'node_list_store.g.dart';
9 +
10 +class NodeListStore = NodeListBase with _$NodeListStore;
11 +
12 +abstract class NodeListBase with Store {
13 + @observable
14 + ObservableList<Node> nodes;
15 +
16 + @observable
17 + bool isValid;
18 +
19 + @observable
20 + String errorMessage;
21 +
22 + Box<Node> nodesSource;
23 +
24 + StreamSubscription<BoxEvent> _onNodesChangeSubscription;
25 +
26 + NodeListBase({this.nodesSource}) {
27 + nodes = ObservableList<Node>();
28 + _onNodesChangeSubscription = nodesSource.watch().listen((e) => update());
29 + update();
30 + }
31 +
32 + @override
33 + void dispose() {
34 + super.dispose();
35 +
36 + if (_onNodesChangeSubscription != null) {
37 + _onNodesChangeSubscription.cancel();
38 + }
39 + }
40 +
41 + @action
42 + update() async =>
43 + nodes.replaceRange(0, nodes.length, nodesSource.values.toList());
44 +
45 + @action
46 + Future addNode(
47 + {String address, String port, String login, String password}) async {
48 + var uri = address;
49 +
50 + if (port != null && port.isNotEmpty) {
51 + uri += ':' + port;
52 + }
53 +
54 + final node = Node(uri: uri, login: login, password: password);
55 + await nodesSource.add(node);
56 + }
57 +
58 + @action
59 + Future remove({Node node}) async => await node.delete();
60 +
61 + @action
62 + Future reset() async => await resetToDefault(nodesSource);
63 +
64 + Future<bool> isNodeOnline(Node node) async {
65 + try {
66 + return await node.requestNode(node.uri,
67 + login: node.login, password: node.password);
68 + } catch (e) {
69 + return false;
70 + }
71 + }
72 +
73 + void validateNodeAddress(String value) {
74 + String p =
75 + '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\$';
76 + RegExp regExp = new RegExp(p);
77 + isValid = regExp.hasMatch(value);
78 + errorMessage = isValid ? null : S.current.error_text_node_address;
79 + }
80 +
81 + void validateNodePort(String value) {
82 + String p = '^[0-9]{1,5}';
83 + RegExp regExp = new RegExp(p);
84 + if (regExp.hasMatch(value)) {
85 + try {
86 + int intValue = int.parse(value);
87 + isValid = (intValue >= 0 && intValue <= 65535);
88 + } catch (e) {
89 + isValid = false;
90 + }
91 + } else
92 + isValid = false;
93 + errorMessage = isValid ? null : S.current.error_text_node_port;
94 + }
95 +}
lib/src/stores/price/price_store.dart new
+32
@@ -0,0 +1,32 @@
1 +import 'package:mobx/mobx.dart';
2 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
3 +import 'package:cake_wallet/src/domain/common/fetch_price.dart';
4 +import 'package:cake_wallet/src/domain/common/fiat_currency.dart';
5 +
6 +part 'price_store.g.dart';
7 +
8 +class PriceStore = PriceStoreBase with _$PriceStore;
9 +
10 +abstract class PriceStoreBase with Store {
11 + static String generateSymbolForPair(
12 + {FiatCurrency fiat, CryptoCurrency crypto}) =>
13 + crypto.toString().toUpperCase() + fiat.toString().toUpperCase();
14 +
15 + @observable
16 + ObservableMap<String, double> prices;
17 +
18 + PriceStoreBase() : prices = ObservableMap();
19 +
20 + @action
21 + Future updatePrice({FiatCurrency fiat, CryptoCurrency crypto}) async {
22 + final symbol = generateSymbolForPair(fiat: fiat, crypto: crypto);
23 + final price = await fetchPriceFor(fiat: fiat, crypto: crypto);
24 + prices[symbol] = price;
25 + }
26 +
27 + @action
28 + changePriceForPair({FiatCurrency fiat, CryptoCurrency crypto, double price}) {
29 + final symbol = generateSymbolForPair(fiat: fiat, crypto: crypto);
30 + prices[symbol] = price;
31 + }
32 +}
lib/src/stores/rescan/rescan_wallet_store.dart new
+30
@@ -0,0 +1,30 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:mobx/mobx.dart';
3 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
4 +
5 +part 'rescan_wallet_store.g.dart';
6 +
7 +class RescanWalletStore = RescanWalletStoreBase with _$RescanWalletStore;
8 +
9 +enum RescanWalletState {
10 + rescaning, none
11 +}
12 +
13 +abstract class RescanWalletStoreBase with Store {
14 + @observable
15 + RescanWalletState state;
16 +
17 + WalletService _walletService;
18 +
19 + RescanWalletStoreBase({@required WalletService walletService}) {
20 + _walletService = walletService;
21 + state = RescanWalletState.none;
22 + }
23 +
24 + @action
25 + Future rescanCurrentWallet({int restoreHeight}) async {
26 + state = RescanWalletState.rescaning;
27 + await _walletService.rescan(restoreHeight: restoreHeight);
28 + state = RescanWalletState.none;
29 + }
30 +}
lib/src/stores/send/send_store.dart new
+245
@@ -0,0 +1,245 @@
1 +import 'package:hive/hive.dart';
2 +import 'package:intl/intl.dart';
3 +import 'package:mobx/mobx.dart';
4 +import 'package:flutter/foundation.dart';
5 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
6 +import 'package:cake_wallet/src/domain/common/pending_transaction.dart';
7 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
8 +import 'package:cake_wallet/src/domain/monero/monero_transaction_creation_credentials.dart';
9 +import 'package:cake_wallet/src/domain/monero/transaction_description.dart';
10 +import 'package:cake_wallet/src/stores/price/price_store.dart';
11 +import 'package:cake_wallet/src/stores/send/sending_state.dart';
12 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
13 +import 'package:cake_wallet/generated/i18n.dart';
14 +
15 +part 'send_store.g.dart';
16 +
17 +class SendStore = SendStoreBase with _$SendStore;
18 +
19 +abstract class SendStoreBase with Store {
20 + WalletService walletService;
21 + SettingsStore settingsStore;
22 + PriceStore priceStore;
23 + Box<TransactionDescription> transactionDescriptions;
24 +
25 + @observable
26 + SendingState state;
27 +
28 + @observable
29 + String fiatAmount;
30 +
31 + @observable
32 + String cryptoAmount;
33 +
34 + @observable
35 + bool isValid;
36 +
37 + @observable
38 + String errorMessage;
39 +
40 + PendingTransaction get pendingTransaction => _pendingTransaction;
41 + PendingTransaction _pendingTransaction;
42 + NumberFormat _cryptoNumberFormat;
43 + NumberFormat _fiatNumberFormat;
44 + String _lastRecipientAddress;
45 +
46 + SendStoreBase(
47 + {@required this.walletService,
48 + this.settingsStore,
49 + this.transactionDescriptions,
50 + this.priceStore}) {
51 + state = SendingStateInitial();
52 + _pendingTransaction = null;
53 + _cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12;
54 + _fiatNumberFormat = NumberFormat()..maximumFractionDigits = 2;
55 +
56 + reaction((_) => this.state, (state) async {
57 + if (state is TransactionCreatedSuccessfully) {
58 + commitTransaction();
59 + }
60 + });
61 + }
62 +
63 + @action
64 + Future createTransaction(
65 + {String address, String paymentId, String amount}) async {
66 + state = CreatingTransaction();
67 +
68 + try {
69 + final _amount = amount != null
70 + ? amount
71 + : cryptoAmount == S.current.all
72 + ? null
73 + : cryptoAmount.replaceAll(',', '.');
74 + final credentials = MoneroTransactionCreationCredentials(
75 + address: address,
76 + paymentId: paymentId ?? '',
77 + amount: _amount,
78 + priority: settingsStore.transactionPriority);
79 +
80 + _pendingTransaction = await walletService.createTransaction(credentials);
81 + state = TransactionCreatedSuccessfully();
82 + _lastRecipientAddress = address;
83 + } catch (e) {
84 + state = SendingFailed(error: e.toString());
85 + }
86 + }
87 +
88 + @action
89 + Future commitTransaction() async {
90 + try {
91 + final transactionId = _pendingTransaction.hash;
92 + await _pendingTransaction.commit();
93 +
94 + if (settingsStore.shouldSaveRecipientAddress) {
95 + await transactionDescriptions.add(TransactionDescription(
96 + id: transactionId, recipientAddress: _lastRecipientAddress));
97 + }
98 + } catch (e) {
99 + state = SendingFailed(error: e.toString());
100 + }
101 +
102 + _pendingTransaction = null;
103 + }
104 +
105 + @action
106 + void setSendAll() {
107 + cryptoAmount = 'ALL';
108 + fiatAmount = '';
109 + }
110 +
111 + @action
112 + void changeCryptoAmount(String amount) {
113 + cryptoAmount = amount;
114 +
115 + if (cryptoAmount != null && cryptoAmount.isNotEmpty) {
116 + _calculateFiatAmount();
117 + } else {
118 + fiatAmount = '';
119 + }
120 + }
121 +
122 + @action
123 + void changeFiatAmount(String amount) {
124 + fiatAmount = amount;
125 +
126 + if (fiatAmount != null && fiatAmount.isNotEmpty) {
127 + _calculateCryptoAmount();
128 + } else {
129 + cryptoAmount = '';
130 + }
131 + }
132 +
133 + @action
134 + Future _calculateFiatAmount() async {
135 + final symbol = PriceStoreBase.generateSymbolForPair(
136 + fiat: settingsStore.fiatCurrency, crypto: CryptoCurrency.xmr);
137 + final price = priceStore.prices[symbol] ?? 0;
138 +
139 + try {
140 + final amount = double.parse(cryptoAmount) * price;
141 + fiatAmount = _fiatNumberFormat.format(amount);
142 + } catch (e) {
143 + fiatAmount = '0.00';
144 + }
145 + }
146 +
147 + @action
148 + Future _calculateCryptoAmount() async {
149 + final symbol = PriceStoreBase.generateSymbolForPair(
150 + fiat: settingsStore.fiatCurrency, crypto: CryptoCurrency.xmr);
151 + final price = priceStore.prices[symbol] ?? 0;
152 +
153 + try {
154 + final amount = double.parse(fiatAmount) / price;
155 + cryptoAmount = _cryptoNumberFormat.format(amount);
156 + } catch (e) {
157 + cryptoAmount = '0.00';
158 + }
159 + }
160 +
161 + void validateAddress(String value, {CryptoCurrency cryptoCurrency}) {
162 + // XMR (95), BTC (34), ETH (42), LTC (34), BCH (42), DASH (34)
163 + String p = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$';
164 + RegExp regExp = new RegExp(p);
165 + isValid = value == null ? false : regExp.hasMatch(value);
166 + if (isValid && cryptoCurrency != null) {
167 + switch (cryptoCurrency.toString()) {
168 + case 'XMR':
169 + isValid = (value.length == 95);
170 + break;
171 + case 'BTC':
172 + isValid = (value.length == 34);
173 + break;
174 + case 'ETH':
175 + isValid = (value.length == 42);
176 + break;
177 + case 'LTC':
178 + isValid = (value.length == 34);
179 + break;
180 + case 'BCH':
181 + isValid = (value.length == 42);
182 + break;
183 + case 'DASH':
184 + isValid = (value.length == 34);
185 + }
186 + }
187 + errorMessage = isValid ? null : S.current.error_text_address;
188 + }
189 +
190 + void validatePaymentID(String value) {
191 + if (value.isEmpty) {
192 + isValid = true;
193 + } else {
194 + String p = '^[A-Fa-f0-9]{16,64}\$';
195 + RegExp regExp = new RegExp(p);
196 + isValid = regExp.hasMatch(value);
197 + }
198 + errorMessage = isValid ? null : S.current.error_text_payment_id;
199 + }
200 +
201 + void validateXMR(String value, String availableBalance) {
202 + const double maxValue = 18446744.073709551616;
203 + String p = '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$|ALL';
204 + RegExp regExp = new RegExp(p);
205 + if (regExp.hasMatch(value)) {
206 + if (value == 'ALL')
207 + isValid = true;
208 + else {
209 + try {
210 + double dValue = double.parse(value);
211 + double maxAvailable = double.parse(availableBalance);
212 + isValid =
213 + (dValue <= maxAvailable && dValue <= maxValue && dValue > 0);
214 + } catch (e) {
215 + isValid = false;
216 + }
217 + }
218 + } else
219 + isValid = false;
220 + errorMessage = isValid ? null : S.current.error_text_xmr;
221 + }
222 +
223 + void validateFiat(String value, {double maxValue}) {
224 + const double minValue = 0.01;
225 + if (value.isEmpty && cryptoAmount == 'ALL')
226 + isValid = true;
227 + else {
228 + String p = '^([0-9]+([.][0-9]{0,2})?|[.][0-9]{1,2})\$';
229 + RegExp regExp = new RegExp(p);
230 + if (regExp.hasMatch(value)) {
231 + try {
232 + double dValue = double.parse(value);
233 + isValid = (dValue >= minValue && dValue <= maxValue);
234 + } catch (e) {
235 + isValid = false;
236 + }
237 + } else
238 + isValid = false;
239 + }
240 + errorMessage = isValid
241 + ? null
242 + : "Value of amount can't exceed available balance.\n"
243 + "The number of fraction digits must be less or equal to 2";
244 + }
245 +}
lib/src/stores/send/sending_state.dart new
+19
@@ -0,0 +1,19 @@
1 +import 'package:flutter/foundation.dart';
2 +
3 +abstract class SendingState {}
4 +
5 +class SendingStateInitial extends SendingState {}
6 +
7 +class CreatingTransaction extends SendingState {}
8 +
9 +class TransactionCreatedSuccessfully extends SendingState {}
10 +
11 +class TransactionCommiting extends SendingState {}
12 +
13 +class TransactionCommitted extends SendingState {}
14 +
15 +class SendingFailed extends SendingState {
16 + String error;
17 +
18 + SendingFailed({@required this.error});
19 +}
lib/src/stores/settings/settings_store.dart new
+269
@@ -0,0 +1,269 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter/services.dart';
3 +import 'package:mobx/mobx.dart';
4 +import 'package:flutter/foundation.dart';
5 +import 'package:shared_preferences/shared_preferences.dart';
6 +import 'package:hive/hive.dart';
7 +import 'package:cake_wallet/src/domain/common/node.dart';
8 +import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
9 +import 'package:cake_wallet/src/domain/common/fiat_currency.dart';
10 +import 'package:cake_wallet/src/domain/common/transaction_priority.dart';
11 +import 'package:cake_wallet/src/stores/action_list/action_list_display_mode.dart';
12 +import 'package:cake_wallet/src/screens/settings/items/item_headers.dart';
13 +import 'package:cake_wallet/generated/i18n.dart';
14 +
15 +part 'settings_store.g.dart';
16 +
17 +class SettingsStore = SettingsStoreBase with _$SettingsStore;
18 +
19 +abstract class SettingsStoreBase with Store {
20 + static const currentNodeIdKey = 'current_node_id';
21 + static const currentFiatCurrencyKey = 'current_fiat_currency';
22 + static const currentTransactionPriorityKey = 'current_fee_priority';
23 + static const currentBalanceDisplayModeKey = 'current_balance_display_mode';
24 + static const shouldSaveRecipientAddressKey = 'save_recipient_address';
25 + static const allowBiometricalAuthenticationKey =
26 + 'allow_biometrical_authentication';
27 + static const currentDarkTheme = 'dark_theme';
28 + static const displayActionListModeKey = 'display_list_mode';
29 + static const currentPinLength = 'current_pin_length';
30 + static const currentLanguageCode = 'language_code';
31 +
32 + static Future<SettingsStore> load(
33 + {@required SharedPreferences sharedPreferences,
34 + @required Box<Node> nodes,
35 + @required FiatCurrency initialFiatCurrency,
36 + @required TransactionPriority initialTransactionPriority,
37 + @required BalanceDisplayMode initialBalanceDisplayMode}) async {
38 + final currentFiatCurrency = FiatCurrency(
39 + symbol: sharedPreferences.getString(currentFiatCurrencyKey));
40 + final currentTransactionPriority = TransactionPriority.deserialize(
41 + raw: sharedPreferences.getInt(currentTransactionPriorityKey));
42 + final currentBalanceDisplayMode = BalanceDisplayMode.deserialize(
43 + raw: sharedPreferences.getInt(currentBalanceDisplayModeKey));
44 + final shouldSaveRecipientAddress =
45 + sharedPreferences.getBool(shouldSaveRecipientAddressKey);
46 + final allowBiometricalAuthentication =
47 + sharedPreferences.getBool(allowBiometricalAuthenticationKey) == null
48 + ? false
49 + : sharedPreferences.getBool(allowBiometricalAuthenticationKey);
50 + final savedDarkTheme = sharedPreferences.getBool(currentDarkTheme) == null
51 + ? false
52 + : sharedPreferences.getBool(currentDarkTheme);
53 + final actionlistDisplayMode = ObservableList<ActionListDisplayMode>();
54 + actionlistDisplayMode.addAll(deserializeActionlistDisplayModes(
55 + sharedPreferences.getInt(displayActionListModeKey) ?? 11));
56 + final defaultPinLength = sharedPreferences.getInt(currentPinLength) == null
57 + ? 4
58 + : sharedPreferences.getInt(currentPinLength);
59 + final savedLanguageCode =
60 + sharedPreferences.getString(currentLanguageCode) == null
61 + ? 'en'
62 + : sharedPreferences.getString(currentLanguageCode);
63 +
64 + final store = SettingsStore(
65 + sharedPreferences: sharedPreferences,
66 + nodes: nodes,
67 + initialFiatCurrency: currentFiatCurrency,
68 + initialTransactionPriority: currentTransactionPriority,
69 + initialBalanceDisplayMode: currentBalanceDisplayMode,
70 + initialSaveRecipientAddress: shouldSaveRecipientAddress,
71 + initialAllowBiometricalAuthentication: allowBiometricalAuthentication,
72 + initialDarkTheme: savedDarkTheme,
73 + actionlistDisplayMode: actionlistDisplayMode,
74 + initialPinLength: defaultPinLength,
75 + initialLanguageCode: savedLanguageCode);
76 +
77 + await store.loadSettings();
78 +
79 + return store;
80 + }
81 +
82 + @observable
83 + Node node;
84 +
85 + @observable
86 + FiatCurrency fiatCurrency;
87 +
88 + @observable
89 + ObservableList<ActionListDisplayMode> actionlistDisplayMode;
90 +
91 + @observable
92 + TransactionPriority transactionPriority;
93 +
94 + @observable
95 + BalanceDisplayMode balanceDisplayMode;
96 +
97 + @observable
98 + bool shouldSaveRecipientAddress;
99 +
100 + @observable
101 + bool allowBiometricalAuthentication;
102 +
103 + @observable
104 + bool isDarkTheme;
105 +
106 + @observable
107 + int defaultPinLength;
108 + String languageCode;
109 +
110 + @observable
111 + Map<String, String> itemHeaders;
112 +
113 + SharedPreferences _sharedPreferences;
114 + Box<Node> _nodes;
115 +
116 + SettingsStoreBase(
117 + {@required SharedPreferences sharedPreferences,
118 + @required Box<Node> nodes,
119 + @required FiatCurrency initialFiatCurrency,
120 + @required TransactionPriority initialTransactionPriority,
121 + @required BalanceDisplayMode initialBalanceDisplayMode,
122 + @required bool initialSaveRecipientAddress,
123 + @required bool initialAllowBiometricalAuthentication,
124 + @required bool initialDarkTheme,
125 + this.actionlistDisplayMode,
126 + @required int initialPinLength,
127 + @required String initialLanguageCode}) {
128 + fiatCurrency = initialFiatCurrency;
129 + transactionPriority = initialTransactionPriority;
130 + balanceDisplayMode = initialBalanceDisplayMode;
131 + shouldSaveRecipientAddress = initialSaveRecipientAddress;
132 + _sharedPreferences = sharedPreferences;
133 + _nodes = nodes;
134 + allowBiometricalAuthentication = initialAllowBiometricalAuthentication;
135 + isDarkTheme = initialDarkTheme;
136 + defaultPinLength = initialPinLength;
137 + languageCode = initialLanguageCode;
138 + itemHeaders = Map();
139 +
140 + actionlistDisplayMode.observe(
141 + (dynamic _) => _sharedPreferences.setInt(displayActionListModeKey,
142 + serializeActionlistDisplayModes(actionlistDisplayMode)),
143 + fireImmediately: false);
144 + }
145 +
146 + @action
147 + Future setAllowBiometricalAuthentication(
148 + {@required bool allowBiometricalAuthentication}) async {
149 + this.allowBiometricalAuthentication = allowBiometricalAuthentication;
150 + await _sharedPreferences.setBool(
151 + allowBiometricalAuthenticationKey, allowBiometricalAuthentication);
152 + }
153 +
154 + @action
155 + Future saveDarkTheme({@required bool isDarkTheme}) async {
156 + this.isDarkTheme = isDarkTheme;
157 + SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
158 + statusBarColor: isDarkTheme ? Colors.black : Colors.white));
159 + await _sharedPreferences.setBool(currentDarkTheme, isDarkTheme);
160 + }
161 +
162 + @action
163 + Future saveLanguageCode({@required String languageCode}) async {
164 + this.languageCode = languageCode;
165 + await _sharedPreferences.setString(currentLanguageCode, languageCode);
166 + }
167 +
168 + @action
169 + Future setCurrentNode({@required Node node}) async {
170 + this.node = node;
171 + await _sharedPreferences.setInt(currentNodeIdKey, node.key);
172 + }
173 +
174 + @action
175 + Future setCurrentFiatCurrency({@required FiatCurrency currency}) async {
176 + this.fiatCurrency = currency;
177 + await _sharedPreferences.setString(
178 + currentFiatCurrencyKey, fiatCurrency.serialize());
179 + }
180 +
181 + @action
182 + Future setCurrentTransactionPriority(
183 + {@required TransactionPriority priority}) async {
184 + this.transactionPriority = priority;
185 + await _sharedPreferences.setInt(
186 + currentTransactionPriorityKey, priority.serialize());
187 + }
188 +
189 + @action
190 + Future setCurrentBalanceDisplayMode(
191 + {@required BalanceDisplayMode balanceDisplayMode}) async {
192 + this.balanceDisplayMode = balanceDisplayMode;
193 + await _sharedPreferences.setInt(
194 + currentBalanceDisplayModeKey, balanceDisplayMode.serialize());
195 + }
196 +
197 + @action
198 + Future setSaveRecipientAddress(
199 + {@required bool shouldSaveRecipientAddress}) async {
200 + this.shouldSaveRecipientAddress = shouldSaveRecipientAddress;
201 + await _sharedPreferences.setBool(
202 + shouldSaveRecipientAddressKey, shouldSaveRecipientAddress);
203 + }
204 +
205 + Future loadSettings() async => node = await _fetchCurrentNode();
206 +
207 + @action
208 + void toggleTransactionsDisplay() =>
209 + actionlistDisplayMode.contains(ActionListDisplayMode.transactions)
210 + ? _hideTransaction()
211 + : _showTransaction();
212 +
213 + @action
214 + void toggleTradesDisplay() =>
215 + actionlistDisplayMode.contains(ActionListDisplayMode.trades)
216 + ? _hideTrades()
217 + : _showTrades();
218 +
219 + @action
220 + void _hideTransaction() =>
221 + actionlistDisplayMode.remove(ActionListDisplayMode.transactions);
222 +
223 + @action
224 + void _hideTrades() =>
225 + actionlistDisplayMode.remove(ActionListDisplayMode.trades);
226 +
227 + @action
228 + void _showTransaction() =>
229 + actionlistDisplayMode.add(ActionListDisplayMode.transactions);
230 +
231 + @action
232 + void _showTrades() => actionlistDisplayMode.add(ActionListDisplayMode.trades);
233 +
234 + @action
235 + Future setDefaultPinLength({@required int pinLength}) async {
236 + this.defaultPinLength = pinLength;
237 + await _sharedPreferences.setInt(currentPinLength, pinLength);
238 + }
239 +
240 + Future<Node> _fetchCurrentNode() async {
241 + final id = _sharedPreferences.getInt(currentNodeIdKey);
242 +
243 + return _nodes.get(id);
244 + }
245 +
246 + @action
247 + void setItemHeaders() {
248 + itemHeaders.clear();
249 + itemHeaders.addAll({
250 + ItemHeaders.nodes: S.current.settings_nodes,
251 + ItemHeaders.currentNode: S.current.settings_current_node,
252 + ItemHeaders.wallets: S.current.settings_wallets,
253 + ItemHeaders.displayBalanceAs: S.current.settings_display_balance_as,
254 + ItemHeaders.currency: S.current.settings_currency,
255 + ItemHeaders.feePriority: S.current.settings_fee_priority,
256 + ItemHeaders.saveRecipientAddress:
257 + S.current.settings_save_recipient_address,
258 + ItemHeaders.personal: S.current.settings_personal,
259 + ItemHeaders.changePIN: S.current.settings_change_pin,
260 + ItemHeaders.changeLanguage: S.current.settings_change_language,
261 + ItemHeaders.allowBiometricalAuthentication:
262 + S.current.settings_allow_biometrical_authentication,
263 + ItemHeaders.darkMode: S.current.settings_dark_mode,
264 + ItemHeaders.support: S.current.settings_support,
265 + ItemHeaders.termsAndConditions: S.current.settings_terms_and_conditions,
266 + ItemHeaders.faq: S.current.faq
267 + });
268 + }
269 +}
lib/src/stores/subaddress_creation/subaddress_creation_state.dart new
+13
@@ -0,0 +1,13 @@
1 +abstract class SubaddressCreationState {}
2 +
3 +class SubaddressCreationStateInitial extends SubaddressCreationState {}
4 +
5 +class SubaddressIsCreating extends SubaddressCreationState {}
6 +
7 +class SubaddressCreatedSuccessfully extends SubaddressCreationState {}
8 +
9 +class SubaddressCreationFailure extends SubaddressCreationState {
10 + String error;
11 +
12 + SubaddressCreationFailure({this.error});
13 +}
\ No newline at end of file
lib/src/stores/subaddress_creation/subaddress_creation_store.dart new
+85
@@ -0,0 +1,85 @@
1 +import 'dart:async';
2 +import 'package:flutter/foundation.dart';
3 +import 'package:mobx/mobx.dart';
4 +import 'package:cake_wallet/src/domain/common/wallet.dart';
5 +import 'package:cake_wallet/src/domain/monero/monero_wallet.dart';
6 +import 'package:cake_wallet/src/domain/monero/subaddress_list.dart';
7 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
8 +import 'package:cake_wallet/src/stores/subaddress_creation/subaddress_creation_state.dart';
9 +import 'package:cake_wallet/src/domain/monero/account.dart';
10 +import 'package:cake_wallet/generated/i18n.dart';
11 +
12 +part 'subaddress_creation_store.g.dart';
13 +
14 +class SubadrressCreationStore = SubadrressCreationStoreBase
15 + with _$SubadrressCreationStore;
16 +
17 +abstract class SubadrressCreationStoreBase with Store {
18 + SubaddressCreationState state;
19 +
20 + @observable
21 + bool isValid;
22 +
23 + @observable
24 + String errorMessage;
25 +
26 + SubaddressList _subaddressList;
27 + StreamSubscription<Wallet> _onWalletChangeSubscription;
28 + StreamSubscription<Account> _onAccountChangeSubscription;
29 + Account _account;
30 +
31 + SubadrressCreationStoreBase({@required WalletService walletService}) {
32 + state = SubaddressCreationStateInitial();
33 +
34 + if (walletService.currentWallet != null) {
35 + _onWalletChanged(walletService.currentWallet);
36 + }
37 +
38 + _onWalletChangeSubscription =
39 + walletService.onWalletChange.listen(_onWalletChanged);
40 + }
41 +
42 + @override
43 + void dispose() {
44 + _onWalletChangeSubscription.cancel();
45 +
46 + if (_onAccountChangeSubscription != null) {
47 + _onAccountChangeSubscription.cancel();
48 + }
49 +
50 + super.dispose();
51 + }
52 +
53 + Future add({String label}) async {
54 + try {
55 + state = SubaddressIsCreating();
56 + await _subaddressList.addSubaddress(
57 + accountIndex: _account.id, label: label);
58 + state = SubaddressCreatedSuccessfully();
59 + } catch (e) {
60 + state = SubaddressCreationFailure(error: e.toString());
61 + }
62 + }
63 +
64 + Future _onWalletChanged(Wallet wallet) async {
65 + if (wallet is MoneroWallet) {
66 + _account = wallet.account;
67 + _subaddressList = wallet.getSubaddress();
68 +
69 + _onAccountChangeSubscription = wallet.onAccountChange.listen((account) async {
70 + _account = account;
71 + _subaddressList.update(accountIndex: account.id);
72 + });
73 + return;
74 + }
75 +
76 + print('Incorrect wallet type for this operation (SubaddressList)');
77 + }
78 +
79 + void validateSubaddressName(String value) {
80 + String p = '''^[^`,'"]{1,20}\$''';
81 + RegExp regExp = new RegExp(p);
82 + isValid = regExp.hasMatch(value);
83 + errorMessage = isValid ? null : S.current.error_text_subaddress_name;
84 + }
85 +}
lib/src/stores/subaddress_list/subaddress_list_store.dart new
+77
@@ -0,0 +1,77 @@
1 +import 'dart:async';
2 +import 'package:flutter/foundation.dart';
3 +import 'package:mobx/mobx.dart';
4 +import 'package:cake_wallet/src/domain/common/wallet.dart';
5 +import 'package:cake_wallet/src/domain/monero/monero_wallet.dart';
6 +import 'package:cake_wallet/src/domain/monero/subaddress.dart';
7 +import 'package:cake_wallet/src/domain/monero/subaddress_list.dart';
8 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
9 +import 'package:cake_wallet/src/domain/monero/account.dart';
10 +
11 +part 'subaddress_list_store.g.dart';
12 +
13 +class SubaddressListStore = SubaddressListStoreBase with _$SubaddressListStore;
14 +
15 +abstract class SubaddressListStoreBase with Store {
16 + @observable
17 + ObservableList<Subaddress> subaddresses;
18 +
19 + SubaddressList _subaddressList;
20 + StreamSubscription<Wallet> _onWalletChangeSubscription;
21 + StreamSubscription<List<Subaddress>> _onSubaddressesChangeSubscription;
22 + StreamSubscription<Account> _onAccountChangeSubscription;
23 + Account _account;
24 +
25 + SubaddressListStoreBase({@required WalletService walletService}) {
26 + subaddresses = ObservableList<Subaddress>();
27 +
28 + if (walletService.currentWallet != null) {
29 + _onWalletChanged(walletService.currentWallet);
30 + }
31 +
32 + _onWalletChangeSubscription =
33 + walletService.onWalletChange.listen(_onWalletChanged);
34 + }
35 +
36 + @override
37 + void dispose() {
38 + if (_onSubaddressesChangeSubscription != null) {
39 + _onSubaddressesChangeSubscription.cancel();
40 + }
41 +
42 + if (_onAccountChangeSubscription != null) {
43 + _onAccountChangeSubscription.cancel();
44 + }
45 +
46 + _onWalletChangeSubscription.cancel();
47 + super.dispose();
48 + }
49 +
50 + Future _updateSubaddressList({int accountIndex}) async {
51 + await _subaddressList.refresh(accountIndex: accountIndex);
52 + subaddresses = ObservableList.of(_subaddressList.getAll());
53 + }
54 +
55 + Future _onWalletChanged(Wallet wallet) async {
56 + if (_onSubaddressesChangeSubscription != null) {
57 + _onSubaddressesChangeSubscription.cancel();
58 + }
59 +
60 + if (wallet is MoneroWallet) {
61 + _account = wallet.account;
62 + _subaddressList = wallet.getSubaddress();
63 + _onSubaddressesChangeSubscription = _subaddressList.subaddresses
64 + .listen((subaddress) => subaddresses = ObservableList.of(subaddress));
65 + await _updateSubaddressList(accountIndex: _account.id);
66 +
67 + _onAccountChangeSubscription = wallet.onAccountChange.listen((account) async {
68 + _account = account;
69 + await _updateSubaddressList(accountIndex: account.id);
70 + });
71 +
72 + return;
73 + }
74 +
75 + print('Incorrect wallet type for this operation (SubaddressList)');
76 + }
77 +}
lib/src/stores/sync/sync_store.dart new
+50
@@ -0,0 +1,50 @@
1 +import 'dart:async';
2 +import 'package:flutter/foundation.dart';
3 +import 'package:mobx/mobx.dart';
4 +import 'package:cake_wallet/src/domain/common/sync_status.dart';
5 +import 'package:cake_wallet/src/domain/common/wallet.dart';
6 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
7 +
8 +part 'sync_store.g.dart';
9 +
10 +class SyncStore = SyncStoreBase with _$SyncStore;
11 +
12 +abstract class SyncStoreBase with Store {
13 + @observable
14 + SyncStatus status;
15 +
16 + StreamSubscription<Wallet> _onWalletChangeSubscription;
17 + StreamSubscription<SyncStatus> _onSyncStatusChangeSubscription;
18 +
19 + SyncStoreBase(
20 + {SyncStatus syncStatus = const NotConnectedSyncStatus(),
21 + @required WalletService walletService}) {
22 + status = syncStatus;
23 +
24 + if (walletService.currentWallet != null) {
25 + _onWalletChanged(walletService.currentWallet);
26 + }
27 +
28 + _onWalletChangeSubscription =
29 + walletService.onWalletChange.listen(_onWalletChanged);
30 + }
31 +
32 + @override
33 + void dispose() {
34 + if (_onSyncStatusChangeSubscription != null) {
35 + _onSyncStatusChangeSubscription.cancel();
36 + }
37 +
38 + _onWalletChangeSubscription.cancel();
39 + super.dispose();
40 + }
41 +
42 + void _onWalletChanged(Wallet wallet) {
43 + if (_onSyncStatusChangeSubscription != null) {
44 + _onSyncStatusChangeSubscription.cancel();
45 + }
46 +
47 + _onSyncStatusChangeSubscription =
48 + wallet.syncStatus.listen((status) => this.status = status);
49 + }
50 +}
lib/src/stores/user/user_store.dart new
+32
@@ -0,0 +1,32 @@
1 +import 'package:mobx/mobx.dart';
2 +import 'package:flutter/foundation.dart';
3 +import 'package:cake_wallet/src/domain/services/user_service.dart';
4 +import 'package:cake_wallet/src/stores/user/user_store_state.dart';
5 +
6 +part 'user_store.g.dart';
7 +
8 +class UserStore = UserStoreBase with _$UserStore;
9 +
10 +abstract class UserStoreBase with Store {
11 + UserService accountService;
12 +
13 + @observable
14 + UserStoreState state;
15 +
16 + @observable
17 + String errorMessage;
18 +
19 + UserStoreBase({@required this.accountService});
20 +
21 + @action
22 + Future set({String password}) async {
23 + state = UserStoreStateInitial();
24 +
25 + try {
26 + await accountService.setPassword(password);
27 + state = PinCodeSetSuccesfully();
28 + } catch(e) {
29 + state = PinCodeSetFailed(error: e.toString());
30 + }
31 + }
32 +}
lib/src/stores/user/user_store_state.dart new
+13
@@ -0,0 +1,13 @@
1 +import 'package:flutter/foundation.dart';
2 +
3 +abstract class UserStoreState {}
4 +
5 +class UserStoreStateInitial extends UserStoreState {}
6 +
7 +class PinCodeSetSuccesfully extends UserStoreState {}
8 +
9 +class PinCodeSetFailed extends UserStoreState {
10 + String error;
11 +
12 + PinCodeSetFailed({@required this.error});
13 +}
lib/src/stores/wallet/wallet_keys_store.dart new
+37
@@ -0,0 +1,37 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:mobx/mobx.dart';
3 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
4 +
5 +part 'wallet_keys_store.g.dart';
6 +
7 +class WalletKeysStore = WalletKeysStoreBase with _$WalletKeysStore;
8 +
9 +abstract class WalletKeysStoreBase with Store {
10 + @observable
11 + String publicViewKey;
12 +
13 + @observable
14 + String privateViewKey;
15 +
16 + @observable
17 + String publicSpendKey;
18 +
19 + @observable
20 + String privateSpendKey;
21 +
22 + WalletKeysStoreBase({@required WalletService walletService}) {
23 + publicViewKey = '';
24 + privateViewKey = '';
25 + publicSpendKey = '';
26 + privateSpendKey = '';
27 +
28 + if (walletService.currentWallet != null) {
29 + walletService.getKeys().then((keys) {
30 + publicViewKey = keys['publicViewKey'];
31 + privateViewKey = keys['privateViewKey'];
32 + publicSpendKey = keys['publicSpendKey'];
33 + privateSpendKey = keys['privateSpendKey'];
34 + });
35 + }
36 + }
37 +}
lib/src/stores/wallet/wallet_store.dart new
+159
@@ -0,0 +1,159 @@
1 +import 'dart:async';
2 +import 'package:cake_wallet/src/domain/common/node.dart';
3 +import 'package:mobx/mobx.dart';
4 +import 'package:cake_wallet/src/domain/common/wallet.dart';
5 +import 'package:cake_wallet/src/domain/monero/account.dart';
6 +import 'package:cake_wallet/src/domain/monero/monero_wallet.dart';
7 +import 'package:cake_wallet/src/domain/monero/subaddress.dart';
8 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
9 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
10 +import 'package:cake_wallet/src/stores/settings/settings_store.dart';
11 +import 'package:cake_wallet/generated/i18n.dart';
12 +
13 +part 'wallet_store.g.dart';
14 +
15 +class WalletStore = WalletStoreBase with _$WalletStore;
16 +
17 +abstract class WalletStoreBase with Store {
18 + @observable
19 + String address;
20 +
21 + @observable
22 + String name;
23 +
24 + @observable
25 + Subaddress subaddress;
26 +
27 + @observable
28 + Account account;
29 +
30 + @observable
31 + CryptoCurrency type;
32 +
33 + @observable
34 + String amountValue;
35 +
36 + @observable
37 + bool isValid;
38 +
39 + @observable
40 + String errorMessage;
41 +
42 + String get id => name + type.toString().toLowerCase();
43 +
44 + WalletService _walletService;
45 + SettingsStore _settingsStore;
46 + StreamSubscription<Wallet> _onWalletChangeSubscription;
47 + StreamSubscription<Account> _onAccountChangeSubscription;
48 + StreamSubscription<Subaddress> _onSubaddressChangeSubscription;
49 +
50 +
51 + WalletStoreBase({WalletService walletService, SettingsStore settingsStore}) {
52 + _walletService = walletService;
53 + _settingsStore = settingsStore;
54 + name = '';
55 + type = CryptoCurrency.xmr;
56 + amountValue = '';
57 +
58 + if (_walletService.currentWallet != null) {
59 + _onWalletChanged(_walletService.currentWallet);
60 + }
61 +
62 + _onWalletChangeSubscription = _walletService.onWalletChange
63 + .listen((wallet) async => await _onWalletChanged(wallet));
64 + }
65 +
66 + @override
67 + void dispose() {
68 + if (_onWalletChangeSubscription != null) {
69 + _onWalletChangeSubscription.cancel();
70 + }
71 +
72 + if (_onAccountChangeSubscription != null) {
73 + _onAccountChangeSubscription.cancel();
74 + }
75 +
76 + if (_onSubaddressChangeSubscription != null) {
77 + _onSubaddressChangeSubscription.cancel();
78 + }
79 +
80 + super.dispose();
81 + }
82 +
83 + @action
84 + void setAccount(Account account) {
85 + final wallet = _walletService.currentWallet;
86 +
87 + if (wallet is MoneroWallet) {
88 + this.account = account;
89 + wallet.changeAccount(account);
90 + }
91 + }
92 +
93 + @action
94 + void setSubaddress(Subaddress subaddress) {
95 + final wallet = _walletService.currentWallet;
96 +
97 + if (wallet is MoneroWallet) {
98 + this.subaddress = subaddress;
99 + wallet.changeCurrentSubaddress(subaddress);
100 + }
101 + }
102 +
103 + @action
104 + Future reconnect() async =>
105 + await _walletService.connectToNode(node: _settingsStore.node);
106 +
107 + @action
108 + Future rescan({int restoreHeight}) async =>
109 + await _walletService.rescan(restoreHeight: restoreHeight);
110 +
111 + @action
112 + Future startSync() async => await _walletService.startSync();
113 +
114 + @action
115 + Future connectToNode({Node node}) async => await _walletService.connectToNode(node: node);
116 +
117 + Future _onWalletChanged(Wallet wallet) async {
118 + if (this == null) {
119 + return;
120 + }
121 +
122 + wallet.onNameChange.listen((name) => this.name = name);
123 + wallet.onAddressChange.listen((address) => this.address = address);
124 +
125 + if (wallet is MoneroWallet) {
126 + _onAccountChangeSubscription = wallet.onAccountChange.listen((account) => this.account = account);
127 + _onSubaddressChangeSubscription = wallet.subaddress.listen((subaddress) => this.subaddress = subaddress);
128 + }
129 + }
130 +
131 + @action
132 + onChangedAmountValue(String value) {
133 + amountValue = value.isNotEmpty ? '?tx_amount=' + value : '';
134 + }
135 +
136 + @action
137 + void validateAmount(String value) {
138 + const double maxValue = 18446744.073709551616;
139 +
140 + if (value.isEmpty) {
141 + isValid = true;
142 + } else {
143 + String p = '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$';
144 + RegExp regExp = new RegExp(p);
145 + if (regExp.hasMatch(value)) {
146 + try {
147 + double dValue = double.parse(value);
148 + isValid = dValue <= maxValue;
149 + } catch (e) {
150 + isValid = false;
151 + }
152 + } else isValid = false;
153 + }
154 +
155 + errorMessage = isValid ? null : S.current.error_text_amount;
156 + }
157 +
158 + Future<bool> isConnected() async => await _walletService.isConnected();
159 +}
lib/src/stores/wallet_creation/wallet_creation_state.dart new
+14
@@ -0,0 +1,14 @@
1 +import 'package:flutter/foundation.dart';
2 +
3 +abstract class WalletCreationState {}
4 +
5 +class WalletCreationStateInitial extends WalletCreationState {}
6 +
7 +class WalletIsCreating extends WalletCreationState {}
8 +
9 +class WalletCreatedSuccessfully extends WalletCreationState {}
10 +
11 +class WalletCreationFailure extends WalletCreationState {
12 + String error;
13 + WalletCreationFailure({@required this.error});
14 +}
\ No newline at end of file
lib/src/stores/wallet_creation/wallet_creation_store.dart new
+54
@@ -0,0 +1,54 @@
1 +import 'package:mobx/mobx.dart';
2 +import 'package:flutter/foundation.dart';
3 +import 'package:shared_preferences/shared_preferences.dart';
4 +import 'package:cake_wallet/src/domain/services/wallet_list_service.dart';
5 +import 'package:cake_wallet/src/stores/wallet_creation/wallet_creation_state.dart';
6 +import 'package:cake_wallet/src/stores/authentication/authentication_store.dart';
7 +import 'package:cake_wallet/generated/i18n.dart';
8 +
9 +part 'wallet_creation_store.g.dart';
10 +
11 +class WalletCreationStore = WalletCreationStoreBase with _$WalletCreationStore;
12 +
13 +abstract class WalletCreationStoreBase with Store {
14 + final AuthenticationStore authStore;
15 + final WalletListService walletListService;
16 + final SharedPreferences sharedPreferences;
17 +
18 + @observable
19 + WalletCreationState state;
20 +
21 + @observable
22 + String errorMessage;
23 +
24 + @observable
25 + bool isValid;
26 +
27 + WalletCreationStoreBase(
28 + {@required this.authStore,
29 + @required this.walletListService,
30 + @required this.sharedPreferences}) {
31 + state = WalletCreationStateInitial();
32 + }
33 +
34 + @action
35 + Future create({String name}) async {
36 + state = WalletCreationStateInitial();
37 +
38 + try {
39 + state = WalletIsCreating();
40 + await walletListService.create(name);
41 + authStore.created();
42 + state = WalletCreatedSuccessfully();
43 + } catch (e) {
44 + state = WalletCreationFailure(error: e.toString());
45 + }
46 + }
47 +
48 + void validateWalletName(String value) {
49 + String p = '^[a-zA-Z0-9_]{1,15}\$';
50 + RegExp regExp = new RegExp(p);
51 + isValid = regExp.hasMatch(value);
52 + errorMessage = isValid ? null : S.current.error_text_wallet_name;
53 + }
54 +}
lib/src/stores/wallet_list/wallet_list_store.dart new
+46
@@ -0,0 +1,46 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:mobx/mobx.dart';
3 +import 'package:cake_wallet/src/domain/common/wallet_description.dart';
4 +import 'package:cake_wallet/src/domain/services/wallet_list_service.dart';
5 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
6 +
7 +part 'wallet_list_store.g.dart';
8 +
9 +class WalletListStore = WalletListStoreBase with _$WalletListStore;
10 +
11 +abstract class WalletListStoreBase with Store {
12 + @observable
13 + List<WalletDescription> wallets;
14 +
15 + WalletListService _walletListService;
16 + WalletService _walletService;
17 +
18 + WalletListStoreBase(
19 + {@required WalletListService walletListService,
20 + @required WalletService walletService}) {
21 + _walletListService = walletListService;
22 + _walletService = walletService;
23 + wallets = [];
24 + walletListService.getAll().then((walletList) => wallets = walletList);
25 + }
26 +
27 + bool isCurrentWallet(WalletDescription wallet) {
28 + return _walletService.description?.name == wallet.name;
29 + }
30 +
31 + @action
32 + Future updateWalletList() async {
33 + wallets = await _walletListService.getAll();
34 + }
35 +
36 + @action
37 + Future loadWallet(WalletDescription wallet) async {
38 + await _walletListService.openWallet(wallet.name);
39 + }
40 +
41 + @action
42 + Future remove(WalletDescription wallet) async {
43 + await _walletListService.remove(wallet);
44 + await updateWalletList();
45 + }
46 +}
lib/src/stores/wallet_restoration/wallet_restoration_state.dart new
+14
@@ -0,0 +1,14 @@
1 +import 'package:flutter/foundation.dart';
2 +
3 +abstract class WalletRestorationState {}
4 +
5 +class WalletRestorationStateInitial extends WalletRestorationState {}
6 +
7 +class WalletIsRestoring extends WalletRestorationState {}
8 +
9 +class WalletRestoredSuccessfully extends WalletRestorationState {}
10 +
11 +class WalletRestorationFailure extends WalletRestorationState {
12 + String error;
13 + WalletRestorationFailure({@required this.error});
14 +}
\ No newline at end of file
lib/src/stores/wallet_restoration/wallet_restoration_store.dart new
+154
@@ -0,0 +1,154 @@
1 +import 'package:mobx/mobx.dart';
2 +import 'package:flutter/foundation.dart';
3 +import 'package:shared_preferences/shared_preferences.dart';
4 +import 'package:cake_wallet/src/domain/services/wallet_list_service.dart';
5 +import 'package:cake_wallet/src/domain/common/mnemotic_item.dart';
6 +import 'package:cake_wallet/src/stores/wallet_restoration/wallet_restoration_state.dart';
7 +import 'package:cake_wallet/src/stores/authentication/authentication_store.dart';
8 +import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
9 +import 'package:cake_wallet/generated/i18n.dart';
10 +
11 +part 'wallet_restoration_store.g.dart';
12 +
13 +class WalletRestorationStore = WalleRestorationStoreBase
14 + with _$WalletRestorationStore;
15 +
16 +abstract class WalleRestorationStoreBase with Store {
17 + final AuthenticationStore authStore;
18 + final WalletListService walletListService;
19 + final SharedPreferences sharedPreferences;
20 +
21 + @observable
22 + WalletRestorationState state;
23 +
24 + @observable
25 + String errorMessage;
26 +
27 + @observable
28 + bool isValid;
29 +
30 + @observable
31 + List<MnemoticItem> seed;
32 +
33 + WalleRestorationStoreBase(
34 + {this.seed,
35 + @required this.authStore,
36 + @required this.walletListService,
37 + @required this.sharedPreferences}) {
38 + state = WalletRestorationStateInitial();
39 + }
40 +
41 + @action
42 + Future restoreFromSeed({String name, String seed, int restoreHeight}) async {
43 + state = WalletRestorationStateInitial();
44 + final _seed = seed ?? _seedText();
45 +
46 + try {
47 + state = WalletIsRestoring();
48 + await walletListService.restoreFromSeed(name, _seed, restoreHeight);
49 + authStore.restored();
50 + state = WalletRestoredSuccessfully();
51 + } catch (e) {
52 + state = WalletRestorationFailure(error: e.toString());
53 + }
54 + }
55 +
56 + @action
57 + Future restoreFromKeys(
58 + {String name,
59 + String address,
60 + String viewKey,
61 + String spendKey,
62 + int restoreHeight}) async {
63 + state = WalletRestorationStateInitial();
64 +
65 + try {
66 + state = WalletIsRestoring();
67 + await walletListService.restoreFromKeys(
68 + name, restoreHeight, address, viewKey, spendKey);
69 + authStore.restored();
70 + state = WalletRestoredSuccessfully();
71 + } catch (e) {
72 + state = WalletRestorationFailure(error: e.toString());
73 + }
74 + }
75 +
76 + @action
77 + void setSeed(List<MnemoticItem> seed) {
78 + this.seed = seed;
79 + validateSeed(seed);
80 + }
81 +
82 + @action
83 + void validateSeed(List<MnemoticItem> seed) {
84 + final _seed = seed != null ? seed : this.seed;
85 + bool isValid = _seed.length == 25;
86 +
87 + if (!isValid) {
88 + errorMessage = S.current.wallet_restoration_store_incorrect_seed_length;
89 + this.isValid = isValid;
90 + return;
91 + }
92 +
93 + for (final item in _seed) {
94 + if (!item.isCorrect()) {
95 + isValid = false;
96 + break;
97 + }
98 + }
99 +
100 + if (isValid) {
101 + errorMessage = null;
102 + }
103 +
104 + this.isValid = isValid;
105 + return;
106 + }
107 +
108 + String _seedText() {
109 + return seed.fold('', (acc, item) => acc + ' ' + item.toString());
110 + }
111 +
112 + void validateWalletName(String value) {
113 + String p = '^[a-zA-Z0-9_]{1,15}\$';
114 + RegExp regExp = new RegExp(p);
115 + isValid = regExp.hasMatch(value);
116 + errorMessage = isValid ? null : S.current.error_text_wallet_name;
117 + }
118 +
119 + void validateAddress(String value, {CryptoCurrency cryptoCurrency}) {
120 + // XMR (95), BTC (34), ETH (42), LTC (34), BCH (42), DASH (34)
121 + String p = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$';
122 + RegExp regExp = new RegExp(p);
123 + isValid = regExp.hasMatch(value);
124 + if (isValid && cryptoCurrency != null) {
125 + switch (cryptoCurrency.toString()) {
126 + case 'XMR':
127 + isValid = (value.length == 95);
128 + break;
129 + case 'BTC':
130 + isValid = (value.length == 34);
131 + break;
132 + case 'ETH':
133 + isValid = (value.length == 42);
134 + break;
135 + case 'LTC':
136 + isValid = (value.length == 34);
137 + break;
138 + case 'BCH':
139 + isValid = (value.length == 42);
140 + break;
141 + case 'DASH':
142 + isValid = (value.length == 34);
143 + }
144 + }
145 + errorMessage = isValid ? null : S.current.error_text_address;
146 + }
147 +
148 + void validateKeys(String value) {
149 + String p = '^[A-Fa-f0-9]{64}\$';
150 + RegExp regExp = new RegExp(p);
151 + isValid = regExp.hasMatch(value);
152 + errorMessage = isValid ? null : S.current.error_text_keys;
153 + }
154 +}
lib/src/stores/wallet_seed/wallet_seed_store.dart new
+24
@@ -0,0 +1,24 @@
1 +import 'package:flutter/foundation.dart';
2 +import 'package:mobx/mobx.dart';
3 +import 'package:cake_wallet/src/domain/services/wallet_service.dart';
4 +
5 +part 'wallet_seed_store.g.dart';
6 +
7 +class WalletSeedStore = WalletSeedStoreBase with _$WalletSeedStore;
8 +
9 +abstract class WalletSeedStoreBase with Store {
10 + @observable
11 + String name;
12 +
13 + @observable
14 + String seed;
15 +
16 + WalletSeedStoreBase({@required WalletService walletService}) {
17 + seed = '';
18 +
19 + if (walletService.currentWallet != null) {
20 + walletService.getSeed().then((seed) => this.seed = seed);
21 + walletService.getName().then((name) => this.name = name);
22 + }
23 + }
24 +}
lib/src/util/index.dart
lib/src/widgets/address_text_field.dart new
+157
@@ -0,0 +1,157 @@
1 +import 'package:cake_wallet/routes.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:cake_wallet/palette.dart';
4 +import 'package:cake_wallet/generated/i18n.dart';
5 +import 'package:cake_wallet/src/domain/common/contact.dart';
6 +import 'package:cake_wallet/src/domain/monero/subaddress.dart';
7 +import 'package:cake_wallet/src/domain/common/qr_scanner.dart';
8 +
9 +enum AddressTextFieldOption { qrCode, addressBook, subaddressList }
10 +
11 +class AddressTextField extends StatelessWidget {
12 + static const prefixIconWidth = 34.0;
13 + static const prefixIconHeight = 34.0;
14 + static const spaceBetweenPrefixIcons = 10.0;
15 +
16 + final TextEditingController controller;
17 + final bool isActive;
18 + final String placeholder;
19 + final Function(Uri) onURIScanned;
20 + final List<AddressTextFieldOption> options;
21 + final FormFieldValidator<String> validator;
22 +
23 + AddressTextField(
24 + {@required this.controller,
25 + this.isActive = true,
26 + this.placeholder,
27 + this.options = const [
28 + AddressTextFieldOption.qrCode,
29 + AddressTextFieldOption.addressBook
30 + ],
31 + this.onURIScanned,
32 + this.validator});
33 +
34 + @override
35 + Widget build(BuildContext context) {
36 + return TextFormField(
37 + onFieldSubmitted: (_) => FocusScope.of(context).unfocus(),
38 + enabled: isActive,
39 + controller: controller,
40 + decoration: InputDecoration(
41 + suffixIcon: SizedBox(
42 + width: prefixIconWidth * options.length +
43 + (spaceBetweenPrefixIcons * options.length),
44 + child: Row(
45 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
46 + children: [
47 + SizedBox(width: 5),
48 + if (this.options.contains(AddressTextFieldOption.qrCode)) ...[
49 + Container(
50 + width: prefixIconWidth,
51 + height: prefixIconHeight,
52 + padding: EdgeInsets.only(top: 0),
53 + child: InkWell(
54 + onTap: () async => _presentQRScanner(context),
55 + child: Container(
56 + padding: EdgeInsets.all(8),
57 + decoration: BoxDecoration(
58 + color: Palette.wildDarkBlueWithOpacity,
59 + borderRadius:
60 + BorderRadius.all(Radius.circular(8))),
61 + child: Image.asset('assets/images/qr_code_icon.png')),
62 + ))
63 + ],
64 + if (this
65 + .options
66 + .contains(AddressTextFieldOption.addressBook)) ...[
67 + Container(
68 + width: prefixIconWidth,
69 + height: prefixIconHeight,
70 + padding: EdgeInsets.only(top: 0),
71 + child: InkWell(
72 + onTap: () async => _presetAddressBookPicker(context),
73 + child: Container(
74 + padding: EdgeInsets.all(8),
75 + decoration: BoxDecoration(
76 + color: Palette.wildDarkBlueWithOpacity,
77 + borderRadius:
78 + BorderRadius.all(Radius.circular(8))),
79 + child: Image.asset(
80 + 'assets/images/address_book_icon.png')),
81 + ))
82 + ],
83 + if (this
84 + .options
85 + .contains(AddressTextFieldOption.subaddressList)) ...[
86 + Container(
87 + width: prefixIconWidth,
88 + height: prefixIconHeight,
89 + padding: EdgeInsets.only(top: 0),
90 + child: InkWell(
91 + onTap: () async => _presetSubaddressListPicker(context),
92 + child: Container(
93 + padding: EdgeInsets.all(8),
94 + decoration: BoxDecoration(
95 + color: Palette.wildDarkBlueWithOpacity,
96 + borderRadius:
97 + BorderRadius.all(Radius.circular(8))),
98 + child: Image.asset(
99 + 'assets/images/receive_icon_raw.png')),
100 + ))
101 + ],
102 + ],
103 + ),
104 + ),
105 + hintStyle: TextStyle(color: Theme.of(context).hintColor),
106 + hintText: placeholder ?? S.current.widgets_address,
107 + focusedBorder: UnderlineInputBorder(
108 + borderSide:
109 + BorderSide(color: Palette.cakeGreen, width: 2.0)),
110 + enabledBorder: UnderlineInputBorder(
111 + borderSide:
112 + BorderSide(color: Theme.of(context).focusColor, width: 1.0)),
113 + ),
114 + validator: validator,
115 + );
116 + }
117 +
118 + Future _presentQRScanner(BuildContext context) async {
119 + try {
120 + String code = await presentQRScanner();
121 + var uri = Uri.parse(code);
122 + var address = '';
123 +
124 + if (uri == null) {
125 + controller.text = code;
126 + return;
127 + }
128 +
129 + address = uri.path;
130 + controller.text = address;
131 +
132 + if (onURIScanned != null) {
133 + onURIScanned(uri);
134 + }
135 + } catch (e) {
136 + print('Error $e');
137 + }
138 + }
139 +
140 + Future _presetAddressBookPicker(BuildContext context) async {
141 + final contact = await Navigator.of(context, rootNavigator: true)
142 + .pushNamed(Routes.pickerAddressBook);
143 +
144 + if (contact is Contact && contact.address != null) {
145 + controller.text = contact.address;
146 + }
147 + }
148 +
149 + Future _presetSubaddressListPicker(BuildContext context) async {
150 + final subaddress = await Navigator.of(context, rootNavigator: true)
151 + .pushNamed(Routes.subaddressList);
152 +
153 + if (subaddress is Subaddress && subaddress.address != null) {
154 + controller.text = subaddress.address;
155 + }
156 + }
157 +}
lib/src/widgets/blockchain_height_widget.dart new
+120
@@ -0,0 +1,120 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:intl/intl.dart';
3 +import 'package:cake_wallet/generated/i18n.dart';
4 +import 'package:cake_wallet/src/domain/monero/get_height_by_date.dart';
5 +import 'package:cake_wallet/palette.dart';
6 +
7 +class BlockchainHeightWidget extends StatefulWidget {
8 + BlockchainHeightWidget({GlobalKey key}) : super(key: key);
9 +
10 + @override
11 + State<StatefulWidget> createState() => BlockchainHeightState();
12 +}
13 +
14 +class BlockchainHeightState extends State<BlockchainHeightWidget> {
15 + final dateController = TextEditingController();
16 + final restoreHeightController = TextEditingController();
17 + int get height => _height;
18 + int _height = 0;
19 +
20 + @override
21 + void initState() {
22 + restoreHeightController.addListener(() => _height =
23 + restoreHeightController.text != null
24 + ? int.parse(restoreHeightController.text)
25 + : 0);
26 + super.initState();
27 + }
28 +
29 + @override
30 + Widget build(BuildContext context) {
31 + return Column(
32 + crossAxisAlignment: CrossAxisAlignment.start,
33 + children: <Widget>[
34 + Row(
35 + children: <Widget>[
36 + Flexible(
37 + child: Container(
38 + padding: EdgeInsets.only(top: 20.0, bottom: 10.0),
39 + child: TextFormField(
40 + style: TextStyle(fontSize: 14.0),
41 + controller: restoreHeightController,
42 + keyboardType: TextInputType.numberWithOptions(
43 + signed: false, decimal: false),
44 + decoration: InputDecoration(
45 + hintStyle: TextStyle(color: Theme.of(context).hintColor),
46 + hintText: S.of(context).widgets_restore_from_blockheight,
47 + focusedBorder: UnderlineInputBorder(
48 + borderSide: BorderSide(
49 + color: Palette.cakeGreen, width: 2.0)),
50 + enabledBorder: UnderlineInputBorder(
51 + borderSide: BorderSide(
52 + color: Theme.of(context).focusColor, width: 1.0))),
53 + ),
54 + ))
55 + ],
56 + ),
57 + Padding(
58 + padding: EdgeInsets.only(top: 15, bottom: 15),
59 + child: Text(
60 + S.of(context).widgets_or,
61 + style: TextStyle(
62 + fontSize: 16.0,
63 + fontWeight: FontWeight.bold,
64 + color: Theme.of(context).primaryTextTheme.title.color),
65 + ),
66 + ),
67 + Row(
68 + children: <Widget>[
69 + Flexible(
70 + child: Container(
71 + child: InkWell(
72 + onTap: () => _selectDate(context),
73 + child: IgnorePointer(
74 + child: TextFormField(
75 + style: TextStyle(fontSize: 14.0),
76 + decoration: InputDecoration(
77 + hintStyle:
78 + TextStyle(color: Theme.of(context).hintColor),
79 + hintText: S.of(context).widgets_restore_from_date,
80 + focusedBorder: UnderlineInputBorder(
81 + borderSide: BorderSide(
82 + color: Palette.cakeGreen,
83 + width: 2.0)),
84 + enabledBorder: UnderlineInputBorder(
85 + borderSide: BorderSide(
86 + color: Theme.of(context).focusColor,
87 + width: 1.0))),
88 + controller: dateController,
89 + validator: (value) {
90 + return null;
91 + },
92 + ),
93 + ),
94 + ),
95 + ))
96 + ],
97 + ),
98 + ],
99 + );
100 + }
101 +
102 + Future _selectDate(BuildContext context) async {
103 + final now = DateTime.now();
104 + final DateTime date = await showDatePicker(
105 + context: context,
106 + initialDate: now.subtract(Duration(days: 1)),
107 + firstDate: DateTime(2014, DateTime.april),
108 + lastDate: now);
109 +
110 + if (date != null) {
111 + final height = getHeigthByDate(date: date);
112 +
113 + setState(() {
114 + dateController.text = DateFormat('yyyy-MM-dd').format(date);
115 + restoreHeightController.text = '$height';
116 + _height = height;
117 + });
118 + }
119 + }
120 +}
lib/src/widgets/index.dart
lib/src/widgets/nav_bar.dart new
+100
@@ -0,0 +1,100 @@
1 +import 'package:cake_wallet/theme_changer.dart';
2 +import 'package:cake_wallet/themes.dart';
3 +import 'package:flutter/cupertino.dart';
4 +import 'package:flutter/material.dart';
5 +import 'package:provider/provider.dart';
6 +
7 +class NavBar extends StatelessWidget implements ObstructingPreferredSizeWidget {
8 + static const _originalHeight = 44.0; // iOS nav bar height
9 + static const _height = 60.0;
10 +
11 + factory NavBar.withShadow(
12 + {BuildContext context,
13 + Widget leading,
14 + Widget middle,
15 + Widget trailing,
16 + Color backgroundColor}) {
17 + final _themeChanger = Provider.of<ThemeChanger>(context);
18 + final _isDarkTheme = _themeChanger.getTheme() == Themes.darkTheme;
19 +
20 + return NavBar._internal(
21 + leading: leading,
22 + middle: middle,
23 + trailing: trailing,
24 + height: 80,
25 + backgroundColor:
26 + _isDarkTheme ? Theme.of(context).backgroundColor : backgroundColor,
27 + decoration: BoxDecoration(
28 + color: _isDarkTheme
29 + ? Theme.of(context).backgroundColor
30 + : backgroundColor,
31 + boxShadow: [
32 + BoxShadow(
33 + color: Color.fromRGBO(132, 141, 198, 0.11),
34 + blurRadius: 8,
35 + offset: Offset(0, 2))
36 + ]),
37 + );
38 + }
39 +
40 + factory NavBar(
41 + {BuildContext context,
42 + Widget leading,
43 + Widget middle,
44 + Widget trailing,
45 + Color backgroundColor}) {
46 + final _themeChanger = Provider.of<ThemeChanger>(context);
47 + final _isDarkTheme = _themeChanger.getTheme() == Themes.darkTheme;
48 +
49 + return NavBar._internal(
50 + leading: leading,
51 + middle: middle,
52 + trailing: trailing,
53 + height: _height,
54 + backgroundColor:
55 + _isDarkTheme ? Theme.of(context).backgroundColor : backgroundColor);
56 + }
57 +
58 + final Widget leading;
59 + final Widget middle;
60 + final Widget trailing;
61 + final Color backgroundColor;
62 + final BoxDecoration decoration;
63 + final double height;
64 +
65 + NavBar._internal(
66 + {this.leading,
67 + this.middle,
68 + this.trailing,
69 + this.backgroundColor,
70 + this.decoration,
71 + this.height = _height});
72 +
73 + @override
74 + Widget build(BuildContext context) {
75 + final pad = height - _originalHeight;
76 + final paddingTop = pad / 2;
77 + final _paddingBottom = (pad / 2);
78 +
79 + return Container(
80 + decoration: decoration ?? BoxDecoration(color: backgroundColor),
81 + padding:
82 + EdgeInsetsDirectional.only(bottom: _paddingBottom, top: paddingTop),
83 + child: CupertinoNavigationBar(
84 + leading: leading,
85 + middle: middle,
86 + trailing: trailing,
87 + backgroundColor: backgroundColor,
88 + border: null,
89 + ),
90 + );
91 + }
92 +
93 + @override
94 + Size get preferredSize => Size.fromHeight(height);
95 +
96 + @override
97 + bool shouldFullyObstruct(BuildContext context) {
98 + return false;
99 + }
100 +}
lib/src/widgets/picker.dart new
+105
@@ -0,0 +1,105 @@
1 +import 'dart:ui';
2 +import 'package:flutter/material.dart';
3 +
4 +class Picker<Item extends Object> extends StatelessWidget {
5 + final int selectedAtIndex;
6 + final List<Item> items;
7 + final String title;
8 + final double pickerHeight;
9 + final Function(Item) onItemSelected;
10 +
11 + Picker(
12 + {@required this.selectedAtIndex,
13 + @required this.items,
14 + @required this.title,
15 + this.pickerHeight = 300,
16 + this.onItemSelected});
17 +
18 + @override
19 + Widget build(BuildContext context) {
20 +
21 + return GestureDetector(
22 + onTap: () => Navigator.of(context).pop(),
23 + child: Container(
24 + color: Colors.transparent,
25 + child: BackdropFilter(
26 + filter: ImageFilter.blur(sigmaX: 3.0, sigmaY: 3.0),
27 + child: Container(
28 + decoration: BoxDecoration(color: Colors.white.withOpacity(0.55)),
29 + child: Column(
30 + mainAxisAlignment: MainAxisAlignment.end,
31 + children: [
32 + GestureDetector(
33 + onTap: () => null,
34 + child: Container(
35 + width: double.infinity,
36 + height: pickerHeight,
37 + color: Theme.of(context).backgroundColor,
38 + child: ListView.separated(
39 + itemCount: items.length + 1,
40 + separatorBuilder: (_, index) => index == 0
41 + ? SizedBox()
42 + : Divider(
43 + height: 1,
44 + color: Color.fromRGBO(235, 238, 242, 1)),
45 + itemBuilder: (_, index) {
46 + if (index == 0) {
47 + return Container(
48 + height: 100,
49 + width: double.infinity,
50 + color: Theme.of(context).backgroundColor,
51 + child: Center(
52 + child: Text(
53 + title,
54 + textAlign: TextAlign.center,
55 + style: TextStyle(
56 + fontSize: 26,
57 + fontWeight: FontWeight.w600,
58 + fontFamily: 'Lato',
59 + decoration: TextDecoration.none,
60 + color: Theme.of(context).primaryTextTheme.caption.color
61 + ),
62 + ),
63 + ),
64 + );
65 + }
66 +
67 + index -= 1;
68 + final item = items[index];
69 +
70 + return GestureDetector(
71 + onTap: () {
72 + if (onItemSelected == null) {
73 + return;
74 + }
75 + Navigator.of(context).pop();
76 + onItemSelected(item);
77 + },
78 + child: Container(
79 + color: Colors.transparent,
80 + padding: EdgeInsets.only(top: 18, bottom: 18),
81 + child: Center(
82 + child: Text(
83 + item.toString(),
84 + style: TextStyle(
85 + decoration: TextDecoration.none,
86 + fontSize: 18,
87 + fontWeight: FontWeight.normal,
88 + fontFamily: 'Lato',
89 + color: index == selectedAtIndex
90 + ? Color.fromRGBO(138, 80, 255, 1)
91 + : Theme.of(context).primaryTextTheme.caption.color),
92 + )),
93 + ),
94 + );
95 + },
96 + )),
97 + )
98 + ],
99 + ),
100 + ),
101 + ),
102 + ),
103 + );
104 + }
105 +}
lib/src/widgets/primary_button.dart new
+188
@@ -0,0 +1,188 @@
1 +import 'package:flutter/cupertino.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:cake_wallet/palette.dart';
4 +
5 +class PrimaryButton extends StatelessWidget {
6 + final VoidCallback onPressed;
7 + final Color color;
8 + final Color borderColor;
9 + final String text;
10 +
11 + const PrimaryButton(
12 + {@required this.onPressed,
13 + @required this.text,
14 + @required this.color,
15 + @required this.borderColor});
16 +
17 + @override
18 + Widget build(BuildContext context) {
19 +
20 + return ButtonTheme(
21 + minWidth: double.infinity,
22 + height: 56.0,
23 + child: FlatButton(
24 + onPressed: onPressed,
25 + color: color,
26 + shape: RoundedRectangleBorder(
27 + side: BorderSide(color: borderColor),
28 + borderRadius: BorderRadius.circular(10.0)),
29 + child: Text(text,
30 + style: TextStyle(
31 + fontSize: 16.0,
32 + color: Theme.of(context).primaryTextTheme.button.color)),
33 + ));
34 + }
35 +}
36 +
37 +class LoadingPrimaryButton extends StatelessWidget {
38 + final VoidCallback onPressed;
39 + final Color color;
40 + final Color borderColor;
41 + final bool isLoading;
42 + final bool isDisabled;
43 + final String text;
44 +
45 + const LoadingPrimaryButton(
46 + {@required this.onPressed,
47 + @required this.text,
48 + @required this.color,
49 + @required this.borderColor,
50 + this.isDisabled = false,
51 + this.isLoading = false});
52 +
53 + @override
54 + Widget build(BuildContext context) {
55 +
56 + return ButtonTheme(
57 + minWidth: double.infinity,
58 + height: 56.0,
59 + child: FlatButton(
60 + onPressed: (isLoading || isDisabled) ? null : onPressed,
61 + color: color,
62 + shape: RoundedRectangleBorder(
63 + side: BorderSide(color: borderColor),
64 + borderRadius: BorderRadius.circular(10.0)),
65 + child: isLoading
66 + ? CupertinoActivityIndicator(animating: true)
67 + : Text(text,
68 + style: TextStyle(
69 + fontSize: 16.0,
70 + color: Theme.of(context).primaryTextTheme.button.color)),
71 + ));
72 + }
73 +}
74 +
75 +class PrimaryIconButton extends StatelessWidget {
76 + final VoidCallback onPressed;
77 + final IconData iconData;
78 + final Color color;
79 + final Color borderColor;
80 + final Color iconColor;
81 + final Color iconBackgroundColor;
82 + final String text;
83 +
84 + const PrimaryIconButton({
85 + @required this.onPressed,
86 + @required this.iconData,
87 + @required this.text,
88 + @required this.color,
89 + @required this.borderColor,
90 + @required this.iconColor,
91 + @required this.iconBackgroundColor,
92 + });
93 +
94 + @override
95 + Widget build(BuildContext context) {
96 +
97 + return ButtonTheme(
98 + minWidth: double.infinity,
99 + height: 56.0,
100 + child: FlatButton(
101 + onPressed: onPressed,
102 + color: color,
103 + shape: RoundedRectangleBorder(
104 + side: BorderSide(color: borderColor),
105 + borderRadius: BorderRadius.circular(10.0)),
106 + child: Stack(
107 + children: <Widget>[
108 + Row(
109 + mainAxisAlignment: MainAxisAlignment.start,
110 + children: <Widget>[
111 + Container(
112 + width: 28.0,
113 + height: 56.0,
114 + decoration: BoxDecoration(
115 + shape: BoxShape.circle, color: iconBackgroundColor),
116 + child: Icon(iconData, color: iconColor, size: 22.0),
117 + ),
118 + ],
119 + ),
120 + Container(
121 + height: 56.0,
122 + child: Center(
123 + child: Text(text,
124 + style: TextStyle(
125 + fontSize: 16.0,
126 + color: Theme.of(context).primaryTextTheme.button.color)),
127 + ),
128 + )
129 + ],
130 + ),
131 + ));
132 + }
133 +}
134 +
135 +class PrimaryImageButton extends StatelessWidget {
136 + final VoidCallback onPressed;
137 + final Image image;
138 + final Color color;
139 + final Color borderColor;
140 + final Color iconColor;
141 + final String text;
142 +
143 + const PrimaryImageButton(
144 + {@required this.onPressed,
145 + @required this.image,
146 + @required this.text,
147 + this.color = Palette.purple,
148 + this.borderColor = Palette.deepPink,
149 + this.iconColor = Colors.black});
150 +
151 + @override
152 + Widget build(BuildContext context) {
153 + return ButtonTheme(
154 + minWidth: double.infinity,
155 + height: 58.0,
156 + child: FlatButton(
157 + onPressed: onPressed,
158 + color: color,
159 + shape: RoundedRectangleBorder(
160 + side: BorderSide(color: borderColor),
161 + borderRadius: BorderRadius.circular(12.0)),
162 + child: Row(
163 + children: <Widget>[
164 + Container(
165 + width: 28.0,
166 + height: 56.0,
167 + decoration: BoxDecoration(
168 + shape: BoxShape.circle, color: Colors.transparent),
169 + child: image,
170 + ),
171 + Expanded(
172 + child: Row(
173 + mainAxisAlignment: MainAxisAlignment.center,
174 + children: <Widget>[
175 + Container(
176 + height: 56.0,
177 + child: Center(
178 + child: Text(text, style: TextStyle(fontSize: 18.0,
179 + color: Theme.of(context).primaryTextTheme.button.color
180 + )),
181 + ),
182 + )
183 + ]))
184 + ],
185 + ),
186 + ));
187 + }
188 +}
lib/src/widgets/scollable_with_bottom_section.dart new
+50
@@ -0,0 +1,50 @@
1 +import 'package:flutter/cupertino.dart';
2 +import 'package:flutter/material.dart';
3 +
4 +class ScrollableWithBottomSection extends StatefulWidget {
5 + final Widget content;
6 + final Widget bottomSection;
7 + final EdgeInsets contentPadding;
8 + final EdgeInsets bottomSectionPadding;
9 +
10 + ScrollableWithBottomSection(
11 + {this.content,
12 + this.bottomSection,
13 + this.contentPadding,
14 + this.bottomSectionPadding});
15 +
16 + @override
17 + ScrollableWithBottomSectionState createState() =>
18 + ScrollableWithBottomSectionState();
19 +}
20 +
21 +class ScrollableWithBottomSectionState
22 + extends State<ScrollableWithBottomSection> {
23 + @override
24 + Widget build(BuildContext context) {
25 + return LayoutBuilder(builder: (context, constraints) {
26 + return SingleChildScrollView(
27 + // physics:
28 + // const AlwaysScrollableScrollPhysics(), // const NeverScrollableScrollPhysics(), //
29 + child: ConstrainedBox(
30 + constraints: BoxConstraints(
31 + minHeight: constraints.heightConstraints().maxHeight),
32 + child: Column(
33 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
34 + children: <Widget>[
35 + Padding(
36 + padding: widget.contentPadding ??
37 + EdgeInsets.only(left: 20, right: 20),
38 + child: widget.content,
39 + ),
40 + Padding(
41 + padding: widget.bottomSectionPadding ??
42 + EdgeInsets.only(bottom: 20, right: 20, left: 20),
43 + child: widget.bottomSection)
44 + ],
45 + ),
46 + ),
47 + );
48 + });
49 + }
50 +}
lib/src/widgets/seed_widget.dart new
+251
@@ -0,0 +1,251 @@
1 +import 'package:flutter/cupertino.dart';
2 +import 'package:flutter/material.dart';
3 +import 'package:flutter/services.dart';
4 +import 'package:cake_wallet/palette.dart';
5 +import 'package:cake_wallet/src/domain/monero/mnemonics/english.dart';
6 +import 'package:cake_wallet/src/domain/common/mnemotic_item.dart';
7 +import 'package:cake_wallet/generated/i18n.dart';
8 +
9 +class SeedWidget extends StatefulWidget {
10 + final Function(List<MnemoticItem>) onMnemoticChange;
11 +
12 + SeedWidget({Key key, this.onMnemoticChange}) : super(key: key);
13 +
14 + SeedWidgetState createState() => SeedWidgetState();
15 +}
16 +
17 +class SeedWidgetState extends State<SeedWidget> {
18 + List<MnemoticItem> items = <MnemoticItem>[];
19 + final _seedController = TextEditingController();
20 + MnemoticItem selectedItem;
21 + bool isValid;
22 + String errorMessage;
23 +
24 + @override
25 + void initState() {
26 + super.initState();
27 + isValid = true;
28 + _seedController.addListener(() => mnemoticFromText(_seedController.text));
29 + }
30 +
31 + void addMnemotic(String text) {
32 + setState(() => items.add(MnemoticItem(
33 + text: text.trim().toLowerCase(), dic: EnglishMnemonics.words)));
34 + _seedController.text = '';
35 +
36 + if (widget.onMnemoticChange != null) {
37 + widget.onMnemoticChange(items);
38 + }
39 + }
40 +
41 + void deleteMnemotic(MnemoticItem item) {
42 + setState(() => items.remove(item));
43 +
44 + if (widget.onMnemoticChange != null) {
45 + widget.onMnemoticChange(items);
46 + }
47 + }
48 +
49 + void mnemoticFromText(String text) {
50 + final splitted = text.split(' ');
51 +
52 + if (splitted.length >= 2) {
53 + for (final text in splitted) {
54 + if (text == ' ' || text.isEmpty) {
55 + continue;
56 + }
57 +
58 + if (selectedItem != null) {
59 + editTextOfSelectedMnemotic(text);
60 + } else {
61 + addMnemotic(text);
62 + }
63 + }
64 + }
65 + }
66 +
67 + void selectMnemotic(MnemoticItem item) {
68 + setState(() => selectedItem = item);
69 + _seedController
70 + ..text = item.text
71 + ..selection = TextSelection.collapsed(offset: item.text.length);
72 + }
73 +
74 + void onMnemoticTap(MnemoticItem item) {
75 + if (selectedItem == item) {
76 + setState(() => selectedItem = null);
77 + _seedController.text = '';
78 + return;
79 + }
80 +
81 + selectMnemotic(item);
82 + }
83 +
84 + void editTextOfSelectedMnemotic(String text) {
85 + setState(() => selectedItem.changeText(text));
86 + selectedItem = null;
87 + _seedController.text = '';
88 +
89 + if (widget.onMnemoticChange != null) {
90 + widget.onMnemoticChange(items);
91 + }
92 + }
93 +
94 + void onFieldSubmitted(String text) {
95 + if (text.isEmpty || text == null) {
96 + return;
97 + }
98 +
99 + if (selectedItem != null) {
100 + editTextOfSelectedMnemotic(text);
101 + } else {
102 + addMnemotic(text);
103 + }
104 + }
105 +
106 + void clear() {
107 + setState(() {
108 + items = [];
109 + _seedController.text = '';
110 +
111 + if (widget.onMnemoticChange != null) {
112 + widget.onMnemoticChange(items);
113 + }
114 + });
115 + }
116 +
117 + void invalidate() {
118 + setState(() => isValid = false);
119 + }
120 +
121 + void validated() {
122 + setState(() => isValid = true);
123 + }
124 +
125 + void setErrorMessage(String errorMessage) {
126 + setState(() => this.errorMessage = errorMessage);
127 + }
128 +
129 + void replaceText(String text) {
130 + setState(() => items = []);
131 + mnemoticFromText(text);
132 + }
133 +
134 + @override
135 + Widget build(BuildContext context) {
136 + return Container(
137 + child: Column(children: [
138 + TextFormField(
139 + onFieldSubmitted: (text) => onFieldSubmitted(text),
140 + style: TextStyle(fontSize: 14.0),
141 + controller: _seedController,
142 + textInputAction: TextInputAction.done,
143 + decoration: InputDecoration(
144 + suffixIcon: GestureDetector(
145 + behavior: HitTestBehavior.opaque,
146 + child: SizedBox(
147 + width: 65,
148 + child: Row(
149 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
150 + children: <Widget>[
151 + InkWell(
152 + onTap: () {
153 + clear();
154 + FocusScope.of(context).unfocus();
155 + },
156 + child: Container(
157 + height: 20,
158 + width: 20,
159 + padding: EdgeInsets.all(3),
160 + decoration: BoxDecoration(
161 + color: Palette.wildDarkBlueWithOpacity,
162 + borderRadius: BorderRadius.circular(10.0)),
163 + child: Image.asset(
164 + 'assets/images/x.png',
165 + color: Palette.wildDarkBlue,
166 + ),
167 + ),
168 + ),
169 + InkWell(
170 + onTap: () async => Clipboard.getData('text/plain')
171 + .then((clipboard) => replaceText(clipboard.text)),
172 + child: Container(
173 + height: 35,
174 + width: 35,
175 + padding: EdgeInsets.all(7),
176 + decoration: BoxDecoration(
177 + color: Palette.wildDarkBlueWithOpacity,
178 + borderRadius: BorderRadius.circular(10.0)),
179 + child: Image.asset('assets/images/paste_button.png',
180 + height: 5, width: 5, color: Palette.wildDarkBlue),
181 + ),
182 + )
183 + ],
184 + ),
185 + ),
186 + ),
187 + errorText: errorMessage,
188 + hintStyle: TextStyle(color: Theme.of(context).hintColor),
189 + hintText: S.of(context).widgets_seed,
190 + focusedBorder: UnderlineInputBorder(
191 + borderSide: BorderSide(
192 + color: Palette.cakeGreen, width: 2.0)),
193 + enabledBorder: UnderlineInputBorder(
194 + borderSide: BorderSide(
195 + color:
196 + isValid ? Theme.of(context).focusColor : Palette.red,
197 + width: 1.0))),
198 + ),
199 + SizedBox(height: 20),
200 + Expanded(
201 + child: GridView.count(
202 + physics: NeverScrollableScrollPhysics(),
203 + crossAxisCount: 3,
204 + childAspectRatio: 3.3,
205 + mainAxisSpacing: 10,
206 + crossAxisSpacing: 10,
207 + children: List.generate(items.length, (index) {
208 + final item = items[index];
209 + final isValid = item.isCorrect();
210 + final isSelected = selectedItem == item;
211 +
212 + return InkWell(
213 + onTap: () => onMnemoticTap(item),
214 + child: Container(
215 + decoration: BoxDecoration(
216 + color: isValid ? Palette.brightBlue : Palette.red,
217 + border: Border.all(
218 + color:
219 + isSelected ? Palette.violet : Colors.transparent),
220 + borderRadius: BorderRadius.circular(15.0)),
221 + padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
222 + child: Row(
223 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
224 + children: [
225 + Text(
226 + item.toString(),
227 + style: TextStyle(
228 + color:
229 + isValid ? Palette.blueGrey : Palette.lightGrey,
230 + fontSize: 12,
231 + fontWeight: FontWeight.w600),
232 + ),
233 + InkWell(
234 + onTap: () => deleteMnemotic(item),
235 + child: Image.asset(
236 + 'assets/images/x.png',
237 + height: 15,
238 + width: 15,
239 + color: Palette.wildDarkBlue,
240 + ))
241 + ],
242 + ),
243 + ),
244 + );
245 + }),
246 + ),
247 + ),
248 + ]),
249 + );
250 + }
251 +}
lib/src/widgets/standart_close_button.dart new
+16
@@ -0,0 +1,16 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter/cupertino.dart';
3 +
4 +class StandartCloseButton extends StatelessWidget {
5 + @override
6 + Widget build(BuildContext context) {
7 + return SizedBox(
8 + height: 37,
9 + width: 37,
10 + child: FlatButton(
11 + padding: EdgeInsets.all(0),
12 + onPressed: () => Navigator.of(context).pop(),
13 + child: Image.asset('assets/images/close_button.png')),
14 + );
15 + }
16 +}
\ No newline at end of file
lib/src/widgets/standart_switch.dart new
+59
@@ -0,0 +1,59 @@
1 +import 'package:flutter/material.dart';
2 +
3 +class StandartSwitch extends StatefulWidget {
4 +
5 + final bool value;
6 + final VoidCallback onTaped;
7 +
8 + const StandartSwitch({
9 + @required this.value,
10 + @required this.onTaped});
11 +
12 + @override
13 + createState() => StandartSwitchState();
14 +
15 +}
16 +
17 +class StandartSwitchState extends State<StandartSwitch> {
18 +
19 + @override
20 + Widget build(BuildContext context) {
21 +
22 + return GestureDetector(
23 + onTap: widget.onTaped,
24 + child: AnimatedContainer(
25 + padding: EdgeInsets.only(left: 4.0, right: 4.0),
26 + alignment: widget.value
27 + ? Alignment.centerRight
28 + : Alignment.centerLeft,
29 + duration: Duration(milliseconds: 250),
30 + width: 55.0,
31 + height: 33.0,
32 + decoration: BoxDecoration(
33 + color: Theme.of(context).toggleButtonsTheme.color,
34 + border: Border.all(
35 + color: Theme.of(context).toggleButtonsTheme.borderColor
36 + ),
37 + borderRadius:
38 + BorderRadius.all(Radius.circular(10.0))),
39 + child: Container(
40 + width: 25.0,
41 + height: 25.0,
42 + decoration: BoxDecoration(
43 + color: widget.value
44 + ? Theme.of(context).toggleButtonsTheme.selectedColor
45 + : Theme.of(context).toggleButtonsTheme.disabledColor,
46 + borderRadius:
47 + BorderRadius.all(Radius.circular(8.0))),
48 + child: Icon(widget.value
49 + ? Icons.check
50 + : Icons.close,
51 + color: Colors.white,
52 + size: 16.0,
53 + ),
54 + ),
55 + ),
56 + );
57 + }
58 +
59 +}
\ No newline at end of file
lib/theme_changer.dart new
+17
@@ -0,0 +1,17 @@
1 +import 'package:flutter/material.dart';
2 +
3 +class ThemeChanger with ChangeNotifier {
4 +
5 + ThemeData _themeData;
6 +
7 + ThemeChanger(this._themeData);
8 +
9 + getTheme() => _themeData;
10 +
11 + setTheme(ThemeData theme){
12 + _themeData = theme;
13 +
14 + notifyListeners();
15 + }
16 +
17 +}
\ No newline at end of file
lib/themes.dart new
+185
@@ -0,0 +1,185 @@
1 +import 'package:flutter/material.dart';
2 +import 'palette.dart';
3 +
4 +class Themes {
5 +
6 + static final ThemeData lightTheme = ThemeData(
7 + fontFamily: 'Lato',
8 + brightness: Brightness.light,
9 + backgroundColor: Colors.white,
10 + scaffoldBackgroundColor: Colors.white,
11 + hintColor: Palette.lightBlue,
12 + focusColor: Palette.lightGrey, // focused and enabled border color for text fields
13 + primaryTextTheme: TextTheme(
14 + title: TextStyle(
15 + color: Colors.black
16 + ),
17 + caption: TextStyle(
18 + color: Colors.black,
19 + ),
20 + button: TextStyle(
21 + color: Colors.black,
22 + backgroundColor: Palette.purple, // button purple background color
23 + decorationColor: Palette.deepPink // button pink border color
24 + ),
25 + headline: TextStyle(
26 + color: Colors.black // account list tile, contact page
27 + ),
28 + subtitle: TextStyle(
29 + color: Palette.wildDarkBlue // filters
30 + ),
31 + subhead: TextStyle(
32 + color: Colors.black // transaction raw, trade raw
33 + ),
34 + overline: TextStyle(
35 + color: PaletteDark.darkThemeCloseButton // standart list row, transaction details
36 + )
37 + ),
38 + toggleButtonsTheme: ToggleButtonsThemeData(
39 + selectedColor: Palette.cakeGreen,
40 + disabledColor: Palette.wildDarkBlue,
41 + color: Palette.switchBackground,
42 + borderColor: Palette.switchBorder
43 + ),
44 + selectedRowColor: Palette.purple,
45 + dividerColor: Palette.lightGrey,
46 + dividerTheme: DividerThemeData(
47 + color: Palette.lightGrey
48 + ),
49 + accentTextTheme: TextTheme(
50 + title: TextStyle(
51 + color: Colors.grey,
52 + backgroundColor: Palette.creamyGrey // pin button color
53 + ),
54 + caption: TextStyle(
55 + color: Palette.wildDarkBlue, // clear button color, exchange page
56 + backgroundColor: Palette.brightBlue, // button blue background color
57 + decorationColor: Palette.cloudySky // button blue border color
58 + ),
59 + button: TextStyle(
60 + backgroundColor: Palette.indigo, // button indigo background color
61 + decorationColor: Palette.deepIndigo // button indigo border color
62 + ),
63 + subtitle: TextStyle(
64 + color: Colors.black,
65 + backgroundColor: Palette.lightLavender // send page border color
66 + ),
67 + headline: TextStyle(
68 + color: Palette.lightGrey2, // receive page
69 + backgroundColor: Colors.white, // restore button background color
70 + decorationColor: Palette.darkGrey, // restore button border color
71 + ),
72 + subhead: TextStyle(
73 + color: Palette.lightBlue, // restore button description
74 + backgroundColor: Palette.lightGrey2 // change language background color
75 + ),
76 + overline: TextStyle(
77 + color: Palette.nightBlue, // send page text
78 + backgroundColor: Palette.nightBlue, // send page text
79 + decorationColor: Palette.manatee // send page text
80 + )
81 + ),
82 + cardColor: Palette.lavender,
83 + cardTheme: CardTheme(
84 + color: Palette.cadetBlue
85 + ),
86 + buttonColor: Palette.darkGrey,
87 + primaryIconTheme: IconThemeData(
88 + color: Colors.white
89 + ),
90 + accentIconTheme: IconThemeData(
91 + color: Colors.white
92 + )
93 + );
94 +
95 +
96 + static final ThemeData darkTheme = ThemeData(
97 + fontFamily: 'Lato',
98 + brightness: Brightness.dark,
99 + backgroundColor: PaletteDark.darkThemeBackgroundDark,
100 + scaffoldBackgroundColor: PaletteDark.darkThemeBlack,
101 + hintColor: PaletteDark.darkThemeGrey,
102 + focusColor: PaletteDark.darkThemeGreyWithOpacity, // focused and enabled border color for text fields
103 + primaryTextTheme: TextTheme(
104 + title: TextStyle(
105 + color: PaletteDark.darkThemeTitle
106 + ),
107 + caption: TextStyle(
108 + color: Colors.white
109 + ),
110 + button: TextStyle(
111 + color: Palette.wildDarkBlue,
112 + backgroundColor: PaletteDark.darkThemePurpleButton, // button purple background color
113 + decorationColor: PaletteDark.darkThemePurpleButtonBorder // button pink border color
114 + ),
115 + headline: TextStyle(
116 + color: PaletteDark.darkThemeGrey // account list tile, contact page
117 + ),
118 + subtitle: TextStyle(
119 + color: PaletteDark.darkThemeGrey // filters
120 + ),
121 + subhead: TextStyle(
122 + color: Palette.blueGrey // transaction raw, trade raw
123 + ),
124 + overline: TextStyle(
125 + color: PaletteDark.darkThemeGrey // standart list row, transaction details
126 + )
127 + ),
128 + toggleButtonsTheme: ToggleButtonsThemeData(
129 + selectedColor: Palette.cakeGreen,
130 + disabledColor: Palette.wildDarkBlue,
131 + color: PaletteDark.switchBackground,
132 + borderColor: PaletteDark.darkThemeMidGrey
133 + ),
134 + selectedRowColor: PaletteDark.darkThemeViolet,
135 + dividerColor: PaletteDark.darkThemeDarkGrey,
136 + dividerTheme: DividerThemeData(
137 + color: PaletteDark.darkThemeGreyWithOpacity
138 + ),
139 + accentTextTheme: TextTheme(
140 + title: TextStyle(
141 + color: PaletteDark.darkThemeTitle,
142 + backgroundColor: PaletteDark.darkThemePinDigitButton // pin button color
143 + ),
144 + caption: TextStyle(
145 + color: PaletteDark.darkThemeTitleViolet, // clear button color, exchange page
146 + backgroundColor: PaletteDark.darkThemeBlueButton, // button blue background color
147 + decorationColor: PaletteDark.darkThemeBlueButtonBorder // button blue border color
148 + ),
149 + button: TextStyle(
150 + backgroundColor: PaletteDark.darkThemeIndigoButton, // button indigo background color
151 + decorationColor: PaletteDark.darkThemeIndigoButtonBorder // button indigo border color
152 + ),
153 + subtitle: TextStyle(
154 + color: PaletteDark.wildDarkBlueWithOpacity,
155 + backgroundColor: PaletteDark.darkThemeDarkGrey // send page border color
156 + ),
157 + headline: TextStyle(
158 + color: PaletteDark.darkThemeBlack, // receive page
159 + backgroundColor: PaletteDark.darkThemeMidGrey, // restore button background color
160 + decorationColor: PaletteDark.darkThemeDarkGrey, // restore button border color
161 + ),
162 + subhead: TextStyle(
163 + color: Palette.wildDarkBlue, // restore button description
164 + backgroundColor: PaletteDark.darkThemeMidGrey // change language background color
165 + ),
166 + overline: TextStyle(
167 + color: PaletteDark.darkThemeTitle, // send page text
168 + backgroundColor: PaletteDark.darkThemeGrey, // send page text
169 + decorationColor: PaletteDark.darkThemeTitle // send page text
170 + )
171 + ),
172 + cardColor: PaletteDark.darkThemeMidGrey,
173 + cardTheme: CardTheme(
174 + color: PaletteDark.darkThemeGrey
175 + ),
176 + buttonColor: PaletteDark.darkThemePinButton,
177 + primaryIconTheme: IconThemeData(
178 + color: PaletteDark.darkThemeViolet
179 + ),
180 + accentIconTheme: IconThemeData(
181 + color: PaletteDark.darkThemeIndigoButtonBorder
182 + )
183 + );
184 +
185 +}
\ No newline at end of file
pubspec.lock new
+759
@@ -0,0 +1,759 @@
1 +# Generated by pub
2 +# See https://dart.dev/tools/pub/glossary#lockfile
3 +packages:
4 + analyzer:
5 + dependency: transitive
6 + description:
7 + name: analyzer
8 + url: "https://pub.dartlang.org"
9 + source: hosted
10 + version: "0.36.4"
11 + archive:
12 + dependency: transitive
13 + description:
14 + name: archive
15 + url: "https://pub.dartlang.org"
16 + source: hosted
17 + version: "2.0.11"
18 + args:
19 + dependency: transitive
20 + description:
21 + name: args
22 + url: "https://pub.dartlang.org"
23 + source: hosted
24 + version: "1.5.2"
25 + asn1lib:
26 + dependency: transitive
27 + description:
28 + name: asn1lib
29 + url: "https://pub.dartlang.org"
30 + source: hosted
31 + version: "0.5.15"
32 + async:
33 + dependency: transitive
34 + description:
35 + name: async
36 + url: "https://pub.dartlang.org"
37 + source: hosted
38 + version: "2.4.0"
39 + barcode_scan:
40 + dependency: "direct main"
41 + description:
42 + name: barcode_scan
43 + url: "https://pub.dartlang.org"
44 + source: hosted
45 + version: "1.0.0"
46 + boolean_selector:
47 + dependency: transitive
48 + description:
49 + name: boolean_selector
50 + url: "https://pub.dartlang.org"
51 + source: hosted
52 + version: "1.0.5"
53 + build:
54 + dependency: transitive
55 + description:
56 + name: build
57 + url: "https://pub.dartlang.org"
58 + source: hosted
59 + version: "1.2.2"
60 + build_config:
61 + dependency: transitive
62 + description:
63 + name: build_config
64 + url: "https://pub.dartlang.org"
65 + source: hosted
66 + version: "0.4.1+1"
67 + build_daemon:
68 + dependency: transitive
69 + description:
70 + name: build_daemon
71 + url: "https://pub.dartlang.org"
72 + source: hosted
73 + version: "2.1.2"
74 + build_resolvers:
75 + dependency: transitive
76 + description:
77 + name: build_resolvers
78 + url: "https://pub.dartlang.org"
79 + source: hosted
80 + version: "1.2.1"
81 + build_runner:
82 + dependency: "direct dev"
83 + description:
84 + name: build_runner
85 + url: "https://pub.dartlang.org"
86 + source: hosted
87 + version: "1.7.2"
88 + build_runner_core:
89 + dependency: transitive
90 + description:
91 + name: build_runner_core
92 + url: "https://pub.dartlang.org"
93 + source: hosted
94 + version: "4.2.0"
95 + built_collection:
96 + dependency: transitive
97 + description:
98 + name: built_collection
99 + url: "https://pub.dartlang.org"
100 + source: hosted
101 + version: "4.3.0"
102 + built_value:
103 + dependency: transitive
104 + description:
105 + name: built_value
106 + url: "https://pub.dartlang.org"
107 + source: hosted
108 + version: "7.0.0"
109 + characters:
110 + dependency: transitive
111 + description:
112 + name: characters
113 + url: "https://pub.dartlang.org"
114 + source: hosted
115 + version: "0.3.1"
116 + charcode:
117 + dependency: transitive
118 + description:
119 + name: charcode
120 + url: "https://pub.dartlang.org"
121 + source: hosted
122 + version: "1.1.2"
123 + checked_yaml:
124 + dependency: transitive
125 + description:
126 + name: checked_yaml
127 + url: "https://pub.dartlang.org"
128 + source: hosted
129 + version: "1.0.2"
130 + clock:
131 + dependency: transitive
132 + description:
133 + name: clock
134 + url: "https://pub.dartlang.org"
135 + source: hosted
136 + version: "1.0.1"
137 + code_builder:
138 + dependency: transitive
139 + description:
140 + name: code_builder
141 + url: "https://pub.dartlang.org"
142 + source: hosted
143 + version: "3.2.1"
144 + collection:
145 + dependency: transitive
146 + description:
147 + name: collection
148 + url: "https://pub.dartlang.org"
149 + source: hosted
150 + version: "1.14.11"
151 + convert:
152 + dependency: transitive
153 + description:
154 + name: convert
155 + url: "https://pub.dartlang.org"
156 + source: hosted
157 + version: "2.1.1"
158 + crypto:
159 + dependency: transitive
160 + description:
161 + name: crypto
162 + url: "https://pub.dartlang.org"
163 + source: hosted
164 + version: "2.1.3"
165 + csslib:
166 + dependency: transitive
167 + description:
168 + name: csslib
169 + url: "https://pub.dartlang.org"
170 + source: hosted
171 + version: "0.16.1"
172 + cupertino_icons:
173 + dependency: "direct main"
174 + description:
175 + name: cupertino_icons
176 + url: "https://pub.dartlang.org"
177 + source: hosted
178 + version: "0.1.3"
179 + cw_monero:
180 + dependency: "direct main"
181 + description:
182 + path: cw_monero
183 + relative: true
184 + source: path
185 + version: "0.0.1"
186 + dart_style:
187 + dependency: transitive
188 + description:
189 + name: dart_style
190 + url: "https://pub.dartlang.org"
191 + source: hosted
192 + version: "1.2.9"
193 + dartx:
194 + dependency: transitive
195 + description:
196 + name: dartx
197 + url: "https://pub.dartlang.org"
198 + source: hosted
199 + version: "0.2.0"
200 + date_range_picker:
201 + dependency: "direct main"
202 + description:
203 + name: date_range_picker
204 + url: "https://pub.dartlang.org"
205 + source: hosted
206 + version: "1.0.6"
207 + dio:
208 + dependency: "direct main"
209 + description:
210 + name: dio
211 + url: "https://pub.dartlang.org"
212 + source: hosted
213 + version: "3.0.7"
214 + encrypt:
215 + dependency: "direct main"
216 + description:
217 + name: encrypt
218 + url: "https://pub.dartlang.org"
219 + source: hosted
220 + version: "4.0.0"
221 + esys_flutter_share:
222 + dependency: "direct main"
223 + description:
224 + name: esys_flutter_share
225 + url: "https://pub.dartlang.org"
226 + source: hosted
227 + version: "1.0.2"
228 + ffi:
229 + dependency: transitive
230 + description:
231 + name: ffi
232 + url: "https://pub.dartlang.org"
233 + source: hosted
234 + version: "0.1.3"
235 + fixnum:
236 + dependency: transitive
237 + description:
238 + name: fixnum
239 + url: "https://pub.dartlang.org"
240 + source: hosted
241 + version: "0.10.11"
242 + flutter:
243 + dependency: "direct main"
244 + description: flutter
245 + source: sdk
246 + version: "0.0.0"
247 + flutter_cupertino_localizations:
248 + dependency: "direct main"
249 + description:
250 + name: flutter_cupertino_localizations
251 + url: "https://pub.dartlang.org"
252 + source: hosted
253 + version: "1.0.1"
254 + flutter_launcher_icons:
255 + dependency: "direct dev"
256 + description:
257 + name: flutter_launcher_icons
258 + url: "https://pub.dartlang.org"
259 + source: hosted
260 + version: "0.7.4"
261 + flutter_localizations:
262 + dependency: "direct main"
263 + description: flutter
264 + source: sdk
265 + version: "0.0.0"
266 + flutter_mobx:
267 + dependency: "direct main"
268 + description:
269 + name: flutter_mobx
270 + url: "https://pub.dartlang.org"
271 + source: hosted
272 + version: "0.3.0+1"
273 + flutter_secure_storage:
274 + dependency: "direct main"
275 + description:
276 + name: flutter_secure_storage
277 + url: "https://pub.dartlang.org"
278 + source: hosted
279 + version: "3.3.1+1"
280 + flutter_slidable:
281 + dependency: "direct main"
282 + description:
283 + name: flutter_slidable
284 + url: "https://pub.dartlang.org"
285 + source: hosted
286 + version: "0.5.4"
287 + flutter_test:
288 + dependency: "direct dev"
289 + description: flutter
290 + source: sdk
291 + version: "0.0.0"
292 + flutter_web_plugins:
293 + dependency: transitive
294 + description: flutter
295 + source: sdk
296 + version: "0.0.0"
297 + front_end:
298 + dependency: transitive
299 + description:
300 + name: front_end
301 + url: "https://pub.dartlang.org"
302 + source: hosted
303 + version: "0.1.19"
304 + glob:
305 + dependency: transitive
306 + description:
307 + name: glob
308 + url: "https://pub.dartlang.org"
309 + source: hosted
310 + version: "1.2.0"
311 + graphs:
312 + dependency: transitive
313 + description:
314 + name: graphs
315 + url: "https://pub.dartlang.org"
316 + source: hosted
317 + version: "0.2.0"
318 + hive:
319 + dependency: "direct main"
320 + description:
321 + name: hive
322 + url: "https://pub.dartlang.org"
323 + source: hosted
324 + version: "1.2.0"
325 + hive_flutter:
326 + dependency: "direct main"
327 + description:
328 + name: hive_flutter
329 + url: "https://pub.dartlang.org"
330 + source: hosted
331 + version: "0.2.1"
332 + hive_generator:
333 + dependency: "direct dev"
334 + description:
335 + name: hive_generator
336 + url: "https://pub.dartlang.org"
337 + source: hosted
338 + version: "0.6.0"
339 + html:
340 + dependency: transitive
341 + description:
342 + name: html
343 + url: "https://pub.dartlang.org"
344 + source: hosted
345 + version: "0.14.0+3"
346 + http:
347 + dependency: "direct main"
348 + description:
349 + name: http
350 + url: "https://pub.dartlang.org"
351 + source: hosted
352 + version: "0.12.0+2"
353 + http_multi_server:
354 + dependency: transitive
355 + description:
356 + name: http_multi_server
357 + url: "https://pub.dartlang.org"
358 + source: hosted
359 + version: "2.1.0"
360 + http_parser:
361 + dependency: transitive
362 + description:
363 + name: http_parser
364 + url: "https://pub.dartlang.org"
365 + source: hosted
366 + version: "3.1.3"
367 + image:
368 + dependency: transitive
369 + description:
370 + name: image
371 + url: "https://pub.dartlang.org"
372 + source: hosted
373 + version: "2.1.4"
374 + intl:
375 + dependency: "direct main"
376 + description:
377 + name: intl
378 + url: "https://pub.dartlang.org"
379 + source: hosted
380 + version: "0.16.0"
381 + io:
382 + dependency: transitive
383 + description:
384 + name: io
385 + url: "https://pub.dartlang.org"
386 + source: hosted
387 + version: "0.3.3"
388 + js:
389 + dependency: transitive
390 + description:
391 + name: js
392 + url: "https://pub.dartlang.org"
393 + source: hosted
394 + version: "0.6.1+1"
395 + json_annotation:
396 + dependency: transitive
397 + description:
398 + name: json_annotation
399 + url: "https://pub.dartlang.org"
400 + source: hosted
401 + version: "3.0.0"
402 + kernel:
403 + dependency: transitive
404 + description:
405 + name: kernel
406 + url: "https://pub.dartlang.org"
407 + source: hosted
408 + version: "0.3.19"
409 + logging:
410 + dependency: transitive
411 + description:
412 + name: logging
413 + url: "https://pub.dartlang.org"
414 + source: hosted
415 + version: "0.11.3+2"
416 + matcher:
417 + dependency: transitive
418 + description:
419 + name: matcher
420 + url: "https://pub.dartlang.org"
421 + source: hosted
422 + version: "0.12.6"
423 + meta:
424 + dependency: transitive
425 + description:
426 + name: meta
427 + url: "https://pub.dartlang.org"
428 + source: hosted
429 + version: "1.1.8"
430 + mime:
431 + dependency: transitive
432 + description:
433 + name: mime
434 + url: "https://pub.dartlang.org"
435 + source: hosted
436 + version: "0.9.6+3"
437 + mobx:
438 + dependency: "direct main"
439 + description:
440 + name: mobx
441 + url: "https://pub.dartlang.org"
442 + source: hosted
443 + version: "0.3.9+3"
444 + mobx_codegen:
445 + dependency: "direct dev"
446 + description:
447 + name: mobx_codegen
448 + url: "https://pub.dartlang.org"
449 + source: hosted
450 + version: "0.3.3+1"
451 + node_interop:
452 + dependency: transitive
453 + description:
454 + name: node_interop
455 + url: "https://pub.dartlang.org"
456 + source: hosted
457 + version: "1.0.3"
458 + node_io:
459 + dependency: transitive
460 + description:
461 + name: node_io
462 + url: "https://pub.dartlang.org"
463 + source: hosted
464 + version: "1.0.1+2"
465 + package_config:
466 + dependency: transitive
467 + description:
468 + name: package_config
469 + url: "https://pub.dartlang.org"
470 + source: hosted
471 + version: "1.1.0"
472 + package_resolver:
473 + dependency: transitive
474 + description:
475 + name: package_resolver
476 + url: "https://pub.dartlang.org"
477 + source: hosted
478 + version: "1.0.10"
479 + password:
480 + dependency: "direct main"
481 + description:
482 + name: password
483 + url: "https://pub.dartlang.org"
484 + source: hosted
485 + version: "1.0.0"
486 + path:
487 + dependency: transitive
488 + description:
489 + name: path
490 + url: "https://pub.dartlang.org"
491 + source: hosted
492 + version: "1.6.4"
493 + path_provider:
494 + dependency: "direct main"
495 + description:
496 + name: path_provider
497 + url: "https://pub.dartlang.org"
498 + source: hosted
499 + version: "1.5.1"
500 + pedantic:
501 + dependency: transitive
502 + description:
503 + name: pedantic
504 + url: "https://pub.dartlang.org"
505 + source: hosted
506 + version: "1.8.0+1"
507 + petitparser:
508 + dependency: transitive
509 + description:
510 + name: petitparser
511 + url: "https://pub.dartlang.org"
512 + source: hosted
513 + version: "2.4.0"
514 + platform:
515 + dependency: transitive
516 + description:
517 + name: platform
518 + url: "https://pub.dartlang.org"
519 + source: hosted
520 + version: "2.2.1"
521 + pointycastle:
522 + dependency: transitive
523 + description:
524 + name: pointycastle
525 + url: "https://pub.dartlang.org"
526 + source: hosted
527 + version: "1.0.2"
528 + pool:
529 + dependency: transitive
530 + description:
531 + name: pool
532 + url: "https://pub.dartlang.org"
533 + source: hosted
534 + version: "1.4.0"
535 + provider:
536 + dependency: "direct main"
537 + description:
538 + name: provider
539 + url: "https://pub.dartlang.org"
540 + source: hosted
541 + version: "3.2.0"
542 + pub_semver:
543 + dependency: transitive
544 + description:
545 + name: pub_semver
546 + url: "https://pub.dartlang.org"
547 + source: hosted
548 + version: "1.4.2"
549 + pubspec_parse:
550 + dependency: transitive
551 + description:
552 + name: pubspec_parse
553 + url: "https://pub.dartlang.org"
554 + source: hosted
555 + version: "0.1.5"
556 + qr:
557 + dependency: "direct main"
558 + description:
559 + name: qr
560 + url: "https://pub.dartlang.org"
561 + source: hosted
562 + version: "1.2.0"
563 + quiver:
564 + dependency: transitive
565 + description:
566 + name: quiver
567 + url: "https://pub.dartlang.org"
568 + source: hosted
569 + version: "2.0.5"
570 + rxdart:
571 + dependency: "direct main"
572 + description:
573 + name: rxdart
574 + url: "https://pub.dartlang.org"
575 + source: hosted
576 + version: "0.22.6"
577 + share:
578 + dependency: "direct main"
579 + description:
580 + name: share
581 + url: "https://pub.dartlang.org"
582 + source: hosted
583 + version: "0.6.3+5"
584 + shared_preferences:
585 + dependency: "direct main"
586 + description:
587 + name: shared_preferences
588 + url: "https://pub.dartlang.org"
589 + source: hosted
590 + version: "0.5.4+9"
591 + shared_preferences_platform_interface:
592 + dependency: transitive
593 + description:
594 + name: shared_preferences_platform_interface
595 + url: "https://pub.dartlang.org"
596 + source: hosted
597 + version: "1.0.1"
598 + shelf:
599 + dependency: transitive
600 + description:
601 + name: shelf
602 + url: "https://pub.dartlang.org"
603 + source: hosted
604 + version: "0.7.5"
605 + shelf_web_socket:
606 + dependency: transitive
607 + description:
608 + name: shelf_web_socket
609 + url: "https://pub.dartlang.org"
610 + source: hosted
611 + version: "0.2.3"
612 + sky_engine:
613 + dependency: transitive
614 + description: flutter
615 + source: sdk
616 + version: "0.0.99"
617 + source_gen:
618 + dependency: transitive
619 + description:
620 + name: source_gen
621 + url: "https://pub.dartlang.org"
622 + source: hosted
623 + version: "0.9.4+4"
624 + source_span:
625 + dependency: transitive
626 + description:
627 + name: source_span
628 + url: "https://pub.dartlang.org"
629 + source: hosted
630 + version: "1.5.5"
631 + stack_trace:
632 + dependency: transitive
633 + description:
634 + name: stack_trace
635 + url: "https://pub.dartlang.org"
636 + source: hosted
637 + version: "1.9.3"
638 + stream_channel:
639 + dependency: transitive
640 + description:
641 + name: stream_channel
642 + url: "https://pub.dartlang.org"
643 + source: hosted
644 + version: "2.0.0"
645 + stream_transform:
646 + dependency: transitive
647 + description:
648 + name: stream_transform
649 + url: "https://pub.dartlang.org"
650 + source: hosted
651 + version: "0.0.20"
652 + string_scanner:
653 + dependency: transitive
654 + description:
655 + name: string_scanner
656 + url: "https://pub.dartlang.org"
657 + source: hosted
658 + version: "1.0.5"
659 + term_glyph:
660 + dependency: transitive
661 + description:
662 + name: term_glyph
663 + url: "https://pub.dartlang.org"
664 + source: hosted
665 + version: "1.1.0"
666 + test_api:
667 + dependency: transitive
668 + description:
669 + name: test_api
670 + url: "https://pub.dartlang.org"
671 + source: hosted
672 + version: "0.2.11"
673 + time:
674 + dependency: transitive
675 + description:
676 + name: time
677 + url: "https://pub.dartlang.org"
678 + source: hosted
679 + version: "1.2.0"
680 + timing:
681 + dependency: transitive
682 + description:
683 + name: timing
684 + url: "https://pub.dartlang.org"
685 + source: hosted
686 + version: "0.1.1+2"
687 + typed_data:
688 + dependency: transitive
689 + description:
690 + name: typed_data
691 + url: "https://pub.dartlang.org"
692 + source: hosted
693 + version: "1.1.6"
694 + url_launcher:
695 + dependency: "direct main"
696 + description:
697 + name: url_launcher
698 + url: "https://pub.dartlang.org"
699 + source: hosted
700 + version: "5.3.0"
701 + url_launcher_platform_interface:
702 + dependency: transitive
703 + description:
704 + name: url_launcher_platform_interface
705 + url: "https://pub.dartlang.org"
706 + source: hosted
707 + version: "1.0.1"
708 + url_launcher_web:
709 + dependency: transitive
710 + description:
711 + name: url_launcher_web
712 + url: "https://pub.dartlang.org"
713 + source: hosted
714 + version: "0.1.0+1"
715 + uuid:
716 + dependency: "direct main"
717 + description:
718 + name: uuid
719 + url: "https://pub.dartlang.org"
720 + source: hosted
721 + version: "2.0.1"
722 + vector_math:
723 + dependency: transitive
724 + description:
725 + name: vector_math
726 + url: "https://pub.dartlang.org"
727 + source: hosted
728 + version: "2.0.8"
729 + watcher:
730 + dependency: transitive
731 + description:
732 + name: watcher
733 + url: "https://pub.dartlang.org"
734 + source: hosted
735 + version: "0.9.7+13"
736 + web_socket_channel:
737 + dependency: transitive
738 + description:
739 + name: web_socket_channel
740 + url: "https://pub.dartlang.org"
741 + source: hosted
742 + version: "1.1.0"
743 + xml:
744 + dependency: transitive
745 + description:
746 + name: xml
747 + url: "https://pub.dartlang.org"
748 + source: hosted
749 + version: "3.5.0"
750 + yaml:
751 + dependency: "direct main"
752 + description:
753 + name: yaml
754 + url: "https://pub.dartlang.org"
755 + source: hosted
756 + version: "2.2.0"
757 +sdks:
758 + dart: ">=2.6.0 <3.0.0"
759 + flutter: ">=1.12.8 <2.0.0"
pubspec.yaml new
+122
@@ -0,0 +1,122 @@
1 +name: cake_wallet
2 +description: Cake Wallet.
3 +
4 +# The following defines the version and build number for your application.
5 +# A version number is three numbers separated by dots, like 1.2.43
6 +# followed by an optional build number separated by a +.
7 +# Both the version and the builder number may be overridden in flutter
8 +# build by specifying --build-name and --build-number, respectively.
9 +# In Android, build-name is used as versionName while build-number used as versionCode.
10 +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
11 +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
12 +# Read more about iOS versioning at
13 +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
14 +version: 1.0.0+1
15 +
16 +environment:
17 + sdk: ">=2.2.2 <3.0.0"
18 +
19 +dependencies:
20 + flutter:
21 + sdk: flutter
22 + flutter_localizations:
23 + sdk: flutter
24 + flutter_cupertino_localizations: ^1.0.1
25 + intl: ^0.16.0
26 + url_launcher: ^5.1.2
27 + qr: ^1.2.0
28 + uuid: 2.0.1
29 + shared_preferences: ^0.5.3+4
30 + flutter_secure_storage: ^3.2.1+1
31 + provider: ^3.1.0
32 + rxdart: ^0.22.2
33 + yaml: ^2.1.16
34 + barcode_scan: any
35 + http: ^0.12.0+2
36 + path_provider: ^1.3.0
37 + mobx: ^0.3.7
38 + flutter_mobx: 0.3.0+1
39 + flutter_slidable: ^0.5.3
40 + share: ^0.6.2+1
41 + esys_flutter_share: ^1.0.2
42 + date_range_picker: ^1.0.6
43 + dio: 3.0.7
44 + cw_monero:
45 + path: ./cw_monero
46 + hive: ^1.2.0
47 + hive_flutter: ^0.2.1
48 +
49 + # The following adds the Cupertino Icons font to your application.
50 + # Use with the CupertinoIcons class for iOS style icons.
51 + cupertino_icons: ^0.1.2
52 + encrypt: ^4.0.0
53 + password: ^1.0.0
54 +
55 +dev_dependencies:
56 + flutter_test:
57 + sdk: flutter
58 + build_runner: ^1.3.1
59 + mobx_codegen: 0.3.3+1
60 + hive_generator: ^0.6.0
61 + flutter_launcher_icons: ^0.7.4
62 +
63 +flutter_icons:
64 + image_path: "assets/images/app_logo.png"
65 + android: true
66 + ios: true
67 +
68 +# For information on the generic Dart part of this file, see the
69 +# following page: https://dart.dev/tools/pub/pubspec
70 +
71 +# The following section is specific to Flutter.
72 +flutter:
73 +
74 + # The following line ensures that the Material Icons font is
75 + # included with your application, so that you can use the icons in
76 + # the material Icons class.
77 + uses-material-design: true
78 +
79 + assets:
80 + - assets/images/
81 + - assets/node_list.yml
82 + - assets/text/
83 + - assets/faq/
84 +
85 + fonts:
86 + - family: Lato
87 + fonts:
88 + - asset: assets/fonts/Lato-Regular.ttf
89 + - asset: assets/fonts/Lato-Bold.ttf
90 + - asset: assets/fonts/Lato-Semibold.ttf
91 +
92 +
93 + # To add assets to your application, add an assets section, like this:
94 + # assets:
95 + # - images/a_dot_burr.jpeg
96 + # - images/a_dot_ham.jpeg
97 +
98 + # An image asset can refer to one or more resolution-specific "variants", see
99 + # https://flutter.dev/assets-and-images/#resolution-aware.
100 +
101 + # For details regarding adding assets from package dependencies, see
102 + # https://flutter.dev/assets-and-images/#from-packages
103 +
104 + # To add custom fonts to your application, add a fonts section here,
105 + # in this "flutter" section. Each entry in this list should have a
106 + # "family" key with the font family name, and a "fonts" key with a
107 + # list giving the asset and other descriptors for the font. For
108 + # example:
109 + # fonts:
110 + # - family: Schyler
111 + # fonts:
112 + # - asset: fonts/Schyler-Regular.ttf
113 + # - asset: fonts/Schyler-Italic.ttf
114 + # style: italic
115 + # - family: Trajan Pro
116 + # fonts:
117 + # - asset: fonts/TrajanPro.ttf
118 + # - asset: fonts/TrajanPro_Bold.ttf
119 + # weight: 700
120 + #
121 + # For details regarding fonts from package dependencies,
122 + # see https://flutter.dev/custom-fonts/#from-packages
res/values/strings_de.arb new
+334
@@ -0,0 +1,334 @@
1 +{
2 + "welcome" : "Willkommen\nzu CAKE WALLET",
3 + "first_wallet_text" : "tolle Brieftasche\nzum Monero",
4 + "please_make_selection" : "Bitte treffen Sie unten eine Auswahl zu\nErstellen oder Wiederherstellen Ihrer Brieftasche.",
5 + "create_new" : "Erstelle neu",
6 + "restore_wallet" : "Wallet wiederherstellen",
7 +
8 +
9 + "accounts" : "Konten",
10 + "edit" : "Bearbeiten",
11 + "account" : "Konto",
12 + "add" : "Hinzufügen",
13 +
14 +
15 + "address_book" : "Adressbuch",
16 + "contact" : "Kontakt",
17 + "please_select" : "Bitte auswählen:",
18 + "cancel" : "Abbrechen",
19 + "ok" : "OK",
20 + "contact_name" : "Name des Ansprechpartners",
21 + "reset" : "Zurücksetzen",
22 + "save" : "speichern",
23 +
24 +
25 + "authenticated" : "Authentifiziert",
26 + "authentication" : "Authentifizierung",
27 + "failed_authentication" : "Authentifizierung fehlgeschlagen. ${state_error}",
28 +
29 +
30 + "wallet_menu" : "Brieftaschen-Menü",
31 + "Blocks_remaining" : "${status} Verbleibende Blöcke",
32 + "please_try_to_connect_to_another_node" : "Bitte versuchen Sie, eine Verbindung zu einem anderen Knoten herzustellen",
33 + "xmr_hidden" : "XMR versteckt",
34 + "xmr_available_balance" : "XMR verfügbares Guthaben",
35 + "xmr_full_balance" : "XMR Volle Balance",
36 + "send" : "Senden",
37 + "receive" : "Erhalten",
38 + "transactions" : "Transaktionen",
39 + "incoming" : "Eingehend",
40 + "outgoing" : "Ausgehend",
41 + "transactions_by_date" : "Transaktionen nach Datum",
42 + "trades" : "Handel",
43 + "filters" : "Filter",
44 + "today" : "Heute",
45 + "yesterday" : "Gestern",
46 + "received" : "Empfangen",
47 + "sent" : "Geschickt",
48 + "pending" : " (steht aus)",
49 + "rescan" : "Erneut scannen",
50 + "reconnect" : "Erneut verbinden",
51 + "wallets" : "Wallets",
52 + "show_seed" : "Seed zeigen",
53 + "show_keys" : "Schlüssel anzeigen",
54 + "address_book_menu" : "Adressbuch",
55 + "reconnection" : "Wiederverbindung",
56 + "reconnect_alert_text" : "Sind Sie sicher, dass Sie die Verbindung wiederherstellen möchten?",
57 +
58 +
59 + "exchange" : "Austausch",
60 + "clear" : "klar",
61 + "change_exchange_provider" : "Wechseln Sie den Exchange-Anbieter",
62 + "you_will_send" : "Du wirst senden",
63 + "you_will_get" : "Sie erhalten",
64 + "amount_is_guaranteed" : "Der Empfangsbetrag ist garantiert",
65 + "amount_is_estimate" : "Der empfangene Betrag ist eine Schätzung",
66 + "powered_by" : "Unterstützt von ${title}",
67 + "error" : "Error",
68 + "estimated" : "Geschätzt",
69 + "min_value" : "Mindest: ${value} ${currency}",
70 + "max_value" : "Max: ${value} ${currency}",
71 + "change_currency" : "Währung ändern",
72 +
73 +
74 + "copy_id" : "ID kopieren",
75 + "exchange_result_write_down_trade_id" : "Bitte kopieren oder notieren Sie die Handel-ID, um fortzufahren.",
76 + "trade_id" : "Handel-ID:\n${id}",
77 + "copied_to_clipboard" : "In die Zwischenablage kopiert",
78 + "saved_the_trade_id" : "Ich habe die Geschäfts-ID gespeichert",
79 + "fetching" : "holen",
80 + "id" : "ID: ",
81 + "amount" : "Menge: ",
82 + "payment_id" : "Zahlungs ID: ",
83 + "status" : "Status: ",
84 + "offer_expires_in" : "Angebot läuft ab in: ",
85 + "trade_is_powered_by" : "Dieser Handel wird betrieben von ${provider}",
86 + "copy_address" : "Adresse kopieren",
87 + "exchange_result_confirm" : "Durch Drücken von Bestätigen wird gesendet ${fetchingLabel} ${from} von Ihrer Brieftasche aus angerufen ${walletName} an die oben angegebene Adresse. Oder Sie können von Ihrem externen Portemonnaie an die oben angegebene Adresse / QR-Code senden.\n\nBitte bestätigen Sie, um fortzufahren, oder gehen Sie zurück, um die Beträge zu änderns.\n\n",
88 + "exchange_result_description" : "Bitte senden ${fetchingLabel} ${from} an die oben angegebene Adresse.\n\n'",
89 + "exchange_result_write_down_ID" : "*Bitte kopieren oder notieren Sie Ihren oben gezeigten Ausweis.",
90 + "confirm" : "Bestätigen",
91 + "confirm_sending" : "Bestätigen Sie das Senden",
92 + "commit_transaction_amount_fee" : "Transaktion festschreiben\nMenge: ${amount}\nGebühr: ${fee}",
93 + "sending" : "Senden",
94 + "transaction_sent" : "Transaktion gesendet!",
95 + "expired" : "Abgelaufen",
96 + "time" : "${minutes}m ${seconds}s",
97 + "send_xmr" : "Senden XMR",
98 +
99 + "faq" : "FAQ",
100 +
101 +
102 + "enter_your_pin" : "PIN eingeben",
103 + "loading_your_wallet" : "Laden Sie Ihre Brieftasche",
104 +
105 +
106 + "new_wallet" : "Neues Wallet",
107 + "wallet_name" : "Walletname",
108 + "continue_text" : "Fortsetzen",
109 +
110 +
111 + "node_new" : "Neuer Knoten",
112 + "node_address" : "Knotenadresse",
113 + "node_port" : "Knotenport",
114 + "login" : "Einloggen",
115 + "password" : "Passwort",
116 + "nodes" : "Knoten",
117 + "node_reset_settings_title" : "Einstellungen zurücksetzen",
118 + "nodes_list_reset_to_default_message" : "Möchten Sie die Einstellungen wirklich auf die Standardeinstellungen zurücksetzen?",
119 + "change_current_node" : "Möchten Sie den aktuellen Knoten wirklich auf ändern? ${node}?",
120 + "change" : "Veränderung",
121 + "remove_node" : "Knoten entfernen",
122 + "remove_node_message" : "Möchten Sie den ausgewählten Knoten wirklich entfernen?",
123 + "remove" : "Löschen",
124 + "delete" : "Löschen",
125 +
126 +
127 + "use" : "Verwenden ",
128 + "digit_pin" : "-stelliger Pin",
129 +
130 +
131 + "share_address" : "Adresse teilen ",
132 + "receive_amount" : "Menge",
133 + "subaddresses" : "Unteradressen",
134 +
135 +
136 + "restore_restore_wallet" : "Wallet wiederherstellen",
137 + "restore_title_from_seed_keys" : "Vom Seed / Schlüssel wiederherstellen",
138 + "restore_description_from_seed_keys" : "Holen Sie sich Ihr Wallet von Seed / Schlüsseln zurück, die Sie an einem sicheren Ort aufbewahrt haben",
139 + "restore_next" : "Nächster",
140 + "restore_title_from_backup" : "Aus einer Sicherungsdatei wiederherstellen",
141 + "restore_description_from_backup" : "Sie können die gesamte Cake Wallet-App von wiederherstellen \nIhre Sicherungsdatei",
142 + "restore_seed_keys_restore" : "Seed / Schlüssel wiederherstellen",
143 + "restore_title_from_seed" : "Aus Seed wiederherstellen",
144 + "restore_description_from_seed" : "Stellen Sie Ihr Wallet aus den 25 Wörtern wieder her\noder 13-Wort-Kombinationscode",
145 + "restore_title_from_keys" : "Wiederherstellen von Schlüsseln",
146 + "restore_description_from_keys" : "Stellen Sie Ihr Wallet von generiert wieder her\nTastenanschläge, die von Ihren privaten Schlüsseln gespeichert wurden",
147 + "restore_wallet_name" : "Walletname",
148 + "restore_address" : "Adresse",
149 + "restore_view_key_private" : "Schlüssel anzeigen(geheim)",
150 + "restore_spend_key_private" : "Schlüssel ausgeben (geheim)",
151 + "restore_recover" : "Genesen",
152 + "restore_wallet_restore_description" : "Beschreibung zur Wiederherstellung der Brieftasche",
153 +
154 +
155 + "seed_title" : "Seed",
156 + "seed_share" : "Teilen Sie Seed",
157 + "copy" : "Kopieren",
158 +
159 +
160 + "seed_alert_first_text" : "Die nächste Seite wird angezeigt\nDu bist ein Seed.",
161 + "seed_alert_second_text" : "Bitte schreiben Sie diese nur in\nFalls Sie Ihr Telefon verlieren oder abwischen.",
162 + "seed_alert_third_text" : "Sie können den Seed auch wieder sehen\nin dem ",
163 + "seed_alert_settings" : "die Einstellungen",
164 + "seed_alert_menu" : " Speisekarte.",
165 + "seed_alert_understand" : "ich verstehe",
166 +
167 +
168 + "send_title" : "Senden Sie Monero",
169 + "send_your_wallet" : "Deine Geldbörse",
170 + "send_monero_address" : "Monero-Adresse",
171 + "send_payment_id" : "Zahlungs ID (wahlweise)",
172 + "all" : "ALLE",
173 + "send_error_minimum_value" : "Der Mindestbetrag beträgt 0,01",
174 + "send_error_currency" : "Die Währung kann nur Zahlen enthalten",
175 + "send_estimated_fee" : "Geschätzte Gebühr:",
176 + "send_priority" : "Derzeit ist die Gebühr auf festgelegt ${transactionPriority} priorität.\nDie Transaktionspriorität kann in den Einstellungen angepasst werden",
177 + "send_creating_transaction" : "Transaktion erstellen",
178 +
179 +
180 + "settings_title" : "die Einstellungen",
181 + "settings_nodes" : "Knoten",
182 + "settings_current_node" : "Aktueller Knoten",
183 + "settings_wallets" : "Brieftaschen",
184 + "settings_display_balance_as" : "Kontostand anzeigen als",
185 + "settings_currency" : "Währung",
186 + "settings_fee_priority" : "Gebührenpriorität",
187 + "settings_save_recipient_address" : "Empfängeradresse speichern",
188 + "settings_personal" : "persönlich",
189 + "settings_change_pin" : "PIN ändern",
190 + "settings_change_language" : "Sprache ändern",
191 + "settings_allow_biometrical_authentication" : "Biometrische Authentifizierung zulassen",
192 + "settings_dark_mode" : "Dunkler Modus",
193 + "settings_transactions" : "Transaktionen",
194 + "settings_trades" : "Handel",
195 + "settings_display_on_dashboard_list" : "Anzeige in der Dashboard-Liste",
196 + "settings_all" : "ALLE",
197 + "settings_only_trades" : "Nur Trades",
198 + "settings_only_transactions" : "Nur Transaktionen",
199 + "settings_none" : "Keiner",
200 + "settings_support" : "Unterstützung",
201 + "settings_terms_and_conditions" : "Geschäftsbedingungen",
202 + "pin_is_incorrect" : "PIN ist falsch",
203 +
204 +
205 + "setup_pin" : "PIN einrichten",
206 + "enter_your_pin_again" : "Geben Sie Ihre PIN erneut ein",
207 + "setup_successful" : "Ihre PIN wurde erfolgreich eingerichtet!",
208 +
209 +
210 + "wallet_keys" : "Wallet schlüssel",
211 + "view_key_private" : "Schlüssel anzeigen (eheim)",
212 + "view_key_public" : "Schlüssel anzeigen (Öffentlichkeit)",
213 + "spend_key_private" : "Schlüssel ausgeben (geheim)",
214 + "spend_key_public" : "Schlüssel ausgeben (Öffentlichkeit)",
215 + "copied_key_to_clipboard" : "Kopiert ${key} Zur Zwischenablage",
216 +
217 +
218 + "new_subaddress_title" : "Neue Unteradresse",
219 + "new_subaddress_label_name" : "Markenname",
220 + "new_subaddress_create" : "Erstellen",
221 +
222 +
223 + "subaddress_title" : "Unteradressenliste",
224 +
225 +
226 + "trade_details_title" : "Handel Einzelheiten",
227 + "trade_details_id" : "ID",
228 + "trade_details_state" : "Zustand",
229 + "trade_details_fetching" : "Holen",
230 + "trade_details_provider" : "Anbieter",
231 + "trade_details_created_at" : "Hergestellt in",
232 + "trade_details_pair" : "Paar",
233 + "trade_details_copied" : "${title} in die Zwischenablage kopiert",
234 +
235 +
236 + "trade_history_title" : "Handelsgeschichte",
237 +
238 +
239 + "transaction_details_title" : "Transaktionsdetails",
240 + "transaction_details_transaction_id" : "Transaktions-ID",
241 + "transaction_details_date" : "Datum",
242 + "transaction_details_height" : "Höhe",
243 + "transaction_details_amount" : "Menge",
244 + "transaction_details_copied" : "${title} in die Zwischenablage kopiert",
245 + "transaction_details_recipient_address" : "Empfängeradresse",
246 +
247 +
248 + "wallet_list_title" : "Monero Wallet",
249 + "wallet_list_create_new_wallet" : "Neue Wallet erstellen",
250 + "wallet_list_restore_wallet" : "Wallet wiederherstellen",
251 + "wallet_list_load_wallet" : "Wallet einlegen",
252 + "wallet_list_loading_wallet" : "Wird geladen ${wallet_name} Wallet",
253 + "wallet_list_failed_to_load" : "Laden fehlgeschlagen ${wallet_name} Wallet. ${error}",
254 + "wallet_list_removing_wallet" : "Entfernen ${wallet_name} Wallet",
255 + "wallet_list_failed_to_remove" : "Fehler beim Entfernen ${wallet_name} Wallet. ${error}",
256 +
257 +
258 + "widgets_address" : "Adresse",
259 + "widgets_restore_from_blockheight" : "Aus Blockhöhe wiederherstellen",
260 + "widgets_restore_from_date" : "Vom Datum wiederherstellen",
261 + "widgets_or" : "oder",
262 + "widgets_seed" : "Seed",
263 +
264 +
265 + "router_no_route" : "Keine Route definiert für ${name}",
266 +
267 +
268 + "error_text_account_name" : "Der Kontoname darf nur Wallet und Zahlen enthalten\nund muss zwischen 1 und 15 Zeichen lang sein",
269 + "error_text_contact_name" : "Kontaktname darf nicht enthalten sein ` , ' \" Symbole\nund muss zwischen 1 und 32 Zeichen lang sein",
270 + "error_text_address" : "Die Walletadresse muss dem Typ entsprechen\nder Kryptowährung",
271 + "error_text_node_address" : "Bitte geben Sie eine iPv4-Adresse ein",
272 + "error_text_node_port" : "Der Knotenport kann nur Nummern zwischen 0 und 65535 enthalten",
273 + "error_text_payment_id" : "Die Zahlungs-ID kann nur 16 bis 64 hexadezimale Zeichen enthalten",
274 + "error_text_xmr" : "Der XMR-Wert kann das verfügbare Guthaben nicht überschreiten.\nDie Anzahl der Nachkommastellen muss kleiner oder gleich 12 sein",
275 + "error_text_fiat" : "Der Wert des Betrags darf den verfügbaren Kontostand nicht überschreiten.\nDie Anzahl der Nachkommastellen muss kleiner oder gleich 2 sein",
276 + "error_text_subaddress_name" : "Der Name der Unteradresse darf nicht enthalten sein ` , ' \" symbole\nund muss zwischen 1 und 20 Zeichen lang sein",
277 + "error_text_amount" : "Betrag kann nur Zahlen enthalten",
278 + "error_text_wallet_name" : "Der Wallet darf nur Buchstaben und Zahlen enthalten\nund muss zwischen 1 und 15 Zeichen lang sein",
279 + "error_text_keys" : "Walletschlüssel können nur 64 hexadezimale Zeichen enthalten",
280 + "error_text_crypto_currency" : "Die Anzahl der Nachkommastellen\nmuss kleiner oder gleich 12 sein.",
281 +
282 +
283 + "auth_store_ban_timeout" : "Auszeit verbieten",
284 + "auth_store_banned_for" : "Gebannt für ",
285 + "auth_store_banned_minutes" : " Protokoll",
286 + "auth_store_incorrect_password" : "Falsches PIN",
287 + "wallet_store_monero_wallet" : "Monero Wallet",
288 + "wallet_restoration_store_incorrect_seed_length" : "Falsche Samenlänge",
289 +
290 +
291 + "full_balance" : "Volle Balance",
292 + "available_balance" : "Verfügbares Guthaben",
293 + "hidden_balance" : "Verstecktes Gleichgewicht",
294 +
295 +
296 + "sync_status_syncronizing" : "SYNCHRONISIERUNG",
297 + "sync_status_syncronized" : "SYNCHRONISIERT",
298 + "sync_status_not_connected" : "NICHT VERBUNDEN",
299 + "sync_status_starting_sync" : "STARTEN DER SYNCHRONISIERUNG",
300 + "sync_status_failed_connect" : "Verbindung zum Knoten fehlgeschlagen",
301 + "sync_status_connecting" : "ANSCHLUSS",
302 + "sync_status_connected" : "IN VERBINDUNG GEBRACHT",
303 +
304 +
305 + "transaction_priority_slow" : "Schleppend",
306 + "transaction_priority_regular" : "Regulär",
307 + "transaction_priority_medium" : "Mittel",
308 + "transaction_priority_fast" : "Schnell",
309 + "transaction_priority_fastest" : "Am schnellsten",
310 +
311 +
312 + "trade_for_not_created" : "Handel für ${title} wird nicht erstellt.",
313 + "trade_not_created" : "Handel nicht angelegt.",
314 + "trade_id_not_found" : "Handel ${tradeId} von ${title} nicht gefunden.",
315 + "trade_not_found" : "Handel nicht gefunden.",
316 +
317 +
318 + "trade_state_pending" : "Steht aus",
319 + "trade_state_confirming" : "Bestätigung",
320 + "trade_state_trading" : "Handel",
321 + "trade_state_traded" : "Handeln",
322 + "trade_state_complete" : "Komplett",
323 + "trade_state_to_be_created" : "Geschaffen werden",
324 + "trade_state_unpaid" : "Unbezahlt",
325 + "trade_state_underpaid" : "Unterbezahlt",
326 + "trade_state_paid_unconfirmed" : "Unbestätigt bezahlt",
327 + "trade_state_paid" : "Bezahlt",
328 + "trade_state_btc_sent" : "geschickt",
329 + "trade_state_timeout" : "Auszeit",
330 + "trade_state_created" : "Erstellt",
331 + "trade_state_finished" : "Fertig",
332 +
333 + "change_language" : "Sprache ändern",
334 + "change_language_to" : "Ändern Sie die Sprache in ${language}?"}
\ No newline at end of file
res/values/strings_en.arb new
+335
@@ -0,0 +1,335 @@
1 +{
2 + "welcome" : "WELCOME\nTO CAKE WALLET",
3 + "first_wallet_text" : "Awesome wallet\nfor Monero",
4 + "please_make_selection" : "Please make selection below to\ncreate or recover your wallet.",
5 + "create_new" : "Create new",
6 + "restore_wallet" : "Restore wallet",
7 +
8 +
9 + "accounts" : "Accounts",
10 + "edit" : "Edit",
11 + "account" : "Account",
12 + "add" : "Add",
13 +
14 +
15 + "address_book" : "Address Book",
16 + "contact" : "Contact",
17 + "please_select" : "Please select:",
18 + "cancel" : "Cancel",
19 + "ok" : "OK",
20 + "contact_name" : "Contact Name",
21 + "reset" : "Reset",
22 + "save" : "Save",
23 +
24 +
25 + "authenticated" : "Authenticated",
26 + "authentication" : "Authentication",
27 + "failed_authentication" : "Failed authentication. ${state_error}",
28 +
29 +
30 + "wallet_menu" : "Menu",
31 + "Blocks_remaining" : "${status} Blocks Remaining",
32 + "please_try_to_connect_to_another_node" : "Please try to connect to another node",
33 + "xmr_hidden" : "XMR Hidden",
34 + "xmr_available_balance" : "XMR Available Balance",
35 + "xmr_full_balance" : "XMR Full Balance",
36 + "send" : "Send",
37 + "receive" : "Receive",
38 + "transactions" : "Transactions",
39 + "incoming" : "Incoming",
40 + "outgoing" : "Outgoing",
41 + "transactions_by_date" : "Transactions by date",
42 + "trades" : "Trades",
43 + "filters" : "Filters",
44 + "today" : "Today",
45 + "yesterday" : "Yesterday",
46 + "received" : "Received",
47 + "sent" : "Sent",
48 + "pending" : " (pending)",
49 + "rescan" : "Rescan",
50 + "reconnect" : "Reconnect",
51 + "wallets" : "Wallets",
52 + "show_seed" : "Show seed",
53 + "show_keys" : "Show keys",
54 + "address_book_menu" : "Address book",
55 + "reconnection" : "Reconnection",
56 + "reconnect_alert_text" : "Are you sure to reconnect?",
57 +
58 +
59 + "exchange" : "Exchange",
60 + "clear" : "Clear",
61 + "change_exchange_provider" : "Change Exchange Provider",
62 + "you_will_send" : "You will send",
63 + "you_will_get" : "You will get",
64 + "amount_is_guaranteed" : "The receive amount is guaranteed",
65 + "amount_is_estimate" : "The receive amount is an estimate",
66 + "powered_by" : "Powered by ${title}",
67 + "error" : "Error",
68 + "estimated" : "Estimated",
69 + "min_value" : "Min: ${value} ${currency}",
70 + "max_value" : "Max: ${value} ${currency}",
71 + "change_currency" : "Change Currency",
72 +
73 +
74 + "copy_id" : "Copy ID",
75 + "exchange_result_write_down_trade_id" : "Please copy or write down the trade ID to continue.",
76 + "trade_id" : "Trade ID:\n${id}",
77 + "copied_to_clipboard" : "Copied to Clipboard",
78 + "saved_the_trade_id" : "I've saved the trade ID",
79 + "fetching" : "Fetching",
80 + "id" : "ID: ",
81 + "amount" : "Amount: ",
82 + "payment_id" : "Payment ID: ",
83 + "status" : "Status: ",
84 + "offer_expires_in" : "Offer expires in: ",
85 + "trade_is_powered_by" : "This trade is powered by ${provider}",
86 + "copy_address" : "Copy Address",
87 + "exchange_result_confirm" : "By pressing confirm, you will be sending ${fetchingLabel} ${from} from your wallet called ${walletName} to the address shown above. Or you can send from your external wallet to the above address/QR code.\n\nPlease press confirm to continue or go back to change the amounts.\n\n",
88 + "exchange_result_description" : "Please send ${fetchingLabel} ${from} to the address shown above.\n\n",
89 + "exchange_result_write_down_ID" : "*Please copy or write down your ID shown above.",
90 + "confirm" : "Confirm",
91 + "confirm_sending" : "Confirm sending",
92 + "commit_transaction_amount_fee" : "Commit transaction\nAmount: ${amount}\nFee: ${fee}",
93 + "sending" : "Sending",
94 + "transaction_sent" : "Transaction sent!",
95 + "expired" : "Expired",
96 + "time" : "${minutes}m ${seconds}s",
97 + "send_xmr" : "Send XMR",
98 +
99 + "faq" : "FAQ",
100 +
101 +
102 + "enter_your_pin" : "Enter your PIN",
103 + "loading_your_wallet" : "Loading your wallet",
104 +
105 +
106 + "new_wallet" : "New Wallet",
107 + "wallet_name" : "Wallet name",
108 + "continue_text" : "Continue",
109 +
110 +
111 + "node_new" : "New Node",
112 + "node_address" : "Node Address",
113 + "node_port" : "Node port",
114 + "login" : "Login",
115 + "password" : "Password",
116 + "nodes" : "Nodes",
117 + "node_reset_settings_title" : "Reset settings",
118 + "nodes_list_reset_to_default_message" : "Are you sure that you want to reset settings to default?",
119 + "change_current_node" : "Are you sure to change current node to ${node}?",
120 + "change" : "Change",
121 + "remove_node" : "Remove node",
122 + "remove_node_message" : "Are you sure that you want to remove selected node?",
123 + "remove" : "Remove",
124 + "delete" : "Delete",
125 +
126 +
127 + "use" : "Use ",
128 + "digit_pin" : "-digit Pin",
129 +
130 +
131 + "share_address" : "Share address",
132 + "receive_amount" : "Amount",
133 + "subaddresses" : "Subaddresses",
134 +
135 +
136 + "restore_restore_wallet" : "Restore Wallet",
137 + "restore_title_from_seed_keys" : "Restore from seed/keys",
138 + "restore_description_from_seed_keys" : "Get back your wallet from seed/keys that you've saved to secure place",
139 + "restore_next" : "Next",
140 + "restore_title_from_backup" : "Restore from a back-up file",
141 + "restore_description_from_backup" : "You can restore the whole Cake Wallet app from\nyour back-up file",
142 + "restore_seed_keys_restore" : "Seed/Keys Restore",
143 + "restore_title_from_seed" : "Restore from seed",
144 + "restore_description_from_seed" : "Restore your wallet from either the 25 word\nor 13 word combination code",
145 + "restore_title_from_keys" : "Restore from keys",
146 + "restore_description_from_keys" : "Restore your wallet from generated\nkeystrokes saved from your private keys",
147 + "restore_wallet_name" : "Wallet name",
148 + "restore_address" : "Address",
149 + "restore_view_key_private" : "View key (private)",
150 + "restore_spend_key_private" : "Spend key (private)",
151 + "restore_recover" : "Restore",
152 + "restore_wallet_restore_description" : "Wallet restore description",
153 +
154 +
155 + "seed_title" : "Seed",
156 + "seed_share" : "Share seed",
157 + "copy" : "Copy",
158 +
159 +
160 + "seed_alert_first_text" : "The next page will show\nyou a seed.",
161 + "seed_alert_second_text" : "Please write these down just in\ncase you lose or wipe your phone.",
162 + "seed_alert_third_text" : "You can also see the seed again\nin the ",
163 + "seed_alert_settings" : "settings",
164 + "seed_alert_menu" : " menu.",
165 + "seed_alert_understand" : "I understand",
166 +
167 +
168 + "send_title" : "Send Monero",
169 + "send_your_wallet" : "Your wallet",
170 + "send_monero_address" : "Monero address",
171 + "send_payment_id" : "Payment ID (optional)",
172 + "all" : "ALL",
173 + "send_error_minimum_value" : "Minimum value of amount is 0.01",
174 + "send_error_currency" : "Currency can only contain numbers",
175 + "send_estimated_fee" : "Estimated fee:",
176 + "send_priority" : "Currently the fee is set at ${transactionPriority} priority.\nTransaction priority can be adjusted in the settings",
177 + "send_creating_transaction" : "Creating transaction",
178 +
179 +
180 + "settings_title" : "Settings",
181 + "settings_nodes" : "Nodes",
182 + "settings_current_node" : "Current node",
183 + "settings_wallets" : "Wallets",
184 + "settings_display_balance_as" : "Display balance as",
185 + "settings_currency" : "Currency",
186 + "settings_fee_priority" : "Fee priority",
187 + "settings_save_recipient_address" : "Save recipient address",
188 + "settings_personal" : "Personal",
189 + "settings_change_pin" : "Change PIN",
190 + "settings_change_language" : "Change language",
191 + "settings_allow_biometrical_authentication" : "Allow biometrical authentication",
192 + "settings_dark_mode" : "Dark mode",
193 + "settings_transactions" : "Transactions",
194 + "settings_trades" : "Trades",
195 + "settings_display_on_dashboard_list" : "Display on dashboard list",
196 + "settings_all" : "ALL",
197 + "settings_only_trades" : "Only trades",
198 + "settings_only_transactions" : "Only transactions",
199 + "settings_none" : "None",
200 + "settings_support" : "Support",
201 + "settings_terms_and_conditions" : "Terms and conditions",
202 + "pin_is_incorrect" : "PIN is incorrect",
203 +
204 +
205 + "setup_pin" : "Setup PIN",
206 + "enter_your_pin_again" : "Enter your pin again",
207 + "setup_successful" : "Your PIN has been set up successfully!",
208 +
209 +
210 + "wallet_keys" : "Wallet keys",
211 + "view_key_private" : "View key (private)",
212 + "view_key_public" : "View key (public)",
213 + "spend_key_private" : "Spend key (private)",
214 + "spend_key_public" : "Spend key (public)",
215 + "copied_key_to_clipboard" : "Copied ${key} to Clipboard",
216 +
217 +
218 + "new_subaddress_title" : "New subaddress",
219 + "new_subaddress_label_name" : "Label name",
220 + "new_subaddress_create" : "Create",
221 +
222 +
223 + "subaddress_title" : "Subaddress list",
224 +
225 +
226 + "trade_details_title" : "Trade Details",
227 + "trade_details_id" : "ID",
228 + "trade_details_state" : "State",
229 + "trade_details_fetching" : "Fetching",
230 + "trade_details_provider" : "Provider",
231 + "trade_details_created_at" : "Created at",
232 + "trade_details_pair" : "Pair",
233 + "trade_details_copied" : "${title} copied to Clipboard",
234 +
235 +
236 + "trade_history_title" : "Trade history",
237 +
238 +
239 + "transaction_details_title" : "Transaction Details",
240 + "transaction_details_transaction_id" : "Transaction ID",
241 + "transaction_details_date" : "Date",
242 + "transaction_details_height" : "Height",
243 + "transaction_details_amount" : "Amount",
244 + "transaction_details_copied" : "${title} copied to Clipboard",
245 + "transaction_details_recipient_address" : "Recipient address",
246 +
247 +
248 + "wallet_list_title" : "Monero Wallet",
249 + "wallet_list_create_new_wallet" : "Create New Wallet",
250 + "wallet_list_restore_wallet" : "Restore Wallet",
251 + "wallet_list_load_wallet" : "Load wallet",
252 + "wallet_list_loading_wallet" : "Loading ${wallet_name} wallet",
253 + "wallet_list_failed_to_load" : "Failed to load ${wallet_name} wallet. ${error}",
254 + "wallet_list_removing_wallet" : "Removing ${wallet_name} wallet",
255 + "wallet_list_failed_to_remove" : "Failed to remove ${wallet_name} wallet. ${error}",
256 +
257 +
258 + "widgets_address" : "Address",
259 + "widgets_restore_from_blockheight" : "Restore from blockheight",
260 + "widgets_restore_from_date" : "Restore from date",
261 + "widgets_or" : "or",
262 + "widgets_seed" : "Seed",
263 +
264 +
265 + "router_no_route" : "No route defined for ${name}",
266 +
267 +
268 + "error_text_account_name" : "Account name can only contain letters, numbers\nand must be between 1 and 15 characters long",
269 + "error_text_contact_name" : "Contact name can't contain ` , ' \" symbols\nand must be between 1 and 32 characters long",
270 + "error_text_address" : "Wallet address must correspond to the type\nof cryptocurrency",
271 + "error_text_node_address" : "Please enter a iPv4 address",
272 + "error_text_node_port" : "Node port can only contain numbers between 0 and 65535",
273 + "error_text_payment_id" : "Payment ID can only contain from 16 to 64 chars in hex",
274 + "error_text_xmr" : "XMR value can't exceed available balance.\nThe number of fraction digits must be less or equal to 12",
275 + "error_text_fiat" : "Value of amount can't exceed available balance.\nThe number of fraction digits must be less or equal to 2",
276 + "error_text_subaddress_name" : "Subaddress name can't contain ` , ' \" symbols\nand must be between 1 and 20 characters long",
277 + "error_text_amount" : "Amount can only contain numbers",
278 + "error_text_wallet_name" : "Wallet name can only contain letters, numbers\nand must be between 1 and 15 characters long",
279 + "error_text_keys" : "Wallet keys can only contain 64 chars in hex",
280 + "error_text_crypto_currency" : "The number of fraction digits\nmust be less or equal to 12",
281 +
282 +
283 + "auth_store_ban_timeout" : "ban_timeout",
284 + "auth_store_banned_for" : "Banned for ",
285 + "auth_store_banned_minutes" : " minutes",
286 + "auth_store_incorrect_password" : "Wrong PIN",
287 + "wallet_store_monero_wallet" : "Monero Wallet",
288 + "wallet_restoration_store_incorrect_seed_length" : "Incorrect seed length",
289 +
290 +
291 + "full_balance" : "Full Balance",
292 + "available_balance" : "Available Balance",
293 + "hidden_balance" : "Hidden Balance",
294 +
295 +
296 + "sync_status_syncronizing" : "SYNCRONIZING",
297 + "sync_status_syncronized" : "SYNCHRONIZED",
298 + "sync_status_not_connected" : "NOT CONNECTED",
299 + "sync_status_starting_sync" : "STARTING SYNC",
300 + "sync_status_failed_connect" : "FAILED CONNECT TO THE NODE",
301 + "sync_status_connecting" : "CONNECTING",
302 + "sync_status_connected" : "CONNECTED",
303 +
304 +
305 + "transaction_priority_slow" : "Slow",
306 + "transaction_priority_regular" : "Regular",
307 + "transaction_priority_medium" : "Medium",
308 + "transaction_priority_fast" : "Fast",
309 + "transaction_priority_fastest" : "Fastest",
310 +
311 +
312 + "trade_for_not_created" : "Trade for ${title} is not created.",
313 + "trade_not_created" : "Trade not created.",
314 + "trade_id_not_found" : "Trade ${tradeId} of ${title} not found.",
315 + "trade_not_found" : "Trade not found.",
316 +
317 +
318 + "trade_state_pending" : "Pending",
319 + "trade_state_confirming" : "Confirming",
320 + "trade_state_trading" : "Trading",
321 + "trade_state_traded" : "Traded",
322 + "trade_state_complete" : "Complete",
323 + "trade_state_to_be_created" : "To be created",
324 + "trade_state_unpaid" : "Unpaid",
325 + "trade_state_underpaid" : "Underpaid",
326 + "trade_state_paid_unconfirmed" : "Paid unconfirmed",
327 + "trade_state_paid" : "Paid",
328 + "trade_state_btc_sent" : "Btc sent",
329 + "trade_state_timeout" : "Timeout",
330 + "trade_state_created" : "Created",
331 + "trade_state_finished" : "Finished",
332 +
333 + "change_language" : "Change language",
334 + "change_language_to" : "Change language to ${language}?"
335 +}
\ No newline at end of file
res/values/strings_es.arb new
+335
@@ -0,0 +1,335 @@
1 +{
2 + "welcome" : "Bienvenido\n CAKE WALLET",
3 + "first_wallet_text" : "Impresionante billetera\npara Monero",
4 + "please_make_selection" : "Seleccione a continuación para\ncrear o recuperar su billetera.",
5 + "create_new" : "Crear nuevo",
6 + "restore_wallet" : "Restaurar billetera",
7 +
8 +
9 + "accounts" : "Cuentas",
10 + "edit" : "Editar",
11 + "account" : "Cuenta",
12 + "add" : "Añadir",
13 +
14 +
15 + "address_book" : "Libreta de direcciones",
16 + "contact" : "Contacto",
17 + "please_select" : "Por favor seleccione:",
18 + "cancel" : "Cancelar",
19 + "ok" : "OK",
20 + "contact_name" : "Nombre de contacto",
21 + "reset" : "Reiniciar",
22 + "save" : "Salvar",
23 +
24 +
25 + "authenticated" : "Autenticados",
26 + "authentication" : "Autenticación",
27 + "failed_authentication" : "Autenticación fallida. ${state_error}",
28 +
29 +
30 + "wallet_menu" : "Menú de billetera",
31 + "Blocks_remaining" : "${status} Bloques restantes",
32 + "please_try_to_connect_to_another_node" : "Intenta conectarte a otro nodo",
33 + "xmr_hidden" : "XMR Oculto",
34 + "xmr_available_balance" : "XMR Available Balance",
35 + "xmr_full_balance" : "XMR Saldo disponible",
36 + "send" : "Enviar",
37 + "receive" : "Recibir",
38 + "transactions" : "Actas",
39 + "incoming" : "Entrante",
40 + "outgoing" : "Saliente",
41 + "transactions_by_date" : "Transacciones por fecha",
42 + "trades" : "Cambios",
43 + "filters" : "Filtros",
44 + "today" : "Hoy",
45 + "yesterday" : "Ayer",
46 + "received" : "Recibido",
47 + "sent" : "Expedido",
48 + "pending" : " (pendiente)",
49 + "rescan" : "Reescanear",
50 + "reconnect" : "Volver a conectar",
51 + "wallets" : "Carteras",
52 + "show_seed" : "Mostrar semilla",
53 + "show_keys" : "Mostrar llaves",
54 + "address_book_menu" : "Libreta de direcciones",
55 + "reconnection" : "Reconexión",
56 + "reconnect_alert_text" : "¿Estás seguro de reconectar?",
57 +
58 +
59 + "exchange" : "Intercambiar",
60 + "clear" : "Claro",
61 + "change_exchange_provider" : "Cambiar proveedor de intercambio",
62 + "you_will_send" : "Enviarás",
63 + "you_will_get" : "Conseguirás",
64 + "amount_is_guaranteed" : "El monto recibido está garantizado",
65 + "amount_is_estimate" : "El monto recibido es un estimado",
66 + "powered_by" : "Energizado por ${title}",
67 + "error" : "Error",
68 + "estimated" : "Estimado",
69 + "min_value" : "Min: ${value} ${currency}",
70 + "max_value" : "Max: ${value} ${currency}",
71 + "change_currency" : "Cambiar moneda",
72 +
73 +
74 + "copy_id" : "Copiar ID",
75 + "exchange_result_write_down_trade_id" : "Por favor, copia o escribe el ID.",
76 + "trade_id" : "Comercial ID:\n${id}",
77 + "copied_to_clipboard" : "Copiado al portapapeles",
78 + "saved_the_trade_id" : "He salvado comercial ID",
79 + "fetching" : "Cargando",
80 + "id" : "ID: ",
81 + "amount" : "Cantidad: ",
82 + "payment_id" : "ID de pago: ",
83 + "status" : "Estado: ",
84 + "offer_expires_in" : "Oferta expira en: ",
85 + "trade_is_powered_by" : "Este comercio es impulsado por ${provider}",
86 + "copy_address" : "Copiar dirección ",
87 + "exchange_result_confirm" : "Al presionar confirmar, enviará ${fetchingLabel} ${from} desde su billetera llamada ${walletName} a la dirección que se muestra arriba. O puede enviar desde su billetera externa a la dirección / código QR anterior.\n\nPresione confirmar para continuar o regrese para cambiar los montos.\n\n",
88 + "exchange_result_description" : "Envíe ${fetchingLabel} ${from} a la dirección que se muestra arriba.\n\n'",
89 + "exchange_result_write_down_ID" : "*Copie o escriba su identificación que se muestra arriba.",
90 + "confirm" : "Confirmar",
91 + "confirm_sending" : "Confirmar envío",
92 + "commit_transaction_amount_fee" : "Confirmar transacción\nCantidad: ${amount}\nCuota: ${fee}",
93 + "sending" : "Enviando",
94 + "transaction_sent" : "Transacción enviada!",
95 + "expired" : "Muerto",
96 + "time" : "${minutes}m ${seconds}s",
97 + "send_xmr" : "Enviar XMR",
98 +
99 + "faq" : "FAQ",
100 +
101 +
102 + "enter_your_pin" : "Introduce tu PIN",
103 + "loading_your_wallet" : "Cargando tu billetera",
104 +
105 +
106 + "new_wallet" : "Nueva billetera",
107 + "wallet_name" : "Nombre de la billetera",
108 + "continue_text" : "Continuar",
109 +
110 +
111 + "node_new" : "Nuevo nodo",
112 + "node_address" : "Dirección de nodo",
113 + "node_port" : "Puerto de nodo",
114 + "login" : "Iniciar sesión",
115 + "password" : "Contraseña",
116 + "nodes" : "Nodos",
117 + "node_reset_settings_title" : "Reiniciar ajustes",
118 + "nodes_list_reset_to_default_message" : "¿Está seguro de que desea restablecer la configuración predeterminada?",
119 + "change_current_node" : "¿Está seguro de cambiar el nodo actual a ${node}?",
120 + "change" : "Cambio",
121 + "remove_node" : "Eliminar nodo",
122 + "remove_node_message" : "¿Está seguro de que desea eliminar el nodo seleccionado?",
123 + "remove" : "Retirar",
124 + "delete" : "Borrar",
125 +
126 +
127 + "use" : "Utilizar ",
128 + "digit_pin" : "-dígito Pin",
129 +
130 +
131 + "share_address" : "Compartir dirección",
132 + "receive_amount" : "Cantidad",
133 + "subaddresses" : "Subdirecciones",
134 +
135 +
136 + "restore_restore_wallet" : "Recuperar Cartera",
137 + "restore_title_from_seed_keys" : "Restaurar desde semilla/claves",
138 + "restore_description_from_seed_keys" : "Recupere su billetera de las semillas/claves que ha guardado en un lugar seguro",
139 + "restore_next" : "Próximo",
140 + "restore_title_from_backup" : "Restaurar desde un archivo de respaldo",
141 + "restore_description_from_backup" : "Puede restaurar toda la aplicación Cake Wallet desde \nysu archivo de respaldo",
142 + "restore_seed_keys_restore" : "Restauración de semillas / llaves",
143 + "restore_title_from_seed" : "De la semilla",
144 + "restore_description_from_seed" : "Restaure su billetera desde el código de combinación de 25 palabras \ni de 13 palabras",
145 + "restore_title_from_keys" : "De las claves",
146 + "restore_description_from_keys" : "Restaure su billetera de las pulsaciones de teclas generadas\nguardadas de sus claves privadas",
147 + "restore_wallet_name" : "Nombre de la billetera",
148 + "restore_address" : "Dirección",
149 + "restore_view_key_private" : "View clave (privado)",
150 + "restore_spend_key_private" : "Spend clave (privado)",
151 + "restore_recover" : "Recuperar",
152 + "restore_wallet_restore_description" : "Restaurar billetera",
153 +
154 +
155 + "seed_title" : "Semilla",
156 + "seed_share" : "Compartir semillas",
157 + "copy" : "Dupdo",
158 +
159 +
160 + "seed_alert_first_text" : "La siguiente página te mostrará \nuna semilla.",
161 + "seed_alert_second_text" : "Anótelos solo en caso de que pierda\no limpie su teléfono.",
162 + "seed_alert_third_text" : "También puede ver la semilla nuevamente \nen el ",
163 + "seed_alert_settings" : "de configuración",
164 + "seed_alert_menu" : " menú .",
165 + "seed_alert_understand" : "Entiendo",
166 +
167 +
168 + "send_title" : "Enviar Monero",
169 + "send_your_wallet" : "Tu billetera",
170 + "send_monero_address" : "Dirección de Monero",
171 + "send_payment_id" : "ID de pago (opcional)",
172 + "all" : "TODOS",
173 + "send_error_minimum_value" : "El valor mínimo de la cantidad es 0.01",
174 + "send_error_currency" : "La moneda solo puede contener números",
175 + "send_estimated_fee" : "Tarifa estimada:",
176 + "send_priority" : "Actualmente la tarifa se establece en ${transactionPriority} prioridad.\nLa prioridad de la transacción se puede ajustar en la configuración",
177 + "send_creating_transaction" : "Creando transacción",
178 +
179 +
180 + "settings_title" : "Configuraciones",
181 + "settings_nodes" : "Nodos",
182 + "settings_current_node" : "Nodo actual",
183 + "settings_wallets" : "Carteras",
184 + "settings_display_balance_as" : "Mostrar saldo como",
185 + "settings_currency" : "Moneda",
186 + "settings_fee_priority" : "Prioridad de tasa",
187 + "settings_save_recipient_address" : "Guardar dirección del destinatario",
188 + "settings_personal" : "Personal",
189 + "settings_change_pin" : "Cambiar PIN",
190 + "settings_change_language" : "Cambiar idioma",
191 + "settings_allow_biometrical_authentication" : "Permitir autenticación biométrica",
192 + "settings_dark_mode" : "Modo oscuro",
193 + "settings_transactions" : "Transacciones",
194 + "settings_trades" : "Comercia",
195 + "settings_display_on_dashboard_list" : "Mostrar en la lista del tablero",
196 + "settings_all" : "TODOS",
197 + "settings_only_trades" : "Solo comercia",
198 + "settings_only_transactions" : "Solo transacciones",
199 + "settings_none" : "Ninguno",
200 + "settings_support" : "Apoyo",
201 + "settings_terms_and_conditions" : "Términos y Condiciones",
202 + "pin_is_incorrect" : "PIN es incorrecto",
203 +
204 +
205 + "setup_pin" : "PIN de configuración",
206 + "enter_your_pin_again" : "Ingrese su PIN nuevamente",
207 + "setup_successful" : "Su PIN se ha configurado correctamente!",
208 +
209 +
210 + "wallet_keys" : "Billetera clave",
211 + "view_key_private" : "View clave (privado)",
212 + "view_key_public" : "View clave (público)",
213 + "spend_key_private" : "Spend clave (privado)",
214 + "spend_key_public" : "Spend clave (público)",
215 + "copied_key_to_clipboard" : "Copiado ${key} al portapapeles",
216 +
217 +
218 + "new_subaddress_title" : "Nueva subdirección",
219 + "new_subaddress_label_name" : "Nombre de etiqueta",
220 + "new_subaddress_create" : "Crear",
221 +
222 +
223 + "subaddress_title" : "Lista de subdirecciones",
224 +
225 +
226 + "trade_details_title" : "Detalles comerciales",
227 + "trade_details_id" : "ID",
228 + "trade_details_state" : "Estado",
229 + "trade_details_fetching" : "Cargando",
230 + "trade_details_provider" : "Proveedor",
231 + "trade_details_created_at" : "Creado en",
232 + "trade_details_pair" : "Par",
233 + "trade_details_copied" : "${title} Copiado al portapapeles",
234 +
235 +
236 + "trade_history_title" : "Historia del comercio",
237 +
238 +
239 + "transaction_details_title" : "Detalles de la transacción",
240 + "transaction_details_transaction_id" : "ID de transacción",
241 + "transaction_details_date" : "Fecha",
242 + "transaction_details_height" : "Altura",
243 + "transaction_details_amount" : "Cantidad",
244 + "transaction_details_copied" : "${title} Copiado al portapapeles",
245 + "transaction_details_recipient_address" : "Dirección del receptor",
246 +
247 +
248 + "wallet_list_title" : "Monedero Monero",
249 + "wallet_list_create_new_wallet" : "Crear nueva billetera",
250 + "wallet_list_restore_wallet" : "Restaurar billetera",
251 + "wallet_list_load_wallet" : "Billetera de carga",
252 + "wallet_list_loading_wallet" : "Billetera ${wallet_name} de carga",
253 + "wallet_list_failed_to_load" : "No se pudo cargar ${wallet_name} la billetera. ${error}",
254 + "wallet_list_removing_wallet" : "Retirar ${wallet_name} billetera",
255 + "wallet_list_failed_to_remove" : "Error al elimina ${wallet_name} billetera. ${error}",
256 +
257 +
258 + "widgets_address" : "Dirección",
259 + "widgets_restore_from_blockheight" : "Restaurar desde blockheight",
260 + "widgets_restore_from_date" : "Restaurar desde fecha",
261 + "widgets_or" : "o",
262 + "widgets_seed" : "Semilla",
263 +
264 +
265 + "router_no_route" : "No hay ruta definida para ${name}",
266 +
267 +
268 + "error_text_account_name" : "El nombre de la cuenta solo puede contener letras, números \ny debe tener entre 1 y 15 caracteres de longitud",
269 + "error_text_contact_name" : "El nombre del contacto no puede contener símbolos `, '\" \ny debe tener entre 1 y 32 caracteres de longitud",
270 + "error_text_address" : "La dirección de la billetera debe corresponder al tipo \nde criptomoneda",
271 + "error_text_node_address" : "Por favor, introduzca una dirección iPv4",
272 + "error_text_node_port" : "El puerto de nodo solo puede contener números entre 0 y 65535",
273 + "error_text_payment_id" : "La ID de pago solo puede contener de 16 a 64 caracteres en hexadecimal",
274 + "error_text_xmr" : "El valor XMR no puede exceder el saldo disponible.\nTEl número de dígitos de fracción debe ser menor o igual a 12",
275 + "error_text_fiat" : "El valor de la cantidad no puede exceder el saldo disponible.\nEl número de dígitos de fracción debe ser menor o igual a 2",
276 + "error_text_subaddress_name" : "El nombre de la subdirección no puede contener símbolos `, '\" \ny debe tener entre 1 y 20 caracteres de longitud",
277 + "error_text_amount" : "La cantidad solo puede contener números",
278 + "error_text_wallet_name" : "El nombre de la billetera solo puede contener letras, números \ny debe tener entre 1 y 15 caracteres de longitud",
279 + "error_text_keys" : "Las llaves de billetera solo pueden contener 64 caracteres en hexadecimal",
280 + "error_text_crypto_currency" : "El número de dígitos fraccionarios \ndebe ser menor o igual a 12",
281 +
282 +
283 + "auth_store_ban_timeout" : "prohibición de tiempo de espera",
284 + "auth_store_banned_for" : "Prohibido para ",
285 + "auth_store_banned_minutes" : " minutos",
286 + "auth_store_incorrect_password" : "Contraseña PIN",
287 + "wallet_store_monero_wallet" : "Monedero Monero",
288 + "wallet_restoration_store_incorrect_seed_length" : "Longitud de semilla incorrecta",
289 +
290 +
291 + "full_balance" : "Balance completo",
292 + "available_balance" : "Balance disponible",
293 + "hidden_balance" : "Balance oculto",
294 +
295 +
296 + "sync_status_syncronizing" : "SINCRONIZANDO",
297 + "sync_status_syncronized" : "SINCRONIZADO",
298 + "sync_status_not_connected" : "NO CONECTADO",
299 + "sync_status_starting_sync" : "EMPEZANDO A SINCRONIZAR",
300 + "sync_status_failed_connect" : "CONEXIÓN FALLIDA AL NODO",
301 + "sync_status_connecting" : "CONECTANDO",
302 + "sync_status_connected" : "CONECTADO",
303 +
304 +
305 + "transaction_priority_slow" : "Lento",
306 + "transaction_priority_regular" : "Regular",
307 + "transaction_priority_medium" : "Medio",
308 + "transaction_priority_fast" : "Rápido",
309 + "transaction_priority_fastest" : "Lo más rápido",
310 +
311 +
312 + "trade_for_not_created" : "Comercio por ${title} no se crea.",
313 + "trade_not_created" : "Comercio no se crea.",
314 + "trade_id_not_found" : "Comercio ${tradeId} de ${title} no encontrado.",
315 + "trade_not_found" : "Comercio no encontrado.",
316 +
317 +
318 + "trade_state_pending" : "Pendiente",
319 + "trade_state_confirming" : "Confirmando",
320 + "trade_state_trading" : "Comercio",
321 + "trade_state_traded" : "Negociado",
322 + "trade_state_complete" : "Completar",
323 + "trade_state_to_be_created" : "Ser creado",
324 + "trade_state_unpaid" : "No pagado",
325 + "trade_state_underpaid" : "Poco pagado",
326 + "trade_state_paid_unconfirmed" : "Pagado sin confirmar",
327 + "trade_state_paid" : "Pagado",
328 + "trade_state_btc_sent" : "Btc expedido",
329 + "trade_state_timeout" : "Se acabó el tiempo",
330 + "trade_state_created" : "Creado",
331 + "trade_state_finished" : "Terminado",
332 +
333 + "change_language" : "Cambiar idioma",
334 + "change_language_to" : "Cambiar el idioma a ${language}?"
335 +}
\ No newline at end of file
res/values/strings_hi.arb new
+335
@@ -0,0 +1,335 @@
1 +{
2 + "welcome" : "स्वागत हे\nसेवा मेरे CAKE WALLET",
3 + "first_wallet_text" : "बहुत बढ़िया बटुआ\nके लिये Monero",
4 + "please_make_selection" : "कृपया नीचे चयन करें\nअपना बटुआ बनाएं या पुनर्प्राप्त करें.",
5 + "create_new" : "नया बनाओ",
6 + "restore_wallet" : "वॉलेट को पुनर्स्थापित करें",
7 +
8 +
9 + "accounts" : "हिसाब किताब",
10 + "edit" : "संपादित करें",
11 + "account" : "लेखा",
12 + "add" : "जोड़ना",
13 +
14 +
15 + "address_book" : "पता पुस्तिका",
16 + "contact" : "संपर्क करें",
17 + "please_select" : "कृपया चुने:",
18 + "cancel" : "रद्द करना",
19 + "ok" : "ठीक है",
20 + "contact_name" : "संपर्क नाम",
21 + "reset" : "रीसेट",
22 + "save" : "बचाना",
23 +
24 +
25 + "authenticated" : "प्रमाणीकृत",
26 + "authentication" : "प्रमाणीकरण",
27 + "failed_authentication" : "प्रमाणीकरण विफल. ${state_error}",
28 +
29 +
30 + "wallet_menu" : "बटुआ मेनू",
31 + "Blocks_remaining" : "${status} शेष रहते हैं",
32 + "please_try_to_connect_to_another_node" : "कृपया दूसरे नोड से कनेक्ट करने का प्रयास करें",
33 + "xmr_hidden" : "XMR छिपा हुआ",
34 + "xmr_available_balance" : "XMR उपलब्ध शेष राशि",
35 + "xmr_full_balance" : "XMR पूर्ण संतुलन",
36 + "send" : "संदेश",
37 + "receive" : "प्राप्त करना",
38 + "transactions" : "लेन-देन",
39 + "incoming" : "आने वाली",
40 + "outgoing" : "निवर्तमान",
41 + "transactions_by_date" : "तारीख से लेन-देन",
42 + "trades" : "ट्रेडों",
43 + "filters" : "फिल्टर",
44 + "today" : "आज",
45 + "yesterday" : "बिता कल",
46 + "received" : "प्राप्त किया",
47 + "sent" : "भेज दिया",
48 + "pending" : " (अपूर्ण)",
49 + "rescan" : "पुन: स्कैन",
50 + "reconnect" : "रिकनेक्ट",
51 + "wallets" : "पर्स",
52 + "show_seed" : "बीज दिखाओ",
53 + "show_keys" : "चाबी दिखाओ",
54 + "address_book_menu" : "पता पुस्तिका",
55 + "reconnection" : "पुनर्संयोजन",
56 + "reconnect_alert_text" : "क्या आप पुन: कनेक्ट होना सुनिश्चित करते हैं?",
57 +
58 +
59 + "exchange" : "अदला बदली",
60 + "clear" : "स्पष्ट",
61 + "change_exchange_provider" : "एक्सचेंज प्रदाता बदलें",
62 + "you_will_send" : "तुम भेजोगे",
63 + "you_will_get" : "आपको मिल जायेगा",
64 + "amount_is_guaranteed" : "प्राप्त राशि की गारंटी है",
65 + "amount_is_estimate" : "प्राप्त राशि एक अनुमान है",
66 + "powered_by" : "द्वारा संचालित ${title}",
67 + "error" : "त्रुटि",
68 + "estimated" : "अनुमानित",
69 + "min_value" : "मिन: ${value} ${currency}",
70 + "max_value" : "मैक्स: ${value} ${currency}",
71 + "change_currency" : "मुद्रा परिवर्तन करें",
72 +
73 +
74 + "copy_id" : "प्रतिलिपि ID",
75 + "exchange_result_write_down_trade_id" : "जारी रखने के लिए कृपया ट्रेड ID की प्रतिलिपि बनाएँ या लिखें.",
76 + "trade_id" : "व्यापार ID:\n${id}",
77 + "copied_to_clipboard" : "क्लिपबोर्ड पर नकल",
78 + "saved_the_trade_id" : "मैंने व्यापार बचा लिया है ID",
79 + "fetching" : "ला रहा है",
80 + "id" : "ID: ",
81 + "amount" : "रकम: ",
82 + "payment_id" : "भुगतान ID: ",
83 + "status" : "स्थिति: ",
84 + "offer_expires_in" : "में ऑफर समाप्त हो रहा है: ",
85 + "trade_is_powered_by" : "यह व्यापार द्वारा संचालित है ${provider}",
86 + "copy_address" : "पता कॉपी करें",
87 + "exchange_result_confirm" : "पुष्टि दबाकर, आप भेज रहे होंगे ${fetchingLabel} ${from} अपने बटुए से ${walletName} ऊपर दिखाए गए पते पर। या आप अपने बाहरी वॉलेट से उपरोक्त पते / क्यूआर कोड पर भेज सकते हैं।\n\nकृपया जारी रखने या राशि बदलने के लिए वापस जाने के लिए पुष्टि करें दबाएं.\n\n",
88 + "exchange_result_description" : "कृपया भेजें ${fetchingLabel} ${from} ऊपर दिखाए गए पते पर\n\n'",
89 + "exchange_result_write_down_ID" : "*कृपया ऊपर दिखाए गए अपने ID को कॉपी या लिख लें.",
90 + "confirm" : "की पुष्टि करें",
91 + "confirm_sending" : "भेजने की पुष्टि करें",
92 + "commit_transaction_amount_fee" : "लेन-देन करें\nरकम: ${amount}\nशुल्क: ${fee}",
93 + "sending" : "भेजना",
94 + "transaction_sent" : "भेजा गया लेन-देन",
95 + "expired" : "समय सीमा समाप्त",
96 + "time" : "${minutes}m ${seconds}s",
97 + "send_xmr" : "संदेश XMR",
98 +
99 + "faq" : "FAQ",
100 +
101 +
102 + "enter_your_pin" : "अपना पिन दर्ज करो",
103 + "loading_your_wallet" : "अपना बटुआ लोड कर रहा है",
104 +
105 +
106 + "new_wallet" : "नया बटुआ",
107 + "wallet_name" : "बटुए का नाम",
108 + "continue_text" : "जारी रहना",
109 +
110 +
111 + "node_new" : "नया नोड",
112 + "node_address" : "नोड पता",
113 + "node_port" : "नोड पोर्ट",
114 + "login" : "लॉग इन करें",
115 + "password" : "पारण शब्द",
116 + "nodes" : "नोड्स",
117 + "node_reset_settings_title" : "सेटिंग्स को दुबारा करें",
118 + "nodes_list_reset_to_default_message" : "क्या आप वाकई सेटिंग को डिफ़ॉल्ट पर रीसेट करना चाहते हैं?",
119 + "change_current_node" : "क्या आप वर्तमान नोड को बदलना सुनिश्चित करते हैं ${node}?",
120 + "change" : "परिवर्तन",
121 + "remove_node" : "नोड निकालें",
122 + "remove_node_message" : "क्या आप वाकई चयनित नोड को निकालना चाहते हैं?",
123 + "remove" : "हटाना",
124 + "delete" : "हटाएं",
125 +
126 +
127 + "use" : "उपयोग ",
128 + "digit_pin" : "-अंक पिन",
129 +
130 +
131 + "share_address" : "पता साझा करें",
132 + "receive_amount" : "रकम",
133 + "subaddresses" : "उप पते",
134 +
135 +
136 + "restore_restore_wallet" : "वॉलेट को पुनर्स्थापित करें",
137 + "restore_title_from_seed_keys" : "बीज / कुंजियों से पुनर्स्थापित करें",
138 + "restore_description_from_seed_keys" : "अपने बटुए को बीज से वापस लें/वे कुंजियाँ जिन्हें आपने सुरक्षित स्थान पर सहेजा है",
139 + "restore_next" : "आगामी",
140 + "restore_title_from_backup" : "बैक-अप फ़ाइल से पुनर्स्थापित करें",
141 + "restore_description_from_backup" : "आप से पूरे केक वॉलेट एप्लिकेशन को पुनर्स्थापित कर सकते हैं\nआपकी बैक-अप फ़ाइल",
142 + "restore_seed_keys_restore" : "बीज / कुंजी पुनर्स्थापित करें",
143 + "restore_title_from_seed" : "बीज से पुनर्स्थापित करें",
144 + "restore_description_from_seed" : "या तो 25 शब्द से अपने वॉलेट को पुनर्स्थापित करें\nया 13 शब्द संयोजन कोड",
145 + "restore_title_from_keys" : "कुंजी से पुनर्स्थापित करें",
146 + "restore_description_from_keys" : "अपने वॉलेट को जेनरेट से पुनर्स्थापित करें\nआपकी निजी कुंजी से कीस्ट्रोक्स सहेजे गए",
147 + "restore_wallet_name" : "बटुए का नाम",
148 + "restore_address" : "पता",
149 + "restore_view_key_private" : "कुंजी देखें (निजी)",
150 + "restore_spend_key_private" : "कुंजी खर्च करें (निजीe)",
151 + "restore_recover" : "वसूली",
152 + "restore_wallet_restore_description" : "बटुआ विवरण पुनर्स्थापित करें",
153 +
154 +
155 + "seed_title" : "बीज",
156 + "seed_share" : "बीज साझा करें",
157 + "copy" : "प्रतिलिपि",
158 +
159 +
160 + "seed_alert_first_text" : "अगला पेज दिखाएगा\nतुम एक बीज हो.",
161 + "seed_alert_second_text" : "कृपया इन्हें केवल मामले में लिखें\nआप अपना फोन खो देते हैं या मिटा देते हैं.",
162 + "seed_alert_third_text" : "आप बीज को फिर से देख सकते हैं\nमें ",
163 + "seed_alert_settings" : "सेटिंग्स",
164 + "seed_alert_menu" : " मेन्यू.",
165 + "seed_alert_understand" : "मै समझता हुँ",
166 +
167 +
168 + "send_title" : "संदेश Monero",
169 + "send_your_wallet" : "आपका बटुआ",
170 + "send_monero_address" : "मोनरो पता",
171 + "send_payment_id" : "भुगतान ID (ऐच्छिक)",
172 + "all" : "सब",
173 + "send_error_minimum_value" : "राशि का न्यूनतम मूल्य 0.01 है",
174 + "send_error_currency" : "मुद्रा में केवल संख्याएँ हो सकती हैं",
175 + "send_estimated_fee" : "अनुमानित शुल्क:",
176 + "send_priority" : "वर्तमान में शुल्क निर्धारित है ${transactionPriority} प्राथमिकता.\nलेन-देन की प्राथमिकता को सेटिंग्स में समायोजित किया जा सकता है",
177 + "send_creating_transaction" : "लेन-देन बनाना",
178 +
179 +
180 + "settings_title" : "सेटिंग्स",
181 + "settings_nodes" : "नोड्स",
182 + "settings_current_node" : "वर्तमान नोड",
183 + "settings_wallets" : "पर्स",
184 + "settings_display_balance_as" : "के रूप में संतुलन प्रदर्शित करें",
185 + "settings_currency" : "मुद्रा",
186 + "settings_fee_priority" : "शुल्क प्राथमिकता",
187 + "settings_save_recipient_address" : "प्राप्तकर्ता का पता सहेजें",
188 + "settings_personal" : "निजी",
189 + "settings_change_pin" : "पिन बदलें",
190 + "settings_change_language" : "भाषा बदलो",
191 + "settings_allow_biometrical_authentication" : "बायोमेट्रिक प्रमाणीकरण की अनुमति दें",
192 + "settings_dark_mode" : "डार्क मोड",
193 + "settings_transactions" : "लेन-देन",
194 + "settings_trades" : "ट्रेडों",
195 + "settings_display_on_dashboard_list" : "डैशबोर्ड सूची पर प्रदर्शित करें",
196 + "settings_all" : "सब",
197 + "settings_only_trades" : "केवल ट्रेड करता है",
198 + "settings_only_transactions" : "केवल लेन-देन",
199 + "settings_none" : "कोई नहीं",
200 + "settings_support" : "समर्थन",
201 + "settings_terms_and_conditions" : "नियम और शर्तें",
202 + "pin_is_incorrect" : "पिन गलत है",
203 +
204 +
205 + "setup_pin" : "पिन सेट करें",
206 + "enter_your_pin_again" : "फिर से अपना पिन डालें",
207 + "setup_successful" : "आपका पिन सफलतापूर्वक सेट हो गया है",
208 +
209 +
210 + "wallet_keys" : "बटुआ की",
211 + "view_key_private" : "कुंजी देखें(निजी)",
212 + "view_key_public" : "कुंजी देखें (जनता)",
213 + "spend_key_private" : "खर्च करना (निजी)",
214 + "spend_key_public" : "खर्च करना (जनता)",
215 + "copied_key_to_clipboard" : "की नकल की ${key} क्लिपबोर्ड पर",
216 +
217 +
218 + "new_subaddress_title" : "नई उपशादी",
219 + "new_subaddress_label_name" : "लेबल का नाम",
220 + "new_subaddress_create" : "सर्जन करना",
221 +
222 +
223 + "subaddress_title" : "उपखंड सूची",
224 +
225 +
226 + "trade_details_title" : "व्यापार विवरण",
227 + "trade_details_id" : "आईडी",
228 + "trade_details_state" : "राज्य",
229 + "trade_details_fetching" : "ला रहा है",
230 + "trade_details_provider" : "प्रदाता",
231 + "trade_details_created_at" : "पर बनाया गया",
232 + "trade_details_pair" : "जोड़ा",
233 + "trade_details_copied" : "${title} क्लिपबोर्ड पर नकल",
234 +
235 +
236 + "trade_history_title" : "व्यापार का इतिहास",
237 +
238 +
239 + "transaction_details_title" : "लेनदेन का विवरण",
240 + "transaction_details_transaction_id" : "लेनदेन आईडी",
241 + "transaction_details_date" : "तारीख",
242 + "transaction_details_height" : "ऊंचाई",
243 + "transaction_details_amount" : "रकम",
244 + "transaction_details_copied" : "${title} क्लिपबोर्ड पर नकल",
245 + "transaction_details_recipient_address" : "प्राप्तकर्ता का पता",
246 +
247 +
248 + "wallet_list_title" : "Monero बटुआ",
249 + "wallet_list_create_new_wallet" : "नया बटुआ बनाएँ",
250 + "wallet_list_restore_wallet" : "वॉलेट को पुनर्स्थापित करें",
251 + "wallet_list_load_wallet" : "वॉलेट लोड करें",
252 + "wallet_list_loading_wallet" : "लोड हो रहा है ${wallet_name} बटुआ",
253 + "wallet_list_failed_to_load" : "लोड करने में विफल ${wallet_name} बटुआ. ${error}",
254 + "wallet_list_removing_wallet" : "निकाला जा रहा है ${wallet_name} बटुआ",
255 + "wallet_list_failed_to_remove" : "निकालने में विफल ${wallet_name} बटुआ. ${error}",
256 +
257 +
258 + "widgets_address" : "पता",
259 + "widgets_restore_from_blockheight" : "ब्लॉकचेन से पुनर्स्थापित करें",
260 + "widgets_restore_from_date" : "दिनांक से पुनर्स्थापित करें",
261 + "widgets_or" : "या",
262 + "widgets_seed" : "बीज",
263 +
264 +
265 + "router_no_route" : "के लिए कोई मार्ग निर्धारित नहीं है ${name}",
266 +
267 +
268 + "error_text_account_name" : "खाता नाम में केवल अक्षर, संख्याएं हो सकती हैं\nऔर 1 और 15 वर्णों के बीच लंबा होना चाहिए",
269 + "error_text_contact_name" : "संपर्क नाम शामिल नहीं हो सकता ` , ' \" प्रतीकों\nऔर 1 और 32 वर्णों के बीच लंबा होना चाहिए",
270 + "error_text_address" : "वॉलेट पता प्रकार के अनुरूप होना चाहिए\nक्रिप्टोकरेंसी का",
271 + "error_text_node_address" : "कृपया एक IPv4 पता दर्ज करें",
272 + "error_text_node_port" : "नोड पोर्ट में केवल 0 और 65535 के बीच संख्याएँ हो सकती हैं",
273 + "error_text_payment_id" : "पेमेंट आईडी केवल हेक्स में 16 से 64 चार्ट तक हो सकती है",
274 + "error_text_xmr" : "एक्सएमआर मूल्य उपलब्ध शेष राशि से अधिक नहीं हो सकता.\nअंश अंकों की संख्या 12 से कम या इसके बराबर होनी चाहिए",
275 + "error_text_fiat" : "राशि का मूल्य उपलब्ध शेष राशि से अधिक नहीं हो सकता.\nअंश अंकों की संख्या कम या 2 के बराबर होनी चाहिए",
276 + "error_text_subaddress_name" : "सबड्रेस नाम नहीं हो सकता` , ' \" प्रतीकों\nऔर 1 और 20 वर्णों के बीच लंबा होना चाहिए",
277 + "error_text_amount" : "राशि में केवल संख्याएँ हो सकती हैं",
278 + "error_text_wallet_name" : "वॉलेट नाम में केवल अक्षर, संख्याएं हो सकती हैं\nऔर 1 और 15 वर्णों के बीच लंबा होना चाहिए",
279 + "error_text_keys" : "वॉलेट कीज़ में हेक्स में केवल 64 वर्ण हो सकते हैं",
280 + "error_text_crypto_currency" : "अंश अंकों की संख्या\n12 से कम या इसके बराबर होना चाहिए",
281 +
282 +
283 + "auth_store_ban_timeout" : "समय की पाबंदी",
284 + "auth_store_banned_for" : "के लिए प्रतिबंधित है ",
285 + "auth_store_banned_minutes" : " मिनट",
286 + "auth_store_incorrect_password" : "गलत पिन",
287 + "wallet_store_monero_wallet" : "मोनरो वॉलेट",
288 + "wallet_restoration_store_incorrect_seed_length" : "गलत बीज की लंबाई",
289 +
290 +
291 + "full_balance" : "पूर्ण संतुलन",
292 + "available_balance" : "उपलब्ध शेष राशि",
293 + "hidden_balance" : "छिपा हुआ संतुलन",
294 +
295 +
296 + "sync_status_syncronizing" : "सिंक्रनाइज़ करने",
297 + "sync_status_syncronized" : "सिंक्रनाइज़",
298 + "sync_status_not_connected" : "जुड़े नहीं हैं",
299 + "sync_status_starting_sync" : "सिताज़ा करना",
300 + "sync_status_failed_connect" : "फेल हुआ कनेक्ट नोड",
301 + "sync_status_connecting" : "कनेक्ट",
302 + "sync_status_connected" : "जुड़े हुए",
303 +
304 +
305 + "transaction_priority_slow" : "धीरे",
306 + "transaction_priority_regular" : "नियमित",
307 + "transaction_priority_medium" : "मध्यम",
308 + "transaction_priority_fast" : "उपवास",
309 + "transaction_priority_fastest" : "सबसे तेजी से",
310 +
311 +
312 + "trade_for_not_created" : "के लिए व्यापार ${title} निर्मित नहीं है.",
313 + "trade_not_created" : "व्यापार नहीं बनाया गया.",
314 + "trade_id_not_found" : "व्यापार ${tradeId} of ${title} नहीं मिला.",
315 + "trade_not_found" : "व्यापार नहीं मिला",
316 +
317 +
318 + "trade_state_pending" : "विचाराधीन",
319 + "trade_state_confirming" : "पुष्टि",
320 + "trade_state_trading" : "व्यापार",
321 + "trade_state_traded" : "ट्रेडेड",
322 + "trade_state_complete" : "पूर्ण",
323 + "trade_state_to_be_created" : "बनाए जाने के लिए",
324 + "trade_state_unpaid" : "अवैतनिक",
325 + "trade_state_underpaid" : "के तहत भुगतान किया",
326 + "trade_state_paid_unconfirmed" : "अपुष्ट भुगतान किया",
327 + "trade_state_paid" : "भुगतान किया है",
328 + "trade_state_btc_sent" : "भेज दिया",
329 + "trade_state_timeout" : "समय समाप्त",
330 + "trade_state_created" : "बनाया था",
331 + "trade_state_finished" : "ख़त्म होना",
332 +
333 + "change_language" : "भाषा बदलो",
334 + "change_language_to" : "को भाषा बदलें ${language}?"
335 +}
\ No newline at end of file
res/values/strings_ja.arb new
+335
@@ -0,0 +1,335 @@
1 +{
2 + "welcome" : "ようこそ\nに CAKE WALLET",
3 + "first_wallet_text" : "素晴らしい財布\nために Monero",
4 + "please_make_selection" : "以下を選択してください\nウォレットを作成または回復する.",
5 + "create_new" : "新しく作る",
6 + "restore_wallet" : "ウォレットを復元する",
7 +
8 +
9 + "accounts" : "アカウント",
10 + "edit" : "編集",
11 + "account" : "アカウント",
12 + "add" : "加える",
13 +
14 +
15 + "address_book" : "住所録",
16 + "contact" : "接触",
17 + "please_select" : "選んでください:",
18 + "cancel" : "キャンセル",
19 + "ok" : "OK",
20 + "contact_name" : "連絡先",
21 + "reset" : "リセットする",
22 + "save" : "セーブ",
23 +
24 +
25 + "authenticated" : "認証済み",
26 + "authentication" : "認証",
27 + "failed_authentication" : "認証失敗. ${state_error}",
28 +
29 +
30 + "wallet_menu" : "ウォレットメニュー",
31 + "Blocks_remaining" : "${status} 残りのブロック",
32 + "please_try_to_connect_to_another_node" : "別のノードに接続してみてください",
33 + "xmr_hidden" : "XMR非表示",
34 + "xmr_available_balance" : "XMR利用可能残高",
35 + "xmr_full_balance" : "XMRフルバランス",
36 + "send" : "送る",
37 + "receive" : "受け取る",
38 + "transactions" : "取引",
39 + "incoming" : "着信",
40 + "outgoing" : "発信",
41 + "transactions_by_date" : "日付ごとの取引",
42 + "trades" : "取引",
43 + "filters" : "フィルター",
44 + "today" : "今日",
45 + "yesterday" : "昨日",
46 + "received" : "受け取った",
47 + "sent" : "送信済み",
48 + "pending" : " (保留中)",
49 + "rescan" : "再スキャン",
50 + "reconnect" : "再接続",
51 + "wallets" : "財布",
52 + "show_seed" : "シードを表示",
53 + "show_keys" : "キーを表示",
54 + "address_book_menu" : "住所録",
55 + "reconnection" : "再接続",
56 + "reconnect_alert_text" : "再接続しますか?",
57 +
58 +
59 + "exchange" : "交換する",
60 + "clear" : "クリア",
61 + "change_exchange_provider" : "Exchangeプロバイダーの変更",
62 + "you_will_send" : "送ります",
63 + "you_will_get" : "あなたが取得します",
64 + "amount_is_guaranteed" : "受信金額は保証されています",
65 + "amount_is_estimate" : "受け取り金額は見積もりです",
66 + "powered_by" : "搭載 ${title}",
67 + "error" : "エラー",
68 + "estimated" : "推定",
69 + "min_value" : "分: ${value} ${currency}",
70 + "max_value" : "マックス: ${value} ${currency}",
71 + "change_currency" : "通貨を変更する",
72 +
73 +
74 + "copy_id" : "IDをコピー",
75 + "exchange_result_write_down_trade_id" : "続行するには、取引IDをコピーまたは書き留めてください.",
76 + "trade_id" : "取引ID:\n${id}",
77 + "copied_to_clipboard" : "クリップボードにコピーしました",
78 + "saved_the_trade_id" : "取引IDを保存しました",
79 + "fetching" : "フェッチング",
80 + "id" : "ID: ",
81 + "amount" : "量: ",
82 + "payment_id" : "支払いID: ",
83 + "status" : "状態: ",
84 + "offer_expires_in" : "で有効期限が切れます: ",
85 + "trade_is_powered_by" : "この取引は ${provider}",
86 + "copy_address" : "住所をコピー",
87 + "exchange_result_confirm" : "確認を押すと、送信されます ${fetchingLabel} ${from} と呼ばれるあなたの財布から ${walletName} 上記のアドレスへ. または、外部ウォレットから上記のアドレス/ QRコードに送信できます.\n\n確認を押して続行するか、戻って金額を変更してください.\n\n",
88 + "exchange_result_description" : "送信してください ${fetchingLabel} ${from} 上記のアドレスへ.\n\n'",
89 + "exchange_result_write_down_ID" : "*上記のIDをコピーまたは書き留めてください.",
90 + "confirm" : "確認する",
91 + "confirm_sending" : "送信を確認",
92 + "commit_transaction_amount_fee" : "トランザクションをコミット\n量: ${amount}\n費用: ${fee}",
93 + "sending" : "送信",
94 + "transaction_sent" : "トランザクションが送信されました!",
95 + "expired" : "期限切れ",
96 + "time" : "${minutes}m ${seconds}s",
97 + "send_xmr" : "送る XMR",
98 +
99 + "faq" : "FAQ",
100 +
101 +
102 + "enter_your_pin" : "PINを入力してください",
103 + "loading_your_wallet" : "ウォレットをロードしています",
104 +
105 +
106 + "new_wallet" : "新しいウォレット",
107 + "wallet_name" : "ウォレット名",
108 + "continue_text" : "持続する",
109 +
110 +
111 + "node_new" : "新しいノード",
112 + "node_address" : "ノードアドレス",
113 + "node_port" : "ノードポート",
114 + "login" : "ログイン",
115 + "password" : "パスワード",
116 + "nodes" : "ノード",
117 + "node_reset_settings_title" : "設定をリセット",
118 + "nodes_list_reset_to_default_message" : "設定をデフォルトにリセットしてもよろしいですか?",
119 + "change_current_node" : "現在のノードを変更してよろしいですか ${node}?",
120 + "change" : "変化する",
121 + "remove_node" : "ノードを削除",
122 + "remove_node_message" : "選択したノードを削除してもよろしいですか?",
123 + "remove" : "削除する",
124 + "delete" : "削除する",
125 +
126 +
127 + "use" : "つかいます ",
128 + "digit_pin" : "桁ピン",
129 +
130 +
131 + "share_address" : "住所を共有する",
132 + "receive_amount" : "量",
133 + "subaddresses" : "サブアドレス",
134 +
135 +
136 + "restore_restore_wallet" : "ウォレットを復元",
137 + "restore_title_from_seed_keys" : "シード/キーから復元",
138 + "restore_description_from_seed_keys" : "安全な場所に保存したシード/キーから財布を取り戻す",
139 + "restore_next" : "次",
140 + "restore_title_from_backup" : "バックアップファイルから復元する",
141 + "restore_description_from_backup" : "Cake Walletアプリ全体を復元できます\nバックアップファイル",
142 + "restore_seed_keys_restore" : "シード/キーの復元",
143 + "restore_title_from_seed" : "シードから復元",
144 + "restore_description_from_seed" : "25ワードからウォレットを復元します\nまたは13ワードの組み合わせコード",
145 + "restore_title_from_keys" : "キーから復元する",
146 + "restore_description_from_keys" : "生成されたウォレットを復元します\n秘密鍵から保存されたキーストローク",
147 + "restore_wallet_name" : "ウォレット名",
148 + "restore_address" : "住所",
149 + "restore_view_key_private" : "ビューキー (プライベート)",
150 + "restore_spend_key_private" : "キーを使う (プライベート)",
151 + "restore_recover" : "回復します",
152 + "restore_wallet_restore_description" : "ウォレットの復元",
153 +
154 +
155 + "seed_title" : "シード",
156 + "seed_share" : "シードを共有する",
157 + "copy" : "コピー",
158 +
159 +
160 + "seed_alert_first_text" : "次のページが表示されます\nあなたは種.",
161 + "seed_alert_second_text" : "これらを書き留めてください \n電話を紛失した場合や拭いた場合.",
162 + "seed_alert_third_text" : "また、種子を見ることができます\nの中に ",
163 + "seed_alert_settings" : "設定",
164 + "seed_alert_menu" : " メニュー.",
165 + "seed_alert_understand" : "わかります",
166 +
167 +
168 + "send_title" : "Moneroを送信",
169 + "send_your_wallet" : "あなたの財布",
170 + "send_monero_address" : "Monero 住所",
171 + "send_payment_id" : "支払いID (オプショナル)",
172 + "all" : "すべて",
173 + "send_error_minimum_value" : "金額の最小値は0.01です",
174 + "send_error_currency" : "通貨には数字のみを含めることができます",
175 + "send_estimated_fee" : "見積手数料:",
176 + "send_priority" : "現在、料金は ${transactionPriority} 優先度.\nトランザクションの優先度は設定で調整できます",
177 + "send_creating_transaction" : "トランザクションを作成する",
178 +
179 +
180 + "settings_title" : "設定",
181 + "settings_nodes" : "ノード",
182 + "settings_current_node" : "現在のノード",
183 + "settings_wallets" : "財布",
184 + "settings_display_balance_as" : "残高を表示",
185 + "settings_currency" : "通貨",
186 + "settings_fee_priority" : "料金優先",
187 + "settings_save_recipient_address" : "受信者のアドレスを保存",
188 + "settings_personal" : "パーソナル",
189 + "settings_change_pin" : "PINを変更",
190 + "settings_change_language" : "言語を変えてください",
191 + "settings_allow_biometrical_authentication" : "生体認証を許可する",
192 + "settings_dark_mode" : "ダークモード",
193 + "settings_transactions" : "取引",
194 + "settings_trades" : "取引",
195 + "settings_display_on_dashboard_list" : "ダッシュボードリストに表示",
196 + "settings_all" : "すべて",
197 + "settings_only_trades" : "取引のみ",
198 + "settings_only_transactions" : "トランザクションのみ",
199 + "settings_none" : "なし",
200 + "settings_support" : "サポート",
201 + "settings_terms_and_conditions" : "規約と条件",
202 + "pin_is_incorrect" : "PINが間違っています",
203 +
204 +
205 + "setup_pin" : "PINのセットアップ",
206 + "enter_your_pin_again" : "ピンをもう一度入力してください",
207 + "setup_successful" : "PINは正常に設定されました!",
208 +
209 +
210 + "wallet_keys" : "ウォレットキー",
211 + "view_key_private" : "ビューキー (プライベート)",
212 + "view_key_public" : "ビューキー (パブリック)",
213 + "spend_key_private" : "キーを使う (プライベート)",
214 + "spend_key_public" : "キーを使う (パブリック)",
215 + "copied_key_to_clipboard" : "コピー済み ${key} クリップボードへ",
216 +
217 +
218 + "new_subaddress_title" : "新しいサブアドレス",
219 + "new_subaddress_label_name" : "ラベル名",
220 + "new_subaddress_create" : "作成する",
221 +
222 +
223 + "subaddress_title" : "サブアドレス一覧",
224 +
225 +
226 + "trade_details_title" : "取引の詳細",
227 + "trade_details_id" : "ID",
228 + "trade_details_state" : "状態",
229 + "trade_details_fetching" : "フェッチング",
230 + "trade_details_provider" : "プロバイダー",
231 + "trade_details_created_at" : "で作成",
232 + "trade_details_pair" : "ペア",
233 + "trade_details_copied" : "${title} クリップボードにコピーしました",
234 +
235 +
236 + "trade_history_title" : "取引履歴",
237 +
238 +
239 + "transaction_details_title" : "取引の詳細",
240 + "transaction_details_transaction_id" : "トランザクションID",
241 + "transaction_details_date" : "日付",
242 + "transaction_details_height" : "高さ",
243 + "transaction_details_amount" : "量",
244 + "transaction_details_copied" : "${title} クリップボードにコピーしました",
245 + "transaction_details_recipient_address" : "受取人の住所",
246 +
247 +
248 + "wallet_list_title" : "Monero 財布",
249 + "wallet_list_create_new_wallet" : "新しいウォレットを作成",
250 + "wallet_list_restore_wallet" : "ウォレットを復元",
251 + "wallet_list_load_wallet" : "ウォレットをロード",
252 + "wallet_list_loading_wallet" : "読み込み中 ${wallet_name} 財布",
253 + "wallet_list_failed_to_load" : "読み込みに失敗しました ${wallet_name} 財布. ${error}",
254 + "wallet_list_removing_wallet" : "取りはずし ${wallet_name} 財布",
255 + "wallet_list_failed_to_remove" : "削除できませんでした ${wallet_name} 財布. ${error}",
256 +
257 +
258 + "widgets_address" : "住所",
259 + "widgets_restore_from_blockheight" : "ブロックの高さから復元",
260 + "widgets_restore_from_date" : "日付から復元",
261 + "widgets_or" : "または",
262 + "widgets_seed" : "シード",
263 +
264 +
265 + "router_no_route" : "ルートが定義されていません ${name}",
266 +
267 +
268 + "error_text_account_name" : "アカウント名には文字のみを含めることができます \n1〜15文字である必要があります",
269 + "error_text_contact_name" : "連絡先名に含めることはできません ` , ' \" シンボル\n長さは1〜32文字でなければなりません",
270 + "error_text_address" : "ウォレットアドレスは、\n暗号通貨",
271 + "error_text_node_address" : "iPv4アドレスを入力してください",
272 + "error_text_node_port" : "ノードポートには、0〜65535の数字のみを含めることができます",
273 + "error_text_payment_id" : "支払いIDには、16進数で16〜64文字しか含めることができません",
274 + "error_text_xmr" : "XMR値は利用可能な残高を超えることはできません.\n小数桁数は12以下でなければなりません",
275 + "error_text_fiat" : "金額は利用可能な残高を超えることはできません.\n小数桁の数は2以下でなければなりません",
276 + "error_text_subaddress_name" : "サブアドレス名に含めることはできません` , ' \" シンボル\n1〜20文字の長さである必要があります",
277 + "error_text_amount" : "金額には数字のみを含めることができます",
278 + "error_text_wallet_name" : "ウォレット名には文字のみを含めることができます\n1〜15文字である必要があります",
279 + "error_text_keys" : "ウォレットキーには、16進数で64文字しか含めることができません",
280 + "error_text_crypto_currency" : "小数桁数\n12以下でなければなりません",
281 +
282 +
283 + "auth_store_ban_timeout" : "禁止タイムアウト",
284 + "auth_store_banned_for" : "禁止されています ",
285 + "auth_store_banned_minutes" : " 数分",
286 + "auth_store_incorrect_password" : "間違ったPIN",
287 + "wallet_store_monero_wallet" : "Monero 財布",
288 + "wallet_restoration_store_incorrect_seed_length" : "誤ったシード長s",
289 +
290 +
291 + "full_balance" : "フルバランス",
292 + "available_balance" : "利用可能残高",
293 + "hidden_balance" : "隠れたバランス",
294 +
295 +
296 + "sync_status_syncronizing" : "同期",
297 + "sync_status_syncronized" : "同期された",
298 + "sync_status_not_connected" : "接続されていません",
299 + "sync_status_starting_sync" : "同期の開始",
300 + "sync_status_failed_connect" : "ノードへの接続に失敗しました",
301 + "sync_status_connecting" : "接続中",
302 + "sync_status_connected" : "接続済み",
303 +
304 +
305 + "transaction_priority_slow" : "スロー",
306 + "transaction_priority_regular" : "レギュラー",
307 + "transaction_priority_medium" : "中",
308 + "transaction_priority_fast" : "速い",
309 + "transaction_priority_fastest" : "最速",
310 +
311 +
312 + "trade_for_not_created" : "取引 ${title} 作成されません",
313 + "trade_not_created" : "作成されていない取引",
314 + "trade_id_not_found" : "トレード ${tradeId} of ${title} 見つかりません",
315 + "trade_not_found" : "取引が見つかりません",
316 +
317 +
318 + "trade_state_pending" : "保留中",
319 + "trade_state_confirming" : "確認中",
320 + "trade_state_trading" : "トレーディング",
321 + "trade_state_traded" : "取引済み",
322 + "trade_state_complete" : "コンプリート",
323 + "trade_state_to_be_created" : "作成される",
324 + "trade_state_unpaid" : "未払い",
325 + "trade_state_underpaid" : "支払不足",
326 + "trade_state_paid_unconfirmed" : "未確認の支払い",
327 + "trade_state_paid" : "有料",
328 + "trade_state_btc_sent" : "送った",
329 + "trade_state_timeout" : "タイムアウト",
330 + "trade_state_created" : "作成した",
331 + "trade_state_finished" : "完成した",
332 +
333 + "change_language" : "言語を変えてください",
334 + "change_language_to" : "言語を変更 ${language}?"
335 +}
\ No newline at end of file
res/values/strings_ko.arb new
+335
@@ -0,0 +1,335 @@
1 +{
2 + "welcome" : "환영\n에 CAKE WALLET",
3 + "first_wallet_text" : "멋진 지갑\n에 대한 Monero",
4 + "please_make_selection" : "아래에서 선택하십시오\n지갑 만들기 또는 복구.",
5 + "create_new" : "새로 만들기",
6 + "restore_wallet" : "지갑 복원",
7 +
8 +
9 + "accounts" : "계정",
10 + "edit" : "편집하다",
11 + "account" : "계정",
12 + "add" : "더하다",
13 +
14 +
15 + "address_book" : "주소록",
16 + "contact" : "접촉",
17 + "please_select" : "선택 해주세요:",
18 + "cancel" : "취소",
19 + "ok" : "승인",
20 + "contact_name" : "담당자 이름",
21 + "reset" : "다시 놓기",
22 + "save" : "구하다",
23 +
24 +
25 + "authenticated" : "인증",
26 + "authentication" : "입증",
27 + "failed_authentication" : "인증 실패. ${state_error}",
28 +
29 +
30 + "wallet_menu" : "월렛 메뉴",
31 + "Blocks_remaining" : "${status} 남은 블록",
32 + "please_try_to_connect_to_another_node" : "다른 노드에 연결을 시도하십시오",
33 + "xmr_hidden" : "XMR 숨김",
34 + "xmr_available_balance" : "XMR 사용 가능한 잔액",
35 + "xmr_full_balance" : "XMR 풀 밸런스",
36 + "send" : "보내다",
37 + "receive" : "받다",
38 + "transactions" : "업무",
39 + "incoming" : "들어오는",
40 + "outgoing" : "나가는",
41 + "transactions_by_date" : "날짜 별 거래",
42 + "trades" : "거래",
43 + "filters" : "필터",
44 + "today" : "오늘",
45 + "yesterday" : "어제",
46 + "received" : "받았습니다",
47 + "sent" : "보냄",
48 + "pending" : " (보류 중)",
49 + "rescan" : "재검색",
50 + "reconnect" : "다시 연결",
51 + "wallets" : "지갑",
52 + "show_seed" : "종자 표시",
53 + "show_keys" : "키 표시",
54 + "address_book_menu" : "주소록",
55 + "reconnection" : "재 연결",
56 + "reconnect_alert_text" : "다시 연결 하시겠습니까?",
57 +
58 +
59 + "exchange" : "교환",
60 + "clear" : "명확한",
61 + "change_exchange_provider" : "교환 공급자 변경",
62 + "you_will_send" : "보내드립니다",
63 + "you_will_get" : "당신은 얻을 것이다",
64 + "amount_is_guaranteed" : "수신 금액이 보장됩니다",
65 + "amount_is_estimate" : "수신 금액은 견적입니다",
66 + "powered_by" : "에 의해 구동 ${title}",
67 + "error" : "오류",
68 + "estimated" : "예상",
69 + "min_value" : "최소: ${value} ${currency}",
70 + "max_value" : "맥스: ${value} ${currency}",
71 + "change_currency" : "통화 변경",
72 +
73 +
74 + "copy_id" : "부 ID",
75 + "exchange_result_write_down_trade_id" : "계속하려면 거래 ID를 복사하거나 적어 두십시오..",
76 + "trade_id" : "무역 ID:\n${id}",
77 + "copied_to_clipboard" : "클립 보드에 복사",
78 + "saved_the_trade_id" : "거래 ID를 저장했습니다",
79 + "fetching" : "가져 오는 중",
80 + "id" : "ID: ",
81 + "amount" : "양: ",
82 + "payment_id" : "지불 ID: ",
83 + "status" : "지위: ",
84 + "offer_expires_in" : "쿠폰 만료일: ",
85 + "trade_is_powered_by" : "이 거래는 ${provider}",
86 + "copy_address" : "주소 복사",
87 + "exchange_result_confirm" : "확인을 누르면 전송됩니다 ${fetchingLabel} ${from} 지갑에서 ${walletName} 위에 표시된 주소로. 또는 외부 지갑에서 위의 주소 / QR 코드로 보낼 수 있습니다.\n\n확인을 눌러 계속하거나 금액을 변경하려면 돌아가십시오.\n\n",
88 + "exchange_result_description" : "보내주세요 ${fetchingLabel} ${from} 위에 표시된 주소로.\n\n'",
89 + "exchange_result_write_down_ID" : "*위에 표시된 ID를 복사하거나 적어 두십시오.",
90 + "confirm" : "확인",
91 + "confirm_sending" : "전송 확인",
92 + "commit_transaction_amount_fee" : "커밋 거래\n양: ${amount}\n보수: ${fee}",
93 + "sending" : "배상",
94 + "transaction_sent" : "거래가 전송되었습니다!",
95 + "expired" : "만료",
96 + "time" : "${minutes}m ${seconds}s",
97 + "send_xmr" : "보내다 XMR",
98 +
99 + "faq" : "FAQ",
100 +
101 +
102 + "enter_your_pin" : "PIN을 입력하십시오",
103 + "loading_your_wallet" : "지갑 넣기",
104 +
105 +
106 + "new_wallet" : "새 월렛",
107 + "wallet_name" : "지갑 이름",
108 + "continue_text" : "잇다",
109 +
110 +
111 + "node_new" : "새로운 노드",
112 + "node_address" : "노드 주소",
113 + "node_port" : "노드 포트",
114 + "login" : "로그인",
115 + "password" : "암호",
116 + "nodes" : "노드",
117 + "node_reset_settings_title" : "설정 초기화",
118 + "nodes_list_reset_to_default_message" : "설정을 기본값으로 재설정 하시겠습니까?",
119 + "change_current_node" : "현재 노드를 다음으로 변경 하시겠습니까 ${node}?",
120 + "change" : "변화",
121 + "remove_node" : "노드 제거",
122 + "remove_node_message" : "선택한 노드를 제거 하시겠습니까?",
123 + "remove" : "없애다",
124 + "delete" : "지우다",
125 +
126 +
127 + "use" : "용도 ",
128 + "digit_pin" : "숫자 PIN",
129 +
130 +
131 + "share_address" : "주소 공유",
132 + "receive_amount" : "양",
133 + "subaddresses" : "하위 주소",
134 +
135 +
136 + "restore_restore_wallet" : "월렛 복원",
137 + "restore_title_from_seed_keys" : "시드 / 키에서 복원",
138 + "restore_description_from_seed_keys" : "안전한 장소에 저장 한 종자 / 키로 지갑을 되 찾으십시오.",
139 + "restore_next" : "다음 것",
140 + "restore_title_from_backup" : "백업 파일에서 복원",
141 + "restore_description_from_backup" : "백업 파일에서 전체 Cake Wallet 앱을 복원 할 수 있습니다.",
142 + "restore_seed_keys_restore" : "종자 / 키 복원",
143 + "restore_title_from_seed" : "종자에서 복원",
144 + "restore_description_from_seed" : "25 단어 또는 13 단어 조합 코드에서 지갑을 복원하십시오.",
145 + "restore_title_from_keys" : "키에서 복원",
146 + "restore_description_from_keys" : "개인 키에서 저장된 생성 된\n키 스트로크에서 월렛 복원",
147 + "restore_wallet_name" : "지갑 이름",
148 + "restore_address" : "주소",
149 + "restore_view_key_private" : "키보기 (은밀한)",
150 + "restore_spend_key_private" : "지출 키 (은밀한)",
151 + "restore_recover" : "다시 덮다",
152 + "restore_wallet_restore_description" : "월렛 복원 설명",
153 +
154 +
155 + "seed_title" : "씨",
156 + "seed_share" : "시드 공유",
157 + "copy" : "부",
158 +
159 +
160 + "seed_alert_first_text" : "다음 페이지가 표시됩니다\n당신은 씨앗.",
161 + "seed_alert_second_text" : "아래에 적어주세요\n휴대 전화를 분실하거나 닦을 경우.",
162 + "seed_alert_third_text" : "당신은 또한 씨앗을 다시 볼 수 있습니다\n에서 ",
163 + "seed_alert_settings" : "설정",
164 + "seed_alert_menu" : " 메뉴.",
165 + "seed_alert_understand" : "이해 했어",
166 +
167 +
168 + "send_title" : "모네로 보내기",
169 + "send_your_wallet" : "지갑",
170 + "send_monero_address" : "모네로 주소",
171 + "send_payment_id" : "지불 ID (optional)",
172 + "all" : "모든",
173 + "send_error_minimum_value" : "금액의 최소값은 0.01입니다",
174 + "send_error_currency" : "통화는 숫자 만 포함 할 수 있습니다",
175 + "send_estimated_fee" : "예상 수수료:",
176 + "send_priority" : "현재 수수료는 ${transactionPriority} 우선 순위.\n거래 우선 순위는 설정에서 조정할 수 있습니다",
177 + "send_creating_transaction" : "거래 생성",
178 +
179 +
180 + "settings_title" : "설정",
181 + "settings_nodes" : "노드",
182 + "settings_current_node" : "현재 노드",
183 + "settings_wallets" : "지갑",
184 + "settings_display_balance_as" : "잔액 표시",
185 + "settings_currency" : "통화",
186 + "settings_fee_priority" : "수수료 우선",
187 + "settings_save_recipient_address" : "수신자 주소 저장",
188 + "settings_personal" : "개인적인",
189 + "settings_change_pin" : "PIN 변경",
190 + "settings_change_language" : "언어 변경",
191 + "settings_allow_biometrical_authentication" : "생체 인증 허용",
192 + "settings_dark_mode" : "다크 모드",
193 + "settings_transactions" : "업무",
194 + "settings_trades" : "거래",
195 + "settings_display_on_dashboard_list" : "대시 보드 목록에 표시",
196 + "settings_all" : "모든",
197 + "settings_only_trades" : "거래 만",
198 + "settings_only_transactions" : "거래 만",
199 + "settings_none" : "없음",
200 + "settings_support" : "지원하다",
201 + "settings_terms_and_conditions" : "이용 약관",
202 + "pin_is_incorrect" : "PIN이 잘못되었습니다",
203 +
204 +
205 + "setup_pin" : "설정 PIN",
206 + "enter_your_pin_again" : "다시 핀을 입력",
207 + "setup_successful" : "PIN이 성공적으로 설정되었습니다!",
208 +
209 +
210 + "wallet_keys" : "지갑 키",
211 + "view_key_private" : "키보기(은밀한)",
212 + "view_key_public" : "키보기 (공공의)",
213 + "spend_key_private" : "지출 키 (은밀한)",
214 + "spend_key_public" : "지출 키 (공공의)",
215 + "copied_key_to_clipboard" : "복사 ${key} 클립 보드로",
216 +
217 +
218 + "new_subaddress_title" : "새로운 하위 주소",
219 + "new_subaddress_label_name" : "라벨 이름",
220 + "new_subaddress_create" : "몹시 떠들어 대다",
221 +
222 +
223 + "subaddress_title" : "하위 주소 목록",
224 +
225 +
226 + "trade_details_title" : "거래 세부 사항",
227 + "trade_details_id" : "ID",
228 + "trade_details_state" : "상태",
229 + "trade_details_fetching" : "가져 오는 중",
230 + "trade_details_provider" : "공급자",
231 + "trade_details_created_at" : "에 작성",
232 + "trade_details_pair" : "쌍",
233 + "trade_details_copied" : "${title} 클립 보드에 복사",
234 +
235 +
236 + "trade_history_title" : "무역 역사",
237 +
238 +
239 + "transaction_details_title" : "상세 거래 내역",
240 + "transaction_details_transaction_id" : "트랜잭션 ID",
241 + "transaction_details_date" : "날짜",
242 + "transaction_details_height" : "신장",
243 + "transaction_details_amount" : "양",
244 + "transaction_details_copied" : "${title} 클립 보드에 복사",
245 + "transaction_details_recipient_address" : "받는 사람 주소",
246 +
247 +
248 + "wallet_list_title" : "모네로 월렛",
249 + "wallet_list_create_new_wallet" : "새 월렛 만들기",
250 + "wallet_list_restore_wallet" : "월렛 복원",
251 + "wallet_list_load_wallet" : "지갑로드",
252 + "wallet_list_loading_wallet" : "로딩 ${wallet_name} 지갑",
253 + "wallet_list_failed_to_load" : "불러 오지 못했습니다 ${wallet_name} 지갑. ${error}",
254 + "wallet_list_removing_wallet" : "풀이 ${wallet_name} 지갑",
255 + "wallet_list_failed_to_remove" : "제거하지 못했습니다 ${wallet_name} 지갑. ${error}",
256 +
257 +
258 + "widgets_address" : "주소",
259 + "widgets_restore_from_blockheight" : "블록 높이에서 복원",
260 + "widgets_restore_from_date" : "날짜에서 복원",
261 + "widgets_or" : "또는",
262 + "widgets_seed" : "씨",
263 +
264 +
265 + "router_no_route" : "에 정의 된 경로가 없습니다 ${name}",
266 +
267 +
268 + "error_text_account_name" : "계정 이름은 문자, 숫자 만 포함 할 수 있습니다\n1 ~ 15 자 사이 여야합니다",
269 + "error_text_contact_name" : "담당자 이름은 포함 할 수 없습니다 ` , ' \" 기호\n1 자에서 32 자 사이 여야합니다",
270 + "error_text_address" : "지갑 주소는 유형과 일치해야합니다\n암호 화폐",
271 + "error_text_node_address" : "iPv4 주소를 입력하십시오",
272 + "error_text_node_port" : "노드 포트는 0에서 65535 사이의 숫자 만 포함 할 수 있습니다",
273 + "error_text_payment_id" : "지불 ID는 16 ~ 64 자의 16 진 문자 만 포함 할 수 있습니다",
274 + "error_text_xmr" : "XMR 값은 사용 가능한 잔액을 초과 할 수 없습니다.\n소수 자릿수는 12 이하 여야합니다",
275 + "error_text_fiat" : "금액은 사용 가능한 잔액을 초과 할 수 없습니다.\n소수 자릿수는 2보다 작거나 같아야합니다",
276 + "error_text_subaddress_name" : "하위 주소 이름은 포함 할 수 없습니다 ` , ' \" 기호 \n1 ~ 20 자 사이 여야합니다",
277 + "error_text_amount" : "금액은 숫자 만 포함 할 수 있습니다",
278 + "error_text_wallet_name" : "지갑 이름은 문자, 숫자 만 포함 할 수 있습니다\n1 ~ 15 자 사이 여야합니다",
279 + "error_text_keys" : "지갑 키는 16 진수로 64 자만 포함 할 수 있습니다",
280 + "error_text_crypto_currency" : "소수 자릿수\n12 이하 여야합니다",
281 +
282 +
283 + "auth_store_ban_timeout" : "타임 아웃 금지",
284 + "auth_store_banned_for" : "금지",
285 + "auth_store_banned_minutes" : " 의사록",
286 + "auth_store_incorrect_password" : "잘못된 PIN",
287 + "wallet_store_monero_wallet" : "모네로 월렛",
288 + "wallet_restoration_store_incorrect_seed_length" : "시드 길이가 잘못되었습니다",
289 +
290 +
291 + "full_balance" : "풀 밸런스",
292 + "available_balance" : "사용 가능한 잔액",
293 + "hidden_balance" : "숨겨진 균형",
294 +
295 +
296 + "sync_status_syncronizing" : "동기화",
297 + "sync_status_syncronized" : "동기화",
298 + "sync_status_not_connected" : "연결되지 않은",
299 + "sync_status_starting_sync" : "동기화 시작",
300 + "sync_status_failed_connect" : "노드에 연결하지 못했습니다",
301 + "sync_status_connecting" : "연결 중",
302 + "sync_status_connected" : "연결됨",
303 +
304 +
305 + "transaction_priority_slow" : "느린",
306 + "transaction_priority_regular" : "정규병",
307 + "transaction_priority_medium" : "매질",
308 + "transaction_priority_fast" : "빠른",
309 + "transaction_priority_fastest" : "가장 빠른",
310 +
311 +
312 + "trade_for_not_created" : "거래 ${title} 생성되지 않습니다.",
313 + "trade_not_created" : "거래가 생성되지 않았습니다.",
314 + "trade_id_not_found" : "무역 ${tradeId} 의 ${title} 찾을 수 없습니다.",
315 + "trade_not_found" : "거래를 찾을 수 없습니다.",
316 +
317 +
318 + "trade_state_pending" : "대기 중",
319 + "trade_state_confirming" : "확인 중",
320 + "trade_state_trading" : "거래",
321 + "trade_state_traded" : "거래",
322 + "trade_state_complete" : "완전한",
323 + "trade_state_to_be_created" : "만들려면",
324 + "trade_state_unpaid" : "미지급",
325 + "trade_state_underpaid" : "미지급",
326 + "trade_state_paid_unconfirmed" : "미확인 유료",
327 + "trade_state_paid" : "유료",
328 + "trade_state_btc_sent" : "보냄",
329 + "trade_state_timeout" : "타임 아웃",
330 + "trade_state_created" : "만들어진",
331 + "trade_state_finished" : "끝마친",
332 +
333 + "change_language" : "언어 변경",
334 + "change_language_to" : "언어를로 변경 ${language}?"
335 +}
\ No newline at end of file
res/values/strings_nl.arb new
+335
@@ -0,0 +1,335 @@
1 +{
2 + "welcome" : "WELKOM\nBIJ CAKE WALLET",
3 + "first_wallet_text" : "Geweldige portemonnee\nfvoor Monero",
4 + "please_make_selection" : "Maak hieronder uw keuze tot\nmaak of herstel je portemonnee.",
5 + "create_new" : "Maak nieuw",
6 + "restore_wallet" : "Portemonnee herstellen",
7 +
8 +
9 + "accounts" : "Accounts",
10 + "edit" : "Bewerk",
11 + "account" : "Account",
12 + "add" : "Toevoegen",
13 +
14 +
15 + "address_book" : "Adresboek",
16 + "contact" : "Contact",
17 + "please_select" : "Selecteer alstublieft:",
18 + "cancel" : "Annuleer",
19 + "ok" : "OK",
20 + "contact_name" : "Contactnaam",
21 + "reset" : "Reset",
22 + "save" : "Opslaan",
23 +
24 +
25 + "authenticated" : "Authenticated",
26 + "authentication" : "Authenticatie",
27 + "failed_authentication" : "Mislukte authenticatie. ${state_error}",
28 +
29 +
30 + "wallet_menu" : "Portemonnee-menu",
31 + "Blocks_remaining" : "${status} Resterende blokken",
32 + "please_try_to_connect_to_another_node" : "Probeer verbinding te maken met een ander knooppunt",
33 + "xmr_hidden" : "XMR Verborgen",
34 + "xmr_available_balance" : "XMR Beschikbaar saldo",
35 + "xmr_full_balance" : "XMR Volledig saldo",
36 + "send" : "Sturen",
37 + "receive" : "Krijgen",
38 + "transactions" : "Transacties",
39 + "incoming" : "inkomend",
40 + "outgoing" : "Uitgaande",
41 + "transactions_by_date" : "Transacties op datum",
42 + "trades" : "Trades",
43 + "filters" : "Filters",
44 + "today" : "Vandaag",
45 + "yesterday" : "Gisteren",
46 + "received" : "Ontvangen",
47 + "sent" : "Verzonden",
48 + "pending" : " (in afwachting)",
49 + "rescan" : "Opnieuw scannen",
50 + "reconnect" : "Sluit",
51 + "wallets" : "Portefeuilles",
52 + "show_seed" : "Toon zaad",
53 + "show_keys" : "Toon sleutels",
54 + "address_book_menu" : "Adresboek",
55 + "reconnection" : "Reconnection",
56 + "reconnect_alert_text" : "Weet u zeker dat u opnieuw verbinding wilt maken?",
57 +
58 +
59 + "exchange" : "Uitwisseling",
60 + "clear" : "Duidelijk",
61 + "change_exchange_provider" : "Wijzig Exchange Provider",
62 + "you_will_send" : "Je zal versturen",
63 + "you_will_get" : "Je zult krijgen",
64 + "amount_is_guaranteed" : "Het ontvangen bedrag is gegarandeerd",
65 + "amount_is_estimate" : "Het ontvangen bedrag is een schatting",
66 + "powered_by" : "Aangedreven door ${title}",
67 + "error" : "Fout",
68 + "estimated" : "Geschatte",
69 + "min_value" : "Min: ${value} ${currency}",
70 + "max_value" : "Max: ${value} ${currency}",
71 + "change_currency" : "Verander valuta",
72 +
73 +
74 + "copy_id" : "ID kopiëren",
75 + "exchange_result_write_down_trade_id" : "Kopieer of noteer de handels-ID om door te gaan.",
76 + "trade_id" : "Trade ID:\n${id}",
77 + "copied_to_clipboard" : "Gekopieerd naar het klembord",
78 + "saved_the_trade_id" : "Ik heb de ruil-ID opgeslagen",
79 + "fetching" : "Ophalen",
80 + "id" : "ID: ",
81 + "amount" : "Bedrag: ",
82 + "payment_id" : "Betaling ID: ",
83 + "status" : "Staat: ",
84 + "offer_expires_in" : "Aanbieding verloopt over: ",
85 + "trade_is_powered_by" : "Deze transactie wordt mogelijk gemaakt door ${provider}",
86 + "copy_address" : "Adres kopiëren",
87 + "exchange_result_confirm" : "Door op bevestigen te drukken, wordt u verzonden ${fetchingLabel} ${from} uit je portemonnee genoemd ${walletName} naar bovenstaand adres. Of u kunt uw externe portemonnee naar bovenstaand adres / QR-code sturen.\n\nDruk op bevestigen om door te gaan of terug te gaan om de bedragen te wijzigen.\n\n",
88 + "exchange_result_description" : "Zend alstublieft ${fetchingLabel} ${from} naar bovenstaand adres.\n\n'",
89 + "exchange_result_write_down_ID" : "*Kopieer of noteer uw hierboven getoonde ID.",
90 + "confirm" : "Bevestigen",
91 + "confirm_sending" : "Bevestig verzending",
92 + "commit_transaction_amount_fee" : "Verricht transactie\nBedrag: ${amount}\nhonorarium: ${fee}",
93 + "sending" : "Bezig met verzenden",
94 + "transaction_sent" : "Transactie verzonden!",
95 + "expired" : "Verlopen",
96 + "time" : "${minutes}m ${seconds}s",
97 + "send_xmr" : "Sturen XMR",
98 +
99 + "faq" : "FAQ",
100 +
101 +
102 + "enter_your_pin" : "Voer uw pincode in",
103 + "loading_your_wallet" : "Uw portemonnee laden",
104 +
105 +
106 + "new_wallet" : "Nieuwe portemonnee",
107 + "wallet_name" : "Portemonnee naam",
108 + "continue_text" : "Doorgaan met",
109 +
110 +
111 + "node_new" : "Nieuw knooppunt",
112 + "node_address" : "Knooppunt adres",
113 + "node_port" : "Knooppunt poort",
114 + "login" : "Log in",
115 + "password" : "Wachtwoord",
116 + "nodes" : "Knooppunten",
117 + "node_reset_settings_title" : "Reset instellingen",
118 + "nodes_list_reset_to_default_message" : "Weet u zeker dat u de standaardinstellingen wilt herstellen?",
119 + "change_current_node" : "Weet u zeker dat u het huidige knooppunt wilt wijzigen in ${node}?",
120 + "change" : "Verandering",
121 + "remove_node" : "Knoop verwijderen",
122 + "remove_node_message" : "Weet u zeker dat u het geselecteerde knooppunt wilt verwijderen?",
123 + "remove" : "Verwijderen",
124 + "delete" : "Delete",
125 +
126 +
127 + "use" : "Gebruik ",
128 + "digit_pin" : "-cijferige PIN",
129 +
130 +
131 + "share_address" : "Deel adres",
132 + "receive_amount" : "Bedrag",
133 + "subaddresses" : "Subadressen",
134 +
135 +
136 + "restore_restore_wallet" : "Portemonnee herstellen",
137 + "restore_title_from_seed_keys" : "Herstel van zaad / sleutels",
138 + "restore_description_from_seed_keys" : "Ontvang uw portemonnee terug uit seed / keys die u hebt opgeslagen op een veilige plaats",
139 + "restore_next" : "Volgende",
140 + "restore_title_from_backup" : "Herstellen vanuit een back-upbestand",
141 + "restore_description_from_backup" : "Je kunt de hele Cake Wallet-app herstellen van\nuw back-upbestand",
142 + "restore_seed_keys_restore" : "Zaad / sleutels herstellen",
143 + "restore_title_from_seed" : "Herstel van zaad",
144 + "restore_description_from_seed" : "Herstel uw portemonnee van het 25 woord\nof 13 woord combinatiecode",
145 + "restore_title_from_keys" : "Herstel van sleutels",
146 + "restore_description_from_keys" : "Herstel uw portemonnee van gegenereerd\ntoetsaanslagen opgeslagen van uw privésleutels",
147 + "restore_wallet_name" : "Portemonnee naam",
148 + "restore_address" : "Adres",
149 + "restore_view_key_private" : "Bekijk sleutel (privaat)",
150 + "restore_spend_key_private" : "Sleutel uitgeven (privaat)",
151 + "restore_recover" : "Herstellen",
152 + "restore_wallet_restore_description" : "Portemonnee-herstelbeschrijving",
153 +
154 +
155 + "seed_title" : "Zaad",
156 + "seed_share" : "Deel zaad",
157 + "copy" : "Kopiëren",
158 +
159 +
160 + "seed_alert_first_text" : "De volgende pagina wordt getoond\njij een zaadje.",
161 + "seed_alert_second_text" : "Noteer deze voor het geval dat\nje verliest of veegt je telefoon.",
162 + "seed_alert_third_text" : "Je kunt het zaad ook weer zien\nin de ",
163 + "seed_alert_settings" : "instellingen",
164 + "seed_alert_menu" : " menu.",
165 + "seed_alert_understand" : "Ik begrijp het",
166 +
167 +
168 + "send_title" : "Stuur Monero",
169 + "send_your_wallet" : "Uw portemonnee",
170 + "send_monero_address" : "Monero-adres",
171 + "send_payment_id" : "Betaling ID (facultatief)",
172 + "all" : "ALLE",
173 + "send_error_minimum_value" : "Minimale waarde van bedrag is 0,01",
174 + "send_error_currency" : "Valuta kan alleen cijfers bevatten",
175 + "send_estimated_fee" : "Geschatte vergoeding:",
176 + "send_priority" : "Momenteel is de vergoeding vastgesteld op ${transactionPriority} prioriteit.\nTransactieprioriteit kan worden aangepast in de instellingen",
177 + "send_creating_transaction" : "Transactie maken",
178 +
179 +
180 + "settings_title" : "Instellingen",
181 + "settings_nodes" : "knooppunten",
182 + "settings_current_node" : "Huidige knooppunt",
183 + "settings_wallets" : "Portemonnee",
184 + "settings_display_balance_as" : "Toon saldo als",
185 + "settings_currency" : "Valuta",
186 + "settings_fee_priority" : "Tariefprioriteit",
187 + "settings_save_recipient_address" : "Adres ontvanger opslaan",
188 + "settings_personal" : "Persoonlijk",
189 + "settings_change_pin" : "Verander pincode",
190 + "settings_change_language" : "Verander de taal",
191 + "settings_allow_biometrical_authentication" : "Biometrische authenticatie toestaan",
192 + "settings_dark_mode" : "Donkere modus",
193 + "settings_transactions" : "Transacties",
194 + "settings_trades" : "Trades",
195 + "settings_display_on_dashboard_list" : "Weergeven op dashboardlijst",
196 + "settings_all" : "ALLE",
197 + "settings_only_trades" : "Alleen handel",
198 + "settings_only_transactions" : "Alleen transacties",
199 + "settings_none" : "Geen",
200 + "settings_support" : "Ondersteuning",
201 + "settings_terms_and_conditions" : "Voorwaarden",
202 + "pin_is_incorrect" : "PIN is onjuist",
203 +
204 +
205 + "setup_pin" : "PIN instellen",
206 + "enter_your_pin_again" : "Voer uw PIN opnieuw in",
207 + "setup_successful" : "Uw PIN is succesvol ingesteld!",
208 +
209 +
210 + "wallet_keys" : "Portemonnee sleutels",
211 + "view_key_private" : "Bekijk sleutel (privaat)",
212 + "view_key_public" : "Bekijk sleutel (openbaar)",
213 + "spend_key_private" : "Sleutel uitgeven (privaat)",
214 + "spend_key_public" : "Sleutel uitgeven (openbaar)",
215 + "copied_key_to_clipboard" : "Gekopieerd ${key} naar het klembord",
216 +
217 +
218 + "new_subaddress_title" : "Nieuw subadres",
219 + "new_subaddress_label_name" : "Label naam",
220 + "new_subaddress_create" : "Creëren",
221 +
222 +
223 + "subaddress_title" : "Subadreslijst",
224 +
225 +
226 + "trade_details_title" : "Handelsgegevens",
227 + "trade_details_id" : "ID",
228 + "trade_details_state" : "Staat",
229 + "trade_details_fetching" : "Ophalen",
230 + "trade_details_provider" : "Leverancier",
231 + "trade_details_created_at" : "Gemaakt bij",
232 + "trade_details_pair" : "Paar",
233 + "trade_details_copied" : "${title} gekopieerd naar het klembord",
234 +
235 +
236 + "trade_history_title" : "Handelsgeschiedenis",
237 +
238 +
239 + "transaction_details_title" : "Transactie details",
240 + "transaction_details_transaction_id" : "Transactie ID",
241 + "transaction_details_date" : "Datum",
242 + "transaction_details_height" : "Hoogte",
243 + "transaction_details_amount" : "Bedrag",
244 + "transaction_details_copied" : "${title} gekopieerd naar het klembord",
245 + "transaction_details_recipient_address" : "Adres van de ontvanger",
246 +
247 +
248 + "wallet_list_title" : "Monero portemonnee",
249 + "wallet_list_create_new_wallet" : "Maak een nieuwe portemonnee",
250 + "wallet_list_restore_wallet" : "Portemonnee herstellen",
251 + "wallet_list_load_wallet" : "Portemonnee laden",
252 + "wallet_list_loading_wallet" : "Bezig met laden ${wallet_name} portemonnee",
253 + "wallet_list_failed_to_load" : "Laden mislukt ${wallet_name} portemonnee. ${error}",
254 + "wallet_list_removing_wallet" : "Verwijderen ${wallet_name} portemonnee",
255 + "wallet_list_failed_to_remove" : "Verwijderen mislukt ${wallet_name} portemonnee. ${error}",
256 +
257 +
258 + "widgets_address" : "Adres",
259 + "widgets_restore_from_blockheight" : "Herstel vanaf blockheight",
260 + "widgets_restore_from_date" : "Herstel vanaf datum",
261 + "widgets_or" : "of",
262 + "widgets_seed" : "Zaad",
263 +
264 +
265 + "router_no_route" : "Geen route gedefinieerd voor ${name}",
266 +
267 +
268 + "error_text_account_name" : "Accountnaam mag alleen letters, cijfers bevatten\nen moet tussen de 1 en 15 tekens lang zijn",
269 + "error_text_contact_name" : "Naam contactpersoon kan niet bevatten ` , ' \" symbolen\nen moet tussen de 1 en 32 tekens lang zijn",
270 + "error_text_address" : "Portemonnee-adres moet overeenkomen met het type\nvan cryptocurrency",
271 + "error_text_node_address" : "Voer een iPv4-adres in",
272 + "error_text_node_port" : "Knooppuntpoort kan alleen nummers tussen 0 en 65535 bevatten",
273 + "error_text_payment_id" : "Betalings-ID kan alleen 16 tot 64 tekens bevatten in hexadecimale volgorde",
274 + "error_text_xmr" : "XMR-waarde kan het beschikbare saldo niet overschrijden.\nHet aantal breukcijfers moet kleiner zijn dan of gelijk zijn aan 12",
275 + "error_text_fiat" : "Waarde van bedrag kan het beschikbare saldo niet overschrijden.\nHet aantal breukcijfers moet kleiner zijn dan of gelijk zijn aan 2",
276 + "error_text_subaddress_name" : "Naam subadres mag niet bevatten ` , ' \" symbolen\nen moet tussen de 1 en 20 tekens lang zijn",
277 + "error_text_amount" : "Bedrag kan alleen cijfers bevatten",
278 + "error_text_wallet_name" : "Naam portemonnee kan alleen letters, cijfers bevatten\nen moet tussen de 1 en 15 tekens lang zijn",
279 + "error_text_keys" : "Portefeuillesleutels kunnen maximaal 64 tekens bevatten in hexadecimale volgorde",
280 + "error_text_crypto_currency" : "Het aantal breukcijfers\nmoet kleiner zijn dan of gelijk zijn aan 12",
281 +
282 +
283 + "auth_store_ban_timeout" : "time-out verbieden",
284 + "auth_store_banned_for" : "Verboden voor ",
285 + "auth_store_banned_minutes" : " notulen",
286 + "auth_store_incorrect_password" : "Incorrect PIN",
287 + "wallet_store_monero_wallet" : "Monero portemonnee",
288 + "wallet_restoration_store_incorrect_seed_length" : "Onjuiste zaadlengte",
289 +
290 +
291 + "full_balance" : "Volledig saldo",
292 + "available_balance" : "Beschikbaar saldo",
293 + "hidden_balance" : "Verborgen balans",
294 +
295 +
296 + "sync_status_syncronizing" : "SYNCHRONISEREN",
297 + "sync_status_syncronized" : "SYNCHRONIZED",
298 + "sync_status_not_connected" : "NIET VERBONDEN",
299 + "sync_status_starting_sync" : "BEGINNEN MET SYNCHRONISEREN",
300 + "sync_status_failed_connect" : "MISLUKT VERBINDING MET DE NODE",
301 + "sync_status_connecting" : "AANSLUITING",
302 + "sync_status_connected" : "VERBONDEN",
303 +
304 +
305 + "transaction_priority_slow" : "Langzaam",
306 + "transaction_priority_regular" : "Regelmatig",
307 + "transaction_priority_medium" : "Medium",
308 + "transaction_priority_fast" : "Snel",
309 + "transaction_priority_fastest" : "Snelste",
310 +
311 +
312 + "trade_for_not_created" : "Ruilen voor ${title} is niet gemaakt.",
313 + "trade_not_created" : "Handel niet gecreëerd.",
314 + "trade_id_not_found" : "Handel ${tradeId} van ${title} niet gevonden.",
315 + "trade_not_found" : "Handel niet gevonden.",
316 +
317 +
318 + "trade_state_pending" : "In afwachting",
319 + "trade_state_confirming" : "Bevestiging",
320 + "trade_state_trading" : "Handel",
321 + "trade_state_traded" : "Traded",
322 + "trade_state_complete" : "Compleet",
323 + "trade_state_to_be_created" : "Om gecreëerd te worden",
324 + "trade_state_unpaid" : "Onbetaald",
325 + "trade_state_underpaid" : "Slecht betaald",
326 + "trade_state_paid_unconfirmed" : "Niet bevestigd",
327 + "trade_state_paid" : "Betaald",
328 + "trade_state_btc_sent" : "Verzonden",
329 + "trade_state_timeout" : "Time-out",
330 + "trade_state_created" : "Gemaakt",
331 + "trade_state_finished" : "Afgewerkt",
332 +
333 + "change_language" : "Verander de taal",
334 + "change_language_to" : "Verander de taal in ${language}?"
335 +}
\ No newline at end of file
res/values/strings_pl.arb new
+335
@@ -0,0 +1,335 @@
1 +{
2 + "welcome" : "WITAMY\nW CAKE WALLET",
3 + "first_wallet_text" : "Niesamowity portfel\nfdla Monero",
4 + "please_make_selection" : "Wybierz poniżej, aby\ncutwórz lub odzyskaj swój portfel.",
5 + "create_new" : "Tworzyć nowe",
6 + "restore_wallet" : "Przywróć portfel",
7 +
8 +
9 + "accounts" : "Konta",
10 + "edit" : "Edytować",
11 + "account" : "Konto",
12 + "add" : "Dodaj",
13 +
14 +
15 + "address_book" : "Książka adresowa",
16 + "contact" : "Kontakt",
17 + "please_select" : "Proszę wybrać:",
18 + "cancel" : "Anulować",
19 + "ok" : "Dobrze",
20 + "contact_name" : "Nazwa Kontaktu",
21 + "reset" : "Nastawić",
22 + "save" : "Zapisać",
23 +
24 +
25 + "authenticated" : "Zalegalizowany",
26 + "authentication" : "Poświadczenie",
27 + "failed_authentication" : "Nieudane uwierzytelnienie. ${state_error}",
28 +
29 +
30 + "wallet_menu" : "Menu portfela",
31 + "Blocks_remaining" : "${status} Bloki pozostałe",
32 + "please_try_to_connect_to_another_node" : "Spróbuj połączyć się z innym węzłem",
33 + "xmr_hidden" : "XMR Ukryty",
34 + "xmr_available_balance" : "XMR Dostępne saldo",
35 + "xmr_full_balance" : "XMR Pełna równowaga",
36 + "send" : "Wysłać",
37 + "receive" : "Otrzymać",
38 + "transactions" : "Transakcje",
39 + "incoming" : "Przychodzące",
40 + "outgoing" : "Towarzyski",
41 + "transactions_by_date" : "Transakcje według daty",
42 + "trades" : "Transakcje",
43 + "filters" : "Filtry",
44 + "today" : "Dzisiaj",
45 + "yesterday" : "Wczoraj",
46 + "received" : "Odebrane",
47 + "sent" : "Wysłano",
48 + "pending" : " (w oczekiwaniu)",
49 + "rescan" : "Skanuj ponownie",
50 + "reconnect" : "Na nowo połączyć",
51 + "wallets" : "Portfele",
52 + "show_seed" : "Pokaż nasiona",
53 + "show_keys" : "Pokaż klucze",
54 + "address_book_menu" : "Książka adresowa",
55 + "reconnection" : "Ponowne połączenie",
56 + "reconnect_alert_text" : "Czy na pewno ponownie się połączysz?",
57 +
58 +
59 + "exchange" : "Wymieniać się",
60 + "clear" : "Jasny",
61 + "change_exchange_provider" : "Zmień dostawcę programu Exchange",
62 + "you_will_send" : "Wyślesz",
63 + "you_will_get" : "Dostaniesz",
64 + "amount_is_guaranteed" : "Otrzymana kwota jest gwarantowana",
65 + "amount_is_estimate" : "Otrzymana kwota jest wartością szacunkową",
66 + "powered_by" : "Zasilany przez ${title}",
67 + "error" : "Błąd",
68 + "estimated" : "Oszacowano",
69 + "min_value" : "Min: ${value} ${currency}",
70 + "max_value" : "Max: ${value} ${currency}",
71 + "change_currency" : "Change Currency",
72 +
73 +
74 + "copy_id" : "ID kopii",
75 + "exchange_result_write_down_trade_id" : "Skopiuj lub zanotuj identyfikator transakcji, aby kontynuować.",
76 + "trade_id" : "Identyfikator handlu:\n${id}",
77 + "copied_to_clipboard" : "Skopiowane do schowka",
78 + "saved_the_trade_id" : "Zapisałem ID",
79 + "fetching" : "Ujmujący",
80 + "id" : "ID: ",
81 + "amount" : "Ilość: ",
82 + "payment_id" : "Płatności ID: ",
83 + "status" : "Status: ",
84 + "offer_expires_in" : "Oferta wygasa za ",
85 + "trade_is_powered_by" : "Ten handel jest zasilany przez ${provider}",
86 + "copy_address" : "Skopiuj adress",
87 + "exchange_result_confirm" : "Naciskając Potwierdź, wyślesz ${fetchingLabel} ${from} z twojego portfela ${walletName} z twojego portfela. Lub możesz wysłać z zewnętrznego portfela na powyższy adres / kod QR.\n\nNaciśnij Potwierdź, aby kontynuować lub wróć, aby zmienić kwoty.\n\n",
88 + "exchange_result_description" : "Proszę wyślij ${fetchingLabel} ${from} na adres podany powyżej.\n\n'",
89 + "exchange_result_write_down_ID" : "*Skopiuj lub zanotuj swój identyfikator pokazany powyżej.",
90 + "confirm" : "Potwierdzać",
91 + "confirm_sending" : "Potwierdź wysłanie",
92 + "commit_transaction_amount_fee" : "Zatwierdź transakcję\nIlość: ${amount}\nOpłata: ${fee}",
93 + "sending" : "Wysyłanie",
94 + "transaction_sent" : "Transakcja wysłana!",
95 + "expired" : "Przedawniony",
96 + "time" : "${minutes}m ${seconds}s",
97 + "send_xmr" : "Wysłać XMR",
98 +
99 + "faq" : "FAQ",
100 +
101 +
102 + "enter_your_pin" : "Wpisz Twój kod PIN",
103 + "loading_your_wallet" : "Ładowanie portfela",
104 +
105 +
106 + "new_wallet" : "Nowy portfel",
107 + "wallet_name" : "Nazwa portfela",
108 + "continue_text" : "Dalej",
109 +
110 +
111 + "node_new" : "Nowy węzeł",
112 + "node_address" : "Adres węzła",
113 + "node_port" : "Port węzła",
114 + "login" : "Zaloguj Się",
115 + "password" : "Hasło",
116 + "nodes" : "Węzły",
117 + "node_reset_settings_title" : "Resetowanie ustawień",
118 + "nodes_list_reset_to_default_message" : "Czy na pewno chcesz przywrócić ustawienia domyślne?",
119 + "change_current_node" : "Czy na pewno chcesz przywrócić ustawienia domyślne? ${node}?",
120 + "change" : "Zmiana",
121 + "remove_node" : "Usuń węzeł",
122 + "remove_node_message" : "Czy na pewno chcesz usunąć wybrany węzeł?",
123 + "remove" : "Usunąć",
124 + "delete" : "Kasować",
125 +
126 +
127 + "use" : "Posługiwać się ",
128 + "digit_pin" : "- znak PIN",
129 +
130 +
131 + "share_address" : "Udostępnij adres",
132 + "receive_amount" : "Ilość",
133 + "subaddresses" : "Podadresy",
134 +
135 +
136 + "restore_restore_wallet" : "Przywróć portfel",
137 + "restore_title_from_seed_keys" : "Przywróć z nasion / kluczy",
138 + "restore_description_from_seed_keys" : "Odzyskaj swój portfel z nasion / kluczy, które zapisałeś w bezpiecznym miejscu",
139 + "restore_next" : "Kolejny",
140 + "restore_title_from_backup" : "Przywróć z pliku kopii zapasowej",
141 + "restore_description_from_backup" : "Możesz przywrócić całą aplikację Cake Wallet z\nplik kopii zapasowej",
142 + "restore_seed_keys_restore" : "Przywracanie nasion / kluczy",
143 + "restore_title_from_seed" : "Przywróć z nasion",
144 + "restore_description_from_seed" : "Przywróć swój portfel z 25 słów\nlub 13-słowny kod kombinacji",
145 + "restore_title_from_keys" : "Przywróć z kluczy",
146 + "restore_description_from_keys" : "Przywróć swój portfel z wygenerowanego\nnaciśnięcia klawiszy zapisane z kluczy prywatnych",
147 + "restore_wallet_name" : "Nazwa portfela",
148 + "restore_address" : "Adres",
149 + "restore_view_key_private" : "Wyświetl klucz (prywatny)",
150 + "restore_spend_key_private" : "Wydaj klucz (prywatny)",
151 + "restore_recover" : "Wyzdrowieć",
152 + "restore_wallet_restore_description" : "Opis przywracania portfela",
153 +
154 +
155 + "seed_title" : "Ziarno",
156 + "seed_share" : "Udostępnij ziarno",
157 + "copy" : "Kopiuj",
158 +
159 +
160 + "seed_alert_first_text" : "Pojawi się następna strona\nziarno.",
161 + "seed_alert_second_text" : "Zapisz je na wszelki wypadek\nzgubisz lub wyczyścisz telefon.",
162 + "seed_alert_third_text" : "Możesz także ponownie zobaczyć ziarno\nw ",
163 + "seed_alert_settings" : "ustawienia",
164 + "seed_alert_menu" : " menu.",
165 + "seed_alert_understand" : "rozumiem",
166 +
167 +
168 + "send_title" : "Wyślij Monero",
169 + "send_your_wallet" : "Twój portfel",
170 + "send_monero_address" : "Adres Monero",
171 + "send_payment_id" : "Identyfikator płatności (opcjonalny)",
172 + "all" : "WSZYSTKO",
173 + "send_error_minimum_value" : "Minimalna wartość kwoty to 0,01",
174 + "send_error_currency" : "Waluta może zawierać tylko cyfry",
175 + "send_estimated_fee" : "Szacowana opłata:",
176 + "send_priority" : "Obecnie opłata ustalona jest na ${transactionPriority} priorytet.\nPriorytet transakcji można zmienić w ustawieniach",
177 + "send_creating_transaction" : "Tworzenie transakcji",
178 +
179 +
180 + "settings_title" : "Ustawienia",
181 + "settings_nodes" : "Węzły",
182 + "settings_current_node" : "Bieżący węzeł",
183 + "settings_wallets" : "Portfele",
184 + "settings_display_balance_as" : "Wyświetl saldo jako",
185 + "settings_currency" : "Waluta",
186 + "settings_fee_priority" : "Priorytet opłaty",
187 + "settings_save_recipient_address" : "Zapisz adres odbiorcy",
188 + "settings_personal" : "Osobisty",
189 + "settings_change_pin" : "Zmień PIN",
190 + "settings_change_language" : "Zmień język",
191 + "settings_allow_biometrical_authentication" : "Zezwalaj na uwierzytelnianie biometryczne",
192 + "settings_dark_mode" : "Tryb ciemny",
193 + "settings_transactions" : "Transakcje",
194 + "settings_trades" : "Transakcje",
195 + "settings_display_on_dashboard_list" : "Wyświetl na liście kokpitu",
196 + "settings_all" : "Cały",
197 + "settings_only_trades" : "Tylko transakcje",
198 + "settings_only_transactions" : "Tylko transakcje",
199 + "settings_none" : "Żaden",
200 + "settings_support" : "Wsparcie",
201 + "settings_terms_and_conditions" : "Zasady i warunki",
202 + "pin_is_incorrect" : "PPIN jest niepoprawny",
203 +
204 +
205 + "setup_pin" : "Ustaw PIN",
206 + "enter_your_pin_again" : "Wprowadź ponownie swój kod PIN",
207 + "setup_successful" : "Twój kod PIN został pomyślnie skonfigurowany!",
208 +
209 +
210 + "wallet_keys" : "Klucze portfela",
211 + "view_key_private" : "Wyświetl klucz (prywatny)",
212 + "view_key_public" : "Wyświetl klucz (publiczny)",
213 + "spend_key_private" : "Wydaj klucz (prywatny)",
214 + "spend_key_public" : "Wydaj klucz (publiczny)",
215 + "copied_key_to_clipboard" : "Skopiowane ${key} do schowka",
216 +
217 +
218 + "new_subaddress_title" : "Nowy podadres",
219 + "new_subaddress_label_name" : "Nazwa etykiety",
220 + "new_subaddress_create" : "Stwórz",
221 +
222 +
223 + "subaddress_title" : "Lista podadresów",
224 +
225 +
226 + "trade_details_title" : "Szczegóły handlu",
227 + "trade_details_id" : "ID",
228 + "trade_details_state" : "Stan",
229 + "trade_details_fetching" : "Ujmujący",
230 + "trade_details_provider" : "Dostawca",
231 + "trade_details_created_at" : "Utworzono w",
232 + "trade_details_pair" : "Para",
233 + "trade_details_copied" : "${title} skopiowane do schowka",
234 +
235 +
236 + "trade_history_title" : "Historia handlu",
237 +
238 +
239 + "transaction_details_title" : "Szczegóły transakcji",
240 + "transaction_details_transaction_id" : "Transakcja ID",
241 + "transaction_details_date" : "Data",
242 + "transaction_details_height" : "Wysokość",
243 + "transaction_details_amount" : "Ilość",
244 + "transaction_details_copied" : "${title} skopiowane do schowka",
245 + "transaction_details_recipient_address" : "Adres odbiorcy",
246 +
247 +
248 + "wallet_list_title" : "Portfel Monero",
249 + "wallet_list_create_new_wallet" : "Utwórz nowy portfel",
250 + "wallet_list_restore_wallet" : "Przywróć portfel",
251 + "wallet_list_load_wallet" : "Załaduj portfel",
252 + "wallet_list_loading_wallet" : "Ładuję ${wallet_name} portfel",
253 + "wallet_list_failed_to_load" : "Nie udało się załadować ${wallet_name} portfel. ${error}",
254 + "wallet_list_removing_wallet" : "Usuwanie ${wallet_name} portfel",
255 + "wallet_list_failed_to_remove" : "Nie udało się usunąć ${wallet_name} portfel. ${error}",
256 +
257 +
258 + "widgets_address" : "Adres",
259 + "widgets_restore_from_blockheight" : "Przywróć z wysokości bloku",
260 + "widgets_restore_from_date" : "Przywróć od daty",
261 + "widgets_or" : "lub",
262 + "widgets_seed" : "Ziarno",
263 +
264 +
265 + "router_no_route" : "Brak zdefiniowanej trasy dla ${name}",
266 +
267 +
268 + "error_text_account_name" : "Nazwa konta może zawierać tylko litery, cyfry\ni musi mieć od 1 do 15 znaków",
269 + "error_text_contact_name" : "Nazwa kontaktu nie może zawierać` , ' \" symbolika\ni musi mieć od 1 do 32 znaków ",
270 + "error_text_address" : "Wallet address must correspond to the type\nof cryptocurrency",
271 + "error_text_node_address" : "Wpisz adres iPv4",
272 + "error_text_node_port" : "Port węzła może zawierać tylko liczby od 0 do 65535",
273 + "error_text_payment_id" : "ID może zawierać od 16 do 64 znaków w formacie szesnastkowym",
274 + "error_text_xmr" : "Wartość XMR nie może przekraczać dostępnego salda.\nLiczba cyfr ułamkowych musi być mniejsza lub równa 12",
275 + "error_text_fiat" : "Wartość kwoty nie może przekroczyć dostępnego salda.\nLiczba cyfr ułamkowych musi być mniejsza lub równa 2",
276 + "error_text_subaddress_name" : "Nazwa podadresu nie może zawierać ` , ' \" symbolika\ni musi mieć od 1 do 20 znaków",
277 + "error_text_amount" : "Kwota może zawierać tylko liczby",
278 + "error_text_wallet_name" : "Nazwa portfela może zawierać tylko litery i cyfry\ni musi mieć od 1 do 15 znaków",
279 + "error_text_keys" : "Klucze portfela mogą zawierać tylko 64 znaki w systemie szesnastkowym",
280 + "error_text_crypto_currency" : "Liczba cyfr ułamkowych\nmusi być mniejsza lub równa 12",
281 +
282 +
283 + "auth_store_ban_timeout" : "przekroczenie limitu czasu",
284 + "auth_store_banned_for" : "Bzbanowany za ",
285 + "auth_store_banned_minutes" : " minuty",
286 + "auth_store_incorrect_password" : "Niepoprawny PIN",
287 + "wallet_store_monero_wallet" : "Portfel Monero",
288 + "wallet_restoration_store_incorrect_seed_length" : "Nieprawidłowa długość nasion",
289 +
290 +
291 + "full_balance" : "Pełna równowaga",
292 + "available_balance" : "Dostępne saldo",
293 + "hidden_balance" : "Ukryta równowaga",
294 +
295 +
296 + "sync_status_syncronizing" : "SYNCHRONIZACJA",
297 + "sync_status_syncronized" : "SYNCHRONIZOWANY",
298 + "sync_status_not_connected" : "NIE POŁĄCZONY",
299 + "sync_status_starting_sync" : "ROZPOCZĘCIE SYNCHRONIZACJI",
300 + "sync_status_failed_connect" : "NIE MOŻNA PODŁĄCZYĆ DO WĘZŁA",
301 + "sync_status_connecting" : "ZŁĄCZONY",
302 + "sync_status_connected" : "POŁĄCZONY",
303 +
304 +
305 + "transaction_priority_slow" : "Powolny",
306 + "transaction_priority_regular" : "Regularny",
307 + "transaction_priority_medium" : "Średni",
308 + "transaction_priority_fast" : "Szybki",
309 + "transaction_priority_fastest" : "Najszybszy",
310 +
311 +
312 + "trade_for_not_created" : "Zamienić się za ${title} nie jest tworzony.",
313 + "trade_not_created" : "Handel nie utworzony.",
314 + "trade_id_not_found" : "Handel ${tradeId} of ${title} nie znaleziono.",
315 + "trade_not_found" : "Nie znaleziono handlu.",
316 +
317 +
318 + "trade_state_pending" : "W oczekiwaniu",
319 + "trade_state_confirming" : "Potwierdzam",
320 + "trade_state_trading" : "Handlowy",
321 + "trade_state_traded" : "Handlowane",
322 + "trade_state_complete" : "Kompletny",
323 + "trade_state_to_be_created" : "Zostać stworzonym",
324 + "trade_state_unpaid" : "Nie zapłacony",
325 + "trade_state_underpaid" : "Niedopłacone",
326 + "trade_state_paid_unconfirmed" : "Płatne niepotwierdzone",
327 + "trade_state_paid" : "Płatny",
328 + "trade_state_btc_sent" : "Wysłane",
329 + "trade_state_timeout" : "Koniec czasu",
330 + "trade_state_created" : "Stworzony",
331 + "trade_state_finished" : "Skończone",
332 +
333 + "change_language" : "Zmień język",
334 + "change_language_to" : "Zmień język na ${language}?"
335 +}
\ No newline at end of file
res/values/strings_pt.arb new
+335
@@ -0,0 +1,335 @@
1 +{
2 + "welcome" : "BEM-VINDO\nAO CAKE WALLET",
3 + "first_wallet_text" : "Carteira impressionante\npara Monero",
4 + "please_make_selection" : "Faça a seleção abaixo para\ncrie ou recupere sua carteira.",
5 + "create_new" : "Crie um novo",
6 + "restore_wallet" : "Restaurar carteira",
7 +
8 +
9 + "accounts" : "Contas",
10 + "edit" : "Editar",
11 + "account" : "Conta",
12 + "add" : "Adicionar",
13 +
14 +
15 + "address_book" : "Livro de endereços",
16 + "contact" : "Contato",
17 + "please_select" : "Por favor selecione:",
18 + "cancel" : "Cancelar",
19 + "ok" : "Está bem",
20 + "contact_name" : "Nome de contato",
21 + "reset" : "Restabelecer",
22 + "save" : "Salve",
23 +
24 +
25 + "authenticated" : "Autenticado",
26 + "authentication" : "Autenticação",
27 + "failed_authentication" : "Falha na autenticação. ${state_error}",
28 +
29 +
30 + "wallet_menu" : "Menu da Carteira",
31 + "Blocks_remaining" : "${status} Blocos restantes",
32 + "please_try_to_connect_to_another_node" : "Por favor, tente conectar-se a outro nó",
33 + "xmr_hidden" : "XMR Oculto",
34 + "xmr_available_balance" : "Saldo disponível do XMR",
35 + "xmr_full_balance" : "Saldo total do XMR",
36 + "send" : "Mandar",
37 + "receive" : "Receber",
38 + "transactions" : "Transações",
39 + "incoming" : "Entrada",
40 + "outgoing" : "Extrovertido",
41 + "transactions_by_date" : "Transações por data",
42 + "trades" : "Comércios",
43 + "filters" : "Filtros",
44 + "today" : "Hoje",
45 + "yesterday" : "Ontem",
46 + "received" : "Recebido",
47 + "sent" : "Enviei",
48 + "pending" : " (pendente)",
49 + "rescan" : "Verificar novamente",
50 + "reconnect" : "Reconectar",
51 + "wallets" : "Carteiras",
52 + "show_seed" : "Mostrar semente",
53 + "show_keys" : "Mostrar chaves",
54 + "address_book_menu" : "Livro de endereços",
55 + "reconnection" : "Reconexão",
56 + "reconnect_alert_text" : "Você tem certeza de reconectar?",
57 +
58 +
59 + "exchange" : "Troca",
60 + "clear" : "Claro",
61 + "change_exchange_provider" : "Alterar provedor de câmbio",
62 + "you_will_send" : "Você enviará",
63 + "you_will_get" : "Você vai ter",
64 + "amount_is_guaranteed" : "O valor do recebimento é garantido",
65 + "amount_is_estimate" : "O valor recebido é uma estimativa",
66 + "powered_by" : "Distribuído por ${title}",
67 + "error" : "Erro",
68 + "estimated" : "Estimado",
69 + "min_value" : "Mín: ${value} ${currency}",
70 + "max_value" : "Máx: ${value} ${currency}",
71 + "change_currency" : "Alteração de moeda",
72 +
73 +
74 + "copy_id" : "Cópia de ID",
75 + "exchange_result_write_down_trade_id" : "Copie ou anote o ID comercial para continuar.",
76 + "trade_id" : "ID comercial:\n${id}",
77 + "copied_to_clipboard" : "Copiado para a área de transferência",
78 + "saved_the_trade_id" : "Salvei o ID comercial",
79 + "fetching" : "Buscando",
80 + "id" : "ID: ",
81 + "amount" : "Montante: ",
82 + "payment_id" : "ID de pagamento: ",
83 + "status" : "Status: ",
84 + "offer_expires_in" : "A oferta expira em: ",
85 + "trade_is_powered_by" : "Este comércio é alimentado por ${provider}",
86 + "copy_address" : "Copiar endereço",
87 + "exchange_result_confirm" : "Ao pressionar confirmar, você estará enviando ${fetchingLabel} ${from} da sua carteira ${walletName} para o endereço mostrado acima. Ou você pode enviar da sua carteira externa para o endereço / código QR acima.\n\nPressione confirmar para continuar ou voltar para alterar os valores.\n\n",
88 + "exchange_result_description" : "Por favor envie ${fetchingLabel} ${from} para o endereço mostrado acima.\n\n'",
89 + "exchange_result_write_down_ID" : "*Copie ou anote seu ID mostrado acima.",
90 + "confirm" : "Confirme",
91 + "confirm_sending" : "Confirme o envio",
92 + "commit_transaction_amount_fee" : "Confirmar transação\nMontante: ${amount}\nTaxa: ${fee}",
93 + "sending" : "Enviando",
94 + "transaction_sent" : "Transação enviada!",
95 + "expired" : "Expirado",
96 + "time" : "${minutes}m ${seconds}s",
97 + "send_xmr" : "Mandar XMR",
98 +
99 + "faq" : "FAQ",
100 +
101 +
102 + "enter_your_pin" : "Insira seu PIN",
103 + "loading_your_wallet" : "Carregando sua carteira",
104 +
105 +
106 + "new_wallet" : "Nova carteira",
107 + "wallet_name" : "Nome da carteira",
108 + "continue_text" : "Continuar",
109 +
110 +
111 + "node_new" : "Novo nó",
112 + "node_address" : "Endereço do nó",
113 + "node_port" : "Porta do nó",
114 + "login" : "Entrar",
115 + "password" : "Senha",
116 + "nodes" : "Nós",
117 + "node_reset_settings_title" : "Redefinir configurações",
118 + "nodes_list_reset_to_default_message" : "Tem certeza de que deseja redefinir as configurações para o padrão?",
119 + "change_current_node" : "Você tem certeza de alterar o nó atual para ${node}?",
120 + "change" : "Mudança",
121 + "remove_node" : "Remover nó",
122 + "remove_node_message" : "Tem certeza de que deseja remover o nó selecionado?",
123 + "remove" : "Remover",
124 + "delete" : "Excluir",
125 +
126 +
127 + "use" : "Usar ",
128 + "digit_pin" : "de dois dígitos",
129 +
130 +
131 + "share_address" : "Compartilhar endereço",
132 + "receive_amount" : "Montante",
133 + "subaddresses" : "Sub-endereços",
134 +
135 +
136 + "restore_restore_wallet" : "Restaurar carteira",
137 + "restore_title_from_seed_keys" : "Restaurar a partir de sementes / chaves",
138 + "restore_description_from_seed_keys" : "Volte sua carteira a partir de sementes / chaves que você salvou em um local seguro",
139 + "restore_next" : "Próximo",
140 + "restore_title_from_backup" : "Restaurar a partir de um arquivo de backup",
141 + "restore_description_from_backup" : "Você pode restaurar todo o aplicativo Cake Wallet em\nseu arquivo de backup",
142 + "restore_seed_keys_restore" : "Restauração de sementes / chaves",
143 + "restore_title_from_seed" : "Restaurar a partir da semente",
144 + "restore_description_from_seed" : "Restaure sua carteira a partir das 25 palavras\noou código de combinação de 13 palavras",
145 + "restore_title_from_keys" : "Restaurar a partir de chaves",
146 + "restore_description_from_keys" : "Restaure sua carteira da geração\npressionamentos de tecla salvos em suas chaves privadas",
147 + "restore_wallet_name" : "Nome da carteira",
148 + "restore_address" : "Endereço",
149 + "restore_view_key_private" : "Tecla Ver (privado)",
150 + "restore_spend_key_private" : "Chave de gastos (privado)",
151 + "restore_recover" : "Recuperar",
152 + "restore_wallet_restore_description" : "Restauração de carteira",
153 +
154 +
155 + "seed_title" : "Semente",
156 + "seed_share" : "Compartilhar sementes",
157 + "copy" : "Cópia de",
158 +
159 +
160 + "seed_alert_first_text" : "A próxima página mostrará\nvocê é uma semente.",
161 + "seed_alert_second_text" : "Por favor, escreva-as apenas em\ncaso você perca ou limpe seu telefone.",
162 + "seed_alert_third_text" : "Você também pode ver a semente novamente\nno ",
163 + "seed_alert_settings" : "configurações",
164 + "seed_alert_menu" : "cardápio.",
165 + "seed_alert_understand" : "Compreendo",
166 +
167 +
168 + "send_title" : "Enviar Monero",
169 + "send_your_wallet" : "Enviar Monero",
170 + "send_monero_address" : "Endereço Monero",
171 + "send_payment_id" : "ID de pagamento (opcional)",
172 + "all" : "TODOS",
173 + "send_error_minimum_value" : "O valor mínimo da quantia é 0,01",
174 + "send_error_currency" : "A moeda pode conter apenas números",
175 + "send_estimated_fee" : "Taxa estimada:",
176 + "send_priority" : "Atualmente, a taxa está definida em ${transactionPriority} prioridade.\nA prioridade da transação pode ser ajustada nas configurações",
177 + "send_creating_transaction" : "Criando transação",
178 +
179 +
180 + "settings_title" : "Configurações",
181 + "settings_nodes" : "Nós",
182 + "settings_current_node" : "Nó atual",
183 + "settings_wallets" : "Carteiras",
184 + "settings_display_balance_as" : "Exibir saldo como",
185 + "settings_currency" : "Moeda",
186 + "settings_fee_priority" : "Prioridade da taxa",
187 + "settings_save_recipient_address" : "Salvar endereço do destinatário",
188 + "settings_personal" : "Pessoal",
189 + "settings_change_pin" : "Alterar PIN",
190 + "settings_change_language" : "Mudar idioma",
191 + "settings_allow_biometrical_authentication" : "Permitir autenticação biométrica",
192 + "settings_dark_mode" : "Modo escuro",
193 + "settings_transactions" : "Transações",
194 + "settings_trades" : "Comércios",
195 + "settings_display_on_dashboard_list" : "Exibir na lista do painel",
196 + "settings_all" : "TODOS",
197 + "settings_only_trades" : "Somente negociações",
198 + "settings_only_transactions" : "Somente transações",
199 + "settings_none" : "Nenhum",
200 + "settings_support" : "Suporte",
201 + "settings_terms_and_conditions" : "Termos e Condições",
202 + "pin_is_incorrect" : "PIN incorreto",
203 +
204 +
205 + "setup_pin" : "PIN de configuração",
206 + "enter_your_pin_again" : "Insira seu pin novamente",
207 + "setup_successful" : "Seu PIN foi configurado com sucesso!",
208 +
209 +
210 + "wallet_keys" : "Chaves da carteira",
211 + "view_key_private" : "Tecla Ver (privado)",
212 + "view_key_public" : "Tecla Ver (público)",
213 + "spend_key_private" : "Chave de gastos (privado)",
214 + "spend_key_public" : "Chave de gastos (público)",
215 + "copied_key_to_clipboard" : "Copiado ${key} para a área de transferência",
216 +
217 +
218 + "new_subaddress_title" : "Novo sub-endereço",
219 + "new_subaddress_label_name" : "Nome do rótulo",
220 + "new_subaddress_create" : "Crio",
221 +
222 +
223 + "subaddress_title" : "Lista de sub-endereços",
224 +
225 +
226 + "trade_details_title" : "Detalhes do comércio",
227 + "trade_details_id" : "ID",
228 + "trade_details_state" : "Estado",
229 + "trade_details_fetching" : "Buscando",
230 + "trade_details_provider" : "Fornecedor",
231 + "trade_details_created_at" : "Criado em",
232 + "trade_details_pair" : "Par",
233 + "trade_details_copied" : "${title} Copiado para a área de transferência",
234 +
235 +
236 + "trade_history_title" : "Histórico comercial",
237 +
238 +
239 + "transaction_details_title" : "Detalhes da transação",
240 + "transaction_details_transaction_id" : "ID da transação",
241 + "transaction_details_date" : "Encontro",
242 + "transaction_details_height" : "Altura",
243 + "transaction_details_amount" : "Montante",
244 + "transaction_details_copied" : "${title} Copiado para a área de transferência",
245 + "transaction_details_recipient_address" : "Endereço do destinatário",
246 +
247 +
248 + "wallet_list_title" : "Monero Carteira",
249 + "wallet_list_create_new_wallet" : "Criar nova carteira",
250 + "wallet_list_restore_wallet" : "Restaurar carteira",
251 + "wallet_list_load_wallet" : "Carregar carteira",
252 + "wallet_list_loading_wallet" : "Carregando ${wallet_name} carteira",
253 + "wallet_list_failed_to_load" : "Falha ao carregar ${wallet_name} carteira. ${error}",
254 + "wallet_list_removing_wallet" : "Removendo ${wallet_name} carteira",
255 + "wallet_list_failed_to_remove" : "Falha ao remover ${wallet_name} carteira. ${error}",
256 +
257 +
258 + "widgets_address" : "Endereço",
259 + "widgets_restore_from_blockheight" : "Restaurar da altura do bloco",
260 + "widgets_restore_from_date" : "Restaurar a partir da data",
261 + "widgets_or" : "ou",
262 + "widgets_seed" : "Semente",
263 +
264 +
265 + "router_no_route" : "Nenhuma rota definida para ${name}",
266 +
267 +
268 + "error_text_account_name" : "O nome da conta pode conter apenas letras, números\ne deve ter entre 1 e 15 caracteres",
269 + "error_text_contact_name" : "O nome do contato não pode conter ` , ' \" símbolos\ne deve ter entre 1 e 32 caracteres",
270 + "error_text_address" : "O endereço da carteira deve corresponder ao tipo\nde criptomoeda",
271 + "error_text_node_address" : "Digite um endereço iPv4",
272 + "error_text_node_port" : "A porta do nó pode conter apenas números entre 0 e 65535",
273 + "error_text_payment_id" : "O código de pagamento pode conter apenas de 16 a 64 caracteres em hexadecimal",
274 + "error_text_xmr" : "O valor XMR não pode exceder o saldo disponível.\nTO número de dígitos da fração deve ser menor ou igual a 12",
275 + "error_text_fiat" : "O valor do valor não pode exceder o saldo disponível.\nO número de dígitos da fração deve ser menor ou igual a 2",
276 + "error_text_subaddress_name" : "O nome do sub-endereço não pode conter ` , ' \" símbolos\ne deve ter entre 1 e 20 caracteres",
277 + "error_text_amount" : "O valor pode conter apenas números",
278 + "error_text_wallet_name" : "O nome da carteira só pode conter letras, números\ne deve ter entre 1 e 15 caracteres",
279 + "error_text_keys" : "As chaves da carteira podem conter apenas 64 caracteres em hexadecimal",
280 + "error_text_crypto_currency" : "O número de dígitos da fração\ndeve ser menor ou igual a 12",
281 +
282 +
283 + "auth_store_ban_timeout" : "proibir timeout",
284 + "auth_store_banned_for" : "Banido por",
285 + "auth_store_banned_minutes" : " minutes",
286 + "auth_store_incorrect_password" : "PIN incorreto",
287 + "wallet_store_monero_wallet" : "Carteira Monero",
288 + "wallet_restoration_store_incorrect_seed_length" : "Comprimento de semente incorreto",
289 +
290 +
291 + "full_balance" : "Saldo total",
292 + "available_balance" : "Saldo disponível",
293 + "hidden_balance" : "Saldo Oculto",
294 +
295 +
296 + "sync_status_syncronizing" : "SINCRONIZANDO",
297 + "sync_status_syncronized" : "SINCRONIZADO",
298 + "sync_status_not_connected" : "NÃO CONECTADO",
299 + "sync_status_starting_sync" : "INÍCIO DE SINCRONIZAÇÃO",
300 + "sync_status_failed_connect" : "Falha na conexão com o nó",
301 + "sync_status_connecting" : "CONECTANDO",
302 + "sync_status_connected" : "CONECTADO",
303 +
304 +
305 + "transaction_priority_slow" : "Lento",
306 + "transaction_priority_regular" : "Regular",
307 + "transaction_priority_medium" : "Médio",
308 + "transaction_priority_fast" : "Rápido",
309 + "transaction_priority_fastest" : "O mais rápido",
310 +
311 +
312 + "trade_for_not_created" : "Comércio por ${title} não é criado.",
313 + "trade_not_created" : "Comércio não criado.",
314 + "trade_id_not_found" : "Comércio${tradeId} of ${title} não encontrado.",
315 + "trade_not_found" : "Comércio não encontrado.",
316 +
317 +
318 + "trade_state_pending" : "Pendente",
319 + "trade_state_confirming" : "Confirmando",
320 + "trade_state_trading" : "Negociação",
321 + "trade_state_traded" : "Negociados",
322 + "trade_state_complete" : "Completo",
323 + "trade_state_to_be_created" : "Para ser criado",
324 + "trade_state_unpaid" : "Não remunerado",
325 + "trade_state_underpaid" : "Mal pago",
326 + "trade_state_paid_unconfirmed" : "Pago não confirmado",
327 + "trade_state_paid" : "Pago",
328 + "trade_state_btc_sent" : "Enviei",
329 + "trade_state_timeout" : "Tempo esgotado",
330 + "trade_state_created" : "Criado",
331 + "trade_state_finished" : "Acabado",
332 +
333 + "change_language" : "Mudar idioma",
334 + "change_language_to" : "Alterar idioma para ${language}?"
335 +}
\ No newline at end of file
res/values/strings_ru.arb new
+335
@@ -0,0 +1,335 @@
1 +{
2 + "welcome" : "Приветствуем в CAKE WALLET",
3 + "first_wallet_text" : "В самом удобном кошельке для Monero",
4 + "please_make_selection" : "Выберите способ создания кошелька: создать новый или восстановить Ваш существующий.",
5 + "create_new" : "Создать новый",
6 + "restore_wallet" : "Восстановить",
7 +
8 +
9 + "accounts" : "Аккаунты",
10 + "edit" : "Редактировать",
11 + "account" : "Аккаунт",
12 + "add" : "Добавить",
13 +
14 +
15 + "address_book" : "Адресная книга",
16 + "contact" : "Контакт",
17 + "please_select" : "Пожалуйста, выберите:",
18 + "cancel" : "Отменить",
19 + "ok" : "OK",
20 + "contact_name" : "Имя контакта",
21 + "reset" : "Сброс",
22 + "save" : "Сохранить",
23 +
24 +
25 + "authenticated" : "Аутентифицировано",
26 + "authentication" : "Аутентификация",
27 + "failed_authentication" : "Ошибка аутентификации. ${state_error}",
28 +
29 +
30 + "wallet_menu" : "Меню кошелька",
31 + "Blocks_remaining" : "${status} Осталось блоков",
32 + "please_try_to_connect_to_another_node" : "Пожалуйста, попробуйте подключиться к другой ноде",
33 + "xmr_hidden" : "XMR Скрытый",
34 + "xmr_available_balance" : "XMR Доступный баланс",
35 + "xmr_full_balance" : "XMR Полный баланс",
36 + "send" : "Отправить",
37 + "receive" : "Получить",
38 + "transactions" : "Транзакции",
39 + "incoming" : "Входящие",
40 + "outgoing" : "Исходящие",
41 + "transactions_by_date" : "Сортировать по дате",
42 + "trades" : "Сделки",
43 + "filters" : "Фильтры",
44 + "today" : "Сегодня",
45 + "yesterday" : "Вчера",
46 + "received" : "Полученные",
47 + "sent" : "Отправленные",
48 + "pending" : " (в ожидании)",
49 + "rescan" : "Пересканировать",
50 + "reconnect" : "Переподключиться",
51 + "wallets" : "Кошельки",
52 + "show_seed" : "Показать код-фразу",
53 + "show_keys" : "Показать ключи",
54 + "address_book_menu" : "Адресная книга",
55 + "reconnection" : "Переподключение",
56 + "reconnect_alert_text" : "Вы хотите переподключиться?",
57 +
58 +
59 + "exchange" : "Обмен",
60 + "clear" : "Очистить",
61 + "change_exchange_provider" : "Изменить провайдер обмена",
62 + "you_will_send" : "Вы отправите",
63 + "you_will_get" : "Вы получите",
64 + "amount_is_guaranteed" : "Сумма получения гарантирована",
65 + "amount_is_estimate" : "Полученная сумма является приблизительной",
66 + "powered_by" : "Используя ${title}",
67 + "error" : "Ошибка",
68 + "estimated" : "Примерно ",
69 + "min_value" : "Мин: ${value} ${currency}",
70 + "max_value" : "Макс: ${value} ${currency}",
71 + "change_currency" : "Изменить валюту",
72 +
73 +
74 + "copy_id" : "Скопировать ID",
75 + "exchange_result_write_down_trade_id" : "Пожалуйста, скопируйте или запишите ID сделки.",
76 + "trade_id" : "ID сделки:\n${id}",
77 + "copied_to_clipboard" : "Скопировано в буфер обмена",
78 + "saved_the_trade_id" : "Я сохранил ID сделки",
79 + "fetching" : "Загрузка",
80 + "id" : "ID: ",
81 + "amount" : "Сумма: ",
82 + "payment_id" : "ID транзакции: ",
83 + "status" : "Статус: ",
84 + "offer_expires_in" : "Предложение истекает через: ",
85 + "trade_is_powered_by" : "Сделка выполнена ${provider}",
86 + "copy_address" : "Cкопировать адрес",
87 + "exchange_result_confirm" : "Нажимая подтвердить, Вы отправите ${fetchingLabel} ${from} с Вашего кошелька ${walletName} на адрес указанный выше. Или Вы можете отправить со своего внешнего кошелька на вышеуказанный адрес / QR-код.\n\nПожалуйста, нажмите подтвердить для продолжения или вернитесь назад для изменения суммы.\n\n",
88 + "exchange_result_description" : "Пожалуйста отправьте ${fetchingLabel} ${from} на адрес, указанный выше.\n\n'",
89 + "exchange_result_write_down_ID" : "*Пожалуйста, скопируйте или запишите ID, указанный выше.",
90 + "confirm" : "Подтвердить",
91 + "confirm_sending" : "Подтвердить отправку",
92 + "commit_transaction_amount_fee" : "Подтвердить транзакцию \nСумма: ${amount}\nСбор: ${fee}",
93 + "sending" : "Отправка",
94 + "transaction_sent" : "Tранзакция отправлена!",
95 + "expired" : "Истекает",
96 + "time" : "${minutes}мин ${seconds}сек",
97 + "send_xmr" : "Отправить XMR",
98 +
99 + "faq" : "FAQ",
100 +
101 +
102 + "enter_your_pin" : "Введите Ваш PIN",
103 + "loading_your_wallet" : "Загрузка кошелька",
104 +
105 +
106 + "new_wallet" : "Новый кошелек",
107 + "wallet_name" : "Имя кошелька",
108 + "continue_text" : "Продолжить",
109 +
110 +
111 + "node_new" : "Новая нода",
112 + "node_address" : "Адрес ноды",
113 + "node_port" : "Порт ноды",
114 + "login" : "Login",
115 + "password" : "Password",
116 + "nodes" : "Ноды",
117 + "node_reset_settings_title" : "Сбросить настройки",
118 + "nodes_list_reset_to_default_message" : "Вы уверены, что хотите сбросить до настроек по умолчанию?",
119 + "change_current_node" : "Вы уверены, что хотите изменить текущую ноду на ${node}?",
120 + "change" : "Изменить",
121 + "remove_node" : "Удалить ноду",
122 + "remove_node_message" : "Вы уверены, что хотите удалить текущую ноду?",
123 + "remove" : "Удалить",
124 + "delete" : "Удалить",
125 +
126 +
127 + "use" : "Использовать ",
128 + "digit_pin" : "-значный Pin",
129 +
130 +
131 + "share_address" : "Поделиться адресом",
132 + "receive_amount" : "Баланс",
133 + "subaddresses" : "Subaddresses",
134 +
135 +
136 + "restore_restore_wallet" : "Восстановить кошелек",
137 + "restore_title_from_seed_keys" : "Восстановить из код-фразы/ключей",
138 + "restore_description_from_seed_keys" : " Вы можете восстановить кошелек из код-фразы/ключей которые Вы сохранили ранее",
139 + "restore_next" : "Продолжить",
140 + "restore_title_from_backup" : "Восстановить из back-up файла",
141 + "restore_description_from_backup" : "Вы можете восстановить Cake Wallet из\nВашего back-up файла",
142 + "restore_seed_keys_restore" : "Восстановить с помощью код-фразы/ключей",
143 + "restore_title_from_seed" : "Восстановить из код-фразы",
144 + "restore_description_from_seed" : "Вы можете восстановить кошелек используя 25-ти значную код фразу",
145 + "restore_title_from_keys" : "Восстановить с помощью ключей",
146 + "restore_description_from_keys" : "Вы можете восстановить кошелек с помощью приватных ключей",
147 + "restore_wallet_name" : "Имя кошелька",
148 + "restore_address" : "Адрес",
149 + "restore_view_key_private" : "View ключ (приватный)",
150 + "restore_spend_key_private" : "Spend ключ (приватный)",
151 + "restore_recover" : "Восстановить",
152 + "restore_wallet_restore_description" : "Wallet restore description",
153 +
154 +
155 + "seed_title" : "Код-фраза",
156 + "seed_share" : "Поделиться код-фразой",
157 + "copy" : "Скопировать",
158 +
159 +
160 + "seed_alert_first_text" : "Следущая страница содержит\nВашу код-фразу.",
161 + "seed_alert_second_text" : "Пожалуйста, запишите на \nслучай, если Вы потеряете или сотрете Ваш телефон.",
162 + "seed_alert_third_text" : "Вы так же можете посмотреть Вашу код-фразу\nв",
163 + "seed_alert_settings" : "настройках",
164 + "seed_alert_menu" : " меню.",
165 + "seed_alert_understand" : "Я понимаю",
166 +
167 +
168 + "send_title" : "Отправить Monero",
169 + "send_your_wallet" : "Ваш кошелек",
170 + "send_monero_address" : "Monero адрес",
171 + "send_payment_id" : "Payment ID (optional)",
172 + "all" : "ALL",
173 + "send_error_minimum_value" : "Mинимальная сумма 0.01",
174 + "send_error_currency" : "Валюта может включать только цифры",
175 + "send_estimated_fee" : "Предполагаемый сбор:",
176 + "send_priority" : "Сбор установлен в зависимости от приоритета: ${transactionPriority}.\nПриоритет транзакции может быть изменен в настройках",
177 + "send_creating_transaction" : "Создать транзакцию",
178 +
179 +
180 + "settings_title" : "Настройки",
181 + "settings_nodes" : "Ноды",
182 + "settings_current_node" : "Текущая нода",
183 + "settings_wallets" : "Кошельки",
184 + "settings_display_balance_as" : "Отображать баланс",
185 + "settings_currency" : "Валюта",
186 + "settings_fee_priority" : "Приоритет сбора",
187 + "settings_save_recipient_address" : "Сохранять адрес получателя",
188 + "settings_personal" : "Персональные",
189 + "settings_change_pin" : "Изменить PIN",
190 + "settings_change_language" : "Изменить язык",
191 + "settings_allow_biometrical_authentication" : "Включить биометрическую аутентификацию",
192 + "settings_dark_mode" : "Темный режим",
193 + "settings_transactions" : "Транзакции",
194 + "settings_trades" : "Сделки",
195 + "settings_display_on_dashboard_list" : "Показывать в списке транзакций",
196 + "settings_all" : "ВСЕ",
197 + "settings_only_trades" : "Сделки",
198 + "settings_only_transactions" : "Транзакции",
199 + "settings_none" : "Ничего",
200 + "settings_support" : "Поддержка",
201 + "settings_terms_and_conditions" : "Условия и положения",
202 + "pin_is_incorrect" : "Некорректный пин",
203 +
204 +
205 + "setup_pin" : "Настроить PIN",
206 + "enter_your_pin_again" : "Введите pin еще раз",
207 + "setup_successful" : "PIN был успешно изменен!",
208 +
209 +
210 + "wallet_keys" : "Ключи кошелька",
211 + "view_key_private" : "View key (приватный)",
212 + "view_key_public" : "View key (публичный)",
213 + "spend_key_private" : "Spend key (приватный)",
214 + "spend_key_public" : "Spend key (публичный)",
215 + "copied_key_to_clipboard" : "Скопировано ${key} в буфер обмена",
216 +
217 +
218 + "new_subaddress_title" : "Новый subaddress",
219 + "new_subaddress_label_name" : "Имя",
220 + "new_subaddress_create" : "Создать",
221 +
222 +
223 + "subaddress_title" : "Subaddress список",
224 +
225 +
226 + "trade_details_title" : "Детали сделок",
227 + "trade_details_id" : "ID",
228 + "trade_details_state" : "Статус",
229 + "trade_details_fetching" : "Получение",
230 + "trade_details_provider" : "Провайдер",
231 + "trade_details_created_at" : "Создано",
232 + "trade_details_pair" : "Пара",
233 + "trade_details_copied" : "${title} скопировано в буфер обмена",
234 +
235 +
236 + "trade_history_title" : "История сделок",
237 +
238 +
239 + "transaction_details_title" : "Детали транзакции",
240 + "transaction_details_transaction_id" : "ID транзакции",
241 + "transaction_details_date" : "Дата",
242 + "transaction_details_height" : "Высота",
243 + "transaction_details_amount" : "Сумма",
244 + "transaction_details_copied" : "${title} скопировано в буфер обмена",
245 + "transaction_details_recipient_address" : "Адрес получателя",
246 +
247 +
248 + "wallet_list_title" : "Monero кошелек",
249 + "wallet_list_create_new_wallet" : "Создать новый кошелек",
250 + "wallet_list_restore_wallet" : "Восстановить",
251 + "wallet_list_load_wallet" : "Загрузка кошелька",
252 + "wallet_list_loading_wallet" : "Загрузка ${wallet_name} кошелька",
253 + "wallet_list_failed_to_load" : "Ошибка при загрузке ${wallet_name} кошелька. ${error}",
254 + "wallet_list_removing_wallet" : "Удаление ${wallet_name} кошелька",
255 + "wallet_list_failed_to_remove" : "Ошибка при удалении ${wallet_name} кошелька. ${error}",
256 +
257 +
258 + "widgets_address" : "Адрес",
259 + "widgets_restore_from_blockheight" : "Восстановить по высоте",
260 + "widgets_restore_from_date" : "Восстановить по дате",
261 + "widgets_or" : "или",
262 + "widgets_seed" : "Код-фраза",
263 +
264 +
265 + "router_no_route" : "Экран не найден ${name}",
266 +
267 +
268 + "error_text_account_name" : "Имя аккаунта может включать только буквы, цифры\nи может быть от 1 до 15 символов в длину",
269 + "error_text_contact_name" : "Имя контакта не может включать ` , ' \" символы\n и может быть от 1 до 32 символов в длину",
270 + "error_text_address" : "Адрес кошелька должен соответствовать типу\nкриптовалюты",
271 + "error_text_node_address" : "Пожалуйста, введите iPv4 адрес",
272 + "error_text_node_port" : "Порт ноды может включать только цифры от 0 до 65535",
273 + "error_text_payment_id" : "ID транзакции может включать от 16 до 64 символа в hex",
274 + "error_text_xmr" : "XMR баланс не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 12",
275 + "error_text_fiat" : "Значение суммы не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 2",
276 + "error_text_subaddress_name" : "Subaddress имя не может включать ` , ' \" символы\nи может быть от 1 до 32 символов в длину",
277 + "error_text_amount" : "Баланс может включать только цифры",
278 + "error_text_wallet_name" : "Имя кошелька может содержать только буквы, цифры\nи может быть от 1 до 15 символов в длину",
279 + "error_text_keys" : "Ключи кошелька могут содержать только 64 символа в hex",
280 + "error_text_crypto_currency" : "Количество цифр после запятой\nдолжно быть меньше или равно 12",
281 +
282 +
283 + "auth_store_ban_timeout" : "ban_timeout",
284 + "auth_store_banned_for" : "Заблокированно на ",
285 + "auth_store_banned_minutes" : " минут",
286 + "auth_store_incorrect_password" : "Некорректный пин",
287 + "wallet_store_monero_wallet" : "Monero кошелек",
288 + "wallet_restoration_store_incorrect_seed_length" : "Неверная длина код-фразы",
289 +
290 +
291 + "full_balance" : "Полный баланс",
292 + "available_balance" : "Доступный баланс",
293 + "hidden_balance" : "Скрытый баланс",
294 +
295 +
296 + "sync_status_syncronizing" : "СИНХРОНИЗАЦИЯ",
297 + "sync_status_syncronized" : "СИНХРОНИЗИРОВАНО",
298 + "sync_status_not_connected" : "НЕТ ПОДКЛЮЧЕНИЯ",
299 + "sync_status_starting_sync" : "НАЧАЛО СИНХРОНИЗАЦИИ",
300 + "sync_status_failed_connect" : "ОШИБКА ПОДКЛЮЧЕНИЯ К НОДЕ",
301 + "sync_status_connecting" : "ПОДКЛЮЧЕНИЕ",
302 + "sync_status_connected" : "ПОДКЛЮЧЕНО",
303 +
304 +
305 + "transaction_priority_slow" : "Медленный",
306 + "transaction_priority_regular" : "Обычный",
307 + "transaction_priority_medium" : "Средний",
308 + "transaction_priority_fast" : "Быстрый",
309 + "transaction_priority_fastest" : "Самый быстрый",
310 +
311 +
312 + "trade_for_not_created" : "Сделка для ${title} не создана.",
313 + "trade_not_created" : "Сделка не создана.",
314 + "trade_id_not_found" : "Сделка ${tradeId} ${title} не найдена.",
315 + "trade_not_found" : "Trade not found.",
316 +
317 +
318 + "trade_state_pending" : "Ожидание",
319 + "trade_state_confirming" : "Подтверждение",
320 + "trade_state_trading" : "Совершение сделки",
321 + "trade_state_traded" : "Сделка завершена",
322 + "trade_state_complete" : "Полный",
323 + "trade_state_to_be_created" : "Будет создана",
324 + "trade_state_unpaid" : "Неоплаченно",
325 + "trade_state_underpaid" : "Недоплаченно",
326 + "trade_state_paid_unconfirmed" : "Оплата неподтвержденная",
327 + "trade_state_paid" : "Оплачено",
328 + "trade_state_btc_sent" : "Btc отправлен",
329 + "trade_state_timeout" : "Timeout",
330 + "trade_state_created" : "Создано",
331 + "trade_state_finished" : "Окончено",
332 +
333 + "change_language" : "Изменить язык",
334 + "change_language_to" : "Изменить язык на ${language}?"
335 +}
\ No newline at end of file
res/values/strings_zh.arb new
+335
@@ -0,0 +1,335 @@
1 +{
2 + "welcome" : "欢迎\nTO CAKE WALLET",
3 + "first_wallet_text" : "很棒的钱包\n对于 Monero",
4 + "please_make_selection" : "请在下面进行选择\nc创建或恢复您的钱包.",
5 + "create_new" : "创建新的",
6 + "restore_wallet" : "恢复钱包",
7 +
8 +
9 + "accounts" : "帐目",
10 + "edit" : "编辑",
11 + "account" : "帐户",
12 + "add" : "加",
13 +
14 +
15 + "address_book" : "地址簿",
16 + "contact" : "联系",
17 + "please_select" : "请选择:",
18 + "cancel" : "取消",
19 + "ok" : "好",
20 + "contact_name" : "联系人姓名",
21 + "reset" : "重启",
22 + "save" : "保存",
23 +
24 +
25 + "authenticated" : "已认证",
26 + "authentication" : "认证方式",
27 + "failed_authentication" : "身份验证失败. ${state_error}",
28 +
29 +
30 + "wallet_menu" : "钱包菜单",
31 + "Blocks_remaining" : "${status} 剩余的块",
32 + "please_try_to_connect_to_another_node" : "请尝试连接到另一个节点",
33 + "xmr_hidden" : "XMR Hidden",
34 + "xmr_available_balance" : "XMR 可用余额 ",
35 + "xmr_full_balance" : "XMR 全部余额",
36 + "send" : "发送",
37 + "receive" : "接收",
38 + "transactions" : "交易次数",
39 + "incoming" : "传入",
40 + "outgoing" : "外向",
41 + "transactions_by_date" : "按日期交易",
42 + "trades" : "交易",
43 + "filters" : "筛选器",
44 + "today" : "今天",
45 + "yesterday" : "昨天",
46 + "received" : "已收到",
47 + "sent" : "已发送",
48 + "pending" : " (待定)",
49 + "rescan" : "重新扫描",
50 + "reconnect" : "重新连接",
51 + "wallets" : "皮夹",
52 + "show_seed" : "显示种子",
53 + "show_keys" : "显示按键",
54 + "address_book_menu" : "地址簿",
55 + "reconnection" : "重新连线",
56 + "reconnect_alert_text" : "您确定要重新连接吗?",
57 +
58 +
59 + "exchange" : "交换",
60 + "clear" : "明确",
61 + "change_exchange_provider" : "更改交易所提供商",
62 + "you_will_send" : "您将发送",
63 + "you_will_get" : "你会得到",
64 + "amount_is_guaranteed" : "接收金额有保证",
65 + "amount_is_estimate" : "收款金额为估算值",
66 + "powered_by" : "供电 ${title}",
67 + "error" : "错误",
68 + "estimated" : "估计的",
69 + "min_value" : "敏: ${value} ${currency}",
70 + "max_value" : "最高: ${value} ${currency}",
71 + "change_currency" : "更改币种",
72 +
73 +
74 + "copy_id" : "复印ID",
75 + "exchange_result_write_down_trade_id" : "请复制或写下交易编号以继续.",
76 + "trade_id" : "贸易编号:\n${id}",
77 + "copied_to_clipboard" : "复制到剪贴板",
78 + "saved_the_trade_id" : "我已经保存了交易ID",
79 + "fetching" : "正在取得",
80 + "id" : "ID: ",
81 + "amount" : "量: ",
82 + "payment_id" : "付款 ID: ",
83 + "status" : "状态: ",
84 + "offer_expires_in" : "优惠有效期至 ",
85 + "trade_is_powered_by" : "该交易由 ${provider}",
86 + "copy_address" : "复制地址",
87 + "exchange_result_confirm" : "点击确认 您将发送 ${fetchingLabel} ${from} 从你的钱包里 ${walletName} 到上面显示的地址. 或者,您也可以从外部钱包发送上述地址/ QR码。\n\n请按确认继续或返回以更改金额\n\n",
88 + "exchange_result_description" : "请发送 ${fetchingLabel} ${from} 到上面显示的地址.\n\n'",
89 + "exchange_result_write_down_ID" : "*请复制或写下您上面显示的ID.",
90 + "confirm" : "确认",
91 + "confirm_sending" : "确认发送",
92 + "commit_transaction_amount_fee" : "提交交易\n量: ${amount}\nFee: ${fee}",
93 + "sending" : "正在发送",
94 + "transaction_sent" : "交易已发送",
95 + "expired" : "已过期",
96 + "time" : "${minutes}m ${seconds}s",
97 + "send_xmr" : "发送 XMR",
98 +
99 + "faq" : "FAQ",
100 +
101 +
102 + "enter_your_pin" : "输入密码",
103 + "loading_your_wallet" : "装钱包",
104 +
105 +
106 + "new_wallet" : "新钱包",
107 + "wallet_name" : "钱包名称",
108 + "continue_text" : "继续",
109 +
110 +
111 + "node_new" : "新节点",
112 + "node_address" : "节点地址",
113 + "node_port" : "节点端口",
114 + "login" : "登录",
115 + "password" : "密码",
116 + "nodes" : "节点数",
117 + "node_reset_settings_title" : "重新设置",
118 + "nodes_list_reset_to_default_message" : "您确定要将设置重设为默认值吗?",
119 + "change_current_node" : "您确定将当前节点更改为 ${node}?",
120 + "change" : "更改",
121 + "remove_node" : "删除节点",
122 + "remove_node_message" : "您确定要删除所选节点吗?",
123 + "remove" : "去掉",
124 + "delete" : "删除",
125 +
126 +
127 + "use" : "使用 ",
128 + "digit_pin" : "数字别针",
129 +
130 +
131 + "share_address" : "分享地址",
132 + "receive_amount" : "量",
133 + "subaddresses" : "子地址",
134 +
135 +
136 + "restore_restore_wallet" : "恢复钱包",
137 + "restore_title_from_seed_keys" : "从种子/密钥还原",
138 + "restore_description_from_seed_keys" : "从保存到安全地方的种子/钥匙取回钱包",
139 + "restore_next" : "下一个",
140 + "restore_title_from_backup" : "从备份文件还原",
141 + "restore_description_from_backup" : "您可以从还原整个Cake Wallet应用\n您的备份文件",
142 + "restore_seed_keys_restore" : "种子/密钥还原",
143 + "restore_title_from_seed" : "从种子还原",
144 + "restore_description_from_seed" : "从25个字中恢复您的钱包\n或13个字的组合码",
145 + "restore_title_from_keys" : "从密钥还原",
146 + "restore_description_from_keys" : "R从生成的电子钱包\n从您的私钥中保存的击键",
147 + "restore_wallet_name" : "钱包名称",
148 + "restore_address" : "地址",
149 + "restore_view_key_private" : "查看金钥 (私人的)",
150 + "restore_spend_key_private" : "支出金钥 (私人的)",
151 + "restore_recover" : "恢复",
152 + "restore_wallet_restore_description" : "钱包还原说明",
153 +
154 +
155 + "seed_title" : "种子",
156 + "seed_share" : "分享种子",
157 + "copy" : "复制",
158 +
159 +
160 + "seed_alert_first_text" : "下一页将显示\n你是种子.",
161 + "seed_alert_second_text" : "请写下来以防万一\n万一您丢失或擦拭手机.",
162 + "seed_alert_third_text" : "您也可以再次看到种子 \n在里面",
163 + "seed_alert_settings" : "设定",
164 + "seed_alert_menu" : " 菜单.",
165 + "seed_alert_understand" : "我明白",
166 +
167 +
168 + "send_title" : "发送门罗币",
169 + "send_your_wallet" : "你的钱包",
170 + "send_monero_address" : "门罗地址",
171 + "send_payment_id" : "付款编号 (可选的)",
172 + "all" : "所有",
173 + "send_error_minimum_value" : "最小金额为0.01",
174 + "send_error_currency" : "货币只能包含数字",
175 + "send_estimated_fee" : "预估费用:",
176 + "send_priority" : "目前,费用设置为 ${transactionPriority} 优先.\n交易优先级可以在设置中进行调整",
177 + "send_creating_transaction" : "创建交易",
178 +
179 +
180 + "settings_title" : "设定值",
181 + "settings_nodes" : "节点数",
182 + "settings_current_node" : "当前节点",
183 + "settings_wallets" : "皮夹",
184 + "settings_display_balance_as" : "将余额显示为",
185 + "settings_currency" : "货币",
186 + "settings_fee_priority" : "费用优先",
187 + "settings_save_recipient_address" : "保存收件人地址",
188 + "settings_personal" : "个人",
189 + "settings_change_pin" : "更改密码",
190 + "settings_change_language" : "改变语言",
191 + "settings_allow_biometrical_authentication" : "允许生物特征认证",
192 + "settings_dark_mode" : "暗模式",
193 + "settings_transactions" : "交易次数",
194 + "settings_trades" : "交易",
195 + "settings_display_on_dashboard_list" : "显示在仪表板上",
196 + "settings_all" : "所有",
197 + "settings_only_trades" : "只交易",
198 + "settings_only_transactions" : "仅交易",
199 + "settings_none" : "没有",
200 + "settings_support" : "支持",
201 + "settings_terms_and_conditions" : "条款和条件",
202 + "pin_is_incorrect" : "PIN码不正确",
203 +
204 +
205 + "setup_pin" : "设定PIN码",
206 + "enter_your_pin_again" : "再次输入您的PIN码",
207 + "setup_successful" : "您的PIN码已成功设置!",
208 +
209 +
210 + "wallet_keys" : "钱包钥匙",
211 + "view_key_private" : "查看金钥 (私人的)",
212 + "view_key_public" : "查看金钥 (public)",
213 + "spend_key_private" : "支出金钥 (私人的)",
214 + "spend_key_public" : "支出金钥 (public)",
215 + "copied_key_to_clipboard" : "复制 ${key} 到剪贴板",
216 +
217 +
218 + "new_subaddress_title" : "新子地址",
219 + "new_subaddress_label_name" : "标签名称",
220 + "new_subaddress_create" : "创建",
221 +
222 +
223 + "subaddress_title" : "子地址清单",
224 +
225 +
226 + "trade_details_title" : "交易明细",
227 + "trade_details_id" : "ID",
228 + "trade_details_state" : "条件",
229 + "trade_details_fetching" : "正在取得",
230 + "trade_details_provider" : "提供者",
231 + "trade_details_created_at" : "创建于",
232 + "trade_details_pair" : "对",
233 + "trade_details_copied" : "${title} 复制到剪贴板",
234 +
235 +
236 + "trade_history_title" : "交易历史",
237 +
238 +
239 + "transaction_details_title" : "交易明细",
240 + "transaction_details_transaction_id" : "交易编号",
241 + "transaction_details_date" : "日期",
242 + "transaction_details_height" : "高度",
243 + "transaction_details_amount" : "量",
244 + "transaction_details_copied" : "${title} 复制到剪贴板",
245 + "transaction_details_recipient_address" : "收件人地址",
246 +
247 +
248 + "wallet_list_title" : "Monero 钱包",
249 + "wallet_list_create_new_wallet" : "创建新钱包",
250 + "wallet_list_restore_wallet" : "恢复钱包",
251 + "wallet_list_load_wallet" : "装入钱包",
252 + "wallet_list_loading_wallet" : "载入中 ${wallet_name} 钱包",
253 + "wallet_list_failed_to_load" : "加载失败 ${wallet_name} 钱包. ${error}",
254 + "wallet_list_removing_wallet" : "拆下 ${wallet_name} 钱包",
255 + "wallet_list_failed_to_remove" : "删除失败 ${wallet_name} 钱包. ${error}",
256 +
257 +
258 + "widgets_address" : "地址",
259 + "widgets_restore_from_blockheight" : "从块高还原",
260 + "widgets_restore_from_date" : "从日期还原",
261 + "widgets_or" : "要么",
262 + "widgets_seed" : "种子",
263 +
264 +
265 + "router_no_route" : "未定义路线 ${name}",
266 +
267 +
268 + "error_text_account_name" : "帐户名称只能包含字母数字\n且必须介于1到15个字符之间",
269 + "error_text_contact_name" : "联系人姓名不能包含`,' \" 符号\n并且必须介于1到32个字符之间",
270 + "error_text_address" : "钱包地址必须与类型对应\n加密货币",
271 + "error_text_node_address" : "请输入一个iPv4地址",
272 + "error_text_node_port" : "节点端口只能包含0到65535之间的数字",
273 + "error_text_payment_id" : "付款ID只能包含16到64个字符(十六进制)",
274 + "error_text_xmr" : "XMR值不能超过可用余额.\n小数位数必须小于或等于12",
275 + "error_text_fiat" : "金额不能超过可用余额.\n小数位数必须小于或等于2",
276 + "error_text_subaddress_name" : "子地址名称不能包含`,' \" 符号\n并且必须在1到20个字符之间",
277 + "error_text_amount" : "金额只能包含数字",
278 + "error_text_wallet_name" : "钱包名称只能包含字母,数字\n且必须介于1到15个字符之间",
279 + "error_text_keys" : "钱包密钥只能包含16个字符的十六进制字符",
280 + "error_text_crypto_currency" : "小数位数\n必须小于或等于12",
281 +
282 +
283 + "auth_store_ban_timeout" : "禁止超时",
284 + "auth_store_banned_for" : "禁止 ",
285 + "auth_store_banned_minutes" : " 分钟",
286 + "auth_store_incorrect_password" : "PIN码错误",
287 + "wallet_store_monero_wallet" : "Monero 钱包",
288 + "wallet_restoration_store_incorrect_seed_length" : "种子长度错误",
289 +
290 +
291 + "full_balance" : "全部余额",
292 + "available_balance" : "可用余额",
293 + "hidden_balance" : "隐藏余额",
294 +
295 +
296 + "sync_status_syncronizing" : "同步化",
297 + "sync_status_syncronized" : "已同步",
298 + "sync_status_not_connected" : "未连接",
299 + "sync_status_starting_sync" : "开始同步",
300 + "sync_status_failed_connect" : "无法连接到节点",
301 + "sync_status_connecting" : "连接中",
302 + "sync_status_connected" : "连接的",
303 +
304 +
305 + "transaction_priority_slow" : "慢",
306 + "transaction_priority_regular" : "定期",
307 + "transaction_priority_medium" : "介质",
308 + "transaction_priority_fast" : "快速",
309 + "transaction_priority_fastest" : "最快的",
310 +
311 +
312 + "trade_for_not_created" : "交易 ${title} 未创建.",
313 + "trade_not_created" : "未建立交易.",
314 + "trade_id_not_found" : "贸易方式 ${tradeId} 的 ${title} 未找到.",
315 + "trade_not_found" : "找不到交易.",
316 +
317 +
318 + "trade_state_pending" : "待定",
319 + "trade_state_confirming" : "确认中",
320 + "trade_state_trading" : "贸易",
321 + "trade_state_traded" : "交易",
322 + "trade_state_complete" : "完成",
323 + "trade_state_to_be_created" : "待创建",
324 + "trade_state_unpaid" : "未付",
325 + "trade_state_underpaid" : "支付不足",
326 + "trade_state_paid_unconfirmed" : "付费未确认",
327 + "trade_state_paid" : "已付费",
328 + "trade_state_btc_sent" : "已发送",
329 + "trade_state_timeout" : "超时",
330 + "trade_state_created" : "已建立",
331 + "trade_state_finished" : "已完成",
332 +
333 + "change_language" : "改變語言",
334 + "change_language_to" : "將語言更改為 ${language}?"
335 +}
\ No newline at end of file
test/widget_test.dart new
+30
@@ -0,0 +1,30 @@
1 +// This is a basic Flutter widget test.
2 +//
3 +// To perform an interaction with a widget in your test, use the WidgetTester
4 +// utility that Flutter provides. For example, you can send tap and scroll
5 +// gestures. You can also use WidgetTester to find child widgets in the widget
6 +// tree, read text, and verify that the values of widget properties are correct.
7 +
8 +import 'package:flutter/material.dart';
9 +import 'package:flutter_test/flutter_test.dart';
10 +
11 +import 'package:cake_wallet/main.dart';
12 +
13 +void main() {
14 + testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 + // Build our app and trigger a frame.
16 + await tester.pumpWidget(CakeWalletApp());
17 +
18 + // Verify that our counter starts at 0.
19 + expect(find.text('0'), findsOneWidget);
20 + expect(find.text('1'), findsNothing);
21 +
22 + // Tap the '+' icon and trigger a frame.
23 + await tester.tap(find.byIcon(Icons.add));
24 + await tester.pump();
25 +
26 + // Verify that our counter has incremented.
27 + expect(find.text('0'), findsNothing);
28 + expect(find.text('1'), findsOneWidget);
29 + });
30 +}
tool/.secrets-test.json new
+7
@@ -0,0 +1,7 @@
1 +{
2 + "salt": "",
3 + "key": "",
4 + "walletSalt": "",
5 + "shortKey": "",
6 + "change_now_api_key": ""
7 +}
\ No newline at end of file
tool/secrets.dart new
+20
@@ -0,0 +1,20 @@
1 +import 'dart:convert';
2 +import 'dart:io';
3 +
4 +const secretsProdPath = 'tool/.secrets-prod.json';
5 +const secretsTestPath = 'tool/.secrets-test.json';
6 +const outputPath = 'lib/.secrets.g.dart';
7 +
8 +Future<void> main() async {
9 + final inputPath = FileSystemEntity.typeSync(secretsProdPath) !=
10 + FileSystemEntityType.notFound
11 + ? secretsProdPath
12 + : secretsTestPath;
13 +
14 + final inoutContent = File(inputPath).readAsStringSync();
15 + final config = json.decode(inoutContent);
16 + final output =
17 + 'const salt = \'${config["salt"]}\';\nconst key = \'${config["key"]}\';\nconst walletSalt = \'${config["walletSalt"]}\';\nconst shortKey = \'${config["shortKey"]}\';\nconst change_now_api_key = \'${config["change_now_api_key"]}\';';
18 +
19 + File(outputPath).writeAsString(output);
20 +}