Merge main: pull in critical Tron ChainConnection fix + CI infra fixes

main now has the fix for a serious bug that also affects this branch:
ChainRegistry unconditionally attempted a WSS connection for every
chain including Tron (whose node is a plain REST API, not WSS),
hanging indefinitely and blocking all subsequent chain registration
in the sequential registration loop - a real freeze risk for any user
with the Tron chain enabled, found while diagnosing balances_test.yml.

Also pulls in the various CI-only fixes from PR #11 (unrelated to
app behavior).
This commit is contained in:
2026-07-08 08:39:31 -07:00
6 changed files with 45 additions and 12 deletions
+12 -4
View File
@@ -8,8 +8,14 @@ adb -s emulator-5554 install app/debug/app-debug.apk
adb -s emulator-5554 install app/androidTest/debug/app-debug-androidTest.apk
# Run tests
adb logcat -c &&
python - <<END
adb logcat -c
# DIAGNOSTIC: stream logcat live (unbuffered) alongside the test run, so a hang shows real
# device-side activity (network calls, coroutine timeouts, ANRs) instead of just silence.
adb logcat -v time '*:D' &
LOGCAT_PID=$!
python -u - <<END
import os
import re
import subprocess as sp
@@ -26,9 +32,10 @@ def update():
t = threading.Thread(target=update)
t.dameon = True
t.start()
def run():
os.system('adb wait-for-device')
p = sp.Popen('adb shell am instrument -w -m -e debug false -e class "io.novafoundation.nova.balances.BalancesIntegrationTest" io.novafoundation.nova.debug.test/io.qameta.allure.android.runners.AllureAndroidJUnitRunner',
p = sp.Popen('adb shell am instrument -w -m -e debug false -e class "io.novafoundation.nova.balances.BalancesIntegrationTest" io.pezkuwichain.wallet.debug.test/io.qameta.allure.android.runners.AllureAndroidJUnitRunner',
shell=True, stdout=sp.PIPE, stderr=sp.PIPE, stdin=sp.PIPE)
return p.communicate()
success = re.compile(r'OK \(\d+ tests\)')
@@ -44,9 +51,10 @@ else:
sys.exit(1) # make sure we fail if the tests fail
END
EXIT_CODE=$?
kill "$LOGCAT_PID" 2>/dev/null
adb logcat -d '*:E'
# Export results
adb exec-out run-as io.novafoundation.nova.debug sh -c 'cd /data/data/io.novafoundation.nova.debug/files && tar cf - allure-results' > allure-results.tar
adb exec-out run-as io.pezkuwichain.wallet.debug sh -c 'cd /data/data/io.pezkuwichain.wallet.debug/files && tar cf - allure-results' > allure-results.tar
exit $EXIT_CODE
+2 -2
View File
@@ -28,7 +28,7 @@ t.dameon = True
t.start()
def run():
os.system('adb wait-for-device')
p = sp.Popen('adb shell am instrument -w -m -e notClass io.novafoundation.nova.balances.BalancesIntegrationTest -e package io.novafoundation.nova.debug io.novafoundation.nova.debug.test/io.qameta.allure.android.runners.AllureAndroidJUnitRunner',
p = sp.Popen('adb shell am instrument -w -m -e notClass io.novafoundation.nova.balances.BalancesIntegrationTest -e package io.pezkuwichain.wallet.debug io.pezkuwichain.wallet.debug.test/io.qameta.allure.android.runners.AllureAndroidJUnitRunner',
shell=True, stdout=sp.PIPE, stderr=sp.PIPE, stdin=sp.PIPE)
return p.communicate()
success = re.compile(r'OK \(\d+ tests\)')
@@ -47,6 +47,6 @@ EXIT_CODE=$?
adb logcat -d '*:E'
# Export results
adb exec-out run-as io.novafoundation.nova.debug sh -c 'cd /data/data/io.novafoundation.nova.debug/files && tar cf - allure-results' > allure-results.tar
adb exec-out run-as io.pezkuwichain.wallet.debug sh -c 'cd /data/data/io.pezkuwichain.wallet.debug/files && tar cf - allure-results' > allure-results.tar
exit $EXIT_CODE
+9 -1
View File
@@ -19,7 +19,8 @@ jobs:
run-tests:
needs: [build-app]
runs-on: macos-14
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- uses: actions/checkout@v4
@@ -36,12 +37,19 @@ jobs:
- name: Add permissions
run: chmod +x .github/scripts/run_balances_test.sh
- name: Enable KVM group perms
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Run tests
uses: reactivecircus/android-emulator-runner@v2
with:
disable-animations: true
profile: Nexus 6
api-level: 29
arch: x86_64
script: .github/scripts/run_balances_test.sh
- uses: actions/upload-artifact@v4
+8 -1
View File
@@ -2,13 +2,20 @@ name: Pull request
on:
pull_request:
workflow_dispatch:
inputs:
branch:
description: 'Branch to build and test (manual escape hatch for when pull_request-triggered CI does not fire)'
required: true
default: 'main'
type: string
jobs:
test:
uses: pezkuwichain/pezkuwi-wallet-android/.github/workflows/android_build.yml@main
with:
branch: ${{github.head_ref}}
branch: ${{ github.event_name == 'workflow_dispatch' && inputs.branch || github.head_ref }}
gradlew-command: assembleDevelop
keystore-file-name: develop_key.jks # develop variant is signed with signingConfigs.dev (develop_key.jks)
build-debug-tests: false # TODO: Enable this, when debug build will be fixed for tests
+5 -1
View File
@@ -36,6 +36,11 @@ android {
debug {
applicationIdSuffix '.debug'
versionNameSuffix '-debug'
// androidTest is only ever compiled against this build type (AGP's testBuildType
// defaults to "debug" and is not overridden anywhere in this project), so this is the
// only place a testInstrumentationRunner override actually takes effect - the identical
// override on the instrumentialTest build type below is unreachable dead config.
defaultConfig.testInstrumentationRunner "io.qameta.allure.android.runners.AllureAndroidJUnitRunner"
buildConfigField "String", "BuildType", "\"debug\""
}
@@ -94,7 +99,6 @@ android {
instrumentialTest {
initWith buildTypes.debug
matchingFallbacks = ['debug']
defaultConfig.testInstrumentationRunner "io.qameta.allure.android.runners.AllureAndroidJUnitRunner"
buildConfigField "String", "BuildType", "\"instrumentalTest\""
}
@@ -215,12 +215,18 @@ class ChainRegistry(
if (chain.hasSubstrateRuntime) {
runtimeProviderPool.setupRuntimeProvider(chain)
runtimeSyncService.registerChain(chain, connection)
runtimeSubscriptionPool.setupRuntimeSubscription(chain, connection)
runtimeSyncService.registerChain(chain, requireNotNull(connection))
runtimeSubscriptionPool.setupRuntimeSubscription(chain, requireNotNull(connection))
}
}
private suspend fun registerConnection(chain: Chain): ChainConnection {
private suspend fun registerConnection(chain: Chain): ChainConnection? {
// Tron nodes are plain REST APIs (TronGrid), not WSS JSON-RPC endpoints - ChainConnection's
// SocketService can only speak the latter, so attempting to set one up here would hang
// indefinitely instead of failing fast. Tron balance/transfer operations already go through
// their own dedicated TronGridApi client, independent of this connection pool.
if (chain.isTronBased) return null
val connection = connectionPool.setupConnection(chain)
if (chain.isEthereumBased) {