mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 19:49:22 +00:00
Migration for iOS.
This commit is contained in:
parent
5f88c4bafd
commit
b0a31147dd
18 changed files with 467 additions and 213 deletions
|
@ -1,50 +0,0 @@
|
||||||
import Foundation
|
|
||||||
import CryptoSwift
|
|
||||||
|
|
||||||
class EncryptedFile {
|
|
||||||
|
|
||||||
private(set) var fileName: String
|
|
||||||
private(set) var url: URL
|
|
||||||
private let key: Array<UInt8>
|
|
||||||
private let salt: Array<UInt8>
|
|
||||||
|
|
||||||
init(url: URL, key: String, salt: String) {
|
|
||||||
self.key = key.data(using: .utf8)?.bytes ?? []
|
|
||||||
self.salt = salt.data(using: .utf8)?.bytes ?? []
|
|
||||||
self.url = url
|
|
||||||
self.fileName = url.lastPathComponent
|
|
||||||
}
|
|
||||||
|
|
||||||
func readRawContent() -> String? {
|
|
||||||
guard let binaryContent = try? Data(contentsOf: url) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return String(data: binaryContent, encoding: .utf8)
|
|
||||||
}
|
|
||||||
|
|
||||||
func decryptedContent() -> String? {
|
|
||||||
guard
|
|
||||||
let rawContent = readRawContent(),
|
|
||||||
let decryptedBytes = try? cipherBuilder().decrypt(rawContent.bytes) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
let decryptedData = Data(decryptedBytes)
|
|
||||||
return String(data: decryptedData, encoding: .utf8)
|
|
||||||
}
|
|
||||||
|
|
||||||
func cipherBuilder() -> Cipher {
|
|
||||||
let PBKDF2key = try! PKCS5.PBKDF2(password: key, salt: salt, iterations: 4096, variant: .sha256).calculate()
|
|
||||||
return try! Blowfish(key: PBKDF2key, padding: .pkcs7)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func readTradesList(key: String, salt: String) -> String? {
|
|
||||||
let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("trades_list.json")
|
|
||||||
|
|
||||||
return EncryptedFile(
|
|
||||||
url: url,
|
|
||||||
key: key,
|
|
||||||
salt: salt).decryptedContent()
|
|
||||||
}
|
|
16
ios/CakeWallet/decrypt.swift
Normal file
16
ios/CakeWallet/decrypt.swift
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import Foundation
|
||||||
|
import CryptoSwift
|
||||||
|
|
||||||
|
func decrypt(data: Data, key: String, salt: String) -> String? {
|
||||||
|
let keyBytes = key.data(using: .utf8)?.bytes ?? []
|
||||||
|
let saltBytes = salt.data(using: .utf8)?.bytes ?? []
|
||||||
|
|
||||||
|
guard let PBKDF2key = try? PKCS5.PBKDF2(password: keyBytes, salt: saltBytes, iterations: 4096, variant: .sha256).calculate(),
|
||||||
|
let cipher = try? Blowfish(key: PBKDF2key, padding: .pkcs7),
|
||||||
|
let decryptedBytes = try? cipher.decrypt(data.bytes) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let decryptedData = Data(decryptedBytes)
|
||||||
|
return String(data: decryptedData, encoding: .utf8)
|
||||||
|
}
|
|
@ -1 +1 @@
|
||||||
09c81fe0a3d701eb6da3bd2c6fc5ec65
|
bc336703210c48e30d7216fac3fe1c0f
|
|
@ -1,5 +1,6 @@
|
||||||
# Uncomment this line to define a global platform for your project
|
# Uncomment this line to define a global platform for your project
|
||||||
platform :ios, '9.0'
|
platform :ios, '9.0'
|
||||||
|
source 'https://github.com/CocoaPods/Specs.git'
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|
|
@ -64,7 +64,7 @@ DEPENDENCIES:
|
||||||
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
|
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
https://github.com/CocoaPods/Specs.git:
|
||||||
- CryptoSwift
|
- CryptoSwift
|
||||||
- MTBBarcodeScanner
|
- MTBBarcodeScanner
|
||||||
- Reachability
|
- Reachability
|
||||||
|
@ -117,6 +117,6 @@ SPEC CHECKSUMS:
|
||||||
SwiftProtobuf: 4ef85479c18ca85b5482b343df9c319c62bda699
|
SwiftProtobuf: 4ef85479c18ca85b5482b343df9c319c62bda699
|
||||||
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
|
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
|
||||||
|
|
||||||
PODFILE CHECKSUM: ade2ba43f8c2af4060c025bfd25a553d068ab914
|
PODFILE CHECKSUM: ba3d2157523e2f4dc333b987efdac6635da8125d
|
||||||
|
|
||||||
COCOAPODS: 1.8.4
|
COCOAPODS: 1.9.3
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
0C44A71A2518EF8000B570ED /* EncryptedFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C44A7192518EF8000B570ED /* EncryptedFile.swift */; };
|
0C44A71A2518EF8000B570ED /* decrypt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C44A7192518EF8000B570ED /* decrypt.swift */; };
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
20ED0868E1BD7E12278C0CB3 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B26E3F56D69167FBB1DC160A /* Pods_Runner.framework */; };
|
20ED0868E1BD7E12278C0CB3 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B26E3F56D69167FBB1DC160A /* Pods_Runner.framework */; };
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
|
@ -17,21 +17,9 @@
|
||||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
|
||||||
isa = PBXCopyFilesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
dstPath = "";
|
|
||||||
dstSubfolderSpec = 10;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
name = "Embed Frameworks";
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
0C44A7192518EF8000B570ED /* EncryptedFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedFile.swift; sourceTree = "<group>"; };
|
0C44A7192518EF8000B570ED /* decrypt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = decrypt.swift; sourceTree = "<group>"; };
|
||||||
|
0C9986A3251A932F00D566FD /* CryptoSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CryptoSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
20F67A1B2C2FCB2A3BB048C1 /* 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>"; };
|
20F67A1B2C2FCB2A3BB048C1 /* 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>"; };
|
||||||
|
@ -66,6 +54,7 @@
|
||||||
06957875428D0F5AAE053765 /* Frameworks */ = {
|
06957875428D0F5AAE053765 /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
0C9986A3251A932F00D566FD /* CryptoSwift.framework */,
|
||||||
B26E3F56D69167FBB1DC160A /* Pods_Runner.framework */,
|
B26E3F56D69167FBB1DC160A /* Pods_Runner.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
|
@ -74,7 +63,7 @@
|
||||||
0C44A7182518EF4A00B570ED /* CakeWallet */ = {
|
0C44A7182518EF4A00B570ED /* CakeWallet */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
0C44A7192518EF8000B570ED /* EncryptedFile.swift */,
|
0C44A7192518EF8000B570ED /* decrypt.swift */,
|
||||||
);
|
);
|
||||||
path = CakeWallet;
|
path = CakeWallet;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -147,7 +136,6 @@
|
||||||
97C146EA1CF9000F007C117D /* Sources */,
|
97C146EA1CF9000F007C117D /* Sources */,
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
97C146EC1CF9000F007C117D /* Resources */,
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
DD8DB3179CA4E511F9954A6F /* [CP] Embed Pods Frameworks */,
|
DD8DB3179CA4E511F9954A6F /* [CP] Embed Pods Frameworks */,
|
||||||
);
|
);
|
||||||
|
@ -284,7 +272,7 @@
|
||||||
files = (
|
files = (
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||||
0C44A71A2518EF8000B570ED /* EncryptedFile.swift in Sources */,
|
0C44A71A2518EF8000B570ED /* decrypt.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,27 +14,42 @@ import Flutter
|
||||||
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
|
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
|
||||||
|
|
||||||
switch call.method {
|
switch call.method {
|
||||||
case "read_trade_list":
|
case "decrypt":
|
||||||
guard let args = call.arguments as? Dictionary<String, Any>,
|
guard let args = call.arguments as? Dictionary<String, Any>,
|
||||||
|
let data = args["bytes"] as? FlutterStandardTypedData,
|
||||||
let key = args["key"] as? String,
|
let key = args["key"] as? String,
|
||||||
let salt = args["salt"] as? String else {
|
let salt = args["salt"] as? String else {
|
||||||
return
|
result(nil)
|
||||||
}
|
|
||||||
let normalizedKey = key.replacingOccurrences(of: "-", with: "")
|
|
||||||
result(readTradesList(key: normalizedKey, salt: salt))
|
|
||||||
case "read_encrypted_file":
|
|
||||||
guard let args = call.arguments as? Dictionary<String, Any>,
|
|
||||||
let path = args["path"] as? String,
|
|
||||||
let key = args["key"] as? String,
|
|
||||||
let salt = args["salt"] as? String else {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let content = EncryptedFile(url: URL(fileURLWithPath: path), key: key, salt: salt).decryptedContent()
|
let content = decrypt(data: data.data, key: key, salt: salt)
|
||||||
result(content)
|
result(content)
|
||||||
|
case "read_user_defaults":
|
||||||
|
guard let args = call.arguments as? Dictionary<String, Any>,
|
||||||
|
let key = args["key"] as? String,
|
||||||
|
let type = args["type"] as? String else {
|
||||||
|
result(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var value: Any?
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "string":
|
||||||
|
value = UserDefaults.standard.string(forKey: key)
|
||||||
|
case "int":
|
||||||
|
value = UserDefaults.standard.integer(forKey: key)
|
||||||
|
case "bool":
|
||||||
|
value = UserDefaults.standard.bool(forKey: key)
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result(value)
|
||||||
|
default:
|
||||||
|
result(FlutterMethodNotImplemented)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
GeneratedPluginRegistrant.register(with: self)
|
GeneratedPluginRegistrant.register(with: self)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'dart:io' show Platform;
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
@ -8,11 +9,22 @@ import 'package:cake_wallet/entities/balance_display_mode.dart';
|
||||||
import 'package:cake_wallet/entities/fiat_currency.dart';
|
import 'package:cake_wallet/entities/fiat_currency.dart';
|
||||||
import 'package:cake_wallet/entities/node_list.dart';
|
import 'package:cake_wallet/entities/node_list.dart';
|
||||||
import 'package:cake_wallet/entities/transaction_priority.dart';
|
import 'package:cake_wallet/entities/transaction_priority.dart';
|
||||||
|
import 'package:cake_wallet/entities/contact.dart';
|
||||||
|
import 'package:cake_wallet/entities/fs_migration.dart';
|
||||||
|
import 'package:cake_wallet/entities/wallet_info.dart';
|
||||||
|
import 'package:cake_wallet/exchange/trade.dart';
|
||||||
|
|
||||||
Future defaultSettingsMigration(
|
Future defaultSettingsMigration(
|
||||||
{@required int version,
|
{@required int version,
|
||||||
@required SharedPreferences sharedPreferences,
|
@required SharedPreferences sharedPreferences,
|
||||||
@required Box<Node> nodes}) async {
|
@required Box<Node> nodes,
|
||||||
|
@required Box<WalletInfo> walletInfoSource,
|
||||||
|
@required Box<Trade> tradeSource,
|
||||||
|
@required Box<Contact> contactSource}) async {
|
||||||
|
if (Platform.isIOS) {
|
||||||
|
await ios_migrate_v1(walletInfoSource, tradeSource, contactSource);
|
||||||
|
}
|
||||||
|
|
||||||
final currentVersion =
|
final currentVersion =
|
||||||
sharedPreferences.getInt('current_default_settings_migration_version') ??
|
sharedPreferences.getInt('current_default_settings_migration_version') ??
|
||||||
0;
|
0;
|
||||||
|
@ -60,6 +72,7 @@ Future defaultSettingsMigration(
|
||||||
await changeBitcoinCurrentElectrumServerToDefault(
|
await changeBitcoinCurrentElectrumServerToDefault(
|
||||||
sharedPreferences: sharedPreferences, nodes: nodes);
|
sharedPreferences: sharedPreferences, nodes: nodes);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,44 +3,7 @@ import 'package:cake_wallet/entities/enumerable_item.dart';
|
||||||
class FiatCurrency extends EnumerableItem<String> with Serializable<String> {
|
class FiatCurrency extends EnumerableItem<String> with Serializable<String> {
|
||||||
const FiatCurrency({String symbol}) : super(title: symbol, raw: symbol);
|
const FiatCurrency({String symbol}) : super(title: symbol, raw: symbol);
|
||||||
|
|
||||||
@override
|
static List<FiatCurrency> get all => _all.values.toList();
|
||||||
bool operator ==(Object other) => other is FiatCurrency && other.raw == raw;
|
|
||||||
|
|
||||||
static const all = [
|
|
||||||
FiatCurrency.aud,
|
|
||||||
FiatCurrency.bgn,
|
|
||||||
FiatCurrency.brl,
|
|
||||||
FiatCurrency.cad,
|
|
||||||
FiatCurrency.chf,
|
|
||||||
FiatCurrency.cny,
|
|
||||||
FiatCurrency.czk,
|
|
||||||
FiatCurrency.eur,
|
|
||||||
FiatCurrency.dkk,
|
|
||||||
FiatCurrency.gbp,
|
|
||||||
FiatCurrency.hkd,
|
|
||||||
FiatCurrency.hrk,
|
|
||||||
FiatCurrency.huf,
|
|
||||||
FiatCurrency.idr,
|
|
||||||
FiatCurrency.ils,
|
|
||||||
FiatCurrency.inr,
|
|
||||||
FiatCurrency.isk,
|
|
||||||
FiatCurrency.jpy,
|
|
||||||
FiatCurrency.krw,
|
|
||||||
FiatCurrency.mxn,
|
|
||||||
FiatCurrency.myr,
|
|
||||||
FiatCurrency.nok,
|
|
||||||
FiatCurrency.nzd,
|
|
||||||
FiatCurrency.php,
|
|
||||||
FiatCurrency.pln,
|
|
||||||
FiatCurrency.ron,
|
|
||||||
FiatCurrency.rub,
|
|
||||||
FiatCurrency.sek,
|
|
||||||
FiatCurrency.sgd,
|
|
||||||
FiatCurrency.thb,
|
|
||||||
FiatCurrency.usd,
|
|
||||||
FiatCurrency.zar,
|
|
||||||
FiatCurrency.vef
|
|
||||||
];
|
|
||||||
|
|
||||||
static const aud = FiatCurrency(symbol: 'AUD');
|
static const aud = FiatCurrency(symbol: 'AUD');
|
||||||
static const bgn = FiatCurrency(symbol: 'BGN');
|
static const bgn = FiatCurrency(symbol: 'BGN');
|
||||||
|
@ -76,6 +39,47 @@ class FiatCurrency extends EnumerableItem<String> with Serializable<String> {
|
||||||
static const zar = FiatCurrency(symbol: 'ZAR');
|
static const zar = FiatCurrency(symbol: 'ZAR');
|
||||||
static const vef = FiatCurrency(symbol: 'VEF');
|
static const vef = FiatCurrency(symbol: 'VEF');
|
||||||
|
|
||||||
|
static final _all = {
|
||||||
|
FiatCurrency.aud.raw: FiatCurrency.aud,
|
||||||
|
FiatCurrency.bgn.raw: FiatCurrency.bgn,
|
||||||
|
FiatCurrency.brl.raw: FiatCurrency.brl,
|
||||||
|
FiatCurrency.cad.raw: FiatCurrency.cad,
|
||||||
|
FiatCurrency.chf.raw: FiatCurrency.chf,
|
||||||
|
FiatCurrency.cny.raw: FiatCurrency.cny,
|
||||||
|
FiatCurrency.czk.raw: FiatCurrency.czk,
|
||||||
|
FiatCurrency.eur.raw: FiatCurrency.eur,
|
||||||
|
FiatCurrency.dkk.raw: FiatCurrency.dkk,
|
||||||
|
FiatCurrency.gbp.raw: FiatCurrency.gbp,
|
||||||
|
FiatCurrency.hkd.raw: FiatCurrency.hkd,
|
||||||
|
FiatCurrency.hrk.raw: FiatCurrency.hrk,
|
||||||
|
FiatCurrency.huf.raw: FiatCurrency.huf,
|
||||||
|
FiatCurrency.idr.raw: FiatCurrency.idr,
|
||||||
|
FiatCurrency.ils.raw: FiatCurrency.ils,
|
||||||
|
FiatCurrency.inr.raw: FiatCurrency.inr,
|
||||||
|
FiatCurrency.isk.raw: FiatCurrency.isk,
|
||||||
|
FiatCurrency.jpy.raw: FiatCurrency.jpy,
|
||||||
|
FiatCurrency.krw.raw: FiatCurrency.krw,
|
||||||
|
FiatCurrency.mxn.raw: FiatCurrency.mxn,
|
||||||
|
FiatCurrency.myr.raw: FiatCurrency.myr,
|
||||||
|
FiatCurrency.nok.raw: FiatCurrency.nok,
|
||||||
|
FiatCurrency.nzd.raw: FiatCurrency.nzd,
|
||||||
|
FiatCurrency.php.raw: FiatCurrency.php,
|
||||||
|
FiatCurrency.pln.raw: FiatCurrency.pln,
|
||||||
|
FiatCurrency.ron.raw: FiatCurrency.ron,
|
||||||
|
FiatCurrency.rub.raw: FiatCurrency.rub,
|
||||||
|
FiatCurrency.sek.raw: FiatCurrency.sek,
|
||||||
|
FiatCurrency.sgd.raw: FiatCurrency.sgd,
|
||||||
|
FiatCurrency.thb.raw: FiatCurrency.thb,
|
||||||
|
FiatCurrency.usd.raw: FiatCurrency.usd,
|
||||||
|
FiatCurrency.zar.raw: FiatCurrency.zar,
|
||||||
|
FiatCurrency.vef.raw: FiatCurrency.vef
|
||||||
|
};
|
||||||
|
|
||||||
|
static FiatCurrency deserialize({String raw}) => _all[raw];
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => other is FiatCurrency && other.raw == raw;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => raw.hashCode ^ title.hashCode;
|
int get hashCode => raw.hashCode ^ title.hashCode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,56 +1,94 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:cake_wallet/core/key_service.dart';
|
||||||
|
import 'package:cake_wallet/di.dart';
|
||||||
import 'package:cake_wallet/entities/contact.dart';
|
import 'package:cake_wallet/entities/contact.dart';
|
||||||
import 'package:cake_wallet/entities/crypto_currency.dart';
|
import 'package:cake_wallet/entities/crypto_currency.dart';
|
||||||
|
import 'package:cake_wallet/entities/encrypt.dart';
|
||||||
|
import 'package:cake_wallet/entities/fiat_currency.dart';
|
||||||
|
import 'package:cake_wallet/entities/ios_legacy_helper.dart'
|
||||||
|
as ios_legacy_helper;
|
||||||
|
import 'package:cake_wallet/entities/secret_store_key.dart';
|
||||||
import 'package:cake_wallet/entities/wallet_info.dart';
|
import 'package:cake_wallet/entities/wallet_info.dart';
|
||||||
import 'package:cake_wallet/entities/wallet_type.dart';
|
import 'package:cake_wallet/entities/wallet_type.dart';
|
||||||
|
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
|
||||||
import 'package:cake_wallet/exchange/trade.dart';
|
import 'package:cake_wallet/exchange/trade.dart';
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||||
|
|
||||||
const reservedNames = ["flutter_assets", "wallets", "db"];
|
const reservedNames = ["flutter_assets", "wallets", "db"];
|
||||||
|
|
||||||
Future<void> migrate_android_v1() async {
|
Future<void> migrate_android_v1() async {
|
||||||
final appDocDir = await getApplicationDocumentsDirectory();
|
final appDocDir = await getApplicationDocumentsDirectory();
|
||||||
|
|
||||||
await migrate_hives(appDocDir: appDocDir);
|
await android_migrate_hives(appDocDir: appDocDir);
|
||||||
await migrate_wallets(appDocDir: appDocDir);
|
await android_migrate_wallets(appDocDir: appDocDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> migrate_ios_v1() async {
|
Future<void> ios_migrate_v1(Box<WalletInfo> walletInfoSource, Box<Trade> tradeSource, Box<Contact> contactSource) async {
|
||||||
final appDocDir = await getApplicationDocumentsDirectory();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
|
if (prefs.getBool('ios_migration_v1_completed') ?? false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await ios_migrate_user_defaults();
|
||||||
|
await ios_migrate_pin();
|
||||||
|
await ios_migrate_wallet_passwords();
|
||||||
|
await ios_migrate_wallet_info(walletInfoSource);
|
||||||
|
await ios_migrate_trades_list(tradeSource);
|
||||||
|
await ios_migrate_address_book(contactSource);
|
||||||
|
|
||||||
|
await prefs.setBool('ios_migration_v1_completed', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> ios_migrate_user_defaults() async {
|
||||||
//get the new shared preferences instance
|
//get the new shared preferences instance
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
|
if (prefs.getBool('ios_migration_user_defaults_completed') ?? false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//translate the node uri
|
//translate the node uri
|
||||||
String nodeURI = prefs.getString('node_uri');
|
final nodeURI = await ios_legacy_helper.getString('node_uri');
|
||||||
await prefs.setString('current_node_id', nodeURI);
|
// await prefs.setString('current_node_id', nodeURI);
|
||||||
|
await prefs.setInt('current_node_id', 0);
|
||||||
|
|
||||||
//should we provide default btc node key?
|
//should we provide default btc node key?
|
||||||
int activeCurrency = prefs.getInt('currency');
|
final activeCurrency = await ios_legacy_helper.getInt('currency');
|
||||||
await prefs.setInt('current_fiat_currency', activeCurrency);
|
final convertedCurrency = convertFiatLegacy(activeCurrency);
|
||||||
|
|
||||||
|
if (convertedCurrency != null) {
|
||||||
|
await prefs.setString(
|
||||||
|
'current_fiat_currency', convertedCurrency.serialize());
|
||||||
|
}
|
||||||
|
|
||||||
//translate fee priority
|
//translate fee priority
|
||||||
int activeFeeTier = prefs.getInt('saved_fee_priority');
|
final activeFeeTier = await ios_legacy_helper.getInt('saved_fee_priority');
|
||||||
await prefs.setInt('current_fee_priority', activeFeeTier);
|
await prefs.setInt('current_fee_priority', activeFeeTier);
|
||||||
|
|
||||||
//translate current balance mode
|
//translate current balance mode
|
||||||
int currentBalanceMode = prefs.getInt('display_balance_mode');
|
final currentBalanceMode =
|
||||||
|
await ios_legacy_helper.getInt('display_balance_mode');
|
||||||
await prefs.setInt('current_balance_display_mode', currentBalanceMode);
|
await prefs.setInt('current_balance_display_mode', currentBalanceMode);
|
||||||
|
|
||||||
//translate should save recipient address
|
//translate should save recipient address
|
||||||
bool shouldSave = prefs.getBool('should_save_recipient_address');
|
final shouldSave =
|
||||||
|
await ios_legacy_helper.getBool('should_save_recipient_address');
|
||||||
await prefs.setBool('save_recipient_address', shouldSave);
|
await prefs.setBool('save_recipient_address', shouldSave);
|
||||||
|
|
||||||
//translate biometric
|
//translate biometric
|
||||||
bool biometricOn = prefs.getBool('biometric_authentication_on');
|
final biometricOn =
|
||||||
|
await ios_legacy_helper.getBool('biometric_authentication_on');
|
||||||
await prefs.setBool('allow_biometrical_authentication', biometricOn);
|
await prefs.setBool('allow_biometrical_authentication', biometricOn);
|
||||||
|
|
||||||
//read the current theme as integer, write it back as a bool
|
//read the current theme as integer, write it back as a bool
|
||||||
int currentTheme = prefs.getInt('current-theme');
|
final currentTheme = prefs.getInt('current-theme');
|
||||||
bool isDark = false;
|
bool isDark = false;
|
||||||
if (currentTheme == 1) {
|
if (currentTheme == 1) {
|
||||||
isDark = true;
|
isDark = true;
|
||||||
|
@ -58,15 +96,108 @@ Future<void> migrate_ios_v1() async {
|
||||||
await prefs.setBool('dark_theme', isDark);
|
await prefs.setBool('dark_theme', isDark);
|
||||||
|
|
||||||
//assign the pin lenght
|
//assign the pin lenght
|
||||||
int pinLength = prefs.getInt('pin-length');
|
final pinLength = await ios_legacy_helper.getInt('pin-length');
|
||||||
await prefs.setInt('pin-length', pinLength);
|
await prefs.setInt('pin-length', pinLength);
|
||||||
|
|
||||||
//default value for display list key?
|
//default value for display list key?
|
||||||
String walletName = prefs.getString('current_wallet_name');
|
final walletName = await ios_legacy_helper.getString('current_wallet_name');
|
||||||
await prefs.setString('current_wallet_name', walletName);
|
await prefs.setString('current_wallet_name', walletName);
|
||||||
|
|
||||||
|
await prefs.setInt('current_wallet_type', serializeToInt(WalletType.monero));
|
||||||
|
|
||||||
|
await prefs.setBool('ios_migration_user_defaults_completed', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> migrate_hives({Directory appDocDir}) async {
|
Future<void> ios_migrate_pin() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
|
if (prefs.getBool('ios_migration_pin_completed') ?? false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final flutterSecureStorage = FlutterSecureStorage();
|
||||||
|
final pinPassword = await flutterSecureStorage.read(
|
||||||
|
key: 'pin_password', iOptions: IOSOptions(syncFlag: "syna"));
|
||||||
|
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
||||||
|
final encodedPassword = encodedPinCode(pin: pinPassword);
|
||||||
|
await flutterSecureStorage.write(key: key, value: encodedPassword);
|
||||||
|
await prefs.setBool('ios_migration_pin_completed', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> ios_migrate_wallet_passwords() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
|
if (prefs.getBool('ios_migration_wallet_passwords_completed') ?? false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final appDocDir = await getApplicationDocumentsDirectory();
|
||||||
|
final flutterSecureStorage = FlutterSecureStorage();
|
||||||
|
final keyService = KeyService(flutterSecureStorage);
|
||||||
|
final walletsDir = Directory('${appDocDir.path}/wallets');
|
||||||
|
final moneroWalletsDir = Directory('${walletsDir.path}/monero');
|
||||||
|
|
||||||
|
moneroWalletsDir.listSync().forEach((item) async {
|
||||||
|
try {
|
||||||
|
if (item is Directory) {
|
||||||
|
final name = item.path.split('/').last;
|
||||||
|
final oldKey = 'wallet_monero_' + name + '_password';
|
||||||
|
final password = await flutterSecureStorage.read(
|
||||||
|
key: oldKey, iOptions: IOSOptions(syncFlag: "syna"));
|
||||||
|
await keyService.saveWalletPassword(
|
||||||
|
walletName: name, password: password);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print(e.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await prefs.setBool('ios_migration_wallet_passwords_completed', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
FiatCurrency convertFiatLegacy(int raw) {
|
||||||
|
final _map = {
|
||||||
|
0: 'aud',
|
||||||
|
1: 'bgn',
|
||||||
|
2: 'brl',
|
||||||
|
3: 'cad',
|
||||||
|
4: 'chf',
|
||||||
|
5: 'cny',
|
||||||
|
6: 'czk',
|
||||||
|
7: 'eur',
|
||||||
|
8: 'dkk',
|
||||||
|
9: 'gbp',
|
||||||
|
10: 'hkd',
|
||||||
|
11: 'hrk',
|
||||||
|
12: 'huf',
|
||||||
|
13: 'idr',
|
||||||
|
14: 'ils',
|
||||||
|
15: 'inr',
|
||||||
|
16: 'isk',
|
||||||
|
17: 'jpy',
|
||||||
|
18: 'krw',
|
||||||
|
19: 'mxn',
|
||||||
|
20: 'myr',
|
||||||
|
21: 'nok',
|
||||||
|
22: 'nzd',
|
||||||
|
23: 'php',
|
||||||
|
24: 'pln',
|
||||||
|
25: 'ron',
|
||||||
|
26: 'rub',
|
||||||
|
27: 'sek',
|
||||||
|
28: 'sgd',
|
||||||
|
29: 'thb',
|
||||||
|
30: 'try',
|
||||||
|
31: 'usd',
|
||||||
|
32: 'zar',
|
||||||
|
33: 'vef'
|
||||||
|
};
|
||||||
|
final fiatAsString = _map[raw];
|
||||||
|
|
||||||
|
return FiatCurrency.deserialize(raw: fiatAsString.toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> android_migrate_hives({Directory appDocDir}) async {
|
||||||
final dbDir = Directory('${appDocDir.path}/db');
|
final dbDir = Directory('${appDocDir.path}/db');
|
||||||
final files = List<File>();
|
final files = List<File>();
|
||||||
|
|
||||||
|
@ -89,7 +220,7 @@ Future<void> migrate_hives({Directory appDocDir}) async {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> migrate_wallets({Directory appDocDir}) async {
|
Future<void> android_migrate_wallets({Directory appDocDir}) async {
|
||||||
final walletsDir = Directory('${appDocDir.path}/wallets');
|
final walletsDir = Directory('${appDocDir.path}/wallets');
|
||||||
final moneroWalletsDir = Directory('${walletsDir.path}/monero');
|
final moneroWalletsDir = Directory('${walletsDir.path}/monero');
|
||||||
final dirs = List<Directory>();
|
final dirs = List<Directory>();
|
||||||
|
@ -123,54 +254,162 @@ Future<void> migrate_wallets({Directory appDocDir}) async {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> migrate_ios_wallet_info(
|
Future<void> ios_migrate_wallet_info(Box<WalletInfo> walletsInfoSource) async {
|
||||||
{@required Directory appDocDir,
|
final prefs = await SharedPreferences.getInstance();
|
||||||
@required Box<WalletInfo> walletsInfo}) async {
|
|
||||||
// final walletsDir = Directory('${appDocDir.path}/wallets');
|
|
||||||
// final moneroWalletsDir = Directory('${walletsDir.path}/monero');
|
|
||||||
|
|
||||||
// moneroWalletsDir.listSync().forEach((item) async {
|
if (prefs.getBool('ios_migration_wallet_info_completed') ?? false) {
|
||||||
// try {
|
return;
|
||||||
// if (item is Directory) {
|
|
||||||
// final name = item.path.split('/').last;
|
|
||||||
// final configFile = File('${item.path}/$name.json');
|
|
||||||
// final config =
|
|
||||||
// json.decode(configFile.readAsStringSync()) as Map<String, dynamic>;
|
|
||||||
// final isRecovery = config["isRecovery"] as bool ?? false;
|
|
||||||
// final id =
|
|
||||||
// walletTypeToString(WalletType.monero).toLowerCase() + '_' + name;
|
|
||||||
// final walletInfo =
|
|
||||||
// WalletInfo(id: id, name: name, isRecovery: isRecovery);
|
|
||||||
|
|
||||||
// await walletsInfo.add(walletInfo);
|
|
||||||
// }
|
|
||||||
// } catch (e) {
|
|
||||||
// print(e.toString());
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> migrate_ios_trades_list(
|
try {
|
||||||
{@required Directory appDocDir, @required Box<Trade> trades}) async {
|
final appDocDir = await getApplicationDocumentsDirectory();
|
||||||
final adderessBookJSON = File('${appDocDir.path}/trades_list.json');
|
final walletsDir = Directory('${appDocDir.path}/wallets');
|
||||||
final List<dynamic> trades =
|
final moneroWalletsDir = Directory('${walletsDir.path}/monero');
|
||||||
json.decode(adderessBookJSON.readAsStringSync()) as List<dynamic>;
|
final infoRecords = moneroWalletsDir
|
||||||
|
.listSync()
|
||||||
|
.map((item) {
|
||||||
|
try {
|
||||||
|
if (item is Directory) {
|
||||||
|
final name = item.path.split('/').last;
|
||||||
|
final configFile = File('${item.path}/$name.json');
|
||||||
|
|
||||||
|
if (!configFile.existsSync()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final config = json.decode(configFile.readAsStringSync())
|
||||||
|
as Map<String, dynamic>;
|
||||||
|
final isRecovery = config['isRecovery'] as bool ?? false;
|
||||||
|
final dateAsDouble = config['date'] as double;
|
||||||
|
final timestamp = dateAsDouble.toInt() * 1000;
|
||||||
|
final date = DateTime.fromMillisecondsSinceEpoch(timestamp);
|
||||||
|
final id = walletTypeToString(WalletType.monero).toLowerCase() +
|
||||||
|
'_' +
|
||||||
|
name;
|
||||||
|
final exist = walletsInfoSource.values
|
||||||
|
.firstWhere((el) => el.id == id, orElse: () => null) !=
|
||||||
|
null;
|
||||||
|
|
||||||
|
if (exist) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final walletInfo = WalletInfo.external(
|
||||||
|
id: id,
|
||||||
|
type: WalletType.monero,
|
||||||
|
name: name,
|
||||||
|
isRecovery: isRecovery,
|
||||||
|
restoreHeight: 0,
|
||||||
|
date: date,
|
||||||
|
dirPath: item.path,
|
||||||
|
path: '${item.path}/$name');
|
||||||
|
|
||||||
|
return walletInfo;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print(e.toString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.where((el) => el != null)
|
||||||
|
.toList();
|
||||||
|
print(infoRecords);
|
||||||
|
await walletsInfoSource.addAll(infoRecords);
|
||||||
|
await prefs.setBool('ios_migration_wallet_info_completed', true);
|
||||||
|
} catch (e) {
|
||||||
|
print(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> ios_migrate_trades_list(Box<Trade> tradeSource) async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
|
if (prefs.getBool('ios_migration_trade_list_completed') ?? false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final appDocDir = await getApplicationDocumentsDirectory();
|
||||||
|
final url = '${appDocDir.path}/trades_list.json';
|
||||||
|
final file = File(url);
|
||||||
|
|
||||||
|
if (!file.existsSync()) {
|
||||||
|
await prefs.setBool('ios_migration_trade_list_completed', true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final content = file.readAsBytesSync();
|
||||||
|
final flutterSecureStorage = FlutterSecureStorage();
|
||||||
|
final masterPassword = await flutterSecureStorage.read(
|
||||||
|
key: 'master_password', iOptions: IOSOptions(syncFlag: "syna"));
|
||||||
|
final key = masterPassword.replaceAll('-', '');
|
||||||
|
final decoded = await ios_legacy_helper.decrypt(content,
|
||||||
|
key: key, salt: secrets.keychainSalt);
|
||||||
|
final decodedJson = json.decode(decoded) as List<dynamic>;
|
||||||
|
final trades = decodedJson.map((dynamic el) {
|
||||||
|
final elAsMap = el as Map<String, dynamic>;
|
||||||
|
final providerAsString = elAsMap['provider'] as String;
|
||||||
|
final fromAsString = elAsMap['from'] as String;
|
||||||
|
final toAsString = elAsMap['to'] as String;
|
||||||
|
final dateAsDouble = elAsMap['date'] as double;
|
||||||
|
final tradeId = elAsMap['tradeID'] as String;
|
||||||
|
final to = CryptoCurrency.fromString(toAsString);
|
||||||
|
final from = CryptoCurrency.fromString(fromAsString);
|
||||||
|
final timestamp = dateAsDouble.toInt() * 1000;
|
||||||
|
final date = DateTime.fromMillisecondsSinceEpoch(timestamp);
|
||||||
|
ExchangeProviderDescription provider;
|
||||||
|
|
||||||
|
switch (providerAsString.toLowerCase()) {
|
||||||
|
case 'changenow':
|
||||||
|
provider = ExchangeProviderDescription.changeNow;
|
||||||
|
break;
|
||||||
|
case 'xmr.to':
|
||||||
|
provider = ExchangeProviderDescription.xmrto;
|
||||||
|
break;
|
||||||
|
case 'morph':
|
||||||
|
provider = ExchangeProviderDescription.morphToken;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Trade(
|
||||||
|
id: tradeId, provider: provider, from: from, to: to, createdAt: date);
|
||||||
|
});
|
||||||
|
await tradeSource.addAll(trades);
|
||||||
|
await prefs.setBool('ios_migration_trade_list_completed', true);
|
||||||
|
} catch (e) {
|
||||||
|
print(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> ios_migrate_address_book(Box<Contact> contactSource) async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
|
if (prefs.getBool('ios_migration_address_book_completed') ?? false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final appDocDir = await getApplicationDocumentsDirectory();
|
||||||
|
final addressBookJSON = File('${appDocDir.path}/address_book.json');
|
||||||
|
|
||||||
|
if (!addressBookJSON.existsSync()) {
|
||||||
|
await prefs.setBool('ios_migration_address_book_completed', true);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> migrate_ios_address_book(
|
|
||||||
{@required Directory appDocDir, @required Box<Contact> contacts}) async {
|
|
||||||
final adderessBookJSON = File('${appDocDir.path}/address_book.json');
|
|
||||||
final List<dynamic> addresses =
|
final List<dynamic> addresses =
|
||||||
json.decode(adderessBookJSON.readAsStringSync()) as List<dynamic>;
|
json.decode(addressBookJSON.readAsStringSync()) as List<dynamic>;
|
||||||
|
final contacts = addresses.map((dynamic item) {
|
||||||
addresses.forEach((dynamic item) async {
|
|
||||||
final _item = item as Map<String, dynamic>;
|
final _item = item as Map<String, dynamic>;
|
||||||
final type = _item["type"] as String;
|
final type = _item["type"] as String;
|
||||||
final address = _item["address"] as String;
|
final address = _item["address"] as String;
|
||||||
final name = _item["name"] as String;
|
final name = _item["name"] as String;
|
||||||
final contact = Contact(
|
|
||||||
address: address, name: name, type: CryptoCurrency.fromString(type));
|
|
||||||
|
|
||||||
await contacts.add(contact);
|
return Contact(
|
||||||
|
address: address, name: name, type: CryptoCurrency.fromString(type));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await contactSource.addAll(contacts);
|
||||||
|
await prefs.setBool('ios_migration_address_book_completed', true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,25 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:typed_data';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
const platform =
|
const platform =
|
||||||
const MethodChannel('com.cakewallet.cakewallet/legacy_wallet_migration');
|
const MethodChannel('com.cakewallet.cakewallet/legacy_wallet_migration');
|
||||||
|
|
||||||
Future<String> readTradeList(
|
Future<String> decrypt(Uint8List bytes,
|
||||||
{@required String key, @required String salt}) async =>
|
{@required String key, @required String salt}) async =>
|
||||||
await platform.invokeMethod('read_trade_list', {'key': key, 'salt': salt});
|
await platform
|
||||||
|
.invokeMethod('decrypt', {'bytes': bytes, 'key': key, 'salt': salt});
|
||||||
|
|
||||||
Future<String> readEncryptedFile(String url,
|
Future<dynamic> readUserDefaults(String key, {@required String type}) async =>
|
||||||
{@required String key, @required String salt}) async =>
|
await platform
|
||||||
await platform.invokeMethod(
|
.invokeMethod<dynamic>('read_user_defaults', {'key': key, 'type': type});
|
||||||
'read_encrypted_file', {'url': url, 'key': key, 'salt': salt});
|
|
||||||
|
Future<String> getString(String key) async =>
|
||||||
|
await readUserDefaults(key, type: 'string') as String;
|
||||||
|
|
||||||
|
Future<bool> getBool(String key) async =>
|
||||||
|
await readUserDefaults(key, type: 'bool') as bool;
|
||||||
|
|
||||||
|
Future<int> getInt(String key) async =>
|
||||||
|
await readUserDefaults(key, type: 'int') as int;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:cake_wallet/entities/fs_migration.dart';
|
||||||
import 'package:cake_wallet/entities/transaction_description.dart';
|
import 'package:cake_wallet/entities/transaction_description.dart';
|
||||||
import 'package:cake_wallet/entities/transaction_description.dart';
|
import 'package:cake_wallet/entities/transaction_description.dart';
|
||||||
import 'package:cake_wallet/reactions/bootstrap.dart';
|
import 'package:cake_wallet/reactions/bootstrap.dart';
|
||||||
|
@ -94,7 +95,7 @@ void main() async {
|
||||||
final exchangeTemplates =
|
final exchangeTemplates =
|
||||||
await Hive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName);
|
await Hive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName);
|
||||||
|
|
||||||
final sharedPreferences = await SharedPreferences.getInstance();
|
// final sharedPreferences = await SharedPreferences.getInstance();
|
||||||
// final walletService = WalletService();
|
// final walletService = WalletService();
|
||||||
// final fiatConvertationService = FiatConvertationService();
|
// final fiatConvertationService = FiatConvertationService();
|
||||||
// final walletListService = WalletListService(
|
// final walletListService = WalletListService(
|
||||||
|
@ -138,7 +139,6 @@ void main() async {
|
||||||
templates: templates,
|
templates: templates,
|
||||||
exchangeTemplates: exchangeTemplates,
|
exchangeTemplates: exchangeTemplates,
|
||||||
initialMigrationVersion: 4);
|
initialMigrationVersion: 4);
|
||||||
|
|
||||||
// setReactions(
|
// setReactions(
|
||||||
// settingsStore: settingsStore,
|
// settingsStore: settingsStore,
|
||||||
// priceStore: priceStore,
|
// priceStore: priceStore,
|
||||||
|
@ -147,8 +147,8 @@ void main() async {
|
||||||
// walletService: walletService,
|
// walletService: walletService,
|
||||||
// // authenticationStore: authenticationStore,
|
// // authenticationStore: authenticationStore,
|
||||||
// loginStore: loginStore);
|
// loginStore: loginStore);
|
||||||
|
final initialLanguage = await Language.localeDetection();
|
||||||
runApp(CakeWalletApp());
|
runApp(CakeWalletApp(initialLanguage));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> initialSetup(
|
Future<void> initialSetup(
|
||||||
|
@ -160,10 +160,13 @@ Future<void> initialSetup(
|
||||||
// @required FiatConvertationService fiatConvertationService,
|
// @required FiatConvertationService fiatConvertationService,
|
||||||
@required Box<Template> templates,
|
@required Box<Template> templates,
|
||||||
@required Box<ExchangeTemplate> exchangeTemplates,
|
@required Box<ExchangeTemplate> exchangeTemplates,
|
||||||
int initialMigrationVersion = 4}) async {
|
int initialMigrationVersion = 5}) async {
|
||||||
await defaultSettingsMigration(
|
await defaultSettingsMigration(
|
||||||
version: initialMigrationVersion,
|
version: initialMigrationVersion,
|
||||||
sharedPreferences: sharedPreferences,
|
sharedPreferences: sharedPreferences,
|
||||||
|
walletInfoSource: walletInfoSource,
|
||||||
|
contactSource: contactSource,
|
||||||
|
tradeSource: tradesSource,
|
||||||
nodes: nodes);
|
nodes: nodes);
|
||||||
await setup(
|
await setup(
|
||||||
walletInfoSource: walletInfoSource,
|
walletInfoSource: walletInfoSource,
|
||||||
|
@ -177,11 +180,13 @@ Future<void> initialSetup(
|
||||||
}
|
}
|
||||||
|
|
||||||
class CakeWalletApp extends StatelessWidget {
|
class CakeWalletApp extends StatelessWidget {
|
||||||
CakeWalletApp() {
|
CakeWalletApp(this.initialLanguage) {
|
||||||
SystemChrome.setPreferredOrientations(
|
SystemChrome.setPreferredOrientations(
|
||||||
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
|
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final String initialLanguage;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
//final settingsStore = Provider.of<SettingsStore>(context);
|
//final settingsStore = Provider.of<SettingsStore>(context);
|
||||||
|
@ -192,11 +197,14 @@ class CakeWalletApp extends StatelessWidget {
|
||||||
settingsStore.isDarkTheme ? Themes.darkTheme : Themes.lightTheme),
|
settingsStore.isDarkTheme ? Themes.darkTheme : Themes.lightTheme),
|
||||||
child: ChangeNotifierProvider<Language>(
|
child: ChangeNotifierProvider<Language>(
|
||||||
create: (_) => Language(settingsStore.languageCode),
|
create: (_) => Language(settingsStore.languageCode),
|
||||||
child: MaterialAppWithTheme()));
|
child: MaterialAppWithTheme(initialLanguage)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MaterialAppWithTheme extends StatelessWidget {
|
class MaterialAppWithTheme extends StatelessWidget {
|
||||||
|
MaterialAppWithTheme(this.initialLanguage);
|
||||||
|
final String initialLanguage;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// final sharedPreferences = Provider.of<SharedPreferences>(context);
|
// final sharedPreferences = Provider.of<SharedPreferences>(context);
|
||||||
|
@ -209,7 +217,7 @@ class MaterialAppWithTheme extends StatelessWidget {
|
||||||
// final syncStore = Provider.of<SyncStore>(context);
|
// final syncStore = Provider.of<SyncStore>(context);
|
||||||
// final balanceStore = Provider.of<BalanceStore>(context);
|
// final balanceStore = Provider.of<BalanceStore>(context);
|
||||||
final theme = Provider.of<ThemeChanger>(context);
|
final theme = Provider.of<ThemeChanger>(context);
|
||||||
// final currentLanguage = Provider.of<Language>(context);
|
final currentLanguage = Provider.of<Language>(context);
|
||||||
// final contacts = Provider.of<Box<Contact>>(context);
|
// final contacts = Provider.of<Box<Contact>>(context);
|
||||||
// final nodes = Provider.of<Box<Node>>(context);
|
// final nodes = Provider.of<Box<Node>>(context);
|
||||||
// final trades = Provider.of<Box<Trade>>(context);
|
// final trades = Provider.of<Box<Trade>>(context);
|
||||||
|
@ -253,7 +261,7 @@ class MaterialAppWithTheme extends StatelessWidget {
|
||||||
GlobalWidgetsLocalizations.delegate,
|
GlobalWidgetsLocalizations.delegate,
|
||||||
],
|
],
|
||||||
supportedLocales: S.delegate.supportedLocales,
|
supportedLocales: S.delegate.supportedLocales,
|
||||||
// locale: Locale(currentLanguage.getCurrentLanguage()),
|
locale: Locale(currentLanguage.getCurrentLanguage()),
|
||||||
onGenerateRoute: (settings) => Router.generateRoute(settings),
|
onGenerateRoute: (settings) => Router.generateRoute(settings),
|
||||||
initialRoute: initialRoute,
|
initialRoute: initialRoute,
|
||||||
));
|
));
|
||||||
|
|
|
@ -90,12 +90,9 @@ class MoneroWalletService extends WalletService<
|
||||||
final path = await pathForWallet(name: name, type: WalletType.monero);
|
final path = await pathForWallet(name: name, type: WalletType.monero);
|
||||||
final file = File(path);
|
final file = File(path);
|
||||||
final stat = await file.stat();
|
final stat = await file.stat();
|
||||||
print(stat.changed);
|
|
||||||
print(stat.modified);
|
|
||||||
print(stat.accessed);
|
|
||||||
monero_wallet_manager.openWallet(path: path, password: password);
|
monero_wallet_manager.openWallet(path: path, password: password);
|
||||||
final walletInfo = walletInfoSource.values.firstWhere(
|
final walletInfo = walletInfoSource.values.firstWhere(
|
||||||
(info) => info.id == WalletBase.idFor(name, WalletType.monero));
|
(info) => info.id == WalletBase.idFor(name, WalletType.monero), orElse: () => null);
|
||||||
final wallet = MoneroWallet(
|
final wallet = MoneroWallet(
|
||||||
filename: monero_wallet.getFilename(), walletInfo: walletInfo);
|
filename: monero_wallet.getFilename(), walletInfo: walletInfo);
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
|
|
@ -19,10 +19,10 @@ Future<void> bootstrap(GlobalKey<NavigatorState> navigatorKey) async {
|
||||||
final fiatConversionStore = getIt.get<FiatConversionStore>();
|
final fiatConversionStore = getIt.get<FiatConversionStore>();
|
||||||
|
|
||||||
if (authenticationStore.state == AuthenticationState.uninitialized) {
|
if (authenticationStore.state == AuthenticationState.uninitialized) {
|
||||||
authenticationStore.state = getIt
|
final currentWalletName = getIt
|
||||||
.get<SharedPreferences>()
|
.get<SharedPreferences>()
|
||||||
.getString(PreferencesKey.currentWalletName) ==
|
.getString(PreferencesKey.currentWalletName);
|
||||||
null
|
authenticationStore.state = currentWalletName == null
|
||||||
? AuthenticationState.denied
|
? AuthenticationState.denied
|
||||||
: AuthenticationState.installed;
|
: AuthenticationState.installed;
|
||||||
}
|
}
|
||||||
|
|
29
pubspec.lock
29
pubspec.lock
|
@ -399,10 +399,12 @@ packages:
|
||||||
flutter_secure_storage:
|
flutter_secure_storage:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_secure_storage
|
path: "."
|
||||||
url: "https://pub.dartlang.org"
|
ref: cake
|
||||||
source: hosted
|
resolved-ref: a734c2ea3239f9153dba6f5bec740e1df54ee754
|
||||||
version: "3.3.4"
|
url: "https://github.com/cake-tech/flutter_secure_storage.git"
|
||||||
|
source: git
|
||||||
|
version: "3.3.55"
|
||||||
flutter_slidable:
|
flutter_slidable:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -643,7 +645,7 @@ packages:
|
||||||
name: path_provider
|
name: path_provider
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.6.16"
|
version: "1.6.17"
|
||||||
path_provider_linux:
|
path_provider_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -671,7 +673,7 @@ packages:
|
||||||
name: path_provider_windows
|
name: path_provider_windows
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.0.3"
|
version: "0.0.4+1"
|
||||||
pedantic:
|
pedantic:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
|
@ -790,7 +792,7 @@ packages:
|
||||||
name: shared_preferences
|
name: shared_preferences
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.10"
|
version: "0.5.11"
|
||||||
shared_preferences_linux:
|
shared_preferences_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -819,6 +821,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.2+7"
|
version: "0.1.2+7"
|
||||||
|
shared_preferences_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_windows
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.0.1+1"
|
||||||
shelf:
|
shelf:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -851,7 +860,7 @@ packages:
|
||||||
name: source_gen
|
name: source_gen
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.9.6"
|
version: "0.9.7+1"
|
||||||
source_span:
|
source_span:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -928,7 +937,7 @@ packages:
|
||||||
name: url_launcher
|
name: url_launcher
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.6.0"
|
version: "5.7.0"
|
||||||
url_launcher_linux:
|
url_launcher_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -1022,4 +1031,4 @@ packages:
|
||||||
version: "2.2.1"
|
version: "2.2.1"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.9.0-14.0.dev <3.0.0"
|
dart: ">=2.9.0-14.0.dev <3.0.0"
|
||||||
flutter: ">=1.20.0 <2.0.0"
|
flutter: ">=1.12.13+hotfix.5 <2.0.0"
|
||||||
|
|
|
@ -27,7 +27,10 @@ dependencies:
|
||||||
qr: ^1.2.0
|
qr: ^1.2.0
|
||||||
uuid: 2.0.1
|
uuid: 2.0.1
|
||||||
shared_preferences: ^0.5.3+4
|
shared_preferences: ^0.5.3+4
|
||||||
flutter_secure_storage: ^3.2.1+1
|
flutter_secure_storage:
|
||||||
|
git:
|
||||||
|
url: https://github.com/cake-tech/flutter_secure_storage.git
|
||||||
|
ref: cake
|
||||||
provider: ^3.1.0
|
provider: ^3.1.0
|
||||||
rxdart: ^0.22.2
|
rxdart: ^0.22.2
|
||||||
yaml: ^2.1.16
|
yaml: ^2.1.16
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"salt": "",
|
"salt": "",
|
||||||
|
"keychainSalt": "",
|
||||||
"key": "",
|
"key": "",
|
||||||
"walletSalt": "",
|
"walletSalt": "",
|
||||||
"shortKey": "",
|
"shortKey": "",
|
||||||
|
|
|
@ -14,7 +14,7 @@ Future<void> main() async {
|
||||||
final inoutContent = File(inputPath).readAsStringSync();
|
final inoutContent = File(inputPath).readAsStringSync();
|
||||||
final config = json.decode(inoutContent) as Map<String, dynamic>;
|
final config = json.decode(inoutContent) as Map<String, dynamic>;
|
||||||
final output =
|
final output =
|
||||||
'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"]}\';';
|
'const salt = \'${config["salt"]}\';const keychainSalt = \'${config["keychainSalt"]}\';\nconst key = \'${config["key"]}\';\nconst walletSalt = \'${config["walletSalt"]}\';\nconst shortKey = \'${config["shortKey"]}\';\nconst change_now_api_key = \'${config["change_now_api_key"]}\';';
|
||||||
|
|
||||||
await File(outputPath).writeAsString(output);
|
await File(outputPath).writeAsString(output);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue