mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-07-22 20:45:53 +00:00
feat: Bitcoin key derivation, secrets storage, and chain-family plumbing
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.
This commit is contained in:
@@ -272,6 +272,7 @@ fun Chain.requireGenesisHash() = requireNotNull(genesisHash)
|
||||
fun Chain.addressOf(accountId: ByteArray): String {
|
||||
return when {
|
||||
isTronBased -> accountId.toTronAddress()
|
||||
isBitcoinBased -> accountId.toBitcoinAddress()
|
||||
isEthereumBased -> accountId.toEthereumAddress()
|
||||
else -> accountId.toAddress(addressPrefix.toShort())
|
||||
}
|
||||
@@ -282,7 +283,7 @@ fun Chain.addressOf(accountId: AccountIdKey): String {
|
||||
}
|
||||
|
||||
fun Chain.legacyAddressOfOrNull(accountId: ByteArray): String? {
|
||||
return if (isEthereumBased || isTronBased) {
|
||||
return if (isEthereumBased || isTronBased || isBitcoinBased) {
|
||||
null
|
||||
} else {
|
||||
legacyAddressPrefix?.let { accountId.toAddress(it.toShort()) }
|
||||
@@ -296,6 +297,7 @@ fun ByteArray.toEthereumAddress(): String {
|
||||
fun Chain.accountIdOf(address: String): ByteArray {
|
||||
return when {
|
||||
isTronBased -> address.tronAddressToAccountId()
|
||||
isBitcoinBased -> address.bitcoinAddressToAccountId()
|
||||
isEthereumBased -> address.asEthereumAddress().toAccountId().value
|
||||
else -> address.toAccountId()
|
||||
}
|
||||
@@ -329,6 +331,7 @@ fun Chain.accountIdOrNull(address: String): ByteArray? {
|
||||
|
||||
fun Chain.emptyAccountId() = when {
|
||||
isTronBased -> emptyTronAccountId()
|
||||
isBitcoinBased -> emptyBitcoinAccountId()
|
||||
isEthereumBased -> emptyEthereumAccountId()
|
||||
else -> emptySubstrateAccountId()
|
||||
}
|
||||
@@ -342,6 +345,7 @@ fun Chain.accountIdOrDefault(maybeAddress: String): ByteArray {
|
||||
fun Chain.accountIdOf(publicKey: ByteArray): ByteArray {
|
||||
return when {
|
||||
isTronBased -> publicKey.tronPublicKeyToAccountId()
|
||||
isBitcoinBased -> publicKey.bitcoinPublicKeyToAccountId()
|
||||
isEthereumBased -> publicKey.asEthereumPublicKey().toAccountId().value
|
||||
else -> publicKey.substrateAccountId()
|
||||
}
|
||||
@@ -361,13 +365,15 @@ fun Chain.multiAddressOf(accountId: ByteArray): MultiAddress {
|
||||
|
||||
fun Chain.isValidAddress(address: String): Boolean {
|
||||
return runCatching {
|
||||
if (isEthereumBased) {
|
||||
address.asEthereumAddress().isValid()
|
||||
} else {
|
||||
address.toAccountId() // verify supplied address can be converted to account id
|
||||
when {
|
||||
isBitcoinBased -> address.isValidBitcoinAddress()
|
||||
isEthereumBased -> address.asEthereumAddress().isValid()
|
||||
else -> {
|
||||
address.toAccountId() // verify supplied address can be converted to account id
|
||||
|
||||
addressPrefix.toShort() == address.addressPrefix() ||
|
||||
legacyAddressPrefix?.toShort() == address.addressPrefix()
|
||||
addressPrefix.toShort() == address.addressPrefix() ||
|
||||
legacyAddressPrefix?.toShort() == address.addressPrefix()
|
||||
}
|
||||
}
|
||||
}.getOrDefault(false)
|
||||
}
|
||||
|
||||
@@ -221,11 +221,11 @@ class ChainRegistry(
|
||||
}
|
||||
|
||||
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
|
||||
// Tron/Bitcoin nodes are plain REST APIs (TronGrid / mempool.space), 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. Balance/transfer operations for both go through their
|
||||
// own dedicated REST API clients, independent of this connection pool.
|
||||
if (chain.isTronBased || chain.isBitcoinBased) return null
|
||||
|
||||
val connection = connectionPool.setupConnection(chain)
|
||||
|
||||
|
||||
+1
@@ -128,6 +128,7 @@ fun mapChainToLocal(chain: Chain, gson: Gson): ChainLocal {
|
||||
legacyPrefix = chain.legacyAddressPrefix,
|
||||
isEthereumBased = chain.isEthereumBased,
|
||||
isTronBased = chain.isTronBased,
|
||||
isBitcoinBased = chain.isBitcoinBased,
|
||||
isTestNet = chain.isTestNet,
|
||||
hasSubstrateRuntime = chain.hasSubstrateRuntime,
|
||||
pushSupport = chain.pushSupport,
|
||||
|
||||
+1
@@ -276,6 +276,7 @@ fun mapChainLocalToChain(
|
||||
legacyAddressPrefix = legacyPrefix,
|
||||
isEthereumBased = isEthereumBased,
|
||||
isTronBased = isTronBased,
|
||||
isBitcoinBased = isBitcoinBased,
|
||||
isTestNet = isTestNet,
|
||||
hasCrowdloans = hasCrowdloans,
|
||||
pushSupport = pushSupport,
|
||||
|
||||
+2
@@ -21,6 +21,7 @@ import io.novafoundation.nova.runtime.multiNetwork.chain.remote.model.ChainRemot
|
||||
|
||||
private const val ETHEREUM_OPTION = "ethereumBased"
|
||||
private const val TRON_OPTION = "tronBased"
|
||||
private const val BITCOIN_OPTION = "bitcoinBased"
|
||||
private const val CROWDLOAN_OPTION = "crowdloans"
|
||||
private const val TESTNET_OPTION = "testnet"
|
||||
private const val PROXY_OPTION = "proxy"
|
||||
@@ -92,6 +93,7 @@ fun mapRemoteChainToLocal(
|
||||
legacyPrefix = legacyAddressPrefix,
|
||||
isEthereumBased = ETHEREUM_OPTION in optionsOrEmpty,
|
||||
isTronBased = TRON_OPTION in optionsOrEmpty,
|
||||
isBitcoinBased = BITCOIN_OPTION in optionsOrEmpty,
|
||||
isTestNet = TESTNET_OPTION in optionsOrEmpty,
|
||||
hasCrowdloans = CROWDLOAN_OPTION in optionsOrEmpty,
|
||||
supportProxy = PROXY_OPTION in optionsOrEmpty,
|
||||
|
||||
@@ -33,6 +33,7 @@ data class Chain(
|
||||
val types: Types?,
|
||||
val isEthereumBased: Boolean,
|
||||
val isTronBased: Boolean,
|
||||
val isBitcoinBased: Boolean,
|
||||
val isTestNet: Boolean,
|
||||
val source: Source,
|
||||
val hasSubstrateRuntime: Boolean,
|
||||
|
||||
Reference in New Issue
Block a user