-
Notifications
You must be signed in to change notification settings - Fork 170
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(coinjoin): group mixing transactions on home screen (#1272)
* feat: add grouping of CoinJoin transactions * feat: create multiple groups * fix: add method to obtain wrappers
- Loading branch information
1 parent
e89bf41
commit 17e6983
Showing
18 changed files
with
331 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
common/src/main/java/org/dash/wallet/common/transactions/TransactionWrapperFactory.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* Copyright 2024 Dash Core Group. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package org.dash.wallet.common.transactions | ||
|
||
import org.bitcoinj.core.Transaction | ||
|
||
interface TransactionWrapperFactory { | ||
fun tryInclude(tx: Transaction): Pair<Boolean, TransactionWrapper?> | ||
val wrappers: List<TransactionWrapper> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
...va/org/dash/wallet/integrations/crowdnode/transactions/FullCrowdNodeSignUpTxSetFactory.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package org.dash.wallet.integrations.crowdnode.transactions | ||
|
||
import org.bitcoinj.core.NetworkParameters | ||
import org.bitcoinj.core.Transaction | ||
import org.bitcoinj.core.TransactionBag | ||
import org.dash.wallet.common.transactions.TransactionWrapper | ||
import org.dash.wallet.common.transactions.TransactionWrapperFactory | ||
|
||
class FullCrowdNodeSignUpTxSetFactory(params: NetworkParameters, transactionBag: TransactionBag) : | ||
TransactionWrapperFactory { | ||
private val wrapper = FullCrowdNodeSignUpTxSet(params, transactionBag) | ||
override val wrappers = listOf(wrapper) | ||
|
||
override fun tryInclude(tx: Transaction): Pair<Boolean, TransactionWrapper?> { | ||
return Pair(wrapper.tryInclude(tx), wrapper) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
android:width="36dp" | ||
android:height="36dp" | ||
android:viewportWidth="36" | ||
android:viewportHeight="36"> | ||
<path | ||
android:pathData="M0,18C0,8.059 8.059,0 18,0C27.941,0 36,8.059 36,18C36,27.941 27.941,36 18,36C8.059,36 0,27.941 0,18Z" | ||
android:fillColor="#008DE4" | ||
android:fillAlpha="0.1"/> | ||
<path | ||
android:pathData="M18,28C16.634,28 15.346,27.739 14.137,27.216C12.935,26.693 11.873,25.971 10.951,25.049C10.029,24.128 9.307,23.065 8.784,21.863C8.261,20.654 8,19.366 8,18C8,16.634 8.261,15.35 8.784,14.147C9.307,12.938 10.026,11.873 10.941,10.951C11.863,10.029 12.925,9.307 14.127,8.784C15.337,8.261 16.624,8 17.99,8C19.356,8 20.644,8.261 21.853,8.784C23.062,9.307 24.128,10.029 25.049,10.951C25.971,11.873 26.693,12.938 27.216,14.147C27.739,15.35 28,16.634 28,18C28,19.366 27.739,20.654 27.216,21.863C26.693,23.065 25.971,24.128 25.049,25.049C24.128,25.971 23.062,26.693 21.853,27.216C20.65,27.739 19.366,28 18,28ZM18,26.333C19.157,26.333 20.239,26.118 21.245,25.686C22.252,25.255 23.137,24.66 23.902,23.902C24.667,23.137 25.261,22.252 25.686,21.245C26.118,20.239 26.333,19.157 26.333,18C26.333,16.843 26.118,15.761 25.686,14.755C25.255,13.748 24.657,12.863 23.892,12.098C23.134,11.333 22.248,10.739 21.235,10.314C20.229,9.882 19.147,9.667 17.99,9.667C16.833,9.667 15.752,9.882 14.745,10.314C13.739,10.739 12.856,11.333 12.098,12.098C11.34,12.863 10.745,13.748 10.314,14.755C9.889,15.761 9.676,16.843 9.676,18C9.676,19.157 9.889,20.239 10.314,21.245C10.745,22.252 11.34,23.137 12.098,23.902C12.863,24.66 13.748,25.255 14.755,25.686C15.761,26.118 16.843,26.333 18,26.333ZM15.902,15.941C15.431,15.941 15.029,15.774 14.696,15.441C14.363,15.101 14.196,14.699 14.196,14.235C14.196,13.765 14.363,13.363 14.696,13.029C15.036,12.696 15.438,12.529 15.902,12.529C16.366,12.529 16.765,12.696 17.098,13.029C17.438,13.363 17.608,13.765 17.608,14.235C17.608,14.699 17.438,15.101 17.098,15.441C16.765,15.774 16.366,15.941 15.902,15.941ZM20.088,15.941C19.624,15.941 19.222,15.774 18.882,15.441C18.549,15.101 18.382,14.699 18.382,14.235C18.382,13.765 18.549,13.363 18.882,13.029C19.222,12.696 19.624,12.529 20.088,12.529C20.559,12.529 20.961,12.696 21.294,13.029C21.628,13.363 21.794,13.765 21.794,14.235C21.794,14.699 21.628,15.101 21.294,15.441C20.961,15.774 20.559,15.941 20.088,15.941ZM13.814,19.696C13.337,19.696 12.931,19.529 12.598,19.196C12.265,18.856 12.098,18.454 12.098,17.99C12.098,17.526 12.265,17.124 12.598,16.784C12.938,16.444 13.343,16.274 13.814,16.274C14.271,16.274 14.667,16.444 15,16.784C15.34,17.124 15.51,17.526 15.51,17.99C15.51,18.454 15.34,18.856 15,19.196C14.667,19.529 14.271,19.696 13.814,19.696ZM18,19.696C17.536,19.696 17.134,19.529 16.794,19.196C16.454,18.856 16.284,18.454 16.284,17.99C16.284,17.526 16.454,17.124 16.794,16.784C17.134,16.444 17.536,16.274 18,16.274C18.458,16.274 18.856,16.444 19.196,16.784C19.536,17.124 19.706,17.526 19.706,17.99C19.706,18.454 19.536,18.856 19.196,19.196C18.856,19.529 18.458,19.696 18,19.696ZM22.186,19.696C21.722,19.696 21.32,19.529 20.98,19.196C20.647,18.856 20.48,18.454 20.48,17.99C20.48,17.526 20.647,17.124 20.98,16.784C21.32,16.444 21.722,16.274 22.186,16.274C22.65,16.274 23.049,16.444 23.382,16.784C23.722,17.124 23.892,17.526 23.892,17.99C23.892,18.454 23.722,18.856 23.382,19.196C23.049,19.529 22.65,19.696 22.186,19.696ZM15.902,23.451C15.431,23.451 15.029,23.284 14.696,22.951C14.363,22.611 14.196,22.209 14.196,21.745C14.196,21.281 14.363,20.882 14.696,20.549C15.036,20.209 15.438,20.039 15.902,20.039C16.366,20.039 16.765,20.209 17.098,20.549C17.438,20.882 17.608,21.281 17.608,21.745C17.608,22.209 17.438,22.611 17.098,22.951C16.765,23.284 16.366,23.451 15.902,23.451ZM20.088,23.451C19.624,23.451 19.222,23.284 18.882,22.951C18.549,22.611 18.382,22.209 18.382,21.745C18.382,21.281 18.549,20.882 18.882,20.549C19.222,20.209 19.624,20.039 20.088,20.039C20.559,20.039 20.961,20.209 21.294,20.549C21.628,20.882 21.794,21.281 21.794,21.745C21.794,22.209 21.628,22.611 21.294,22.951C20.961,23.284 20.559,23.451 20.088,23.451Z" | ||
android:fillColor="#008DE4"/> | ||
</vector> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
wallet/src/de/schildbach/wallet/transactions/coinjoin/CoinJoinMixingFilter.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Copyright 2024 Dash Core Group. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package de.schildbach.wallet.transactions.coinjoin | ||
|
||
import org.bitcoinj.coinjoin.utils.CoinJoinTransactionType | ||
import org.bitcoinj.core.Transaction | ||
import org.bitcoinj.script.Script | ||
import org.bitcoinj.script.ScriptPattern | ||
import org.bitcoinj.wallet.WalletEx | ||
import org.dash.wallet.common.transactions.filters.TransactionFilter | ||
|
||
open class CoinJoinTxFilter(private val wallet: WalletEx, val type: CoinJoinTransactionType) : TransactionFilter { | ||
override fun matches(tx: Transaction): Boolean { | ||
return CoinJoinTransactionType.fromTx(tx, wallet) == type | ||
} | ||
} | ||
|
||
class CreateDenominationTxFilter(wallet: WalletEx) : CoinJoinTxFilter( | ||
wallet, | ||
CoinJoinTransactionType.CreateDenomination | ||
) | ||
class MakeCollateralTxFilter(wallet: WalletEx) : CoinJoinTxFilter(wallet, CoinJoinTransactionType.MakeCollateralInputs) | ||
class MixingFeeTxFilter(wallet: WalletEx) : CoinJoinTxFilter(wallet, CoinJoinTransactionType.MixingFee) | ||
class MixingTxFilter(wallet: WalletEx) : CoinJoinTxFilter(wallet, CoinJoinTransactionType.Mixing) |
53 changes: 53 additions & 0 deletions
53
wallet/src/de/schildbach/wallet/transactions/coinjoin/CoinJoinMixingTxSet.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package de.schildbach.wallet.transactions.coinjoin | ||
|
||
import org.bitcoinj.core.* | ||
import org.bitcoinj.wallet.WalletEx | ||
import org.dash.wallet.common.transactions.TransactionComparator | ||
import org.dash.wallet.common.transactions.TransactionWrapper | ||
import org.dash.wallet.common.transactions.filters.TransactionFilter | ||
import org.slf4j.LoggerFactory | ||
|
||
open class CoinJoinMixingTxSet( | ||
private val networkParams: NetworkParameters, | ||
private val wallet: WalletEx | ||
) : TransactionWrapper { | ||
private val log = LoggerFactory.getLogger(CoinJoinMixingTxSet::class.java) | ||
private var isFinished = false | ||
|
||
private val coinjoinTxFilters = mutableListOf( | ||
CreateDenominationTxFilter(wallet), | ||
MakeCollateralTxFilter(wallet), | ||
MixingFeeTxFilter(wallet), | ||
MixingTxFilter(wallet) | ||
) | ||
|
||
private val matchedFilters = mutableListOf<TransactionFilter>() | ||
override val transactions = sortedSetOf(TransactionComparator()) | ||
|
||
override fun tryInclude(tx: Transaction): Boolean { | ||
if (isFinished || transactions.any { it.txId == tx.txId }) { | ||
return false | ||
} | ||
|
||
val matchedFilter = coinjoinTxFilters.firstOrNull { it.matches(tx) } | ||
|
||
if (matchedFilter != null) { | ||
transactions.add(tx) | ||
matchedFilters.add(matchedFilter) | ||
return true | ||
} | ||
|
||
return false | ||
} | ||
|
||
override fun getValue(bag: TransactionBag): Coin { | ||
var result = Coin.ZERO | ||
|
||
for (tx in transactions) { | ||
val value = tx.getValue(bag) | ||
result = result.add(value) | ||
} | ||
|
||
return result | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
wallet/src/de/schildbach/wallet/transactions/coinjoin/CoinJoinTxResourceMapper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/* | ||
* Copyright 2024 Dash Core Group. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package de.schildbach.wallet.transactions.coinjoin | ||
|
||
import de.schildbach.wallet.ui.transactions.TxResourceMapper | ||
|
||
import android.text.format.DateUtils | ||
import androidx.annotation.StringRes | ||
import de.schildbach.wallet_test.R | ||
import org.bitcoinj.coinjoin.utils.CoinJoinTransactionType | ||
import org.bitcoinj.core.Transaction | ||
import org.bitcoinj.core.TransactionBag | ||
import org.bitcoinj.wallet.WalletEx | ||
|
||
class CoinJoinTxResourceMapper: TxResourceMapper() { | ||
@StringRes | ||
override fun getTransactionTypeName(tx: Transaction, bag: TransactionBag): Int { | ||
if ((tx.type != Transaction.Type.TRANSACTION_NORMAL && | ||
tx.type != Transaction.Type.TRANSACTION_UNKNOWN) || | ||
tx.confidence.hasErrors() || | ||
tx.isCoinBase | ||
) { | ||
return super.getTransactionTypeName(tx, bag) | ||
} | ||
|
||
return when (CoinJoinTransactionType.fromTx(tx, bag as WalletEx)) { | ||
CoinJoinTransactionType.CreateDenomination -> R.string.transaction_row_status_coinjoin_create_denominations | ||
CoinJoinTransactionType.Mixing -> R.string.transaction_row_status_coinjoin_mixing | ||
CoinJoinTransactionType.MixingFee -> R.string.transaction_row_status_coinjoin_mixing_fee | ||
CoinJoinTransactionType.MakeCollateralInputs -> R.string.transaction_row_status_coinjoin_make_collateral | ||
else -> super.getTransactionTypeName(tx, bag) | ||
} | ||
} | ||
|
||
override fun getDateTimeFormat(): Int { | ||
return DateUtils.FORMAT_SHOW_TIME | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
wallet/src/de/schildbach/wallet/transactions/coinjoin/CoinJoinTxWrapperFactory.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* | ||
* Copyright 2024 Dash Core Group. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package de.schildbach.wallet.transactions.coinjoin | ||
|
||
import org.bitcoinj.coinjoin.utils.CoinJoinTransactionType | ||
import org.bitcoinj.core.NetworkParameters | ||
import org.bitcoinj.core.Transaction | ||
import org.bitcoinj.wallet.WalletEx | ||
import org.dash.wallet.common.transactions.TransactionWrapper | ||
import org.dash.wallet.common.transactions.TransactionWrapperFactory | ||
import java.time.Instant | ||
import java.time.LocalDateTime | ||
import java.time.ZoneId | ||
|
||
class CoinJoinTxWrapperFactory(val params: NetworkParameters, val wallet: WalletEx) : TransactionWrapperFactory { | ||
private val wrapperMap = hashMapOf<Long, CoinJoinMixingTxSet>() | ||
override val wrappers: List<TransactionWrapper> | ||
get() = wrapperMap.values.toList() | ||
|
||
override fun tryInclude(tx: Transaction): Pair<Boolean, TransactionWrapper?> { | ||
return when (CoinJoinTransactionType.fromTx(tx, wallet)) { | ||
CoinJoinTransactionType.None, CoinJoinTransactionType.Send -> { Pair(false, null) } | ||
else -> { | ||
val instant = Instant.ofEpochMilli(tx.updateTime.time) | ||
val localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()) | ||
val startOfDay = localDateTime.toLocalDate().atStartOfDay(ZoneId.systemDefault()) | ||
val startOfDayTimestamp = startOfDay.toInstant().toEpochMilli() | ||
val wrapper = wrapperMap[startOfDayTimestamp] | ||
if (wrapper != null) { | ||
Pair(wrapper.tryInclude(tx), wrapper) | ||
} else { | ||
val newWrapper = CoinJoinMixingTxSet(params, wallet) | ||
val included = newWrapper.tryInclude(tx) | ||
wrapperMap[startOfDayTimestamp] = newWrapper | ||
Pair(included, newWrapper) | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.