diff --git a/android/app/src/main/java/com/zeus/cashudevkit/CashuDevKitModule.kt b/android/app/src/main/java/com/zeus/cashudevkit/CashuDevKitModule.kt index d2e13580d..7ea2fac5a 100644 --- a/android/app/src/main/java/com/zeus/cashudevkit/CashuDevKitModule.kt +++ b/android/app/src/main/java/com/zeus/cashudevkit/CashuDevKitModule.kt @@ -116,6 +116,34 @@ class CashuDevKitModule(private val reactContext: ReactApplicationContext) : return wallet } + private fun executeTransferOperation( + promise: Promise, + operationName: String, + transferOperation: suspend (MultiMintWallet) -> TransferResult + ) { + val initializedWallet = getInitializedWallet(promise) ?: return + + scope.launch { + try { + val result = transferOperation(initializedWallet) + withContext(Dispatchers.Main) { + promise.resolve(encodeTransferResult(result).toString()) + } + } catch (e: FfiException) { + val (code, message) = mapFfiException(e) + Log.e(TAG, "$operationName error: $message", e) + withContext(Dispatchers.Main) { + promise.reject(code, message, e) + } + } catch (e: Exception) { + Log.e(TAG, "$operationName error", e) + withContext(Dispatchers.Main) { + promise.reject("TRANSFER_ERROR", e.message, e) + } + } + } + } + private var currentDbPath: String? = null private fun getDatabasePath(mnemonic: String): String { @@ -938,60 +966,28 @@ class CashuDevKitModule(private val reactContext: ReactApplicationContext) : @ReactMethod fun transferExactReceive(sourceMint: String, targetMint: String, amount: Double, promise: Promise) { - val wallet = getInitializedWallet(promise) ?: return - - scope.launch { - try { + executeTransferOperation( + promise = promise, + operationName = "transferExactReceive" + ) { wallet -> val sourceUrl = MintUrl(sourceMint) val targetUrl = MintUrl(targetMint) val transferMode = TransferMode.ExactReceive(Amount(amount.toLong().toULong())) - val result = wallet.transfer(sourceUrl, targetUrl, transferMode) - - withContext(Dispatchers.Main) { - promise.resolve(encodeTransferResult(result).toString()) - } - } catch (e: FfiException) { - val (code, message) = mapFfiException(e) - Log.e(TAG, "transferExactReceive error: $message", e) - withContext(Dispatchers.Main) { - promise.reject(code, message, e) - } - } catch (e: Exception) { - Log.e(TAG, "transferExactReceive error", e) - withContext(Dispatchers.Main) { - promise.reject("TRANSFER_ERROR", e.message, e) - } - } + wallet.transfer(sourceUrl, targetUrl, transferMode) } } @ReactMethod fun transferFullBalance(sourceMint: String, targetMint: String, promise: Promise) { - val wallet = getInitializedWallet(promise) ?: return - - scope.launch { - try { + executeTransferOperation( + promise = promise, + operationName = "transferFullBalance" + ) { wallet -> val sourceUrl = MintUrl(sourceMint) val targetUrl = MintUrl(targetMint) - val result = wallet.transfer(sourceUrl, targetUrl, TransferMode.FullBalance) - - withContext(Dispatchers.Main) { - promise.resolve(encodeTransferResult(result).toString()) - } - } catch (e: FfiException) { - val (code, message) = mapFfiException(e) - Log.e(TAG, "transferFullBalance error: $message", e) - withContext(Dispatchers.Main) { - promise.reject(code, message, e) - } - } catch (e: Exception) { - Log.e(TAG, "transferFullBalance error", e) - withContext(Dispatchers.Main) { - promise.reject("TRANSFER_ERROR", e.message, e) - } - } + wallet.transfer(sourceUrl, targetUrl, TransferMode.FullBalance) } } diff --git a/ios/CashuDevKit/CashuDevKitModule.swift b/ios/CashuDevKit/CashuDevKitModule.swift index ef14838e5..5a0f47d1b 100644 --- a/ios/CashuDevKit/CashuDevKitModule.swift +++ b/ios/CashuDevKit/CashuDevKitModule.swift @@ -103,6 +103,26 @@ class CashuDevKitModule: RCTEventEmitter { return wallet } + private func executeTransfer( + resolve: @escaping RCTPromiseResolveBlock, + reject: @escaping RCTPromiseRejectBlock, + operation: @escaping (MultiMintWallet) async throws -> TransferResult + ) { + guard let wallet = getInitializedWallet(reject: reject) else { return } + + Task { + do { + let result = try await operation(wallet) + resolve(encodeToJson(encodeTransferResult(result))) + } catch let error as FfiError { + let (code, message) = mapFfiError(error) + reject(code, message, error) + } catch { + reject("TRANSFER_ERROR", error.localizedDescription, error) + } + } + } + private var currentDbPath: String? private func getDatabasePath(for mnemonic: String) -> String { @@ -857,29 +877,18 @@ class CashuDevKitModule: RCTEventEmitter { func transferExactReceive(_ sourceMint: String, targetMint: String, amount: NSNumber, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { - guard let wallet = getInitializedWallet(reject: reject) else { return } - - Task { - do { + executeTransfer(resolve: resolve, reject: reject) { wallet in let sourceMintUrl = MintUrl(url: sourceMint) let targetMintUrl = MintUrl(url: targetMint) let transferMode = TransferMode.exactReceive( amount: Amount(value: amount.uint64Value) ) - let result = try await wallet.transfer( + return try await wallet.transfer( sourceMint: sourceMintUrl, targetMint: targetMintUrl, transferMode: transferMode ) - - resolve(encodeToJson(encodeTransferResult(result))) - } catch let error as FfiError { - let (code, message) = mapFfiError(error) - reject(code, message, error) - } catch { - reject("TRANSFER_ERROR", error.localizedDescription, error) - } } } @@ -887,25 +896,14 @@ class CashuDevKitModule: RCTEventEmitter { func transferFullBalance(_ sourceMint: String, targetMint: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { - guard let wallet = getInitializedWallet(reject: reject) else { return } - - Task { - do { + executeTransfer(resolve: resolve, reject: reject) { wallet in let sourceMintUrl = MintUrl(url: sourceMint) let targetMintUrl = MintUrl(url: targetMint) - let result = try await wallet.transfer( + return try await wallet.transfer( sourceMint: sourceMintUrl, targetMint: targetMintUrl, transferMode: .fullBalance ) - - resolve(encodeToJson(encodeTransferResult(result))) - } catch let error as FfiError { - let (code, message) = mapFfiError(error) - reject(code, message, error) - } catch { - reject("TRANSFER_ERROR", error.localizedDescription, error) - } } } diff --git a/locales/en.json b/locales/en.json index 9d9aba93b..c9e3c2e11 100644 --- a/locales/en.json +++ b/locales/en.json @@ -2264,6 +2264,9 @@ "views.Cashu.CashuPaymentRequest.noBalance": "No ecash balance available. Receive a payment first.", "views.Cashu.CashuPaymentRequest.multiMint": "Multi-mint", "views.Cashu.MultimintPayment.noMintsSelected": "No mints selected. Please select at least one mint to proceed.", + "views.Cashu.MultimintPayment.paying": "Paying...", + "views.Cashu.MultimintPayment.requesting": "Requesting...", + "views.Cashu.MultimintPayment.totalAvailable": "Total Available:", "views.Cashu.CashuPayment.inTransitPayment": "In Transit Cashu Payment", "views.Cashu.CashuPayment.failedPayment": "Failed Cashu Payment", "views.Cashu.CashuToken.proofCount": "Number of proofs", diff --git a/views/Cashu/MultimintPayment.tsx b/views/Cashu/MultimintPayment.tsx index 587137a4e..0ea235a2d 100644 --- a/views/Cashu/MultimintPayment.tsx +++ b/views/Cashu/MultimintPayment.tsx @@ -209,10 +209,14 @@ export default class MultimintPayment extends React.Component< }`; } if (item.status === MintPaymentStatus.PAYING && isProcessing) { - return `Paying... | ${item.mintUrl}`; + return `${localeString( + 'views.Cashu.MultimintPayment.paying' + )} | ${item.mintUrl}`; } if (item.status === MintPaymentStatus.REQUESTING && isProcessing) { - return `Requesting... | ${item.mintUrl}`; + return `${localeString( + 'views.Cashu.MultimintPayment.requesting' + )} | ${item.mintUrl}`; } return item.mintUrl; }; @@ -397,7 +401,9 @@ export default class MultimintPayment extends React.Component< fontFamily: 'PPNeueMontreal-Book' }} > - Total Available: + {localeString( + 'views.Cashu.MultimintPayment.totalAvailable' + )}