mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-07-22 18:25:50 +00:00
fix: Networks screen never showed live health/feedback for Tron's toggle
nodesHealthState() only ever looked at wssNodes(), so an HTTPS-only chain (Tron - no wss endpoint at all) always got an empty node list here: the enable/disable switch itself worked correctly (it reads/writes chain.isEnabled directly, unrelated to this list), but with nothing ever rendering underneath it, the screen looked frozen/unresponsive - this is almost certainly why a single real toggle needed several taps to land correctly, since there was no visible confirmation whichever tap actually took effect. Falls back to httpNodes() when a chain has no wss nodes, and adds a real TronNodeHealthStateTester (GET /wallet/getchainparameters, needs no address) instead of naively reusing EthereumNodeHealthStateTester's eth_getBalance call, which TronGrid doesn't speak and would have always reported the node as down regardless of its actual health.
This commit is contained in:
@@ -37,7 +37,9 @@ import io.novafoundation.nova.runtime.multiNetwork.runtime.types.BaseTypeSynchro
|
||||
import io.novafoundation.nova.runtime.multiNetwork.runtime.types.TypesFetcher
|
||||
import io.novasama.substrate_sdk_android.wsrpc.SocketService
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import java.util.concurrent.TimeUnit
|
||||
import org.web3j.protocol.http.HttpService
|
||||
import javax.inject.Provider
|
||||
|
||||
@@ -165,7 +167,13 @@ class ChainRegistryModule {
|
||||
socketProvider,
|
||||
connectionSecrets,
|
||||
bulkRetriever,
|
||||
web3ApiFactory
|
||||
web3ApiFactory,
|
||||
// A short-lived, minimally-configured client is enough for a health-check ping - unlike Web3ApiFactory's
|
||||
// client, this never needs to survive/reuse connections across a long-lived RPC session.
|
||||
OkHttpClient.Builder()
|
||||
.connectTimeout(10, TimeUnit.SECONDS)
|
||||
.readTimeout(10, TimeUnit.SECONDS)
|
||||
.build()
|
||||
)
|
||||
|
||||
@Provides
|
||||
|
||||
+12
-5
@@ -5,6 +5,7 @@ import io.novafoundation.nova.runtime.ethereum.Web3ApiFactory
|
||||
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
|
||||
import io.novafoundation.nova.runtime.multiNetwork.connection.ConnectionSecrets
|
||||
import io.novasama.substrate_sdk_android.wsrpc.SocketService
|
||||
import okhttp3.OkHttpClient
|
||||
import javax.inject.Provider
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
@@ -12,15 +13,21 @@ class NodeHealthStateTesterFactory(
|
||||
private val socketServiceProvider: Provider<SocketService>,
|
||||
private val connectionSecrets: ConnectionSecrets,
|
||||
private val bulkRetriever: BulkRetriever,
|
||||
private val web3ApiFactory: Web3ApiFactory
|
||||
private val web3ApiFactory: Web3ApiFactory,
|
||||
private val httpClient: OkHttpClient,
|
||||
) {
|
||||
|
||||
fun create(chain: Chain, node: Chain.Node, coroutineScope: CoroutineScope): NodeHealthStateTester {
|
||||
val nodeIsSupported = chain.nodes.nodes.any { it.unformattedUrl == node.unformattedUrl }
|
||||
require(nodeIsSupported)
|
||||
|
||||
return if (chain.hasSubstrateRuntime) {
|
||||
SubstrateNodeHealthStateTester(
|
||||
return when {
|
||||
chain.isTronBased -> TronNodeHealthStateTester(
|
||||
node = node,
|
||||
httpClient = httpClient
|
||||
)
|
||||
|
||||
chain.hasSubstrateRuntime -> SubstrateNodeHealthStateTester(
|
||||
chain = chain,
|
||||
socketService = socketServiceProvider.get(),
|
||||
connectionSecrets = connectionSecrets,
|
||||
@@ -28,8 +35,8 @@ class NodeHealthStateTesterFactory(
|
||||
node = node,
|
||||
coroutineScope = coroutineScope
|
||||
)
|
||||
} else {
|
||||
EthereumNodeHealthStateTester(
|
||||
|
||||
else -> EthereumNodeHealthStateTester(
|
||||
socketService = socketServiceProvider.get(),
|
||||
connectionSecrets = connectionSecrets,
|
||||
node = node,
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package io.novafoundation.nova.runtime.multiNetwork.connection.node.healthState
|
||||
|
||||
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import kotlin.time.ExperimentalTime
|
||||
import kotlin.time.measureTime
|
||||
|
||||
/**
|
||||
* TronGrid speaks a plain REST API, not Ethereum JSON-RPC - reusing [EthereumNodeHealthStateTester] against it
|
||||
* (as this codebase used to, before Tron nodes were included in health checks at all) would send an
|
||||
* `eth_getBalance` call TronGrid doesn't understand, always reporting the node as unreachable regardless of its
|
||||
* actual health. `GET /wallet/getchainparameters` needs no account/address context and is cheap on TronGrid's
|
||||
* side, making it a good generic liveness ping - same endpoint this codebase already uses elsewhere
|
||||
* (`TronGridApi.getChainParameters`), just called directly here since `runtime` cannot depend on
|
||||
* `feature-wallet-impl` (wrong direction) to reuse that Retrofit interface.
|
||||
*/
|
||||
class TronNodeHealthStateTester(
|
||||
private val node: Chain.Node,
|
||||
private val httpClient: OkHttpClient,
|
||||
) : NodeHealthStateTester {
|
||||
|
||||
@OptIn(ExperimentalTime::class)
|
||||
override suspend fun testNodeHealthState(): Result<Long> = withContext(Dispatchers.IO) {
|
||||
runCatching {
|
||||
val request = Request.Builder()
|
||||
.url("${node.unformattedUrl.trimEnd('/')}/wallet/getchainparameters")
|
||||
.build()
|
||||
|
||||
val duration = measureTime {
|
||||
httpClient.newCall(request).execute().use { response ->
|
||||
check(response.isSuccessful) { "HTTP ${response.code}" }
|
||||
}
|
||||
}
|
||||
|
||||
duration.inWholeMilliseconds
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user