diff --git a/app/src/main/java/to/bitkit/env/Env.kt b/app/src/main/java/to/bitkit/env/Env.kt index edf0f08e6..e2a43fde6 100644 --- a/app/src/main/java/to/bitkit/env/Env.kt +++ b/app/src/main/java/to/bitkit/env/Env.kt @@ -76,7 +76,6 @@ internal object Env { val ldkScorerUrl get() = when (network) { Network.BITCOIN -> "https://api.blocktank.to/scorer-prod" - Network.REGTEST -> "https://api.stag0.blocktank.to/scorer" else -> null } diff --git a/app/src/main/java/to/bitkit/repositories/LightningRepo.kt b/app/src/main/java/to/bitkit/repositories/LightningRepo.kt index 9575864cd..bf1e570bc 100644 --- a/app/src/main/java/to/bitkit/repositories/LightningRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/LightningRepo.kt @@ -1360,6 +1360,11 @@ class LightningRepo @Inject constructor( executeWhenNodeRunning("exportNetworkGraphToFile") { lightningService.exportNetworkGraphToFile(outputDir) } + + suspend fun exportPathfindingScoresToFile(outputDir: String): Result = + executeWhenNodeRunning("exportPathfindingScoresToFile") { + lightningService.exportPathfindingScoresToFile(outputDir) + } // endregion // region probing diff --git a/app/src/main/java/to/bitkit/services/LightningService.kt b/app/src/main/java/to/bitkit/services/LightningService.kt index 74e1a2f3a..8231bef2a 100644 --- a/app/src/main/java/to/bitkit/services/LightningService.kt +++ b/app/src/main/java/to/bitkit/services/LightningService.kt @@ -1050,6 +1050,14 @@ class LightningService @Inject constructor( return loggerLdk.exportNetworkGraphToFile(node, outputDir, fileName) } + suspend fun exportPathfindingScoresToFile( + outputDir: String, + fileName: String = "pathfinding_scores.bin", + ): Result { + val node = this.node ?: return Result.failure(ServiceError.NodeNotSetup()) + return loggerLdk.exportPathfindingScoresToFile(node, outputDir, fileName) + } + // endregion } diff --git a/app/src/main/java/to/bitkit/ui/screens/settings/LdkDebugScreen.kt b/app/src/main/java/to/bitkit/ui/screens/settings/LdkDebugScreen.kt index 112dc55f5..6279da3e3 100644 --- a/app/src/main/java/to/bitkit/ui/screens/settings/LdkDebugScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/settings/LdkDebugScreen.kt @@ -57,6 +57,7 @@ fun LdkDebugScreen( onPasteAndAddPeer = viewModel::pasteAndAddPeer, onLogNetworkGraphInfo = viewModel::logNetworkGraphInfo, onExportNetworkGraph = viewModel::exportNetworkGraph, + onExportScorer = viewModel::exportScorer, onRestartNode = viewModel::restartNode, ) } @@ -70,6 +71,7 @@ private fun LdkDebugContent( onPasteAndAddPeer: () -> Unit, onLogNetworkGraphInfo: () -> Unit, onExportNetworkGraph: (onFileReady: (File) -> Unit) -> Unit, + onExportScorer: (onFileReady: (File) -> Unit) -> Unit, onRestartNode: () -> Unit, ) { val context = LocalContext.current @@ -143,6 +145,20 @@ private fun LdkDebugContent( }, ) + SectionHeader("PATHFINDING SCORER") + SettingsTextButtonRow( + title = "Export Scorer", + iconRes = R.drawable.ic_share, + iconSize = 24.dp, + enabled = !uiState.isLoading, + onClick = { + onExportScorer { file -> + val uri = FileProvider.getUriForFile(context, Env.FILE_PROVIDER_AUTHORITY, file) + context.shareFile(uri, "application/octet-stream") + } + }, + ) + SectionHeader("NODE") SettingsTextButtonRow( title = "Restart", @@ -171,6 +187,7 @@ private fun Preview() { onPasteAndAddPeer = {}, onLogNetworkGraphInfo = {}, onExportNetworkGraph = {}, + onExportScorer = {}, onRestartNode = {}, ) } diff --git a/app/src/main/java/to/bitkit/utils/LoggerLdk.kt b/app/src/main/java/to/bitkit/utils/LoggerLdk.kt index c607a7343..b8f8cf0a6 100644 --- a/app/src/main/java/to/bitkit/utils/LoggerLdk.kt +++ b/app/src/main/java/to/bitkit/utils/LoggerLdk.kt @@ -191,6 +191,25 @@ class LoggerLdk @Inject constructor( Logger.error("Failed to export network graph to file", it, context = TAG) } } + + suspend fun exportPathfindingScoresToFile( + node: Node, + outputDir: String, + fileName: String = "pathfinding_scores.bin", + ): Result = withContext(ioDispatcher) { + runCatching { + val bytes = node.exportPathfindingScores() + val outputFile = File(outputDir, fileName) + outputFile.writeBytes(bytes) + Logger.info( + "Exported pathfinding scores '${bytes.size}' bytes to '${outputFile.absolutePath}'", + context = TAG, + ) + outputFile + }.onFailure { + Logger.error("Failed to export pathfinding scores to file", it, context = TAG) + } + } } class LdkLogWriter( diff --git a/app/src/main/java/to/bitkit/viewmodels/LdkDebugViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/LdkDebugViewModel.kt index 19c92ecd9..9330946b5 100644 --- a/app/src/main/java/to/bitkit/viewmodels/LdkDebugViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/LdkDebugViewModel.kt @@ -155,6 +155,32 @@ class LdkDebugViewModel @Inject constructor( } } + fun exportScorer(onFileReady: (File) -> Unit) { + viewModelScope.launch(bgDispatcher) { + _uiState.update { it.copy(isLoading = true) } + val outputDir = File(context.cacheDir, DIR_EXPORTS).apply { mkdirs() }.absolutePath + lightningRepo.exportPathfindingScoresToFile(outputDir).onSuccess { file -> + Logger.info( + "Pathfinding scores exported to '${file.absolutePath}' (${file.length()} bytes)", + context = TAG, + ) + ToastEventBus.send( + type = Toast.ToastType.INFO, + title = "Scorer exported (${file.length()} bytes)", + ) + onFileReady(file) + }.onFailure { e -> + Logger.error("Failed to export pathfinding scores", e, context = TAG) + ToastEventBus.send( + type = Toast.ToastType.ERROR, + title = "Failed to export scorer", + description = e.message, + ) + } + _uiState.update { it.copy(isLoading = false) } + } + } + fun restartNode() { viewModelScope.launch(bgDispatcher) { _uiState.update { it.copy(isLoading = true) }