mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-07-22 18:25:50 +00:00
feat: Bitcoin transaction construction, signing, and sending
RealBitcoinTransactionService builds and signs native SegWit transactions client-side (mempool.space only exposes UTXOs/fee-rate/broadcast, not construction, unlike TronGrid): greedy largest-first UTXO selection over confirmed UTXOs, inputs*68 + outputs*31 + 11 vsize heuristic for fees (matching pezkuwi-exchange's proven approach), RBF-signaled inputs, and a 546-sat dust threshold that folds sub-dust change into the fee rather than creating an uneconomical output. Each input gets its own BIP143 sighash, signed via the existing raw-hash signing primitive (NovaSigner.signRaw with skipMessageHashing) already used for Ethereum/Tron, then DER-encoded with low-S normalization - no new signing call path was added, only the DER encoding step. Also fixes multiChainEncryptionFor/getMetaAccountKeypair to recognize Bitcoin accounts: previously neither function had any Bitcoin (or Tron) branch, so signing would have silently used the wrong keypair. Threads a bitcoin flag through mapMetaAccountSecretsToKeypair/DerivationPath and AccountSecrets.keypair(chain)/derivationPath(chain) the same way ethereum already is.
This commit is contained in:
+12
-3
@@ -156,17 +156,21 @@ val AccountSecrets.isChainAccountSecrets
|
||||
suspend fun SecretStoreV2.getMetaAccountKeypair(
|
||||
metaId: Long,
|
||||
isEthereum: Boolean,
|
||||
isBitcoin: Boolean = false,
|
||||
): Keypair = withContext(Dispatchers.Default) {
|
||||
val secrets = getMetaAccountSecrets(metaId) ?: noMetaSecrets(metaId)
|
||||
|
||||
mapMetaAccountSecretsToKeypair(secrets, isEthereum)
|
||||
mapMetaAccountSecretsToKeypair(secrets, isEthereum, isBitcoin)
|
||||
}
|
||||
|
||||
fun mapMetaAccountSecretsToKeypair(
|
||||
secrets: EncodableStruct<MetaAccountSecrets>,
|
||||
ethereum: Boolean,
|
||||
bitcoin: Boolean = false,
|
||||
): Keypair {
|
||||
val keypairStruct = if (ethereum) {
|
||||
val keypairStruct = if (bitcoin) {
|
||||
secrets[MetaAccountSecrets.BitcoinKeypair] ?: noBitcoinSecret()
|
||||
} else if (ethereum) {
|
||||
secrets[MetaAccountSecrets.EthereumKeypair] ?: noEthereumSecret()
|
||||
} else {
|
||||
secrets[MetaAccountSecrets.SubstrateKeypair]
|
||||
@@ -178,8 +182,11 @@ fun mapMetaAccountSecretsToKeypair(
|
||||
fun mapMetaAccountSecretsToDerivationPath(
|
||||
secrets: EncodableStruct<MetaAccountSecrets>,
|
||||
ethereum: Boolean,
|
||||
bitcoin: Boolean = false,
|
||||
): String? {
|
||||
return if (ethereum) {
|
||||
return if (bitcoin) {
|
||||
secrets[MetaAccountSecrets.BitcoinDerivationPath]
|
||||
} else if (ethereum) {
|
||||
secrets[MetaAccountSecrets.EthereumDerivationPath]
|
||||
} else {
|
||||
secrets[MetaAccountSecrets.SubstrateDerivationPath]
|
||||
@@ -198,6 +205,8 @@ private fun noChainSecrets(metaId: Long, accountId: ByteArray): Nothing {
|
||||
|
||||
private fun noEthereumSecret(): Nothing = error("No ethereum keypair found")
|
||||
|
||||
private fun noBitcoinSecret(): Nothing = error("No bitcoin keypair found")
|
||||
|
||||
fun mapKeypairStructToKeypair(struct: EncodableStruct<KeyPairSchema>): Keypair {
|
||||
return Keypair(
|
||||
publicKey = struct[KeyPairSchema.PublicKey],
|
||||
|
||||
Reference in New Issue
Block a user