Same read/send-capable chain-family pattern as Tron/Bitcoin, but for
Ed25519/SLIP-0010 instead of secp256k1/BIP32 (Solana's account id IS its
raw public key, so no separate address-hash derivation step is needed).
- SLIP-0010 Ed25519 keypair derivation (Bip32Ed25519KeypairFactory),
cross-validated against an independent slip10 reference implementation
and pinned to a known-good test vector.
- Chain.isSolanaBased / Chain.Asset.Type.SolanaNative wired through every
chain-mapper, account-model, and signer dispatch site (mirrors the
existing Tron/Bitcoin wiring exactly).
- SolanaAddressBackfillMigration derives Solana keys for wallets created
before this support existed, same self-healing no-stuck-flag design as
the Tron/Bitcoin backfills - also fixed a latent bug in those two
migrations where MetaAccountSecrets/MetaAccountLocal.addXAccount()
dropped sibling chain-family fields on a re-run.
- Room migration 75->76 adds isSolanaBased/solanaPublicKey/solanaAddress
columns.
- CloudBackup's already-reserved solanaAddress/SolanaSecrets fields are
now actually read/written by RealLocalAccountsCloudBackupFacade; also
fixed isCompletelyEmpty() to check solana, so a Solana-only wallet
doesn't get silently dropped from backup.
Bitcoin was branched off main independently instead of continuing on top
of the Tron send branch, which caused real divergence: both branches touch
the same shared signing/DI code (multiChainEncryptionFor, getMetaAccountKeypair,
NodeHealthStateTesterFactory, AssetsModule/TypeBasedAssetSourceRegistry,
CloudBackup schema, Fee model), and both need to ship together in one
coordinated release once wallet-util's master is unblocked. Merging now
reconciles that before it gets any harder, and gives one branch/versionCode
history for device testing instead of two that silently diverge.
Conflict resolutions of note:
- SecretStoreV2/SecretsSigner: getKeypair and multiChainEncryptionFor now
recognize Tron AND Bitcoin accounts (isTronBased/isBitcoinBased both
threaded through, checked before the Ethereum fallback).
- AccountDataSourceImpl: both address-backfill migrations now run
sequentially in one coroutine (Tron's fix for a race against the legacy
migration applies equally to Bitcoin's backfill).
- CloudBackup: kept Tron's forward-looking Solana schema reservation
alongside Tron's and Bitcoin's now-real fields.
- ChainRegistryModule/NodeHealthStateTesterFactory: adopted Tron's
self-contained short-lived OkHttpClient (simpler than threading the
shared app-wide client through RuntimeDependencies, which is reverted).
- RealSecretsMetaAccount: extended Tron's chain-account MultiChainEncryption
fix to also cover Bitcoin, for the same underlying reason.
- ChainExt.isValidAddress: Tron's branch independently closed the
pre-existing Tron validation gap; kept alongside Bitcoin's own check.
Derives a BIP84 (native SegWit) keypair alongside the existing substrate/
ethereum/tron ones, stores it in MetaAccountSecrets/CloudBackup, persists
bitcoinPublicKey/bitcoinAddress on meta_accounts (DB migration 74->75), and
threads isBitcoinBased through Chain/ChainLocal/mappers/ChainExt/ChainRegistry
the same way isTronBased was wired. Adds BitcoinAddressBackfillMigration,
mirroring TronAddressBackfillMigration, so existing wallets get a Bitcoin
address without re-import.
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.
Real user reported Tron stuck showing "Connecting..." forever in the
Networks screen after the ChainRegistry fix (which correctly skips
creating a ChainConnection for Tron, since TronGrid is a plain REST
API, not WSS). NetworkListAdapterItemFactory.getConnectingState()
rendered every non-Connected state (including the Disconnected
default a missing connection pool entry falls back to) as
"Connecting" with an indefinite shimmer - there was no way to
distinguish "never had a connection to begin with" from "still
negotiating one".
Tron doesn't have a meaningful WS connection state at all (its actual
balance/transfer operations poll TronGridApi directly, confirmed
independent of ChainConnection), so there's nothing correct to show
here - treat it the same as the already-existing isDisabled early
return (no status badge) rather than defaulting into the generic
"still connecting" UI.
* Add read-only Tron (TRC20) chain family support
Adds Tron as a third chain family alongside Substrate and EVM:
address derivation (BIP44 coin type 195, secp256k1 reused from the
existing Ethereum path, Base58Check encoding), TronGrid-backed TRX
and TRC20 USDT balance display, and a Room migration for the new
per-account Tron key/address columns. Read-only only — no send,
signing, or broadcast support yet.
* fix: exhaustive when branches for Trc20/TronNative asset types
ChainExt.kt's onChainAssetId and Common.kt's existentialDepositError
both switch exhaustively over Chain.Asset.Type and didn't have cases
for the new Trc20/TronNative variants, breaking compilation. Trc20
mirrors EvmErc20 (contract address as the on-chain id, dust burns
rather than transfers on removal); TronNative mirrors EvmNative.