Support wallet api

This commit is contained in:
Peter 2019-10-29 23:28:56 +04:00
parent 149e41a23c
commit 901cc99042

View File

@ -281,32 +281,54 @@ private final class WalletStorageInterfaceImpl: WalletStorageInterface {
} }
} }
func customWalletConfiguration() -> Signal<CustomWalletConfiguration?, NoError> { func mergedLocalWalletConfiguration() -> Signal<MergedLocalWalletConfiguration, NoError> {
return self.configurationStorage.watch() return self.configurationStorage.watch()
|> map { data -> CustomWalletConfiguration? in |> map { data -> MergedLocalWalletConfiguration in
guard let data = data, !data.isEmpty else { guard let data = data, !data.isEmpty else {
return nil return .default
} }
do { do {
return try JSONDecoder().decode(CustomWalletConfiguration.self, from: data) return try JSONDecoder().decode(MergedLocalWalletConfiguration.self, from: data)
} catch let error { } catch let error {
print("Error deserializing data: \(error)") print("Error deserializing data: \(error)")
return nil return .default
} }
} }
} }
func updateCustomWalletConfiguration(_ value: CustomWalletConfiguration?) { func localWalletConfiguration() -> Signal<LocalWalletConfiguration, NoError> {
do { return self.mergedLocalWalletConfiguration()
if let value = value { |> mapToSignal { value -> Signal<LocalWalletConfiguration, NoError> in
let updatedData = try JSONEncoder().encode(value) return .single(value.configuration)
let _ = self.configurationStorage.set(data: updatedData).start() }
} else { |> distinctUntilChanged
let _ = self.configurationStorage.set(data: Data()).start() }
func updateMergedLocalWalletConfiguration(_ f: @escaping (MergedLocalWalletConfiguration) -> MergedLocalWalletConfiguration) -> Signal<Never, NoError> {
return self.configurationStorage.update { data -> (Data, Void) in
do {
let current: MergedLocalWalletConfiguration?
if let data = data, !data.isEmpty {
current = try? JSONDecoder().decode(MergedLocalWalletConfiguration.self, from: data)
} else {
current = nil
}
let updated = f(current ?? .default)
let updatedData = try JSONEncoder().encode(updated)
return (updatedData, Void())
} catch let error {
print("Error serializing data: \(error)")
return (Data(), Void())
} }
} catch let error { }
print("Error serializing data: \(error)") |> ignoreValues
let _ = self.configurationStorage.set(data: Data()).start() }
func updateLocalWalletConfiguration(_ f: @escaping (LocalWalletConfiguration) -> LocalWalletConfiguration) -> Signal<Never, NoError> {
return self.updateMergedLocalWalletConfiguration { value in
var value = value
value.configuration = f(value.configuration)
return value
} }
} }
} }
@ -319,6 +341,8 @@ private final class WalletContextImpl: NSObject, WalletContext, UIImagePickerCon
let window: Window1 let window: Window1
let supportsCustomConfigurations: Bool = true let supportsCustomConfigurations: Bool = true
let termsUrl: String? = nil
let feeInfoUrl: String? = nil
private var currentImagePickerCompletion: ((UIImage) -> Void)? private var currentImagePickerCompletion: ((UIImage) -> Void)?
@ -591,78 +615,63 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
print("Starting with \(documentsPath)") print("Starting with \(documentsPath)")
#endif #endif
let storage = WalletStorageInterfaceImpl(path: documentsPath + "/data", configurationPath: documentsPath + "/customConfiguration") let storage = WalletStorageInterfaceImpl(path: documentsPath + "/data", configurationPath: documentsPath + "/configuration")
let configSignal = downloadFile(url: URL(string: "https://test.ton.org/ton-lite-client-test1.config.json")!) let initialConfigValue = storage.mergedLocalWalletConfiguration()
|> mapToSignal { data -> Signal<String, DownloadFileError> in |> take(1)
if let string = String(data: data, encoding: .utf8) { |> mapToSignal { configuration -> Signal<(ResolvedLocalWalletConfiguration, String), NoError> in
return .single(string) if let resolved = configuration.resolved, resolved.source == configuration.configuration.source {
return .single((resolved, configuration.configuration.blockchainName))
} else { } else {
return .complete() return .complete()
} }
} }
|> retry(retryOnError: { error in
if case .network = error {
return true
} else {
return false
}
}, delayIncrement: 0.2, maxDelay: 5.0, maxRetries: 1000, onQueue: Queue.concurrentDefaultQueue())
|> `catch` { _ -> Signal<String, NoError> in
return .complete()
}
let updatedRemoteConfig = Promise<String>() let updatedConfigValue = storage.localWalletConfiguration()
updatedRemoteConfig.set(configSignal) |> mapToSignal { configuration -> Signal<(ResolvedLocalWalletConfiguration, String), NoError> in
switch configuration.source {
let configPath = documentsPath + "/config" case let .url(url):
var initialConfig: Signal<String, NoError> = .complete() guard let parsedUrl = URL(string: url) else {
if let data = try? Data(contentsOf: URL(fileURLWithPath: configPath)), let string = String(data: data, encoding: .utf8) { return .complete()
initialConfig = .single(string)
} else {
initialConfig = updatedRemoteConfig.get()
|> take(1)
|> beforeNext { config in
let _ = try? config.data(using: .utf8)?.write(to: URL(fileURLWithPath: configPath), options: .atomic)
}
}
let resolvedInitialConfig = combineLatest(queue: .mainQueue(),
initialConfig,
storage.customWalletConfiguration() |> take(1)
)
|> map { initialConfig, customConfig -> String in
if let customConfig = customConfig {
switch customConfig {
case let .string(string):
return string
} }
} else { return downloadFile(url: parsedUrl)
return initialConfig |> retry(1.0, maxDelay: 5.0, onQueue: .mainQueue())
|> mapToSignal { data -> Signal<(ResolvedLocalWalletConfiguration, String), NoError> in
if let string = String(data: data, encoding: .utf8) {
return .single((ResolvedLocalWalletConfiguration(source: configuration.source, value: string), configuration.blockchainName))
} else {
return .complete()
}
}
case let .string(string):
return .single((ResolvedLocalWalletConfiguration(source: configuration.source, value: string), configuration.blockchainName))
} }
} }
|> distinctUntilChanged(isEqual: { lhs, rhs in
return lhs.0 == rhs.0 && lhs.1 == rhs.1
})
|> afterNext { (resolved, _) in
let _ = storage.updateMergedLocalWalletConfiguration { current in
var current = current
current.resolved = resolved
return current
}
}
let resolvedInitialConfig = (
initialConfigValue
|> then(updatedConfigValue)
)
|> take(1)
let _ = (resolvedInitialConfig let _ = (resolvedInitialConfig
|> deliverOnMainQueue).start(next: { initialConfig in |> deliverOnMainQueue).start(next: { (initialResolvedConfig, initialConfigBlockchainName) in
let walletContext = WalletContextImpl(basePath: documentsPath, storage: storage, config: initialConfig, blockchainName: "testnet", navigationBarTheme: navigationBarTheme, window: mainWindow) let walletContext = WalletContextImpl(basePath: documentsPath, storage: storage, config: initialResolvedConfig.value, blockchainName: initialConfigBlockchainName, navigationBarTheme: navigationBarTheme, window: mainWindow)
self.walletContext = walletContext self.walletContext = walletContext
let _ = (combineLatest(queue: .mainQueue(), let _ = (updatedConfigValue
updatedRemoteConfig.get(), |> deliverOnMainQueue).start(next: { resolved, blockchainName in
storage.customWalletConfiguration() let _ = walletContext.tonInstance.updateConfig(config: resolved.value, blockchainName: blockchainName).start()
)
|> map { initialConfig, customConfig -> String in
if let customConfig = customConfig {
switch customConfig {
case let .string(string):
return string
}
} else {
return initialConfig
}
}
|> distinctUntilChanged).start(next: { config in
let _ = walletContext.tonInstance.updateConfig(config: config, blockchainName: "testnet").start()
}) })
let _ = (combineLatest(queue: .mainQueue(), let _ = (combineLatest(queue: .mainQueue(),
@ -739,3 +748,19 @@ private func downloadFile(url: URL) -> Signal<Data, DownloadFileError> {
} }
} }
} }
struct ResolvedLocalWalletConfiguration: Codable, Equatable {
var source: LocalWalletConfigurationSource
var value: String
}
struct MergedLocalWalletConfiguration: Codable, Equatable {
var configuration: LocalWalletConfiguration
var resolved: ResolvedLocalWalletConfiguration?
}
private extension MergedLocalWalletConfiguration {
static var `default`: MergedLocalWalletConfiguration {
return MergedLocalWalletConfiguration(configuration: LocalWalletConfiguration(source: .url("https://test.ton.org/config.json"), blockchainName: "testchain"), resolved: nil)
}
}