Skip to content

Commit

Permalink
Add UnspentOutputInfo class
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelekol committed Jan 11, 2024
1 parent b877fb2 commit 4956962
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ class MainViewModel : ViewModel(), BitcoinKit.Listener {

fun onMaxClick() {
try {
amountLiveData.value = bitcoinKit.maximumSpendableValue(address, feePriority.feeRate, getPluginData())
amountLiveData.value = bitcoinKit.maximumSpendableValue(address, feePriority.feeRate, null, getPluginData())
} catch (e: Exception) {
amountLiveData.value = 0
errorLiveData.value = when (e) {
Expand All @@ -205,7 +205,7 @@ class MainViewModel : ViewModel(), BitcoinKit.Listener {
}

private fun fee(value: Long, address: String? = null): BitcoinSendInfo {
return bitcoinKit.sendInfo(value, address, feeRate = feePriority.feeRate, pluginData = getPluginData())
return bitcoinKit.sendInfo(value, address, feeRate = feePriority.feeRate, unspentOutputs = null, pluginData = getPluginData())
}

private fun getPluginData(): MutableMap<Byte, IPluginData> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import io.horizontalsystems.bitcoincore.models.UsedAddress
import io.horizontalsystems.bitcoincore.network.Network
import io.horizontalsystems.bitcoincore.storage.FullTransaction
import io.horizontalsystems.bitcoincore.storage.UnspentOutput
import io.horizontalsystems.bitcoincore.storage.UnspentOutputInfo
import io.horizontalsystems.bitcoincore.transactions.scripts.ScriptType
import io.reactivex.Single

Expand Down Expand Up @@ -69,13 +70,15 @@ abstract class AbstractKit {
address: String? = null,
senderPay: Boolean = true,
feeRate: Int,
unspentOutputs: List<UnspentOutputInfo>?,
pluginData: Map<Byte, IPluginData> = mapOf()
): BitcoinSendInfo {
return bitcoinCore.sendInfo(
value = value,
address = address,
senderPay = senderPay,
feeRate = feeRate,
unspentOutputs = unspentOutputs,
pluginData = pluginData
)
}
Expand All @@ -86,7 +89,7 @@ abstract class AbstractKit {
senderPay: Boolean = true,
feeRate: Int,
sortType: TransactionDataSortType,
unspentOutputs: List<UnspentOutput>? = null,
unspentOutputs: List<UnspentOutputInfo>? = null,
pluginData: Map<Byte, IPluginData> = mapOf()
): FullTransaction {
return bitcoinCore.send(address, value, senderPay, feeRate, sortType, unspentOutputs, pluginData)
Expand All @@ -110,7 +113,7 @@ abstract class AbstractKit {
senderPay: Boolean = true,
feeRate: Int,
sortType: TransactionDataSortType,
unspentOutputs: List<UnspentOutput>? = null,
unspentOutputs: List<UnspentOutputInfo>? = null,
): FullTransaction {
return bitcoinCore.send(hash, scriptType, value, senderPay, feeRate, sortType, unspentOutputs)
}
Expand Down Expand Up @@ -170,8 +173,8 @@ abstract class AbstractKit {
bitcoinCore.watchTransaction(filter, listener)
}

fun maximumSpendableValue(address: String?, feeRate: Int, pluginData: Map<Byte, IPluginData>): Long {
return bitcoinCore.maximumSpendableValue(address, feeRate, pluginData)
fun maximumSpendableValue(address: String?, feeRate: Int, unspentOutputs: List<UnspentOutputInfo>?, pluginData: Map<Byte, IPluginData>): Long {
return bitcoinCore.maximumSpendableValue(address, feeRate, unspentOutputs, pluginData)
}

fun minimumSpendableValue(address: String?): Int {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import io.horizontalsystems.bitcoincore.network.peer.PeerManager
import io.horizontalsystems.bitcoincore.network.peer.PeerTaskHandlerChain
import io.horizontalsystems.bitcoincore.storage.FullTransaction
import io.horizontalsystems.bitcoincore.storage.UnspentOutput
import io.horizontalsystems.bitcoincore.storage.UnspentOutputInfo
import io.horizontalsystems.bitcoincore.transactions.TransactionCreator
import io.horizontalsystems.bitcoincore.transactions.TransactionFeeCalculator
import io.horizontalsystems.bitcoincore.transactions.TransactionSyncer
Expand Down Expand Up @@ -143,8 +144,10 @@ class BitcoinCore(
val watchAccount: Boolean
get() = transactionCreator == null

val unspentOutputs: List<UnspentOutput>
get() = unspentOutputSelector.all
val unspentOutputs: List<UnspentOutputInfo>
get() = unspentOutputSelector.all.map {
UnspentOutputInfo.fromUnspentOutput(it)
}

//
// API methods
Expand Down Expand Up @@ -179,14 +182,20 @@ class BitcoinCore(
address: String? = null,
senderPay: Boolean = true,
feeRate: Int,
unspentOutputs: List<UnspentOutputInfo>?,
pluginData: Map<Byte, IPluginData>
): BitcoinSendInfo {
val outputs = unspentOutputs?.mapNotNull {
unspentOutputSelector.all.firstOrNull { unspentOutput ->
unspentOutput.transaction.hash.contentEquals(it.transactionHash) && unspentOutput.output.index == it.outputIndex
}
}
return transactionFeeCalculator?.sendInfo(
value = value,
feeRate = feeRate,
senderPay = senderPay,
toAddress = address,
unspentOutputs = null,
unspentOutputs = outputs,
pluginData = pluginData
) ?: throw CoreError.ReadOnlyCore
}
Expand All @@ -197,16 +206,21 @@ class BitcoinCore(
senderPay: Boolean = true,
feeRate: Int,
sortType: TransactionDataSortType,
unspentOutputs: List<UnspentOutput>?,
unspentOutputs: List<UnspentOutputInfo>?,
pluginData: Map<Byte, IPluginData>
): FullTransaction {
val outputs = unspentOutputs?.mapNotNull {
unspentOutputSelector.all.firstOrNull { unspentOutput ->
unspentOutput.transaction.hash.contentEquals(it.transactionHash) && unspentOutput.output.index == it.outputIndex
}
}
return transactionCreator?.create(
toAddress = address,
value = value,
feeRate = feeRate,
senderPay = senderPay,
sortType = sortType,
unspentOutputs = unspentOutputs,
unspentOutputs = outputs,
pluginData = pluginData
) ?: throw CoreError.ReadOnlyCore
}
Expand All @@ -218,16 +232,21 @@ class BitcoinCore(
senderPay: Boolean = true,
feeRate: Int,
sortType: TransactionDataSortType,
unspentOutputs: List<UnspentOutput>?,
unspentOutputs: List<UnspentOutputInfo>?,
): FullTransaction {
val address = addressConverter.convert(hash, scriptType)
val outputs = unspentOutputs?.mapNotNull {
unspentOutputSelector.all.firstOrNull { unspentOutput ->
unspentOutput.transaction.hash.contentEquals(it.transactionHash) && unspentOutput.output.index == it.outputIndex
}
}
return transactionCreator?.create(
toAddress = address.stringValue,
value = value,
feeRate = feeRate,
senderPay = senderPay,
sortType = sortType,
unspentOutputs = unspentOutputs,
unspentOutputs = outputs,
pluginData = mapOf()
) ?: throw CoreError.ReadOnlyCore
}
Expand Down Expand Up @@ -373,20 +392,29 @@ class BitcoinCore(
fun maximumSpendableValue(
address: String?,
feeRate: Int,
unspentOutputs: List<UnspentOutputInfo>?,
pluginData: Map<Byte, IPluginData>
): Long {
if (transactionFeeCalculator == null) throw CoreError.ReadOnlyCore

val outputs = unspentOutputs?.mapNotNull {
unspentOutputSelector.all.firstOrNull { unspentOutput ->
unspentOutput.transaction.hash.contentEquals(it.transactionHash) && unspentOutput.output.index == it.outputIndex
}
}

val spendableBalance = outputs?.sumOf { it.output.value } ?: balance.spendable

val sendAllFee = transactionFeeCalculator.sendInfo(
value = balance.spendable,
value = spendableBalance,
feeRate = feeRate,
senderPay = false,
toAddress = address,
unspentOutputs = null,
unspentOutputs = outputs,
pluginData = pluginData
).fee

return max(0L, balance.spendable - sendAllFee)
return max(0L, spendableBalance - sendAllFee)
}

fun minimumSpendableValue(address: String?): Int {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,26 @@ class UnspentOutput(
@Embedded val transaction: Transaction,
@Embedded val block: Block?)

class UnspentOutputInfo(
val outputIndex: Int,
val transactionHash: ByteArray,
val timestamp: Long,
val address: String?,
val value: Long
) {
companion object {
fun fromUnspentOutput(unspentOutput: UnspentOutput): UnspentOutputInfo {
return UnspentOutputInfo(
unspentOutput.output.index,
unspentOutput.output.transactionHash,
unspentOutput.transaction.timestamp,
unspentOutput.output.address,
unspentOutput.output.value,
)
}
}
}

class FullTransactionInfo(
val block: Block?,
val header: Transaction,
Expand Down

0 comments on commit 4956962

Please sign in to comment.