mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
Separate makefiles
This commit is contained in:
@@ -4,6 +4,8 @@ import SwiftSignalKit
|
||||
import BuildConfig
|
||||
import WalletUI
|
||||
import WalletCore
|
||||
import AVFoundation
|
||||
import MtProtoKit
|
||||
|
||||
private func encodeText(_ string: String, _ key: Int) -> String {
|
||||
var result = ""
|
||||
@@ -120,27 +122,173 @@ private class ApplicationStatusBarHost: StatusBarHost {
|
||||
}
|
||||
}
|
||||
|
||||
private let records = Atomic<[WalletStateRecord]>(value: [])
|
||||
|
||||
private final class WalletStorageInterfaceImpl: WalletStorageInterface {
|
||||
func watchWalletRecords() -> Signal<[WalletStateRecord], NoError> {
|
||||
return .single(records.with { $0 })
|
||||
private final class FileBackedStorageImpl {
|
||||
private let queue: Queue
|
||||
private let path: String
|
||||
private var data: Data?
|
||||
private var subscribers = Bag<(Data?) -> Void>()
|
||||
|
||||
init(queue: Queue, path: String) {
|
||||
self.queue = queue
|
||||
self.path = path
|
||||
}
|
||||
|
||||
func getWalletRecords() -> Signal<[WalletStateRecord], NoError> {
|
||||
return .single(records.with { $0 })
|
||||
func get() -> Data? {
|
||||
if let data = self.data {
|
||||
return data
|
||||
} else {
|
||||
self.data = try? Data(contentsOf: URL(fileURLWithPath: self.path))
|
||||
return self.data
|
||||
}
|
||||
}
|
||||
|
||||
func updateWalletRecords(_ f: @escaping ([WalletStateRecord]) -> [WalletStateRecord]) -> Signal<[WalletStateRecord], NoError> {
|
||||
return .single(records.modify(f))
|
||||
func set(data: Data) {
|
||||
self.data = data
|
||||
do {
|
||||
try data.write(to: URL(fileURLWithPath: self.path), options: .atomic)
|
||||
} catch let error {
|
||||
print("Error writng data: \(error)")
|
||||
}
|
||||
for f in self.subscribers.copyItems() {
|
||||
f(data)
|
||||
}
|
||||
}
|
||||
|
||||
func watch(_ f: @escaping (Data?) -> Void) -> Disposable {
|
||||
f(self.get())
|
||||
let index = self.subscribers.add(f)
|
||||
let queue = self.queue
|
||||
return ActionDisposable { [weak self] in
|
||||
queue.async {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.subscribers.remove(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class WalletContextImpl: WalletContext {
|
||||
private final class FileBackedStorage {
|
||||
private let queue = Queue()
|
||||
private let impl: QueueLocalObject<FileBackedStorageImpl>
|
||||
|
||||
init(path: String) {
|
||||
let queue = self.queue
|
||||
self.impl = QueueLocalObject(queue: queue, generate: {
|
||||
return FileBackedStorageImpl(queue: queue, path: path)
|
||||
})
|
||||
}
|
||||
|
||||
func get() -> Signal<Data?, NoError> {
|
||||
return Signal { subscriber in
|
||||
self.impl.with { impl in
|
||||
subscriber.putNext(impl.get())
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
return EmptyDisposable
|
||||
}
|
||||
}
|
||||
|
||||
func set(data: Data) -> Signal<Never, NoError> {
|
||||
return Signal { subscriber in
|
||||
self.impl.with { impl in
|
||||
impl.set(data: data)
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
return EmptyDisposable
|
||||
}
|
||||
}
|
||||
|
||||
func update<T>(_ f: @escaping (Data?) -> (Data, T)) -> Signal<T, NoError> {
|
||||
return Signal { subscriber in
|
||||
self.impl.with { impl in
|
||||
let (data, result) = f(impl.get())
|
||||
impl.set(data: data)
|
||||
subscriber.putNext(result)
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
return EmptyDisposable
|
||||
}
|
||||
}
|
||||
|
||||
func watch() -> Signal<Data?, NoError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
self.impl.with { impl in
|
||||
disposable.set(impl.watch({ data in
|
||||
subscriber.putNext(data)
|
||||
}))
|
||||
}
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let records = Atomic<[WalletStateRecord]>(value: [])
|
||||
|
||||
private final class WalletStorageInterfaceImpl: WalletStorageInterface {
|
||||
private let storage: FileBackedStorage
|
||||
|
||||
init(path: String) {
|
||||
self.storage = FileBackedStorage(path: path)
|
||||
}
|
||||
|
||||
func watchWalletRecords() -> Signal<[WalletStateRecord], NoError> {
|
||||
return self.storage.watch()
|
||||
|> map { data -> [WalletStateRecord] in
|
||||
guard let data = data else {
|
||||
return []
|
||||
}
|
||||
do {
|
||||
return try JSONDecoder().decode(Array<WalletStateRecord>.self, from: data)
|
||||
} catch let error {
|
||||
print("Error deserializing data: \(error)")
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getWalletRecords() -> Signal<[WalletStateRecord], NoError> {
|
||||
return self.storage.get()
|
||||
|> map { data -> [WalletStateRecord] in
|
||||
guard let data = data else {
|
||||
return []
|
||||
}
|
||||
do {
|
||||
return try JSONDecoder().decode(Array<WalletStateRecord>.self, from: data)
|
||||
} catch let error {
|
||||
print("Error deserializing data: \(error)")
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateWalletRecords(_ f: @escaping ([WalletStateRecord]) -> [WalletStateRecord]) -> Signal<[WalletStateRecord], NoError> {
|
||||
return self.storage.update { data -> (Data, [WalletStateRecord]) in
|
||||
let records: [WalletStateRecord] = data.flatMap {
|
||||
try? JSONDecoder().decode(Array<WalletStateRecord>.self, from: $0)
|
||||
} ?? []
|
||||
let updatedRecords = f(records)
|
||||
do {
|
||||
let updatedData = try JSONEncoder().encode(updatedRecords)
|
||||
return (updatedData, updatedRecords)
|
||||
} catch let error {
|
||||
print("Error serializing data: \(error)")
|
||||
return (Data(), updatedRecords)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class WalletContextImpl: NSObject, WalletContext, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
|
||||
let storage: WalletStorageInterface
|
||||
let tonInstance: TonInstance
|
||||
let keychain: TonKeychain
|
||||
let presentationData: WalletPresentationData
|
||||
let window: Window1
|
||||
|
||||
private var currentImagePickerCompletion: ((UIImage) -> Void)?
|
||||
|
||||
var inForeground: Signal<Bool, NoError> {
|
||||
return .single(true)
|
||||
@@ -151,7 +299,7 @@ private final class WalletContextImpl: WalletContext {
|
||||
}
|
||||
|
||||
func presentNativeController(_ controller: UIViewController) {
|
||||
|
||||
self.window.presentNative(controller)
|
||||
}
|
||||
|
||||
func idleTimerExtension() -> Disposable {
|
||||
@@ -159,32 +307,75 @@ private final class WalletContextImpl: WalletContext {
|
||||
}
|
||||
|
||||
func openUrl(_ url: String) {
|
||||
|
||||
if let parsedUrl = URL(string: url) {
|
||||
UIApplication.shared.openURL(parsedUrl)
|
||||
}
|
||||
}
|
||||
|
||||
func shareUrl(_ url: String) {
|
||||
|
||||
if let parsedUrl = URL(string: url) {
|
||||
self.presentNativeController(UIActivityViewController(activityItems: [parsedUrl], applicationActivities: nil))
|
||||
}
|
||||
}
|
||||
|
||||
func openPlatformSettings() {
|
||||
|
||||
if let url = URL(string: UIApplication.openSettingsURLString) {
|
||||
UIApplication.shared.openURL(url)
|
||||
}
|
||||
}
|
||||
|
||||
func authorizeAccessToCamera(completion: @escaping () -> Void) {
|
||||
completion()
|
||||
AVCaptureDevice.requestAccess(for: AVMediaType.video) { response in
|
||||
Queue.mainQueue().async {
|
||||
if response {
|
||||
completion()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func pickImage(completion: @escaping (UIImage) -> Void) {
|
||||
self.currentImagePickerCompletion = completion
|
||||
|
||||
let pickerController = UIImagePickerController()
|
||||
pickerController.delegate = self
|
||||
pickerController.allowsEditing = false
|
||||
pickerController.mediaTypes = ["public.image"]
|
||||
pickerController.sourceType = .photoLibrary
|
||||
self.presentNativeController(pickerController)
|
||||
}
|
||||
|
||||
init(basePath: String, config: String, blockchainName: String, navigationBarTheme: NavigationBarTheme) {
|
||||
self.storage = WalletStorageInterfaceImpl()
|
||||
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
|
||||
let currentImagePickerCompletion = self.currentImagePickerCompletion
|
||||
self.currentImagePickerCompletion = nil
|
||||
if let image = info[.editedImage] as? UIImage {
|
||||
currentImagePickerCompletion?(image)
|
||||
} else if let image = info[.originalImage] as? UIImage {
|
||||
currentImagePickerCompletion?(image)
|
||||
}
|
||||
picker.presentingViewController?.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
|
||||
self.currentImagePickerCompletion = nil
|
||||
picker.presentingViewController?.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
init(basePath: String, config: String, blockchainName: String, navigationBarTheme: NavigationBarTheme, window: Window1) {
|
||||
let _ = try? FileManager.default.createDirectory(at: URL(fileURLWithPath: basePath + "/keys"), withIntermediateDirectories: true, attributes: nil)
|
||||
|
||||
self.storage = WalletStorageInterfaceImpl(path: basePath + "/data")
|
||||
self.window = window
|
||||
self.tonInstance = TonInstance(
|
||||
basePath: basePath,
|
||||
basePath: basePath + "/keys",
|
||||
config: config,
|
||||
blockchainName: blockchainName,
|
||||
proxy: nil
|
||||
proxy: nil /*TonProxyImpl()*/
|
||||
)
|
||||
|
||||
let baseAppBundleId = Bundle.main.bundleIdentifier!
|
||||
|
||||
#if targetEnvironment(simulator)
|
||||
self.keychain = TonKeychain(encryptionPublicKey: {
|
||||
return .single(Data())
|
||||
}, encrypt: { data in
|
||||
@@ -192,6 +383,47 @@ private final class WalletContextImpl: WalletContext {
|
||||
}, decrypt: { data in
|
||||
return .single(data.data)
|
||||
})
|
||||
#else
|
||||
self.keychain = TonKeychain(encryptionPublicKey: {
|
||||
return Signal { subscriber in
|
||||
BuildConfig.getHardwareEncryptionAvailable(withBaseAppBundleId: baseAppBundleId, completion: { value in
|
||||
subscriber.putNext(value)
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
return EmptyDisposable
|
||||
}
|
||||
}, encrypt: { data in
|
||||
return Signal { subscriber in
|
||||
BuildConfig.encryptApplicationSecret(data, baseAppBundleId: baseAppBundleId, completion: { result, publicKey in
|
||||
if let result = result, let publicKey = publicKey {
|
||||
subscriber.putNext(TonKeychainEncryptedData(publicKey: publicKey, data: result))
|
||||
subscriber.putCompletion()
|
||||
} else {
|
||||
subscriber.putError(.generic)
|
||||
}
|
||||
})
|
||||
return EmptyDisposable
|
||||
}
|
||||
}, decrypt: { encryptedData in
|
||||
return Signal { subscriber in
|
||||
BuildConfig.decryptApplicationSecret(encryptedData.data, publicKey: encryptedData.publicKey, baseAppBundleId: baseAppBundleId, completion: { result, cancelled in
|
||||
if let result = result {
|
||||
subscriber.putNext(result)
|
||||
} else {
|
||||
let error: TonKeychainDecryptDataError
|
||||
if cancelled {
|
||||
error = .cancelled
|
||||
} else {
|
||||
error = .generic
|
||||
}
|
||||
subscriber.putError(error)
|
||||
}
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
return EmptyDisposable
|
||||
}
|
||||
})
|
||||
#endif
|
||||
let accentColor = UIColor(rgb: 0x007ee5)
|
||||
self.presentationData = WalletPresentationData(
|
||||
theme: WalletTheme(
|
||||
@@ -271,6 +503,8 @@ private final class WalletContextImpl: WalletContext {
|
||||
groupingSeparator: " "
|
||||
)
|
||||
)
|
||||
|
||||
super.init()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,18 +518,20 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
||||
let statusBarHost = ApplicationStatusBarHost()
|
||||
let (window, hostView) = nativeWindowHostView()
|
||||
self.mainWindow = Window1(hostView: hostView, statusBarHost: statusBarHost)
|
||||
let mainWindow = Window1(hostView: hostView, statusBarHost: statusBarHost)
|
||||
self.mainWindow = mainWindow
|
||||
hostView.containerView.backgroundColor = UIColor.white
|
||||
self.window = window
|
||||
|
||||
let accentColor = UIColor(rgb: 0x007ee5)
|
||||
let navigationBarTheme = NavigationBarTheme(
|
||||
buttonColor: .blue,
|
||||
disabledButtonColor: .gray,
|
||||
buttonColor: accentColor,
|
||||
disabledButtonColor: UIColor(rgb: 0xd0d0d0),
|
||||
primaryTextColor: .black,
|
||||
backgroundColor: .lightGray,
|
||||
separatorColor: .black,
|
||||
badgeBackgroundColor: .red,
|
||||
badgeStrokeColor: .red,
|
||||
backgroundColor: UIColor(rgb: 0xf7f7f7),
|
||||
separatorColor: UIColor(rgb: 0xb1b1b1),
|
||||
badgeBackgroundColor: UIColor(rgb: 0xff3b30),
|
||||
badgeStrokeColor: UIColor(rgb: 0xff3b30),
|
||||
badgeTextColor: .white
|
||||
)
|
||||
|
||||
@@ -309,6 +545,7 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
|
||||
)
|
||||
|
||||
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
|
||||
print("Starting with \(documentsPath)")
|
||||
|
||||
let config =
|
||||
"""
|
||||
@@ -336,16 +573,230 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
|
||||
}
|
||||
"""
|
||||
|
||||
let walletContext = WalletContextImpl(basePath: documentsPath, config: config, blockchainName: "testnet", navigationBarTheme: navigationBarTheme)
|
||||
let walletContext = WalletContextImpl(basePath: documentsPath, config: config, blockchainName: "testnet", navigationBarTheme: navigationBarTheme, window: mainWindow)
|
||||
self.walletContext = walletContext
|
||||
|
||||
let splashScreen = WalletSplashScreen(context: walletContext, mode: .intro, walletCreatedPreloadState: nil)
|
||||
|
||||
navigationController.setViewControllers([splashScreen], animated: false)
|
||||
self.mainWindow?.viewController = navigationController
|
||||
let _ = (combineLatest(queue: .mainQueue(),
|
||||
walletContext.storage.getWalletRecords(),
|
||||
walletContext.keychain.encryptionPublicKey()
|
||||
)
|
||||
|> deliverOnMainQueue).start(next: { records, publicKey in
|
||||
if let record = records.first {
|
||||
if let publicKey = publicKey {
|
||||
print("publicKey = \(publicKey.base64EncodedString())")
|
||||
if record.info.encryptedSecret.publicKey == publicKey {
|
||||
if record.exportCompleted {
|
||||
let _ = (walletAddress(publicKey: record.info.publicKey, tonInstance: walletContext.tonInstance)
|
||||
|> deliverOnMainQueue).start(next: { address in
|
||||
let infoScreen = WalletInfoScreen(context: walletContext, walletInfo: record.info, address: address, enableDebugActions: false)
|
||||
|
||||
navigationController.setViewControllers([infoScreen], animated: false)
|
||||
})
|
||||
} else {
|
||||
let createdScreen = WalletSplashScreen(context: walletContext, mode: .created(record.info, nil), walletCreatedPreloadState: nil)
|
||||
|
||||
navigationController.setViewControllers([createdScreen], animated: false)
|
||||
}
|
||||
} else {
|
||||
let splashScreen = WalletSplashScreen(context: walletContext, mode: .secureStorageReset(.changed), walletCreatedPreloadState: nil)
|
||||
|
||||
navigationController.setViewControllers([splashScreen], animated: false)
|
||||
}
|
||||
} else {
|
||||
let splashScreen = WalletSplashScreen(context: walletContext, mode: WalletSplashMode.secureStorageReset(.notAvailable), walletCreatedPreloadState: nil)
|
||||
|
||||
navigationController.setViewControllers([splashScreen], animated: false)
|
||||
}
|
||||
} else {
|
||||
if publicKey != nil {
|
||||
let splashScreen = WalletSplashScreen(context: walletContext, mode: .intro, walletCreatedPreloadState: nil)
|
||||
|
||||
navigationController.setViewControllers([splashScreen], animated: false)
|
||||
} else {
|
||||
let splashScreen = WalletSplashScreen(context: walletContext, mode: .secureStorageNotAvailable, walletCreatedPreloadState: nil)
|
||||
|
||||
navigationController.setViewControllers([splashScreen], animated: false)
|
||||
}
|
||||
}
|
||||
})
|
||||
mainWindow.viewController = navigationController
|
||||
|
||||
self.window?.makeKeyAndVisible()
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private final class Serialization: NSObject, MTSerialization {
|
||||
func currentLayer() -> UInt {
|
||||
return 106
|
||||
}
|
||||
|
||||
func parseMessage(_ data: Data!) -> Any! {
|
||||
return nil
|
||||
}
|
||||
|
||||
func exportAuthorization(_ datacenterId: Int32, data: AutoreleasingUnsafeMutablePointer<NSData?>!) -> MTExportAuthorizationResponseParser! {
|
||||
return nil
|
||||
}
|
||||
|
||||
func importAuthorization(_ authId: Int32, bytes: Data!) -> Data! {
|
||||
return Data()
|
||||
}
|
||||
|
||||
func requestDatacenterAddress(with data: AutoreleasingUnsafeMutablePointer<NSData?>!) -> MTRequestDatacenterAddressListParser! {
|
||||
return { _ in
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func requestNoop(_ data: AutoreleasingUnsafeMutablePointer<NSData?>!) -> MTRequestNoopParser! {
|
||||
return { _ in
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class Keychain: NSObject, MTKeychain {
|
||||
let get: (String) -> Data?
|
||||
let set: (String, Data) -> Void
|
||||
let remove: (String) -> Void
|
||||
|
||||
init(get: @escaping (String) -> Data?, set: @escaping (String, Data) -> Void, remove: @escaping (String) -> Void) {
|
||||
self.get = get
|
||||
self.set = set
|
||||
self.remove = remove
|
||||
}
|
||||
|
||||
func setObject(_ object: Any!, forKey aKey: String!, group: String!) {
|
||||
if let object = object {
|
||||
let data = NSKeyedArchiver.archivedData(withRootObject: object)
|
||||
self.set(group + ":" + aKey, data)
|
||||
} else {
|
||||
self.remove(group + ":" + aKey)
|
||||
}
|
||||
}
|
||||
|
||||
func object(forKey aKey: String!, group: String!) -> Any! {
|
||||
if let data = self.get(group + ":" + aKey) {
|
||||
return NSKeyedUnarchiver.unarchiveObject(with: data as Data)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeObject(forKey aKey: String!, group: String!) {
|
||||
self.remove(group + ":" + aKey)
|
||||
}
|
||||
|
||||
func dropGroup(_ group: String!) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private final class TonProxyImpl: TonNetworkProxy {
|
||||
private let context: MTContext
|
||||
private let mtProto: MTProto
|
||||
private let requestService: MTRequestMessageService
|
||||
|
||||
init() {
|
||||
let serialization = Serialization()
|
||||
|
||||
var apiEnvironment = MTApiEnvironment()
|
||||
|
||||
apiEnvironment.apiId = 8
|
||||
apiEnvironment.langPack = "ios"
|
||||
apiEnvironment.layer = serialization.currentLayer() as NSNumber
|
||||
apiEnvironment.disableUpdates = true
|
||||
apiEnvironment = apiEnvironment.withUpdatedLangPackCode("en")
|
||||
|
||||
self.context = MTContext(serialization: serialization, apiEnvironment: apiEnvironment, isTestingEnvironment: false, useTempAuthKeys: false)
|
||||
|
||||
let seedAddressList: [Int: [String]]
|
||||
|
||||
seedAddressList = [
|
||||
1: ["149.154.175.50", "2001:b28:f23d:f001::a"],
|
||||
2: ["149.154.167.50", "2001:67c:4e8:f002::a"],
|
||||
3: ["149.154.175.100", "2001:b28:f23d:f003::a"],
|
||||
4: ["149.154.167.91", "2001:67c:4e8:f004::a"],
|
||||
5: ["149.154.171.5", "2001:b28:f23f:f005::a"]
|
||||
]
|
||||
|
||||
for (id, ips) in seedAddressList {
|
||||
self.context.setSeedAddressSetForDatacenterWithId(id, seedAddressSet: MTDatacenterAddressSet(addressList: ips.map { MTDatacenterAddress(ip: $0, port: 443, preferForMedia: false, restrictToTcp: false, cdn: false, preferForProxy: false, secret: nil)! }))
|
||||
}
|
||||
|
||||
let keychainDict = Atomic<[String: Data]>(value: [:])
|
||||
self.context.keychain = Keychain(get: { key in
|
||||
return keychainDict.with { dict -> Data? in
|
||||
return dict[key]
|
||||
}
|
||||
}, set: { key, value in
|
||||
let _ = keychainDict.modify { dict in
|
||||
var dict = dict
|
||||
dict[key] = value
|
||||
return dict
|
||||
}
|
||||
}, remove: { key in
|
||||
let _ = keychainDict.modify { dict in
|
||||
var dict = dict
|
||||
dict.removeValue(forKey: key)
|
||||
return dict
|
||||
}
|
||||
})
|
||||
|
||||
let mtProto = MTProto(context: self.context, datacenterId: 2, usageCalculationInfo: nil)!
|
||||
mtProto.useTempAuthKeys = self.context.useTempAuthKeys
|
||||
mtProto.checkForProxyConnectionIssues = false
|
||||
|
||||
self.mtProto = mtProto
|
||||
|
||||
self.requestService = MTRequestMessageService(context: context)!
|
||||
mtProto.add(self.requestService)
|
||||
|
||||
self.mtProto.resume()
|
||||
}
|
||||
|
||||
func request(data: Data, timeout: Double, completion: @escaping (TonNetworkProxyResult) -> Void) -> Disposable {
|
||||
let request = MTRequest()
|
||||
let outputStream = MTOutputStream()
|
||||
|
||||
//wallet.sendLiteRequest#e2c9d33e body:bytes = wallet.LiteResponse;
|
||||
outputStream.write(Int32(bitPattern: 0xe2c9d33e as UInt32))
|
||||
outputStream.writeBytes(data)
|
||||
|
||||
request.setPayload(outputStream.currentBytes(), metadata: "wallet.sendLiteRequest", shortMetadata: "wallet.sendLiteRequest", responseParser: { response in
|
||||
guard let response = response else {
|
||||
return nil
|
||||
}
|
||||
let inputStream = MTInputStream(data: response)!
|
||||
//wallet.liteResponse#764386d7 response:bytes = wallet.LiteResponse;
|
||||
let signature = inputStream.readInt32()
|
||||
if (signature != 0x764386d7 as Int32) {
|
||||
return nil
|
||||
}
|
||||
return inputStream.readBytes()
|
||||
})
|
||||
|
||||
request.dependsOnPasswordEntry = false
|
||||
request.shouldContinueExecutionWithErrorContext = { _ in
|
||||
return true
|
||||
};
|
||||
|
||||
request.completed = { response, _, error in
|
||||
if let response = response as? Data {
|
||||
completion(.reponse(response))
|
||||
} else {
|
||||
completion(.error(error?.errorDescription ?? "UNKNOWN ERROR"))
|
||||
}
|
||||
}
|
||||
|
||||
let requestId = request.internalId
|
||||
|
||||
self.requestService.add(request)
|
||||
|
||||
return ActionDisposable { [weak self] in
|
||||
self?.requestService.removeRequest(byInternalId: requestId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user