From c4a914156a783b21b560b317ead14ba64ee9507c Mon Sep 17 00:00:00 2001 From: Czino Date: Thu, 18 Jan 2024 16:21:43 +0100 Subject: [PATCH 1/3] Ensure sync is not render blocking --- ios/BdkRnModule.swift | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/ios/BdkRnModule.swift b/ios/BdkRnModule.swift index 28630f8..45c8b9e 100644 --- a/ios/BdkRnModule.swift +++ b/ios/BdkRnModule.swift @@ -522,12 +522,16 @@ class BdkRnModule: NSObject { resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock ) { - DispatchQueue.main.async { [self] in + DispatchQueue.global().async { [self] in do { try getWalletById(id: id).sync(blockchain: self.getBlockchainById(id: blockChainId), progress: BdkProgress()) - resolve(true) + DispatchQueue.main.async { + resolve(true) + } } catch { - reject("Sync wallet error", "\(error)", error) + DispatchQueue.main.async { + reject("Sync wallet error", "\(error)", error) + } } } } @@ -540,17 +544,15 @@ class BdkRnModule: NSObject { resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock ) { - DispatchQueue.main.async { [self] in - do { - let addressInfo = try getWalletById(id: id).getAddress( - addressIndex: setAddressIndex(addressIndex: addressIndex) - ) - let randomId = randomId() - _addresses[randomId] = addressInfo.address - resolve(["index": addressInfo.index, "address": randomId, "keychain": "\(addressInfo.keychain)"] as [String: Any]) - } catch let error { - reject("Get wallet address error", "\(error)", error) - } + do { + let addressInfo = try getWalletById(id: id).getAddress( + addressIndex: setAddressIndex(addressIndex: addressIndex) + ) + let randomId = randomId() + _addresses[randomId] = addressInfo.address + resolve(["index": addressInfo.index, "address": randomId, "keychain": "\(addressInfo.keychain)"] as [String: Any]) + } catch let error { + reject("Get wallet address error", "\(error)", error) } } From d63e3070962aecbfea8637f337e03f426d58663a Mon Sep 17 00:00:00 2001 From: Czino Date: Mon, 29 Jan 2024 10:59:20 +0100 Subject: [PATCH 2/3] Fix initWallet error --- .../main/java/io/ltbl/bdkrn/BdkRnModule.kt | 226 ++++++++---------- 1 file changed, 97 insertions(+), 129 deletions(-) diff --git a/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt b/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt index dd4d688..6331c2c 100644 --- a/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt +++ b/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt @@ -38,49 +38,41 @@ class BdkRnModule(reactContext: ReactApplicationContext) : /** Mnemonic methods starts */ @ReactMethod fun generateSeedFromWordCount(wordCount: Int, result: Promise) { - Thread { - val response = Mnemonic(setWordCount(wordCount)) - result.resolve(response.asString()) - }.start() + val response = Mnemonic(setWordCount(wordCount)) + result.resolve(response.asString()) } @ReactMethod fun generateSeedFromString(mnemonic: String, result: Promise) { - Thread { - try { - val response = Mnemonic.fromString(mnemonic) - result.resolve(response.asString()) - } catch (error: Throwable) { - result.reject("Generate seed error", error.localizedMessage, error) - } - }.start() + try { + val response = Mnemonic.fromString(mnemonic) + result.resolve(response.asString()) + } catch (error: Throwable) { + result.reject("Generate seed error", error.localizedMessage, error) + } } @ReactMethod fun generateSeedFromEntropy(entropy: ReadableArray, result: Promise) { - Thread { - try { - val response = Mnemonic.fromEntropy(getEntropy(entropy)) - result.resolve(response.asString()) - } catch (error: Throwable) { - result.reject("Generate seed error", error.localizedMessage, error) - } - }.start() + try { + val response = Mnemonic.fromEntropy(getEntropy(entropy)) + result.resolve(response.asString()) + } catch (error: Throwable) { + result.reject("Generate seed error", error.localizedMessage, error) + } } /** Mnemonic methods ends */ /** Derviation path methods starts */ @ReactMethod fun createDerivationPath(path: String, result: Promise) { - Thread { - try { - val id = randomId() - _derivationPaths[id] = DerivationPath(path) - result.resolve(id) - } catch (error: Throwable) { - result.reject("Create Derivation path error", error.localizedMessage, error) - } - }.start() + try { + val id = randomId() + _derivationPaths[id] = DerivationPath(path) + result.resolve(id) + } catch (error: Throwable) { + result.reject("Create Derivation path error", error.localizedMessage, error) + } } /** Derviation path methods ends */ @@ -89,118 +81,98 @@ class BdkRnModule(reactContext: ReactApplicationContext) : fun createDescriptorSecret( network: String, mnemonic: String, password: String? = null, result: Promise ) { - Thread { - try { - val id = randomId() - _descriptorSecretKeys[id] = - DescriptorSecretKey( - setNetwork(network), - Mnemonic.fromString(mnemonic), - password - ) - result.resolve(id) - } catch (error: Throwable) { - result.reject("DescriptorSecret create error", error.localizedMessage, error) - } - }.start() + try { + val id = randomId() + _descriptorSecretKeys[id] = + DescriptorSecretKey( + setNetwork(network), + Mnemonic.fromString(mnemonic), + password + ) + result.resolve(id) + } catch (error: Throwable) { + result.reject("DescriptorSecret create error", error.localizedMessage, error) + } } @ReactMethod fun descriptorSecretDerive(secretKeyId: String, derivationPathId: String, result: Promise) { - Thread { - try { - val keyInfo = - _descriptorSecretKeys[secretKeyId]!!.derive(_derivationPaths[derivationPathId]!!) - result.resolve(keyInfo.asString()) - } catch (error: Throwable) { - result.reject("DescriptorSecret derive error", error.localizedMessage, error) - } - }.start() + try { + val keyInfo = + _descriptorSecretKeys[secretKeyId]!!.derive(_derivationPaths[derivationPathId]!!) + result.resolve(keyInfo.asString()) + } catch (error: Throwable) { + result.reject("DescriptorSecret derive error", error.localizedMessage, error) + } } @ReactMethod fun descriptorSecretExtend(secretKeyId: String, derivationPathId: String, result: Promise) { - Thread { - try { - val keyInfo = - _descriptorSecretKeys[secretKeyId]!!.extend(_derivationPaths[derivationPathId]!!) - result.resolve(keyInfo.asString()) - } catch (error: Throwable) { - result.reject("DescriptorSecret extend error", error.localizedMessage, error) - } - }.start() + try { + val keyInfo = + _descriptorSecretKeys[secretKeyId]!!.extend(_derivationPaths[derivationPathId]!!) + result.resolve(keyInfo.asString()) + } catch (error: Throwable) { + result.reject("DescriptorSecret extend error", error.localizedMessage, error) + } } @ReactMethod fun descriptorSecretAsPublic(secretKeyId: String, result: Promise) { - Thread { - val id = randomId() - _descriptorPublicKeys[id] = _descriptorSecretKeys[secretKeyId]!!.asPublic() - result.resolve(id) - }.start() + val id = randomId() + _descriptorPublicKeys[id] = _descriptorSecretKeys[secretKeyId]!!.asPublic() + result.resolve(id) } @ReactMethod fun descriptorSecretAsString(secretKeyId: String, result: Promise) { - Thread { - result.resolve(_descriptorSecretKeys[secretKeyId]!!.asString()) - }.start() + result.resolve(_descriptorSecretKeys[secretKeyId]!!.asString()) } @ReactMethod fun descriptorSecretAsSecretBytes(secretKeyId: String, result: Promise) { - Thread { - val secretBytes = _descriptorSecretKeys[secretKeyId]!!.secretBytes() - result.resolve(makeNativeArray(secretBytes)) - }.start() + val secretBytes = _descriptorSecretKeys[secretKeyId]!!.secretBytes() + result.resolve(makeNativeArray(secretBytes)) } /** Descriptor secret key methods ends */ /** Descriptor public key methods starts */ @ReactMethod fun createDescriptorPublic(publicKey: String, result: Promise) { - Thread { - try { - val id = randomId() - _descriptorPublicKeys[id] = DescriptorPublicKey.fromString(publicKey) - result.resolve(id) - } catch (error: Throwable) { - result.reject("DescriptorPublic create error", error.localizedMessage, error) - } - }.start() + try { + val id = randomId() + _descriptorPublicKeys[id] = DescriptorPublicKey.fromString(publicKey) + result.resolve(id) + } catch (error: Throwable) { + result.reject("DescriptorPublic create error", error.localizedMessage, error) + } } @ReactMethod fun descriptorPublicDerive(publicKeyId: String, derivationPathId: String, result: Promise) { - Thread { - try { - val keyInfo = - _descriptorPublicKeys[publicKeyId]!!.derive(_derivationPaths[derivationPathId]!!) - result.resolve(keyInfo.asString()) - } catch (error: Throwable) { - result.reject("DescriptorPublic derive error", error.localizedMessage, error) - } - }.start() + try { + val keyInfo = + _descriptorPublicKeys[publicKeyId]!!.derive(_derivationPaths[derivationPathId]!!) + result.resolve(keyInfo.asString()) + } catch (error: Throwable) { + result.reject("DescriptorPublic derive error", error.localizedMessage, error) + } } @ReactMethod fun descriptorPublicExtend(publicKeyId: String, derivationPathId: String, result: Promise) { - Thread { - try { - val keyInfo = - _descriptorPublicKeys[publicKeyId]!!.extend(_derivationPaths[derivationPathId]!!) - result.resolve(keyInfo.asString()) - } catch (error: Throwable) { - result.reject("DescriptorPublic extend error", error.localizedMessage, error) - } - }.start() + try { + val keyInfo = + _descriptorPublicKeys[publicKeyId]!!.extend(_derivationPaths[derivationPathId]!!) + result.resolve(keyInfo.asString()) + } catch (error: Throwable) { + result.reject("DescriptorPublic extend error", error.localizedMessage, error) + } } @ReactMethod fun descriptorPublicAsString(publicKeyId: String, result: Promise) { - Thread { - result.resolve(_descriptorPublicKeys[publicKeyId]!!.asString()) - }.start() + result.resolve(_descriptorPublicKeys[publicKeyId]!!.asString()) } /** Descriptor public key methods ends */ @@ -974,19 +946,17 @@ class BdkRnModule(reactContext: ReactApplicationContext) : @ReactMethod fun newBip84(secretKeyId: String, keychain: String, network: String, result: Promise) { - Thread { - try { - val id = randomId() - _descriptors[id] = newBip84( - _descriptorSecretKeys[secretKeyId]!!, - setKeychainKind(keychain), - setNetwork(network) - ) - result.resolve(id) - } catch (error: Throwable) { - result.reject("Create bip84 error", error.localizedMessage, error) + try { + val id = randomId() + _descriptors[id] = newBip84( + _descriptorSecretKeys[secretKeyId]!!, + setKeychainKind(keychain), + setNetwork(network) + ) + result.resolve(id) + } catch (error: Throwable) { + result.reject("Create bip84 error", error.localizedMessage, error) } - }.start() } @ReactMethod @@ -997,20 +967,18 @@ class BdkRnModule(reactContext: ReactApplicationContext) : network: String, result: Promise ) { - Thread { - try { - val id = randomId() - _descriptors[id] = newBip84Public( - _descriptorPublicKeys[publicKeyId]!!, - fingerprint, - setKeychainKind(keychain), - setNetwork(network) - ) - result.resolve(id) - } catch (error: Throwable) { - result.reject("Create bip84Public error", error.localizedMessage, error) - } - }.start() + try { + val id = randomId() + _descriptors[id] = newBip84Public( + _descriptorPublicKeys[publicKeyId]!!, + fingerprint, + setKeychainKind(keychain), + setNetwork(network) + ) + result.resolve(id) + } catch (error: Throwable) { + result.reject("Create bip84Public error", error.localizedMessage, error) + } } @ReactMethod From 780e69eda84660b16f8d8ee449b787dc7442eadb Mon Sep 17 00:00:00 2001 From: Czino Date: Fri, 9 Feb 2024 11:20:59 +0100 Subject: [PATCH 3/3] Move initialization out of separate threads --- .../main/java/io/ltbl/bdkrn/BdkRnModule.kt | 140 +++++++++--------- 1 file changed, 67 insertions(+), 73 deletions(-) diff --git a/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt b/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt index 6331c2c..0bce915 100644 --- a/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt +++ b/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt @@ -192,25 +192,23 @@ class BdkRnModule(reactContext: ReactApplicationContext) : validateDomain: Boolean, result: Promise ) { - Thread { - try { - val _blockchainConfig = BlockchainConfig.Electrum( - ElectrumConfig( - url, - sock5 ?: null, - retry.toUByte(), - timeout.toUByte(), - stopGap.toULong(), - validateDomain - ) + try { + val _blockchainConfig = BlockchainConfig.Electrum( + ElectrumConfig( + url, + sock5 ?: null, + retry.toUByte(), + timeout.toUByte(), + stopGap.toULong(), + validateDomain ) - val blockChainId = randomId() - _blockChains[blockChainId] = Blockchain(_blockchainConfig) - result.resolve(blockChainId) - } catch (error: Throwable) { - result.reject("BlockchainElectrum init error", error.localizedMessage, error) - } - }.start() + ) + val blockChainId = randomId() + _blockChains[blockChainId] = Blockchain(_blockchainConfig) + result.resolve(blockChainId) + } catch (error: Throwable) { + result.reject("BlockchainElectrum init error", error.localizedMessage, error) + } } @@ -223,69 +221,65 @@ class BdkRnModule(reactContext: ReactApplicationContext) : timeout: Int, result: Promise ) { - Thread { - try { - val _blockchainConfig = BlockchainConfig.Esplora( - EsploraConfig( - baseUrl, - proxy ?: null, - concurrency.toUByte(), - stopGap.toULong(), - timeout.toULong(), - ) + try { + val _blockchainConfig = BlockchainConfig.Esplora( + EsploraConfig( + baseUrl, + proxy ?: null, + concurrency.toUByte(), + stopGap.toULong(), + timeout.toULong(), ) - val blockChainId = randomId() - _blockChains[blockChainId] = Blockchain(_blockchainConfig) - result.resolve(blockChainId) - } catch (error: Throwable) { - result.reject("BlockchainEsplora init error", error.localizedMessage, error) - } - }.start() + ) + val blockChainId = randomId() + _blockChains[blockChainId] = Blockchain(_blockchainConfig) + result.resolve(blockChainId) + } catch (error: Throwable) { + result.reject("BlockchainEsplora init error", error.localizedMessage, error) + } } @ReactMethod fun initRpcBlockchain(config: ReadableMap, result: Promise) { - Thread { - try { - var authType: Auth = Auth.None - if (config.getString("authCookie") != null) { - authType = Auth.Cookie(config.getString("authCookie")!!) - } - - if (config.getMap("authUserPass") != null) { - val userPass = config.getMap("authUserPass") as ReadableMap - authType = Auth.UserPass( - userPass.getString("username")!!, - userPass.getString("password")!! - ) - } - var syncParams: RpcSyncParams? = null - if (config.getMap("syncParams") != null) { - val syncParamsConfig = config.getMap("syncParams") as ReadableMap - syncParams = RpcSyncParams( - syncParamsConfig.getInt("startScriptCount").toULong()!!, - syncParamsConfig.getInt("startTime").toULong()!!, - syncParamsConfig.getBoolean("forceStartTime"), - syncParamsConfig.getInt("pollRateSec").toULong()!!, - ) - } + try { + var authType: Auth = Auth.None + if (config.getString("authCookie") != null) { + authType = Auth.Cookie(config.getString("authCookie")!!) + } - val _blockchainConfig = BlockchainConfig.Rpc( - RpcConfig( - config.getString("url")!!, - authType, - setNetwork(config.getString("network")!!), - config.getString("walletName")!!, - syncParams - ) + if (config.getMap("authUserPass") != null) { + val userPass = config.getMap("authUserPass") as ReadableMap + authType = Auth.UserPass( + userPass.getString("username")!!, + userPass.getString("password")!! ) - val blockChainId = randomId() - _blockChains[blockChainId] = Blockchain(_blockchainConfig) - result.resolve(blockChainId) - } catch (error: Throwable) { - result.reject("BlockchainRpc init error", error.localizedMessage, error) } - }.start() + var syncParams: RpcSyncParams? = null + if (config.getMap("syncParams") != null) { + val syncParamsConfig = config.getMap("syncParams") as ReadableMap + syncParams = RpcSyncParams( + syncParamsConfig.getInt("startScriptCount").toULong()!!, + syncParamsConfig.getInt("startTime").toULong()!!, + syncParamsConfig.getBoolean("forceStartTime"), + syncParamsConfig.getInt("pollRateSec").toULong()!!, + ) + } + + val _blockchainConfig = BlockchainConfig.Rpc( + RpcConfig( + config.getString("url")!!, + authType, + setNetwork(config.getString("network")!!), + config.getString("walletName")!!, + syncParams + ) + ) + val blockChainId = randomId() + _blockChains[blockChainId] = Blockchain(_blockchainConfig) + result.resolve(blockChainId) + } catch (error: Throwable) { + result.reject("BlockchainRpc init error", error.localizedMessage, error) + } } @ReactMethod